GCC Code Coverage Report


Directory: src/gate/
File: src/gate/platform/linux/procfs.h
Date: 2025-09-14 13:10:38
Exec Total Coverage
Lines: 54 60 90.0%
Functions: 6 6 100.0%
Branches: 12 24 50.0%

Line Branch Exec Source
1 /* GATE PROJECT LICENSE:
2 +----------------------------------------------------------------------------+
3 | Copyright(c) 2018-2025, Stefan Meislinger <sm@opengate.at> |
4 | All rights reserved. |
5 | |
6 | Redistribution and use in source and binary forms, with or without |
7 | modification, are permitted provided that the following conditions are met:|
8 | |
9 | 1. Redistributions of source code must retain the above copyright notice, |
10 | this list of conditions and the following disclaimer. |
11 | 2. Redistributions in binary form must reproduce the above copyright |
12 | notice, this list of conditions and the following disclaimer in the |
13 | documentation and/or other materials provided with the distribution. |
14 | |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"|
16 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
17 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
18 | ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
19 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
20 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
21 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
22 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
23 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
24 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
25 | THE POSSIBILITY OF SUCH DAMAGE. |
26 +----------------------------------------------------------------------------+
27 */
28
29 #ifndef GATE_PLATFORM_LINUX_PROCFS_H_INCLUDED
30 #define GATE_PLATFORM_LINUX_PROCFS_H_INCLUDED
31
32 #include "gate/gatetypes.h"
33
34 #ifdef GATE_SYS_LINUX
35
36 #include <dirent.h>
37 #include <sys/sysinfo.h>
38 #include <sys/stat.h>
39
40 typedef struct gate_procfs_proc_stat
41 {
42 int pid;
43 char comm[256];
44 char state;
45 int ppid;
46 int pgrp;
47 int session;
48 int tty_nr;
49 int tpgid;
50 unsigned flags;
51 unsigned long minflt;
52 unsigned long cminflt;
53 unsigned long majflt;
54 unsigned long cmajflt;
55 unsigned long utime;
56 unsigned long stime;
57 long long cutime;
58 long long cstime;
59 long long priority;
60 long long nice;
61 long long num_threads;
62 long long itrealvalue;
63 unsigned long long starttime;
64 unsigned long vsize;
65 long rss;
66 unsigned long rsslim;
67 unsigned long startcode;
68 unsigned long endcode;
69 unsigned long startstack;
70 unsigned long kstkesp;
71 unsigned long kstkeip;
72 unsigned long signal;
73 unsigned long blocked;
74 unsigned long sigignore;
75 unsigned long sigcatch;
76 unsigned long wchan;
77 unsigned long nswap;
78 unsigned long cnswap;
79 int exit_signal;
80 int processor;
81 unsigned rt_priority;
82 unsigned policy;
83 unsigned long long delayacct_blkio_ticks;
84 unsigned long guest_time;
85 long cguest_time;
86 unsigned long start_data;
87 unsigned long end_data;
88 unsigned long start_brk;
89 unsigned long arg_start;
90 unsigned long arg_end;
91 unsigned long env_start;
92 unsigned long env_end;
93 int exit_code;
94 } gate_procfs_proc_stat_t;
95
96 8 static gate_bool_t gate_procfs_load_proc_stat(int pid, gate_procfs_proc_stat_t* procstat)
97 {
98 8 gate_bool_t ret = false;
99 8 char file_path[GATE_MAX_FILEPATH_LENGTH] = GATE_INIT_EMPTY;
100 FILE* file;
101 int readcount;
102 do
103 {
104 8 gate_str_print(file_path, sizeof(file_path) - 1,
105 GATE_PRINT_CSTR, "/proc/",
106 GATE_PRINT_UI64, (gate_uint64_t)pid,
107 GATE_PRINT_CSTR, "/stat",
108 GATE_PRINT_END);
109
110 8 file = fopen(file_path, "r");
111
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (file == NULL)
112 {
113 break;
114 }
115 8 readcount = fscanf(file,
116 "%d %s %c %d %d "
117 "%d %d %d %u "
118 "%lu %lu %lu %lu "
119 "%lu %lu %lld %lld "
120 "%lld %lld %lld %lld "
121 "%llu %lu %ld %lu "
122 "%lu %lu %lu %lu %lu "
123 "%lu %lu %lu %lu %lu "
124 "%lu %lu %d %d "
125 "%u %u %llu "
126 "%lu %ld %lu %lu "
127 "%lu %lu %lu "
128 "%lu %lu %d",
129 &procstat->pid, &procstat->comm[0], &procstat->state, &procstat->ppid, &procstat->pgrp,
130 &procstat->session, &procstat->tty_nr, &procstat->tpgid, &procstat->flags,
131 &procstat->minflt, &procstat->cminflt, &procstat->majflt, &procstat->cmajflt,
132 &procstat->utime, &procstat->stime, &procstat->cutime, &procstat->cstime,
133 &procstat->priority, &procstat->nice, &procstat->num_threads, &procstat->itrealvalue,
134 &procstat->starttime, &procstat->vsize, &procstat->rss, &procstat->rsslim,
135 &procstat->startcode, &procstat->endcode, &procstat->startstack, &procstat->kstkesp, &procstat->kstkeip,
136 &procstat->signal, &procstat->blocked, &procstat->sigignore, &procstat->sigcatch, &procstat->wchan,
137 &procstat->nswap, &procstat->cnswap, &procstat->exit_signal, &procstat->processor,
138 &procstat->rt_priority, &procstat->policy, &procstat->delayacct_blkio_ticks,
139 &procstat->guest_time, &procstat->cguest_time, &procstat->start_data, &procstat->end_data,
140 &procstat->start_brk, &procstat->arg_start, &procstat->arg_end,
141 &procstat->env_start, &procstat->env_end, &procstat->exit_code
142 );
143 8 fclose(file);
144
145 8 ret = (readcount >= 48) ? true : false;
146 } while (0);
147 8 return ret;
148 }
149
150 8 static gate_int64_t gate_procfs_get_uptime_ms()
151 {
152 struct sysinfo info;
153 8 gate_int64_t up_time = -1;
154 8 float num = 0.0f;
155 8 FILE* file = fopen("/proc/uptime", "r");
156
157
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 if (file != NULL)
158 {
159
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 if (fscanf(file, "%f", &num) == 1)
160 {
161 8 up_time = (gate_int64_t)(num * 1000.0f);
162 }
163 8 fclose(file);
164 }
165
166
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (up_time < 0)
167 {
168 gate_mem_clear(&info, sizeof(info));
169 if (sysinfo(&info) == 0)
170 {
171 up_time = (gate_int64_t)(info.uptime * 1000.0f);
172 }
173 }
174 8 return up_time;
175 }
176
177
178 typedef struct
179 {
180 unsigned long size;
181 unsigned long resident;
182 unsigned long share;
183 unsigned long text;
184 unsigned long lib;
185 unsigned long data;
186 unsigned long dt;
187 } gate_procfs_memstat_t;
188
189
190 8 static gate_bool_t gate_procfs_get_memstat(int pid, gate_procfs_memstat_t* memstat)
191 {
192 8 gate_bool_t ret = false;
193 8 char file_path[GATE_MAX_FILEPATH_LENGTH] = GATE_INIT_EMPTY;
194 FILE* file;
195 int readcount;
196 do
197 {
198 8 gate_str_print(file_path, sizeof(file_path) - 1,
199 GATE_PRINT_CSTR, "/proc/",
200 GATE_PRINT_UI64, (gate_uint64_t)pid,
201 GATE_PRINT_CSTR, "/statm",
202 GATE_PRINT_END);
203 8 file = fopen(file_path, "r");
204
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (file == NULL)
205 {
206 break;
207 }
208 8 readcount = fscanf(file, "%lu %lu %lu %lu %lu %lu %lu",
209 &memstat->size, &memstat->resident, &memstat->share, &memstat->text,
210 &memstat->lib, &memstat->data, &memstat->dt
211 );
212 8 fclose(file);
213 8 ret = (readcount >= 7) ? true : false;
214 } while (0);
215 8 return ret;
216 }
217
218 8 static gate_uint64_t gate_procfs_get_open_fds(int pid)
219 {
220 8 gate_uint64_t count = 0;
221 8 struct dirent* dir_entry = NULL;
222 DIR* dir_ptr;
223 8 char dir_path[GATE_MAX_FILEPATH_LENGTH] = GATE_INIT_EMPTY;
224
225 8 gate_str_print(dir_path, sizeof(dir_path) - 1,
226 GATE_PRINT_CSTR, "/proc/",
227 GATE_PRINT_UI64, (gate_uint64_t)pid,
228 GATE_PRINT_CSTR, "/fd/",
229 GATE_PRINT_END);
230
231
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 if (NULL != (dir_ptr = opendir(dir_path)))
232 {
233
2/2
✓ Branch 1 taken 57 times.
✓ Branch 2 taken 8 times.
65 while ((dir_entry = readdir(dir_ptr)))
234 {
235 57 ++count;
236 }
237 8 closedir(dir_ptr);
238 }
239 8 return count;
240 }
241
242 8 static gate_size_t gate_procfs_get_exe_path(int pid, char* exe_path, gate_size_t exe_path_len)
243 {
244 char link_path[GATE_MAX_FILEPATH_LENGTH];
245 ssize_t exe_path_used;
246 8 gate_str_print(link_path, sizeof(link_path) - 1,
247 GATE_PRINT_CSTR, "/proc/",
248 GATE_PRINT_UI64, (gate_uint64_t)pid,
249 GATE_PRINT_CSTR, "/exe",
250 GATE_PRINT_END);
251 8 exe_path_used = readlink(link_path, exe_path, exe_path_len - 1);
252
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 if (exe_path_used > 0)
253 {
254 8 exe_path[exe_path_used] = 0;
255 8 return (gate_size_t)exe_path_used;
256 }
257 else
258 {
259 return 0;
260 }
261 }
262
263 8 static gate_bool_t gate_procfs_get_exe_owner(int pid, int* uid, int* gid)
264 {
265 8 gate_bool_t ret = false;
266 struct stat buf;
267 char pid_path[GATE_MAX_FILEPATH_LENGTH];
268 8 gate_str_print(pid_path, sizeof(pid_path) - 1,
269 GATE_PRINT_CSTR, "/proc/",
270 GATE_PRINT_UI64, (gate_uint64_t)pid,
271 GATE_PRINT_END);
272
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 if (0 == stat(pid_path, &buf))
273 {
274
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 if (uid != NULL) *uid = (int)buf.st_uid;
275
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (gid != NULL) *gid = (int)buf.st_gid;
276 8 ret = true;
277 }
278
279 8 return ret;
280 }
281
282
283 #endif
284
285 #endif
286