GCC Code Coverage Report


Directory: src/gate/
File: src/gate/system/os_posix.c
Date: 2026-08-06 22:46:24
Exec Total Coverage
Lines: 332 407 81.6%
Functions: 29 31 93.5%
Branches: 114 224 50.9%

Line Branch Exec Source
1 /* GATE PROJECT LICENSE:
2 +----------------------------------------------------------------------------+
3 | Copyright(c) 2018-2026, Stefan Meislinger |
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 #include "gate/system/os.h"
30 #include "gate/results.h"
31
32 #if defined(GATE_SYS_POSIX) && !defined(GATE_SYS_BEOS)
33
34 #include "gate/processes.h"
35 #include "gate/strings.h"
36 #include "gate/files.h"
37 #include "gate/platforms.h"
38 #include <unistd.h>
39
40 #if !defined(GATE_SYS_DARWIN)
41 # include <sys/reboot.h>
42 #endif
43
44
45 #if !defined(GATE_SYS_ANDROID)
46 #endif
47
48 #if defined(GATE_SYS_LINUX)
49 # include <features.h>
50 # if defined(__GLIBC__)
51 //# include <sys/sysctl.h>
52 # endif
53 # include <sys/sysinfo.h>
54 #endif
55
56 #if defined(GATE_SYS_BSD)
57 # include <sys/sysctl.h>
58 # if defined(GATE_SYS_NETBSD)
59 # include <sys/reboot.h>
60 # endif
61 #endif
62
63 #if defined(GATE_SYS_DARWIN)
64 # include <sys/sysctl.h>
65 #endif
66
67 #include <sys/utsname.h>
68
69 #include <string.h>
70 #include <stdio.h>
71
72 typedef struct linux_os_release_info_class
73 {
74 char os_id[256];
75 char os_id_like[256];
76 char os_name[256];
77 char os_pretty_name[256];
78 char os_version[256];
79 char os_version_id[256];
80 } linux_os_release_info_t;
81
82 static char const* linux_os_release_files[] = {
83 "/etc/os-release"
84 };
85
86 129 static gate_bool_t decode_line(char const* line, gate_size_t linelen, char const* key, gate_size_t keylen, char* value, gate_size_t valuelen)
87 {
88 gate_string_t tmp;
89
2/2
✓ Branch 1 taken 15 times.
✓ Branch 2 taken 114 times.
129 if (gate_str_starts_with(line, linelen, key, keylen))
90 {
91 15 gate_string_create_static_len(&tmp, &line[keylen], linelen - keylen);
92 15 gate_string_trim(&tmp, &tmp);
93
4/6
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 12 times.
✗ Branch 5 not taken.
15 if ((tmp.length >= 2) && (tmp.str[0] == '\"') && (tmp.str[tmp.length - 1] == '\"'))
94 {
95 12 gate_str_print_text(value, valuelen, tmp.str + 1, tmp.length - 2);
96 }
97 else
98 {
99 3 gate_str_print_text(value, valuelen, tmp.str, tmp.length);
100 }
101 15 gate_string_release(&tmp);
102 15 return true;
103 }
104 else
105 {
106 114 return false;
107 }
108 }
109
110 #if defined(GATE_SYS_BSD)
111 static bool gate_get_sysctrl_value(int mib[], size_t miblen, char* buffer, gate_size_t* buffer_used)
112 {
113 size_t buffer_len = *buffer_used - 1;
114 if (sysctl(mib, (int)miblen, buffer, &buffer_len, 0, 0) == 0)
115 {
116 if (buffer_used)
117 {
118 *buffer_used = buffer_len;
119 }
120 buffer[buffer_len] = 0;
121 return true;
122 }
123 return false;
124 }
125 #endif
126
127
128 3 static gate_result_t gate_linux_read_os_release_info(linux_os_release_info_t* info)
129 {
130 3 gate_result_t ret = GATE_RESULT_FAILED;
131 3 gate_mem_clear(info, sizeof(linux_os_release_info_t));
132 3 gate_size_t count = sizeof(linux_os_release_files) / sizeof(linux_os_release_files[0]);
133 gate_size_t index;
134 gate_string_t filename;
135 3 gate_controlstream_t* filestream = NULL;
136 char buffer[GATE_MAX_COPYBUFFER_LENGTH];
137 gate_size_t linelen;
138
139
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 for (index = 0; index != count; ++index)
140 {
141 3 gate_string_create_static(&filename, linux_os_release_files[index]);
142 3 ret = gate_file_openstream(&filename, GATE_STREAM_OPEN_READ, &filestream);
143 3 gate_string_release(&filename);
144
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (GATE_SUCCEEDED(ret))
145 {
146
1/2
✓ Branch 1 taken 30 times.
✗ Branch 2 not taken.
30 while (GATE_SUCCEEDED(ret = gate_stream_read_line((gate_stream_t*)filestream, buffer, sizeof(buffer), &linelen)))
147 {
148
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 27 times.
30 if (linelen == 0)
149 {
150 3 break;
151 }
152
153
2/2
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 24 times.
27 if (decode_line(buffer, linelen, "ID=", 3, info->os_id, sizeof(info->os_id))) continue;
154
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 24 times.
24 if (decode_line(buffer, linelen, "ID_LIKE=", 8, info->os_id_like, sizeof(info->os_id_like))) continue;
155
2/2
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 21 times.
24 if (decode_line(buffer, linelen, "NAME=", 5, info->os_name, sizeof(info->os_name))) continue;
156
2/2
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 18 times.
21 if (decode_line(buffer, linelen, "PRETTY_NAME=", 12, info->os_pretty_name, sizeof(info->os_pretty_name))) continue;
157
2/2
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 15 times.
18 if (decode_line(buffer, linelen, "VERSION=", 8, info->os_version, sizeof(info->os_version))) continue;
158
2/2
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 12 times.
15 if (decode_line(buffer, linelen, "VERSION_ID=", 11, info->os_version_id, sizeof(info->os_version_id))) continue;
159
160 }
161
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 GATE_BREAK_IF_FAILED(ret);
162 3 break;
163 }
164 }
165
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (filestream != NULL)
166 {
167 3 gate_object_release(filestream);
168 }
169
170 3 return ret;
171 }
172
173 2 gate_result_t gate_os_get_platform(gate_uint32_t* ptr_platform)
174 {
175 2 gate_result_t ret = GATE_RESULT_OK;
176 #if defined(GATE_SYS_ANDROID)
177 *ptr_platform = GATE_OS_PLATFORM_LINUX_ANDROID;
178 #elif defined(GATE_SYS_FREEBSD)
179 *ptr_platform = GATE_OS_PLATFORM_BSD_FREEBSD;
180 #elif defined(GATE_SYS_NETBSD)
181 *ptr_platform = GATE_OS_PLATFORM_BSD_NETBSD;
182 #elif defined(GATE_SYS_OPENBSD)
183 *ptr_platform = GATE_OS_PLATFORM_BSD_OPENBSD;
184 #elif defined(GATE_SYS_BSD)
185 *ptr_platform = GATE_OS_PLATFORM_BSD;
186 #elif defined(GATE_SYS_DARWIN)
187 *ptr_platform = GATE_OS_PLATFORM_DARWIN;
188 #elif defined(GATE_SYS_LINUX)
189 2 *ptr_platform = GATE_OS_PLATFORM_LINUX;
190 #else
191 ret = GATE_RESULT_FAILED;
192 #endif
193
194 2 return ret;
195 }
196
197 1 gate_uint32_t gate_os_address_space()
198 {
199 1 return sizeof(void*) * 8;
200 }
201 2 gate_uint32_t gate_os_up_time_seconds()
202 {
203 2 gate_uint32_t ret = 0;
204 gate_result_t result;
205 char buffer[1024];
206 2 gate_size_t buffer_used = sizeof(buffer);
207 2 float flt_uptime = 0.0f;
208 static gate_string_t const proc_path_uptime = { "/proc/uptime", 12, NULL };
209 #if defined(GATE_SYS_LINUX)
210 struct sysinfo info;
211 #endif
212
213 do
214 {
215 2 result = gate_file_get_content_buffer(&proc_path_uptime, buffer, &buffer_used);
216
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (GATE_SUCCEEDED(result))
217 {
218 2 buffer[buffer_used] = 0;
219
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (sscanf(buffer, "%f", &flt_uptime) == 1)
220 {
221 2 ret = (gate_uint32_t)flt_uptime;
222 2 break;
223 }
224 }
225 #if defined(GATE_SYS_LINUX)
226
227 gate_mem_clear(&info, sizeof(info));
228 if (sysinfo(&info) == 0)
229 {
230 ret = (gate_uint32_t)info.uptime;
231 }
232 #endif
233 } while (0);
234
235 2 return ret;
236 }
237 1 gate_result_t gate_os_print_osname(char* buffer, gate_size_t buffer_len, gate_size_t* buffer_used)
238 {
239 1 gate_result_t ret = GATE_RESULT_FAILED;
240
241 #if defined(GATE_SYS_LINUX)
242 1 char const* ptr_data = NULL;
243 struct utsname utsname_buffer;
244 linux_os_release_info_t info;
245 gate_size_t len;
246
247 1 ret = gate_linux_read_os_release_info(&info);
248
249
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (GATE_SUCCEEDED(ret))
250 {
251
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 if (!gate_str_is_empty(info.os_name))
252 {
253 1 ptr_data = info.os_name;
254 }
255 else if (!gate_str_is_empty(info.os_id))
256 {
257 ptr_data = info.os_id;
258 }
259 else if (!gate_str_is_empty(info.os_id_like))
260 {
261 ptr_data = info.os_id_like;
262 }
263 }
264
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (ptr_data == NULL)
265 {
266 if (uname(&utsname_buffer) == 0)
267 {
268 ptr_data = utsname_buffer.sysname;
269 }
270 }
271
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (ptr_data != NULL)
272 {
273 1 len = gate_str_print_text(buffer, buffer_len, ptr_data, gate_str_length(ptr_data));
274
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (buffer_used)
275 {
276 1 *buffer_used = len;
277 }
278 1 ret = GATE_RESULT_OK;
279 }
280 else
281 {
282 ret = GATE_RESULT_FAILED;
283 }
284
285 #elif defined(GATE_SYS_DARWIN)
286 char name[256];
287 size_t namelen = sizeof(name) - 1;
288
289 name[sizeof(name) - 1] = 0;
290 if (sysctlbyname("kern.ostype", name, &namelen, NULL, 0) == 0)
291 {
292 const gate_size_t name_used = gate_str_length_max(name, sizeof(name));
293 const gate_size_t used = gate_str_print_text(buffer, buffer_len, name, namelen);
294 if (buffer_used) *buffer_used = used;
295 return GATE_RESULT_OK;
296 }
297 else
298 {
299 return GATE_RESULT_FAILED;
300 }
301
302 #elif defined(GATE_SYS_BSD)
303 int mib[] = { CTL_KERN, KERN_OSTYPE };
304 size_t miblen = sizeof(mib) / sizeof(mib[0]);
305 *buffer_used = buffer_len;
306 if (gate_get_sysctrl_value(mib, miblen, buffer, buffer_used))
307 {
308 ret = GATE_RESULT_OK;
309 }
310 #endif
311 1 return ret;
312 }
313
314
315 1 gate_result_t gate_os_print_productname(char* buffer, gate_size_t buffer_len, gate_size_t* buffer_used)
316 {
317 1 gate_result_t ret = GATE_RESULT_FAILED;
318
319 #if defined(GATE_SYS_LINUX)
320 1 char const* ptr_data = NULL;
321 gate_size_t len;
322 struct utsname utsname_buffer;
323 linux_os_release_info_t info;
324 1 ret = gate_linux_read_os_release_info(&info);
325
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (GATE_SUCCEEDED(ret))
326 {
327
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 if (!gate_str_is_empty(info.os_pretty_name))
328 {
329 1 ptr_data = info.os_pretty_name;
330 }
331 else if (!gate_str_is_empty(info.os_version))
332 {
333 ptr_data = info.os_id;
334 }
335 }
336
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (ptr_data == NULL)
337 {
338 if (uname(&utsname_buffer) == 0)
339 {
340 ptr_data = utsname_buffer.sysname;
341 }
342 }
343
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (ptr_data != NULL)
344 {
345 1 len = gate_str_print_text(buffer, buffer_len, ptr_data, gate_str_length(ptr_data));
346
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (buffer_used)
347 {
348 1 *buffer_used = len;
349 }
350 1 ret = GATE_RESULT_OK;
351 }
352 else
353 {
354 ret = GATE_RESULT_FAILED;
355 }
356 #elif defined(GATE_SYS_DARWIN)
357 char name[256];
358 size_t namelen = sizeof(name) - 1;
359
360 name[sizeof(name) - 1] = 0;
361 if (sysctlbyname("kern.osproductversion", name, &namelen, NULL, 0) == 0)
362 {
363 const gate_size_t name_used = gate_str_length_max(name, sizeof(name));
364 const gate_size_t used = gate_str_print_text(buffer, buffer_len, name, namelen);
365 if (buffer_used) *buffer_used = used;
366 return GATE_RESULT_OK;
367 }
368 else
369 {
370 return GATE_RESULT_FAILED;
371 }
372
373 #elif defined(GATE_SYS_BSD)
374 int mib[] = { CTL_KERN, KERN_OSRELEASE };
375 size_t miblen = sizeof(mib) / sizeof(mib[0]);
376 *buffer_used = buffer_len;
377 if (gate_get_sysctrl_value(mib, miblen, buffer, buffer_used))
378 {
379 ret = GATE_RESULT_OK;
380 }
381
382 #endif
383 1 return ret;
384 }
385
386 1 gate_result_t gate_os_get_version(gate_version_t* ptr_version)
387 {
388 1 int a = 0, b = 0, c = 0;
389 struct utsname uname_info;
390
391 #if defined(GATE_SYS_LINUX)
392 do
393 {
394 linux_os_release_info_t info;
395 1 gate_result_t result = gate_linux_read_os_release_info(&info);
396
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (GATE_SUCCEEDED(result))
397 {
398 1 sscanf(info.os_version_id, "%d.%d.%d", &a, &b, &c);
399
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (ptr_version)
400 {
401 1 ptr_version->major = a;
402 1 ptr_version->minor = b;
403 1 ptr_version->patch = c;
404 1 ptr_version->build = 0;
405 }
406 1 return GATE_RESULT_OK;
407 }
408 } while (0);
409 #endif /* GATE_SYS_LINUX */
410
411 if (0 == uname(&uname_info))
412 {
413 sscanf(uname_info.release, "%d.%d.%d", &a, &b, &c);
414 if (ptr_version)
415 {
416 ptr_version->major = a;
417 ptr_version->minor = b;
418 ptr_version->patch = c;
419 ptr_version->build = 0;
420 }
421 return GATE_RESULT_OK;
422 }
423 return GATE_RESULT_NOTAVAILABLE;
424 }
425
426
427 2 gate_result_t gate_os_get_hostname_str(char* buffer, gate_size_t buffer_len, gate_size_t* buffer_used)
428 {
429 gate_result_t ret;
430 2 char tmp_buffer[GATE_MAX_FILENAME_LENGTH] = GATE_INIT_EMPTY;
431 gate_size_t used;
432
433 2 int error = gethostname(tmp_buffer, sizeof(tmp_buffer));
434
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (error)
435 {
436 gate_posix_errno(&ret);
437 }
438 else
439 {
440 2 used = gate_str_length_max(tmp_buffer, sizeof(tmp_buffer));
441 2 gate_str_print_text(buffer, buffer_len, tmp_buffer, used);
442
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (buffer_used != NULL)
443 {
444 2 *buffer_used = used;
445 }
446 2 ret = GATE_RESULT_OK;
447 }
448 2 return ret;
449 }
450 1 gate_result_t gate_os_set_hostname(gate_string_t const* hostname)
451 {
452 1 gate_result_t result = GATE_RESULT_NOTSUPPORTED;
453 static gate_string_t const hostname_file_path = GATE_STRING_INIT_STATIC("/etc/hostname");
454 int error_state;
455
456
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 if (GATE_SUCCEEDED(gate_file_exists(&hostname_file_path)))
457 {
458 1 result = gate_file_set_content(&hostname_file_path, hostname);
459 }
460
461 #if defined(GATE_SYS_ANDROID)
462 (void)error_state;
463 #else
464 1 error_state = sethostname(hostname->str, hostname->length);
465
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (error_state)
466 {
467 1 gate_posix_errno(&result);
468 }
469 else
470 {
471 result = GATE_RESULT_OK;
472 }
473 #endif
474 1 return result;
475 }
476 2 gate_result_t gate_os_get_hostdomainname_str(char* buffer, gate_size_t buffer_len, gate_size_t* buffer_used)
477 {
478 gate_result_t ret;
479 2 char tmp_buffer[GATE_MAX_FILENAME_LENGTH] = GATE_INIT_EMPTY;
480 gate_size_t used;
481
482 int error;
483 do
484 {
485 #if defined(GATE_SYS_ANDROID)
486 (void)error;
487 ret = GATE_RESULT_NOTSUPPORTED;
488 break;
489 #else
490 2 error = getdomainname(tmp_buffer, sizeof(tmp_buffer));
491
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (error)
492 {
493 gate_posix_errno(&ret);
494 break;
495 }
496 #endif
497
498 2 used = gate_str_length_max(tmp_buffer, sizeof(tmp_buffer));
499 2 gate_str_print_text(buffer, buffer_len, tmp_buffer, used);
500
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (buffer_used != NULL)
501 {
502 2 *buffer_used = used;
503 }
504 2 ret = GATE_RESULT_OK;
505 } while (0);
506 2 return ret;
507 }
508 1 gate_result_t gate_os_set_hostdomainname(gate_string_t const* domainname)
509 {
510 1 gate_result_t result = GATE_RESULT_NOTSUPPORTED;
511 #if !defined(GATE_SYS_ANDROID)
512 1 int error = setdomainname(domainname->str, domainname->length);
513
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (error)
514 {
515 1 gate_posix_errno(&result);
516 }
517 else
518 {
519 result = GATE_RESULT_OK;
520 }
521 #endif
522 1 return result;
523 }
524
525 1 gate_result_t gate_os_get_uid(gate_uint8_t* buffer, gate_size_t buffer_len, gate_size_t* buffer_used)
526 {
527 1 gate_result_t ret = GATE_RESULT_FAILED;
528 static gate_string_t const etc_machine_id = GATE_STRING_INIT_STATIC("/etc/machine-id");
529 char id_buffer[1024];
530 1 gate_size_t id_buffer_size = sizeof(id_buffer);
531 gate_size_t pos_nl;
532 1 long os_hostid = 0;
533
534 do
535 {
536 1 ret = gate_file_get_content_buffer(&etc_machine_id, id_buffer, &id_buffer_size);
537
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (GATE_SUCCEEDED(ret))
538 {
539 pos_nl = gate_str_char_pos(id_buffer, id_buffer_size, '\n', 0);
540 if (pos_nl != GATE_STR_NPOS)
541 {
542 id_buffer_size = pos_nl;
543 }
544 if (id_buffer_size > 0)
545 {
546 if (id_buffer_size > buffer_len)
547 {
548 ret = GATE_RESULT_BUFFERTOOSMALL;
549 if (buffer_used) *buffer_used = id_buffer_size;
550 break;
551 }
552 else
553 {
554 gate_mem_copy(buffer, id_buffer, id_buffer_size);
555 if (buffer_used) *buffer_used = id_buffer_size;
556 ret = GATE_RESULT_OK;
557 break;
558 }
559 }
560 }
561
562 /* fallback: try bad-old hostid() */
563 #if defined(GATE_SYS_ANDROID)
564 (void)os_hostid;
565 #else
566 1 os_hostid = gethostid();
567
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (buffer_len < sizeof(os_hostid))
568 {
569 if (buffer_used) *buffer_used = id_buffer_size;
570 ret = GATE_RESULT_BUFFERTOOSMALL;
571 break;
572 }
573 else
574 {
575 1 gate_mem_copy(buffer, &os_hostid, sizeof(os_hostid));
576
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (buffer_used) *buffer_used = sizeof(os_hostid);
577 1 ret = GATE_RESULT_OK;
578 1 break;
579 }
580 #endif
581
582 } while (0);
583
584 1 return ret;
585 }
586
587 #if !defined(RB_POWER_OFF) && defined(GATE_SYS_BSD)
588 # if defined(GATE_SYS_OPENBSD) || defined(GATE_SYS_NETBSD)
589 # define RB_POWER_OFF (RB_POWERDOWN | RB_HALT)
590 # else
591 # define RB_POWER_OFF RB_POWEROFF
592 # endif
593 #endif
594
595 #if defined(GATE_SYS_NETBSD)
596 # define GATE_POSIX_REBOOT_EXT_ARGS , NULL
597 #else
598 # define GATE_POSIX_REBOOT_EXT_ARGS
599 #endif
600
601 1 gate_result_t gate_os_shutdown()
602 {
603 #define CMD_SHUTDOWN_DIR "/sbin"
604 #define CMD_SHUTDOWN_PATH "/sbin/shutdown"
605
606 gate_result_t ret;
607 1 int exit_code = -1;
608 int error_code;
609
610 1 gate_string_t command_path = GATE_STRING_INIT_STATIC(CMD_SHUTDOWN_PATH);
611 1 gate_string_t workdir = GATE_STRING_INIT_STATIC(CMD_SHUTDOWN_DIR);
612 do
613 {
614 1 ret = gate_process_run(&command_path, NULL, 0, &workdir, NULL, 0,
615 GATE_PROCESS_START_NOTERMINAL | GATE_PROCESS_START_NOINHERIT,
616 NULL, &exit_code);
617
618
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (GATE_SUCCEEDED(ret))
619 {
620 if (exit_code == 0)
621 {
622 /* script was executed -> seems to be successful */
623 break;
624 }
625 }
626
627 /* try to invoke APIs to get extended error codes */
628 1 sync();
629
630 #if !defined(GATE_SYS_DARWIN)
631 1 error_code = reboot(RB_POWER_OFF GATE_POSIX_REBOOT_EXT_ARGS);
632
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (error_code)
633 {
634 1 gate_posix_errno(&ret);
635 }
636 else
637 {
638 ret = GATE_RESULT_OK;
639 }
640 #endif
641
642 } while (0);
643
644 1 return ret;
645 }
646 1 gate_result_t gate_os_reboot()
647 {
648 #define CMD_REBOOT_DIR "/sbin"
649 #define CMD_REBOOT_PATH "/sbin/reboot"
650
651 gate_result_t ret;
652 1 int exit_code = -1;
653 int error_code;
654
655 1 gate_string_t command_path = GATE_STRING_INIT_STATIC(CMD_REBOOT_PATH);
656 1 gate_string_t workdir = GATE_STRING_INIT_STATIC(CMD_REBOOT_DIR);
657 do
658 {
659 1 ret = gate_process_run(&command_path, NULL, 0, &workdir, NULL, 0,
660 GATE_PROCESS_START_NOTERMINAL | GATE_PROCESS_START_NOINHERIT,
661 NULL, &exit_code);
662
663
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (GATE_SUCCEEDED(ret))
664 {
665 if (exit_code == 0)
666 {
667 /* script was executed -> seems to be successful */
668 break;
669 }
670 }
671
672 /* try to invoke APIs to get extended error codes */
673 1 sync();
674 #if !defined(GATE_SYS_DARWIN)
675 1 error_code = reboot(RB_AUTOBOOT GATE_POSIX_REBOOT_EXT_ARGS);
676
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (error_code)
677 {
678 1 gate_posix_errno(&ret);
679 }
680 else
681 {
682 ret = GATE_RESULT_OK;
683 }
684 #endif
685
686 } while (0);
687
688 1 return ret;
689 }
690
691
692
693
694
695 1 gate_result_t gate_os_get_cpu_architecture(gate_enumint_t* ptr_arch)
696 {
697 1 gate_result_t ret = GATE_RESULT_OK;
698 do
699 {
700 #if (GATE_ARCH == GATE_ARCH_X86IA32)
701 * ptr_arch = GATE_OS_ARCH_X86_32;
702 #elif (GATE_ARCH == GATE_ARCH_X86X64)
703 1 * ptr_arch = GATE_OS_ARCH_X86_64;
704 #elif (GATE_ARCH == GATE_ARCH_X86IA16)
705 * ptr_arch = GATE_OS_ARCH_X86_16;
706 #elif (GATE_ARCH == GATE_ARCH_X86IA64)
707 * ptr_arch = GATE_OS_ARCH_ITANIUM;
708 #elif (GATE_ARCH == GATE_ARCH_ARM64)
709 * ptr_arch = GATE_OS_ARCH_ARM_64;
710 #elif (GATE_ARCH == GATE_ARCH_ARM32)
711 * ptr_arch = GATE_OS_ARCH_ARM_32;
712 #elif (GATE_ARCH == GATE_ARCH_ALPHA)
713 * ptr_arch = GATE_OS_ARCH_ALPHA;
714 #else
715 * ptr_arch = GATE_OS_ARCH_UNKNOWN;
716 #endif
717 } while (0);
718
719 1 return ret;
720 }
721
722 static gate_string_t const gate_os_cpu_key_processor = GATE_STRING_INIT_STATIC("processor");
723 static gate_string_t const gate_os_cpu_key_vendor_id = GATE_STRING_INIT_STATIC("vendor_id");
724 static gate_string_t const gate_os_cpu_key_model_name = GATE_STRING_INIT_STATIC("model name");
725 static gate_string_t const gate_os_cpu_key_cpu_family = GATE_STRING_INIT_STATIC("cpu family");
726 static gate_string_t const gate_os_cpu_key_features = GATE_STRING_INIT_STATIC("features");
727 static gate_string_t const gate_os_cpu_key_model = GATE_STRING_INIT_STATIC("model");
728 static gate_string_t const gate_os_cpu_key_stepping = GATE_STRING_INIT_STATIC("stepping");
729 static gate_string_t const gate_os_cpu_key_flags = GATE_STRING_INIT_STATIC("flags");
730 static gate_string_t const gate_os_cpu_key_cpu_mhz = GATE_STRING_INIT_STATIC("cpu MHz");
731 static gate_string_t const gate_os_cpu_key_cache_size = GATE_STRING_INIT_STATIC("cache size");
732
733 #if defined(GATE_SYS_DARWIN)
734
735 #include <sys/sysctl.h>
736 #include "gate/platforms.h"
737 #include <dlfcn.h>
738
739 //#define GATE_MACOS_HAVE_OS_HEADERS
740
741 #if defined(GATE_MACOS_HAVE_OS_HEADERS)
742 # include <IOKit/IOKitLib.h>
743 # include <CoreFoundation/CoreFoundation.h>
744 #else
745
746 typedef unsigned char UInt8;
747 typedef unsigned int UInt32;
748 typedef signed long CFIndex;
749 typedef int kern_return_t;
750 typedef unsigned long CFTypeID;
751 typedef UInt32 IOOptionBits;
752 typedef UInt32 CFStringEncoding;
753 typedef unsigned int mach_port_t;
754 typedef char io_string_t[512];
755 typedef mach_port_t io_object_t;
756 typedef io_object_t io_registry_entry_t;
757 typedef const void * CFTypeRef;
758 typedef const struct __CFString * CFStringRef;
759 typedef const struct __CFAllocator * CFAllocatorRef;
760 typedef const struct __CFData * CFDataRef;
761 typedef struct
762 {
763 CFIndex location;
764 CFIndex length;
765 } CFRange;
766 #define MACH_PORT_NULL 0
767 enum CFStringEncoding
768 {
769 kCFStringEncodingMacRoman = 0,
770 kCFStringEncodingWindowsLatin1 = 0x0500,
771 kCFStringEncodingISOLatin1 = 0x0201,
772 kCFStringEncodingNextStepLatin = 0x0B01,
773 kCFStringEncodingASCII = 0x0600,
774 kCFStringEncodingUnicode = 0x0100,
775 kCFStringEncodingUTF8 = 0x08000100,
776 kCFStringEncodingNonLossyASCII = 0x0BFF,
777
778 kCFStringEncodingUTF16 = 0x0100,
779 kCFStringEncodingUTF16BE = 0x10000100,
780 kCFStringEncodingUTF16LE = 0x14000100,
781
782 kCFStringEncodingUTF32 = 0x0c000100,
783 kCFStringEncodingUTF32BE = 0x18000100,
784 kCFStringEncodingUTF32LE = 0x1c000100
785 };
786
787 #endif /* !defined(GATE_MACOS_HAVE_OS_HEADERS) */
788
789 static gate_size_t darwin_get_cpu_name(char* buffer, gate_size_t buffer_capacity)
790 {
791 char name[256] = GATE_INIT_EMPTY;
792 size_t size = sizeof(name);
793
794 if (sysctlbyname("machdep.cpu.brand_string", &name, &size, NULL, 0) == 0)
795 {
796 return gate_str_print_text(buffer, buffer_capacity, name, gate_str_length(name));
797 }
798 else
799 {
800 buffer[0] = 0;
801 return 0;
802 }
803 }
804
805 static gate_uint32_t darwin_get_cpu_cores()
806 {
807 int logical = 0;
808 size_t size = sizeof(int);
809 sysctlbyname("hw.logicalcpu", &logical, &size, NULL, 0);
810 return logical;
811 }
812
813 typedef struct darwin_cpu_functions
814 {
815 io_registry_entry_t (*callIORegistryEntryFromPath)(mach_port_t, const io_string_t);
816 CFTypeRef (*callIORegistryEntryCreateCFProperty)(io_registry_entry_t, CFStringRef, CFAllocatorRef, IOOptionBits);
817 kern_return_t (*callIOObjectRelease)(io_object_t);
818 mach_port_t* symkIOMainPortDefault;
819
820 CFTypeID (*callCFGetTypeID)(CFTypeRef);
821 CFTypeID (*callCFDataGetTypeID)(void);
822 void (*callCFDataGetBytes)(CFDataRef, CFRange, UInt8 *);
823 void (*callCFRelease)(CFTypeRef);
824 CFStringRef (*callCFStringCreateWithCString)(CFAllocatorRef alloc, const char *cStr, CFStringEncoding encoding);
825 CFAllocatorRef* symkCFAllocatorDefault;
826
827 } darwin_cpu_functions_t;
828
829 static gate_bool_t load_sym(void* lib, char const* func_name, void* ptr_funcptr)
830 {
831 void* ptrfunc = gate_posix_dlsym(lib, func_name);
832 if (NULL == ptrfunc)
833 {
834 return false;
835 }
836 else
837 {
838 *((void**)ptr_funcptr) = ptrfunc;
839 return true;
840 }
841 }
842 #define LOAD_SYM(lib, func_name, ptr_funcptr) \
843 if(!load_sym(lib,func_name, ptr_funcptr)) \
844 break;
845
846 static darwin_cpu_functions_t* load_darwin_cpu_functions()
847 {
848 static void* lib_iokit = NULL;
849 static void* lib_corefoundation = NULL;
850 static darwin_cpu_functions_t funcs;
851 static gate_bool_t is_initialized = false;
852
853 if (!is_initialized)
854 {
855 if (lib_iokit == NULL)
856 {
857 lib_iokit = gate_posix_dlopen("/System/Library/Frameworks/IOKit.framework/IOKit", RTLD_LAZY | RTLD_LOCAL);
858 if (lib_iokit == NULL) return NULL;
859 }
860 if (lib_corefoundation == NULL)
861 {
862 lib_corefoundation = gate_posix_dlopen("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation", RTLD_LAZY | RTLD_LOCAL);
863 if (lib_corefoundation == NULL) return NULL;
864 }
865 do
866 {
867 LOAD_SYM(lib_iokit, "IORegistryEntryFromPath", &funcs.callIORegistryEntryFromPath);
868 LOAD_SYM(lib_iokit, "IORegistryEntryCreateCFProperty", &funcs.callIORegistryEntryCreateCFProperty);
869 LOAD_SYM(lib_iokit, "IORegistryEntryFromPath", &funcs.callIOObjectRelease);
870 LOAD_SYM(lib_iokit, "kIOMainPortDefault", &funcs.symkIOMainPortDefault);
871
872 LOAD_SYM(lib_corefoundation, "CFGetTypeID", &funcs.callCFGetTypeID);
873 LOAD_SYM(lib_corefoundation, "CFDataGetTypeID", &funcs.callCFDataGetTypeID);
874 LOAD_SYM(lib_corefoundation, "CFDataGetBytes", &funcs.callCFDataGetBytes);
875 LOAD_SYM(lib_corefoundation, "CFRelease", &funcs.callCFRelease);
876 LOAD_SYM(lib_corefoundation, "CFStringCreateWithCString", &funcs.callCFStringCreateWithCString);
877 LOAD_SYM(lib_corefoundation, "kCFAllocatorDefault", &funcs.symkCFAllocatorDefault);
878
879 /* all functions loaded -> success */
880 is_initialized = true;
881 return &funcs;
882 } while (0);
883 /* a break has occured -> error, cancel */
884 return NULL;
885 }
886 return &funcs;
887 }
888
889 static gate_uint64_t darwing_get_cpu_speed_hz()
890 {
891 darwin_cpu_functions_t* funcs = load_darwin_cpu_functions();
892 static CFStringRef cfstr_clock_frequency = NULL;
893 gate_uint64_t ret = 0;
894 io_registry_entry_t cpu = MACH_PORT_NULL;
895 CFTypeRef freq = NULL;
896 do
897 {
898 if (!funcs) break;
899
900 cpu = funcs->callIORegistryEntryFromPath(*funcs->symkIOMainPortDefault, "IODeviceTree:/cpus/cpu0");
901 if (cpu == MACH_PORT_NULL) break;
902
903 if (cfstr_clock_frequency == NULL)
904 {
905 cfstr_clock_frequency = funcs->callCFStringCreateWithCString(*funcs->symkCFAllocatorDefault, "clock-frequency", kCFStringEncodingUTF8);
906 if (cfstr_clock_frequency == NULL)
907 {
908 break;
909 }
910 }
911
912 freq = funcs->callIORegistryEntryCreateCFProperty(cpu, cfstr_clock_frequency, *funcs->symkCFAllocatorDefault, 0);
913 if (freq && funcs->callCFGetTypeID(freq) == funcs->callCFDataGetTypeID())
914 {
915 uint32_t hz;
916 CFRange range;
917 range.location = 0;
918 range.length = sizeof(hz);
919 funcs->callCFDataGetBytes(freq, range, (UInt8*)&hz);
920 ret = hz;
921 }
922 } while (0);
923
924 if (MACH_PORT_NULL != cpu) funcs->callIOObjectRelease(cpu);
925 if (freq) funcs->callCFRelease(freq);
926 return ret;
927 }
928
929 static gate_result_t gate_os_get_cpu_info_darwin(gate_os_cpuinfo_t* info)
930 {
931 gate_result_t ret = GATE_RESULT_FAILED;
932
933 do
934 {
935 gate_mem_clear(info, sizeof(gate_os_cpuinfo_t));
936
937 darwin_get_cpu_name(info->cpu_name, sizeof(info->cpu_name));
938 info->cpu_cores = darwin_get_cpu_cores();
939 info->cpu_speed_mhz = (gate_uint32_t)(darwing_get_cpu_speed_hz() / 1000000);
940
941 ret = GATE_RESULT_OK;
942 } while (0);
943
944 return ret;
945 }
946
947 #endif /* GATE_SYS_DARWIN */
948
949 2 static gate_result_t gate_os_get_cpu_info_procfs(gate_os_cpuinfo_t* info, gate_string_t* ptr_features)
950 {
951 gate_result_t ret;
952 static gate_string_t const procfs_cpuinfo = GATE_STRING_INIT_STATIC("/proc/cpuinfo");
953 char buffer[4092 * 3];
954 2 gate_size_t buffer_len = sizeof(buffer);
955 gate_string_t data;
956 gate_string_t line;
957 gate_string_t tail;
958 gate_string_t key;
959 gate_string_t value;
960 gate_size_t pos;
961 gate_uint64_t ui64;
962 2 gate_uint32_t family = 0;
963 2 gate_uint32_t model = 0;
964 2 gate_uint32_t stepping = 0;
965
966 do
967 {
968 2 gate_bool_t features_processed = false;
969 2 gate_mem_clear(info, sizeof(gate_os_cpuinfo_t));
970 2 ret = gate_file_get_content_buffer(&procfs_cpuinfo, buffer, &buffer_len);
971
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 GATE_BREAK_IF_FAILED(ret);
972
973 2 gate_string_create_static_len(&data, buffer, buffer_len);
974
975
2/2
✓ Branch 1 taken 108 times.
✓ Branch 2 taken 2 times.
110 while (NULL != gate_string_read_line(&line, &data, &tail))
976 {
977 108 data = tail;
978
979 108 pos = gate_string_char_pos(&line, ':', 0);
980
2/2
✓ Branch 0 taken 104 times.
✓ Branch 1 taken 4 times.
108 if (pos != GATE_STR_NPOS)
981 {
982 104 gate_string_create_static_len(&key, line.str, pos);
983 104 gate_string_create_static_len(&value, line.str + pos + 1, line.length - pos - 1);
984 104 gate_string_trim(&key, &key);
985 104 gate_string_trim(&value, &value);
986
987
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 100 times.
104 if (0 == gate_string_comp_ic(&key, &gate_os_cpu_key_processor))
988 {
989 4 ++info->cpu_cores;
990 }
991
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 104 times.
104 if (0 == gate_string_comp_ic(&key, &gate_os_cpu_key_features))
992 {
993 if (!features_processed)
994 {
995 features_processed = true;
996 if (ptr_features != NULL)
997 {
998 gate_string_create(ptr_features, value.str, value.length);
999 }
1000 }
1001 }
1002
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 100 times.
104 if (0 == gate_string_comp_ic(&key, &gate_os_cpu_key_vendor_id))
1003 {
1004 4 gate_str_print_text(info->cpu_vendor, sizeof(info->cpu_vendor), value.str, value.length);
1005 }
1006
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 100 times.
104 if (0 == gate_string_comp_ic(&key, &gate_os_cpu_key_model_name))
1007 {
1008 4 gate_str_print_text(info->cpu_name, sizeof(info->cpu_name), value.str, value.length);
1009 4 gate_str_print_text(info->cpu_description, sizeof(info->cpu_description), value.str, value.length);
1010 }
1011
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 100 times.
104 if (0 == gate_string_comp_ic(&key, &gate_os_cpu_key_model_name))
1012 {
1013 4 gate_str_print_text(info->cpu_description, sizeof(info->cpu_description), value.str, value.length);
1014 }
1015
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 100 times.
104 if (0 == gate_string_comp_ic(&key, &gate_os_cpu_key_cpu_family))
1016 {
1017
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 if (0 != gate_str_parse_uint64(value.str, value.length, &ui64))
1018 {
1019 4 family = (gate_uint32_t)ui64;
1020 }
1021 }
1022
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 100 times.
104 if (0 == gate_string_comp_ic(&key, &gate_os_cpu_key_model))
1023 {
1024
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 if (0 != gate_str_parse_uint64(value.str, value.length, &ui64))
1025 {
1026 4 model = (gate_uint32_t)ui64;
1027 }
1028 }
1029
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 100 times.
104 if (0 == gate_string_comp_ic(&key, &gate_os_cpu_key_stepping))
1030 {
1031
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 if (0 != gate_str_parse_uint64(value.str, value.length, &ui64))
1032 {
1033 4 stepping = (gate_uint32_t)ui64;
1034 }
1035 }
1036
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 100 times.
104 if(0 == gate_string_comp_ic(&key, &gate_os_cpu_key_flags))
1037 {
1038
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if (!features_processed)
1039 {
1040 2 features_processed = true;
1041
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (ptr_features != NULL)
1042 {
1043 1 gate_string_create(ptr_features, value.str, value.length);
1044 }
1045 }
1046 }
1047
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 100 times.
104 if (0 == gate_string_comp_ic(&key, &gate_os_cpu_key_cpu_mhz))
1048 {
1049
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 if (0 != gate_str_parse_uint64(value.str, value.length, &ui64))
1050 {
1051 4 info->cpu_speed_mhz = (gate_uint32_t)ui64;
1052 }
1053 }
1054
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 100 times.
104 if (0 == gate_string_comp_ic(&key, &gate_os_cpu_key_cache_size))
1055 {
1056
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 if (0 != gate_str_parse_uint64(value.str, value.length, &ui64))
1057 {
1058 4 info->cpu_cache_bytes = (gate_uint32_t)(ui64 * 1024);
1059 }
1060 }
1061 }
1062 } // while(...readline...)
1063 2 info->cpu_version = ((family & 0xff) << 24) | ((model & 0xff) << 16) | (stepping & 0xffff);
1064
1065 } while (0);
1066
1067 2 return ret;
1068 }
1069
1070 1 gate_result_t gate_os_get_cpu_info(gate_os_cpuinfo_t* info)
1071 {
1072 #if defined(GATE_SYS_DARWIN)
1073 return gate_os_get_cpu_info_darwin(info);
1074 #else
1075 1 return gate_os_get_cpu_info_procfs(info, NULL);
1076 #endif
1077 }
1078
1079 1 gate_result_t gate_os_enum_cpu_features(gate_os_cpu_feature_callback_t callback, void* param)
1080 {
1081 1 gate_result_t ret = GATE_RESULT_OK;
1082 gate_os_cpuinfo_t dummy;
1083 1 gate_string_t features = GATE_INIT_EMPTY;
1084 static gate_string_t const separator = GATE_STRING_INIT_STATIC(" ");
1085 1 gate_os_get_cpu_info_procfs(&dummy, &features);
1086
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 if (!gate_string_is_empty(&features))
1087 {
1088 1 gate_string_t text = GATE_INIT_EMPTY;
1089 1 gate_string_t head = GATE_INIT_EMPTY;
1090 1 gate_string_t tail = GATE_INIT_EMPTY;
1091 gate_size_t parsed;
1092 1 gate_bool_t continue_parsing = true;
1093 1 gate_string_duplicate(&text, &features);
1094
1/2
✓ Branch 0 taken 99 times.
✗ Branch 1 not taken.
99 while(continue_parsing)
1095 {
1096 99 parsed = gate_string_parse(&text, &separator, 0, &head, &tail, false);
1097
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 98 times.
99 if (parsed == 0)
1098 {
1099 1 break;
1100 }
1101 else
1102 {
1103 98 char buffer[32] = GATE_INIT_EMPTY;
1104 98 gate_str_print_text(buffer, sizeof(buffer), gate_string_ptr(&head, 0), gate_string_length(&head));
1105
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 98 times.
98 if(!callback(buffer, param))
1106 {
1107 continue_parsing = false;
1108 }
1109 98 gate_string_release(&text);
1110 98 gate_string_release(&head);
1111 98 gate_mem_copy(&text, &tail, sizeof(text)); /* move tail into text*/
1112 98 gate_mem_clear(&tail, sizeof(tail));
1113 98 gate_string_ltrim(&text, &text);
1114 }
1115 }
1116
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 if (continue_parsing && !gate_string_is_empty(&text))
1117 {
1118 1 char buffer[32] = GATE_INIT_EMPTY;
1119 1 gate_str_print_text(buffer, sizeof(buffer), gate_string_ptr(&text, 0), gate_string_length(&text));
1120 1 callback(buffer, param);
1121 }
1122 1 gate_string_release(&text);
1123 1 gate_string_release(&head);
1124 1 gate_string_release(&tail);
1125 }
1126 1 gate_string_release(&features);
1127 1 return ret;
1128 }
1129
1130 gate_result_t gate_os_get_process_cpu_affinity(gate_os_cpu_activation_t* affinity)
1131 {
1132 gate_result_t ret = GATE_RESULT_FAILED;
1133 do
1134 {
1135 gate_mem_clear(affinity, sizeof(gate_os_cpu_activation_t));
1136 } while (0);
1137 return ret;
1138 }
1139 gate_result_t gate_os_set_process_cpu_affinity(gate_os_cpu_activation_t const* affinity)
1140 {
1141 gate_result_t ret = GATE_RESULT_FAILED;
1142 do
1143 {
1144 /* TODO */
1145 } while (0);
1146 return ret;
1147 }
1148
1149
1150 #if defined(GATE_SYS_DARWIN)
1151
1152 #include <mach/mach.h>
1153
1154 static gate_result_t gate_os_cpu_load_darwin(gate_int64_t* ptr_total, gate_int64_t* ptr_work)
1155 {
1156 natural_t cpu_count = 0;
1157 processor_info_array_t cpu_info = NULL;
1158 mach_msg_type_number_t num_cpu_info;
1159
1160 kern_return_t kr = host_processor_info(
1161 mach_host_self(),
1162 PROCESSOR_CPU_LOAD_INFO,
1163 &cpu_count,
1164 &cpu_info,
1165 &num_cpu_info
1166 );
1167
1168 if (kr != KERN_SUCCESS)
1169 {
1170 return GATE_RESULT_FAILED;
1171 }
1172 else
1173 {
1174 natural_t ndx;
1175 gate_int64_t total_capacity = 0;
1176 gate_int64_t work_load = 0;
1177 for (ndx = 0; ndx < cpu_count; ++ndx)
1178 {
1179 const unsigned long user = cpu_info[(CPU_STATE_MAX * ndx) + CPU_STATE_USER];
1180 const unsigned long system = cpu_info[(CPU_STATE_MAX * ndx) + CPU_STATE_SYSTEM];
1181 const unsigned long idle = cpu_info[(CPU_STATE_MAX * ndx) + CPU_STATE_IDLE];
1182 const unsigned long nice = cpu_info[(CPU_STATE_MAX * ndx) + CPU_STATE_NICE];
1183
1184 total_capacity += (user + system + idle + nice);
1185 work_load += (user + system + nice);
1186 }
1187 vm_deallocate(mach_task_self(), (vm_address_t)cpu_info, num_cpu_info);
1188 *ptr_total = total_capacity;
1189 *ptr_work = work_load;
1190 return GATE_RESULT_OK;
1191 }
1192 }
1193
1194 #endif /* GATE_SYS_DARWIN */
1195
1196 2 static gate_result_t gate_os_cpu_load_procfs(gate_int64_t* ptr_total, gate_int64_t* ptr_work)
1197 {
1198 gate_result_t ret;
1199 static gate_string_t const procfs_stat = GATE_STRING_INIT_STATIC("/proc/stat");
1200 char stat_buffer[4096];
1201 2 gate_size_t stat_buffer_len = sizeof(stat_buffer);
1202 gate_string_t data;
1203 gate_string_t strvalues;
1204 gate_string_t line;
1205 gate_string_t tail;
1206 gate_string_t value;
1207 gate_size_t cnt;
1208 gate_int64_t values[7];
1209
1210 do
1211 {
1212 2 ret = gate_file_get_content_buffer(&procfs_stat, stat_buffer, &stat_buffer_len);
1213
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 GATE_BREAK_IF_FAILED(ret);
1214
1215 2 gate_string_create_static_len(&data, stat_buffer, stat_buffer_len);
1216 2 ret = GATE_RESULT_FAILED;
1217
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 while (NULL != gate_string_read_line(&line, &data, &tail))
1218 {
1219 2 data = tail;
1220
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 if (gate_str_starts_with_ic(line.str, line.length, "cpu ", 4))
1221 {
1222 2 gate_string_substr(&strvalues, &line, 4, line.length - 4);
1223
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 2 times.
16 for (cnt = 0; cnt != 7; ++cnt)
1224 {
1225
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 14 times.
14 if (NULL == gate_string_read_token(&value, &strvalues, &tail))
1226 {
1227 break;
1228 }
1229 14 values[cnt] = 0;
1230 14 gate_str_parse_int64(value.str, value.length, &values[cnt]);
1231 14 strvalues = tail;
1232 }
1233
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (cnt == 7)
1234 {
1235 2 *ptr_total = values[0] + values[1] + values[2] + values[3] + values[4] + values[5] + values[6];
1236 2 *ptr_work = values[0] + values[1] + values[2];
1237 2 ret = GATE_RESULT_OK;
1238 }
1239 2 break;
1240 }
1241 }
1242 } while (0);
1243 2 return ret;
1244 }
1245
1246 2 static gate_result_t gate_os_cpu_load(gate_int64_t* ptr_total, gate_int64_t* ptr_work)
1247 {
1248 #if defined(GATE_SYS_DARWIN)
1249 return gate_os_cpu_load_darwin(ptr_total, ptr_work);
1250 #else
1251 2 return gate_os_cpu_load_procfs(ptr_total, ptr_work);
1252 #endif
1253 }
1254
1255 1 gate_result_t gate_os_cpu_load_init(gate_os_cpu_load_state_t* state)
1256 {
1257 1 gate_int64_t* ptr_total = (gate_int64_t*)&state->records[0];
1258 1 gate_int64_t* ptr_work = (gate_int64_t*)&state->records[4];
1259
1260 1 return gate_os_cpu_load(ptr_total, ptr_work);
1261 }
1262 1 gate_result_t gate_os_cpu_load_update(gate_os_cpu_load_state_t* state, gate_uint16_t* load65535)
1263 {
1264 gate_result_t ret;
1265 1 gate_int64_t* ptr_total = (gate_int64_t*)&state->records[0];
1266 1 gate_int64_t* ptr_work = (gate_int64_t*)&state->records[4];
1267 gate_int64_t new_total;
1268 gate_int64_t new_work;
1269 gate_int64_t diff_total;
1270 gate_int64_t diff_work;
1271 gate_int64_t result;
1272 1 ret = gate_os_cpu_load(&new_total, &new_work);
1273
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (GATE_SUCCEEDED(ret))
1274 {
1275 1 diff_total = new_total - *ptr_total;
1276 1 diff_work = new_work - *ptr_work;
1277 1 *ptr_total = new_total;
1278 1 *ptr_work = new_work;
1279
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (diff_total > 0)
1280 {
1281 result = (diff_work * (gate_int64_t)65535 / diff_total);
1282 *load65535 = (gate_uint16_t)(result > 65535 ? 65535 : result);
1283 }
1284 else
1285 {
1286 1 *load65535 = 65535;
1287 }
1288 }
1289 1 return ret;
1290 }
1291 1 gate_result_t gate_os_cpu_load_uninit(gate_os_cpu_load_state_t* state)
1292 {
1293 1 return GATE_RESULT_OK;
1294 }
1295
1296 static gate_string_t const filepath_proc_meminfo = GATE_STRING_INIT_STATIC("/proc/meminfo");
1297
1298 2 static gate_size_t gate_os_parse_meminfo_line(char const* data, gate_size_t data_len,
1299 char const* key, gate_size_t key_len, char* value, gate_size_t value_len)
1300 {
1301 2 gate_size_t pos = gate_str_pos(data, data_len, key, key_len, 0);
1302 gate_string_t line;
1303 gate_string_t source;
1304 gate_string_t tail;
1305
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (pos != GATE_STR_NPOS)
1306 {
1307 2 gate_string_create_static_len(&source, data + pos + key_len, data_len - pos - key_len);
1308
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 if (NULL != gate_string_read_line(&line, &source, &tail))
1309 {
1310 2 gate_string_trim(&line, &line);
1311 2 return gate_string_to_buffer(&line, value, value_len);
1312 }
1313 }
1314 return 0;
1315 }
1316 2 static gate_bool_t gate_os_parse_meminfo_num(char const* data, gate_size_t data_len, char const* key, gate_size_t key_len, gate_uint64_t* num)
1317 {
1318 char value[1024];
1319 2 gate_size_t value_used = gate_os_parse_meminfo_line(data, data_len, key, key_len, value, sizeof(value));
1320
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (value_used)
1321 {
1322 2 *num = 0;
1323
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 if (gate_str_parse_uint64(value, value_used, num) > 0)
1324 {
1325 2 return true;
1326 }
1327 }
1328 return false;
1329 }
1330
1331 #if defined(GATE_SYS_DARWIN)
1332 static gate_result_t gate_os_get_physical_memory_darwin(gate_uint64_t* ptr_total, gate_uint64_t* ptr_available)
1333 {
1334 uint64_t usable = 0;
1335 uint64_t memsize = 0;
1336 size_t len = sizeof(memsize);
1337
1338 if (sysctlbyname("hw.memsize", &memsize, &len, NULL, 0) != 0)
1339 {
1340 return GATE_RESULT_NOTAVAILABLE;
1341 }
1342 else
1343 {
1344 mach_msg_type_number_t count = HOST_VM_INFO64_COUNT;
1345 vm_statistics64_data_t vm;
1346 kern_return_t kr = host_statistics64(
1347 mach_host_self(),
1348 HOST_VM_INFO64,
1349 (host_info64_t)&vm,
1350 &count
1351 );
1352
1353 if (kr == KERN_SUCCESS) {
1354 const uint64_t pageSize = vm_page_size;
1355 const uint64_t freeBytes = vm.free_count * pageSize;
1356 const uint64_t inactiveBytes = vm.inactive_count * pageSize;
1357 const uint64_t speculative = vm.speculative_count * pageSize;
1358 usable = freeBytes + inactiveBytes + speculative;
1359 }
1360 }
1361
1362 if (ptr_total) *ptr_total = memsize;
1363 if (ptr_available) *ptr_available = usable;
1364 return GATE_RESULT_OK;
1365 }
1366
1367 #endif /* defined(GATE_SYS_DARWIN) */
1368
1369
1370 1 static gate_result_t gate_os_get_physical_memory_generic(gate_uint64_t* ptr_total, gate_uint64_t* ptr_available)
1371 {
1372 1 gate_result_t ret = GATE_RESULT_OK;
1373 char buffer[8192];
1374 1 gate_size_t buffer_len = sizeof(buffer);
1375 1 gate_uint64_t total = 0;
1376 1 gate_uint64_t available = 0;
1377 1 gate_uint64_t pgsize
1378 #if defined(_SC_PAGESIZE)
1379 1 = (gate_uint64_t)sysconf(_SC_PAGESIZE);
1380 #elif defined(_SC_PAGE_SIZE)
1381 = (gate_uint64_t)sysconf(_SC_PAGE_SIZE);
1382 #else
1383 = 4096;
1384 #endif
1385
1386 #if defined(_SC_PHYS_PAGES)
1387 1 long phys = sysconf(_SC_PHYS_PAGES);
1388 1 total = (gate_uint64_t)(phys) * (gate_uint64_t)(pgsize);
1389 #elif defined(_SC_AIX_REALMEM)
1390 total = (gate_uint64_t)(sysconf(_SC_AIX_REALMEM)) * 1024;
1391 #endif
1392
1393 #if defined(_SC_AVPHYS_PAGES)
1394 1 available = (gate_uint64_t)(sysconf(_SC_AVPHYS_PAGES)) * pgsize;
1395 #endif
1396
1397
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 if ((total == 0) || (available == 0))
1398 {
1399 ret = gate_file_get_content_buffer(&filepath_proc_meminfo, buffer, &buffer_len);
1400 if (GATE_SUCCEEDED(ret))
1401 {
1402 if (total)
1403 {
1404 gate_os_parse_meminfo_num(buffer, buffer_len, "MemTotal:", 9, &total);
1405 total *= 1024;
1406 }
1407 if (available)
1408 {
1409 gate_os_parse_meminfo_num(buffer, buffer_len, "MemFree:", 8, &available);
1410 available *= 1024;
1411 }
1412 }
1413 }
1414
1415
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (ptr_total)
1416 {
1417 1 *ptr_total = total;
1418 }
1419
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (ptr_available)
1420 {
1421 1 *ptr_available = available;
1422 }
1423 1 return ret;
1424 }
1425
1426 1 gate_result_t gate_os_get_physical_memory(gate_uint64_t* ptr_total, gate_uint64_t* ptr_available)
1427 {
1428 #if defined(GATE_SYS_DARWIN)
1429 return gate_os_get_physical_memory_darwin(ptr_total, ptr_available);
1430 #else
1431 1 return gate_os_get_physical_memory_generic(ptr_total, ptr_available);
1432 #endif
1433 }
1434
1435
1436 1 gate_result_t gate_os_get_virtual_memory(gate_uint64_t* ptr_total, gate_uint64_t* ptr_available)
1437 {
1438 1 gate_result_t ret = GATE_RESULT_NOTSUPPORTED;
1439 char buffer[8192];
1440 1 gate_uint64_t vmtotal = 0;
1441 1 gate_uint64_t vmused = 0;
1442 1 gate_size_t buffer_len = sizeof(buffer);
1443 1 ret = gate_file_get_content_buffer(&filepath_proc_meminfo, buffer, &buffer_len);
1444
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (GATE_SUCCEEDED(ret))
1445 {
1446 1 gate_os_parse_meminfo_num(buffer, buffer_len, "VmallocTotal:", 13, &vmtotal);
1447 1 gate_os_parse_meminfo_num(buffer, buffer_len, "VmallocUsed:", 12, &vmused);
1448
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (ptr_total)
1449 {
1450 1 *ptr_total = vmtotal * 1024;
1451 }
1452
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (ptr_available)
1453 {
1454 1 *ptr_available = (vmtotal - vmused) * 1024;
1455 }
1456 }
1457 1 return ret;
1458 }
1459
1460 #endif
1461