GCC Code Coverage Report


Directory: src/gate/
File: src/gate/system/os_posix.c
Date: 2026-02-03 22:06:38
Exec Total Coverage
Lines: 252 363 69.4%
Functions: 21 29 72.4%
Branches: 93 200 46.5%

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 static bool gate_get_sysctrl_value(int mib[], size_t miblen, char* buffer, gate_size_t* buffer_used)
111 {
112 #if defined(GATE_SYS_BSD)
113 # if !defined(GATE_SYS_ANDROID)
114 size_t buffer_len = *buffer_used - 1;
115 if (sysctl(mib, (int)miblen, buffer, &buffer_len, 0, 0) == 0)
116 {
117 if (buffer_used)
118 {
119 *buffer_used = buffer_len;
120 }
121 buffer[buffer_len] = 0;
122 return true;
123 }
124 # endif
125 #endif
126 return false;
127 }
128
129
130 3 static gate_result_t gate_linux_read_os_release_info(linux_os_release_info_t* info)
131 {
132 3 gate_result_t ret = GATE_RESULT_FAILED;
133 3 gate_mem_clear(info, sizeof(linux_os_release_info_t));
134 3 gate_size_t count = sizeof(linux_os_release_files) / sizeof(linux_os_release_files[0]);
135 gate_size_t index;
136 gate_string_t filename;
137 3 gate_controlstream_t* filestream = NULL;
138 char buffer[GATE_MAX_COPYBUFFER_LENGTH];
139 gate_size_t linelen;
140
141
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 for (index = 0; index != count; ++index)
142 {
143 3 gate_string_create_static(&filename, linux_os_release_files[index]);
144 3 ret = gate_file_openstream(&filename, GATE_STREAM_OPEN_READ, &filestream);
145 3 gate_string_release(&filename);
146
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (GATE_SUCCEEDED(ret))
147 {
148
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)))
149 {
150
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 27 times.
30 if (linelen == 0)
151 {
152 3 break;
153 }
154
155
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;
156
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;
157
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;
158
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;
159
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;
160
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;
161
162 }
163
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 GATE_BREAK_IF_FAILED(ret);
164 3 break;
165 }
166 }
167
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (filestream != NULL)
168 {
169 3 gate_object_release(filestream);
170 }
171
172 3 return ret;
173 }
174
175 2 gate_result_t gate_os_get_platform(gate_uint32_t* ptr_platform)
176 {
177 2 gate_result_t ret = GATE_RESULT_OK;
178 #if defined(GATE_SYS_ANDROID)
179 *ptr_platform = GATE_OS_PLATFORM_LINUX_ANDROID;
180 #elif defined(GATE_SYS_FREEBSD)
181 *ptr_platform = GATE_OS_PLATFORM_BSD_FREEBSD;
182 #elif defined(GATE_SYS_NETBSD)
183 *ptr_platform = GATE_OS_PLATFORM_BSD_NETBSD;
184 #elif defined(GATE_SYS_OPENBSD)
185 *ptr_platform = GATE_OS_PLATFORM_BSD_OPENBSD;
186 #elif defined(GATE_SYS_BSD)
187 *ptr_platform = GATE_OS_PLATFORM_BSD;
188 #elif defined(GATE_SYS_DARWIN)
189 *ptr_platform = GATE_OS_PLATFORM_DARWIN;
190 #elif defined(GATE_SYS_LINUX)
191 2 *ptr_platform = GATE_OS_PLATFORM_LINUX;
192 #else
193 ret = GATE_RESULT_FAILED;
194 #endif
195
196 2 return ret;
197 }
198
199 1 gate_uint32_t gate_os_address_space()
200 {
201 1 return sizeof(void*) * 8;
202 }
203 2 gate_uint32_t gate_os_up_time_seconds()
204 {
205 2 gate_uint32_t ret = 0;
206 gate_result_t result;
207 char buffer[1024];
208 2 gate_size_t buffer_used = sizeof(buffer);
209 2 float flt_uptime = 0.0f;
210 static gate_string_t const proc_path_uptime = { "/proc/uptime", 12, NULL };
211 #if defined(GATE_SYS_LINUX)
212 struct sysinfo info;
213 #endif
214
215 do
216 {
217 2 result = gate_file_get_content_buffer(&proc_path_uptime, buffer, &buffer_used);
218
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (GATE_SUCCEEDED(result))
219 {
220 2 buffer[buffer_used] = 0;
221
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (sscanf(buffer, "%f", &flt_uptime) == 1)
222 {
223 2 ret = (gate_uint32_t)flt_uptime;
224 2 break;
225 }
226 }
227 #if defined(GATE_SYS_LINUX)
228
229 gate_mem_clear(&info, sizeof(info));
230 if (sysinfo(&info) == 0)
231 {
232 ret = (gate_uint32_t)info.uptime;
233 }
234 #endif
235 } while (0);
236
237 2 return ret;
238 }
239 1 gate_result_t gate_os_print_osname(char* buffer, gate_size_t buffer_len, gate_size_t* buffer_used)
240 {
241 1 gate_result_t ret = GATE_RESULT_FAILED;
242
243 #if defined(GATE_SYS_LINUX)
244 1 char const* ptr_data = NULL;
245 struct utsname utsname_buffer;
246 linux_os_release_info_t info;
247 gate_size_t len;
248
249 1 ret = gate_linux_read_os_release_info(&info);
250
251
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (GATE_SUCCEEDED(ret))
252 {
253
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 if (!gate_str_is_empty(info.os_name))
254 {
255 1 ptr_data = info.os_name;
256 }
257 else if (!gate_str_is_empty(info.os_id))
258 {
259 ptr_data = info.os_id;
260 }
261 else if (!gate_str_is_empty(info.os_id_like))
262 {
263 ptr_data = info.os_id_like;
264 }
265 }
266
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (ptr_data == NULL)
267 {
268 if (uname(&utsname_buffer) == 0)
269 {
270 ptr_data = utsname_buffer.sysname;
271 }
272 }
273
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (ptr_data != NULL)
274 {
275 1 len = gate_str_print_text(buffer, buffer_len, ptr_data, gate_str_length(ptr_data));
276
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (buffer_used)
277 {
278 1 *buffer_used = len;
279 }
280 1 ret = GATE_RESULT_OK;
281 }
282 else
283 {
284 ret = GATE_RESULT_FAILED;
285 }
286
287 #elif defined(GATE_SYS_DARWIN)
288 char name[256];
289 size_t namelen = sizeof(name) - 1;
290
291 name[sizeof(name) - 1] = 0;
292 if (sysctlbyname("kern.ostype", name, &namelen, NULL, 0) == 0)
293 {
294 const gate_size_t name_used = gate_str_length_max(name, sizeof(name));
295 const gate_size_t used = gate_str_print_text(buffer, buffer_len, name, namelen);
296 if (buffer_used) *buffer_used = used;
297 return GATE_RESULT_OK;
298 }
299 else
300 {
301 return GATE_RESULT_FAILED;
302 }
303
304 #elif defined(GATE_SYS_BSD)
305 int mib[] = { CTL_KERN, KERN_OSTYPE };
306 size_t miblen = sizeof(mib) / sizeof(mib[0]);
307 *buffer_used = buffer_len;
308 if (gate_get_sysctrl_value(mib, miblen, buffer, buffer_used))
309 {
310 ret = GATE_RESULT_OK;
311 }
312 #endif
313 1 return ret;
314 }
315
316
317 1 gate_result_t gate_os_print_productname(char* buffer, gate_size_t buffer_len, gate_size_t* buffer_used)
318 {
319 1 gate_result_t ret = GATE_RESULT_FAILED;
320
321 #if defined(GATE_SYS_LINUX)
322 1 char const* ptr_data = NULL;
323 gate_size_t len;
324 struct utsname utsname_buffer;
325 linux_os_release_info_t info;
326 1 ret = gate_linux_read_os_release_info(&info);
327
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (GATE_SUCCEEDED(ret))
328 {
329
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 if (!gate_str_is_empty(info.os_pretty_name))
330 {
331 1 ptr_data = info.os_pretty_name;
332 }
333 else if (!gate_str_is_empty(info.os_version))
334 {
335 ptr_data = info.os_id;
336 }
337 }
338
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (ptr_data == NULL)
339 {
340 if (uname(&utsname_buffer) == 0)
341 {
342 ptr_data = utsname_buffer.sysname;
343 }
344 }
345
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (ptr_data != NULL)
346 {
347 1 len = gate_str_print_text(buffer, buffer_len, ptr_data, gate_str_length(ptr_data));
348
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (buffer_used)
349 {
350 1 *buffer_used = len;
351 }
352 1 ret = GATE_RESULT_OK;
353 }
354 else
355 {
356 ret = GATE_RESULT_FAILED;
357 }
358 #elif defined(GATE_SYS_DARWIN)
359 char name[256];
360 size_t namelen = sizeof(name) - 1;
361
362 name[sizeof(name) - 1] = 0;
363 if (sysctlbyname("kern.osproductversion", name, &namelen, NULL, 0) == 0)
364 {
365 const gate_size_t name_used = gate_str_length_max(name, sizeof(name));
366 const gate_size_t used = gate_str_print_text(buffer, buffer_len, name, namelen);
367 if (buffer_used) *buffer_used = used;
368 return GATE_RESULT_OK;
369 }
370 else
371 {
372 return GATE_RESULT_FAILED;
373 }
374
375 #elif defined(GATE_SYS_BSD)
376 int mib[] = { CTL_KERN, KERN_OSRELEASE };
377 size_t miblen = sizeof(mib) / sizeof(mib[0]);
378 *buffer_used = buffer_len;
379 if (gate_get_sysctrl_value(mib, miblen, buffer, buffer_used))
380 {
381 ret = GATE_RESULT_OK;
382 }
383
384 #endif
385 1 return ret;
386 }
387
388 1 gate_result_t gate_os_get_version(gate_version_t* ptr_version)
389 {
390 1 int a = 0, b = 0, c = 0;
391 struct utsname uname_info;
392
393 #if defined(GATE_SYS_LINUX)
394 do
395 {
396 linux_os_release_info_t info;
397 1 gate_result_t result = gate_linux_read_os_release_info(&info);
398
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (GATE_SUCCEEDED(result))
399 {
400 1 sscanf(info.os_version_id, "%d.%d.%d", &a, &b, &c);
401
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (ptr_version)
402 {
403 1 ptr_version->major = a;
404 1 ptr_version->minor = b;
405 1 ptr_version->patch = c;
406 1 ptr_version->build = 0;
407 }
408 1 return GATE_RESULT_OK;
409 }
410 } while (0);
411 #endif /* GATE_SYS_LINUX */
412
413 if (0 == uname(&uname_info))
414 {
415 sscanf(uname_info.release, "%d.%d.%d", &a, &b, &c);
416 if (ptr_version)
417 {
418 ptr_version->major = a;
419 ptr_version->minor = b;
420 ptr_version->patch = c;
421 ptr_version->build = 0;
422 }
423 return GATE_RESULT_OK;
424 }
425 return GATE_RESULT_NOTAVAILABLE;
426 }
427
428
429 1 gate_result_t gate_os_get_hostname_str(char* buffer, gate_size_t buffer_len, gate_size_t* buffer_used)
430 {
431 gate_result_t ret;
432 1 char tmp_buffer[GATE_MAX_FILENAME_LENGTH] = GATE_INIT_EMPTY;
433 gate_size_t used;
434
435 1 int error = gethostname(tmp_buffer, sizeof(tmp_buffer));
436
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (error)
437 {
438 gate_posix_errno(&ret);
439 }
440 else
441 {
442 1 used = gate_str_length_max(tmp_buffer, sizeof(tmp_buffer));
443 1 gate_str_print_text(buffer, buffer_len, tmp_buffer, used);
444
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (buffer_used != NULL)
445 {
446 1 *buffer_used = used;
447 }
448 1 ret = GATE_RESULT_OK;
449 }
450 1 return ret;
451 }
452 gate_result_t gate_os_set_hostname(gate_string_t const* hostname)
453 {
454 gate_result_t result = GATE_RESULT_NOTSUPPORTED;
455 static gate_string_t const hostname_file_path = GATE_STRING_INIT_STATIC("/etc/hostname");
456 int error_state;
457
458 if (GATE_SUCCEEDED(gate_file_exists(&hostname_file_path)))
459 {
460 result = gate_file_set_content(&hostname_file_path, hostname);
461 }
462
463 #if defined(GATE_SYS_ANDROID)
464 (void)error_state;
465 #else
466 error_state = sethostname(hostname->str, hostname->length);
467 if (error_state)
468 {
469 gate_posix_errno(&result);
470 }
471 else
472 {
473 result = GATE_RESULT_OK;
474 }
475 #endif
476 return result;
477 }
478 1 gate_result_t gate_os_get_hostdomainname_str(char* buffer, gate_size_t buffer_len, gate_size_t* buffer_used)
479 {
480 gate_result_t ret;
481 1 char tmp_buffer[GATE_MAX_FILENAME_LENGTH] = GATE_INIT_EMPTY;
482 gate_size_t used;
483
484 int error;
485 do
486 {
487 #if defined(GATE_SYS_ANDROID)
488 (void)error;
489 ret = GATE_RESULT_NOTSUPPORTED;
490 break;
491 #else
492 1 error = getdomainname(tmp_buffer, sizeof(tmp_buffer));
493
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (error)
494 {
495 gate_posix_errno(&ret);
496 break;
497 }
498 #endif
499
500 1 used = gate_str_length_max(tmp_buffer, sizeof(tmp_buffer));
501 1 gate_str_print_text(buffer, buffer_len, tmp_buffer, used);
502
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (buffer_used != NULL)
503 {
504 1 *buffer_used = used;
505 }
506 1 ret = GATE_RESULT_OK;
507 } while (0);
508 1 return ret;
509 }
510 gate_result_t gate_os_set_hostdomainname(gate_string_t const* domainname)
511 {
512 gate_result_t result = GATE_RESULT_NOTSUPPORTED;
513 #if !defined(GATE_SYS_ANDROID)
514 int error = setdomainname(domainname->str, domainname->length);
515 if (error)
516 {
517 gate_posix_errno(&result);
518 }
519 else
520 {
521 result = GATE_RESULT_OK;
522 }
523 #endif
524 return result;
525 }
526
527 1 gate_result_t gate_os_get_uid(gate_uint8_t* buffer, gate_size_t buffer_len, gate_size_t* buffer_used)
528 {
529 1 gate_result_t ret = GATE_RESULT_FAILED;
530 static gate_string_t const etc_machine_id = GATE_STRING_INIT_STATIC("/etc/machine-id");
531 char id_buffer[1024];
532 1 gate_size_t id_buffer_size = sizeof(id_buffer);
533 gate_size_t pos_nl;
534 1 long os_hostid = 0;
535
536 do
537 {
538 1 ret = gate_file_get_content_buffer(&etc_machine_id, id_buffer, &id_buffer_size);
539
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (GATE_SUCCEEDED(ret))
540 {
541 pos_nl = gate_str_char_pos(id_buffer, id_buffer_size, '\n', 0);
542 if (pos_nl != GATE_STR_NPOS)
543 {
544 id_buffer_size = pos_nl;
545 }
546 if (id_buffer_size > 0)
547 {
548 if (id_buffer_size > buffer_len)
549 {
550 ret = GATE_RESULT_BUFFERTOOSMALL;
551 if (buffer_used) *buffer_used = id_buffer_size;
552 break;
553 }
554 else
555 {
556 gate_mem_copy(buffer, id_buffer, id_buffer_size);
557 if (buffer_used) *buffer_used = id_buffer_size;
558 ret = GATE_RESULT_OK;
559 break;
560 }
561 }
562 }
563
564 /* fallback: try bad-old hostid() */
565 #if defined(GATE_SYS_ANDROID)
566 (void)os_hostid;
567 #else
568 1 os_hostid = gethostid();
569
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (buffer_len < sizeof(os_hostid))
570 {
571 if (buffer_used) *buffer_used = id_buffer_size;
572 ret = GATE_RESULT_BUFFERTOOSMALL;
573 break;
574 }
575 else
576 {
577 1 gate_mem_copy(buffer, &os_hostid, sizeof(os_hostid));
578
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (buffer_used) *buffer_used = sizeof(os_hostid);
579 1 ret = GATE_RESULT_OK;
580 1 break;
581 }
582 #endif
583
584 } while (0);
585
586 1 return ret;
587 }
588
589 #if !defined(RB_POWER_OFF) && defined(GATE_SYS_BSD)
590 # if defined(GATE_SYS_OPENBSD) || defined(GATE_SYS_NETBSD)
591 # define RB_POWER_OFF (RB_POWERDOWN | RB_HALT)
592 # else
593 # define RB_POWER_OFF RB_POWEROFF
594 # endif
595 #endif
596
597 #if defined(GATE_SYS_NETBSD)
598 # define GATE_POSIX_REBOOT_EXT_ARGS , NULL
599 #else
600 # define GATE_POSIX_REBOOT_EXT_ARGS
601 #endif
602
603 gate_result_t gate_os_shutdown()
604 {
605 #define CMD_SHUTDOWN_DIR "/sbin"
606 #define CMD_SHUTDOWN_PATH "/sbin/shutdown"
607
608 gate_result_t ret;
609 int exit_code = -1;
610 int error_code;
611
612 gate_string_t command_path = GATE_STRING_INIT_STATIC(CMD_SHUTDOWN_PATH);
613 gate_string_t workdir = GATE_STRING_INIT_STATIC(CMD_SHUTDOWN_DIR);
614 do
615 {
616 ret = gate_process_run(&command_path, NULL, 0, &workdir, NULL, 0,
617 GATE_PROCESS_START_NOTERMINAL | GATE_PROCESS_START_NOINHERIT,
618 NULL, &exit_code);
619
620 if (GATE_SUCCEEDED(ret))
621 {
622 if (exit_code == 0)
623 {
624 /* script was executed -> seems to be successful */
625 break;
626 }
627 }
628
629 /* try to invoke APIs to get extended error codes */
630 sync();
631
632 #if !defined(GATE_SYS_DARWIN)
633 error_code = reboot(RB_POWER_OFF GATE_POSIX_REBOOT_EXT_ARGS);
634 if (error_code)
635 {
636 gate_posix_errno(&ret);
637 }
638 else
639 {
640 ret = GATE_RESULT_OK;
641 }
642 #endif
643
644 } while (0);
645
646 return ret;
647 }
648 gate_result_t gate_os_reboot()
649 {
650 #define CMD_REBOOT_DIR "/sbin"
651 #define CMD_REBOOT_PATH "/sbin/reboot"
652
653 gate_result_t ret;
654 int exit_code = -1;
655 int error_code;
656
657 gate_string_t command_path = GATE_STRING_INIT_STATIC(CMD_REBOOT_PATH);
658 gate_string_t workdir = GATE_STRING_INIT_STATIC(CMD_REBOOT_DIR);
659 do
660 {
661 ret = gate_process_run(&command_path, NULL, 0, &workdir, NULL, 0,
662 GATE_PROCESS_START_NOTERMINAL | GATE_PROCESS_START_NOINHERIT,
663 NULL, &exit_code);
664
665 if (GATE_SUCCEEDED(ret))
666 {
667 if (exit_code == 0)
668 {
669 /* script was executed -> seems to be successful */
670 break;
671 }
672 }
673
674 /* try to invoke APIs to get extended error codes */
675 sync();
676 #if !defined(GATE_SYS_DARWIN)
677 error_code = reboot(RB_AUTOBOOT GATE_POSIX_REBOOT_EXT_ARGS);
678 if (error_code)
679 {
680 gate_posix_errno(&ret);
681 }
682 else
683 {
684 ret = GATE_RESULT_OK;
685 }
686 #endif
687
688 } while (0);
689
690 return ret;
691 }
692
693
694
695
696
697 1 gate_result_t gate_os_get_cpu_architecture(gate_enumint_t* ptr_arch)
698 {
699 1 gate_result_t ret = GATE_RESULT_OK;
700 do
701 {
702 #if (GATE_ARCH == GATE_ARCH_X86IA32)
703 * ptr_arch = GATE_OS_ARCH_X86_32;
704 #elif (GATE_ARCH == GATE_ARCH_X86X64)
705 1 * ptr_arch = GATE_OS_ARCH_X86_64;
706 #elif (GATE_ARCH == GATE_ARCH_X86IA16)
707 * ptr_arch = GATE_OS_ARCH_X86_16;
708 #elif (GATE_ARCH == GATE_ARCH_X86IA64)
709 * ptr_arch = GATE_OS_ARCH_ITANIUM;
710 #elif (GATE_ARCH == GATE_ARCH_ARM64)
711 * ptr_arch = GATE_OS_ARCH_ARM_64;
712 #elif (GATE_ARCH == GATE_ARCH_ARM32)
713 * ptr_arch = GATE_OS_ARCH_ARM_32;
714 #elif (GATE_ARCH == GATE_ARCH_ALPHA)
715 * ptr_arch = GATE_OS_ARCH_ALPHA;
716 #else
717 * ptr_arch = GATE_OS_ARCH_UNKNOWN;
718 #endif
719 } while (0);
720
721 1 return ret;
722 }
723
724 static gate_string_t const gate_os_cpu_key_processor = GATE_STRING_INIT_STATIC("processor");
725 static gate_string_t const gate_os_cpu_key_vendor_id = GATE_STRING_INIT_STATIC("vendor_id");
726 static gate_string_t const gate_os_cpu_key_model_name = GATE_STRING_INIT_STATIC("model name");
727 static gate_string_t const gate_os_cpu_key_cpu_family = GATE_STRING_INIT_STATIC("cpu family");
728 static gate_string_t const gate_os_cpu_key_model = GATE_STRING_INIT_STATIC("model");
729 static gate_string_t const gate_os_cpu_key_stepping = GATE_STRING_INIT_STATIC("stepping");
730 static gate_string_t const gate_os_cpu_key_flags = GATE_STRING_INIT_STATIC("flags");
731 static gate_string_t const gate_os_cpu_key_cpu_mhz = GATE_STRING_INIT_STATIC("cpu MHz");
732 static gate_string_t const gate_os_cpu_key_cache_size = GATE_STRING_INIT_STATIC("cache size");
733
734 1 gate_result_t gate_os_get_cpu_info(gate_os_cpuinfo_t* info)
735 {
736 gate_result_t ret;
737 static gate_string_t const procfs_cpuinfo = GATE_STRING_INIT_STATIC("/proc/cpuinfo");
738 char buffer[4092 * 3];
739 1 gate_size_t buffer_len = sizeof(buffer);
740 gate_string_t data;
741 gate_string_t line;
742 gate_string_t tail;
743 gate_string_t key;
744 gate_string_t value;
745 gate_size_t pos;
746 gate_uint64_t ui64;
747 1 gate_uint32_t family = 0;
748 1 gate_uint32_t model = 0;
749 1 gate_uint32_t stepping = 0;
750
751 do
752 {
753 1 gate_mem_clear(info, sizeof(gate_os_cpuinfo_t));
754 1 ret = gate_file_get_content_buffer(&procfs_cpuinfo, buffer, &buffer_len);
755
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_BREAK_IF_FAILED(ret);
756
757 1 gate_string_create_static_len(&data, buffer, buffer_len);
758
759
2/2
✓ Branch 1 taken 54 times.
✓ Branch 2 taken 1 times.
55 while (NULL != gate_string_read_line(&line, &data, &tail))
760 {
761 54 data = tail;
762
763 54 pos = gate_string_char_pos(&line, ':', 0);
764
2/2
✓ Branch 0 taken 52 times.
✓ Branch 1 taken 2 times.
54 if (pos != GATE_STR_NPOS)
765 {
766 52 gate_string_create_static_len(&key, line.str, pos);
767 52 gate_string_create_static_len(&value, line.str + pos + 1, line.length - pos - 1);
768 52 gate_string_trim(&key, &key);
769 52 gate_string_trim(&value, &value);
770
771
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 50 times.
52 if (0 == gate_string_comp_ic(&key, &gate_os_cpu_key_processor))
772 {
773 2 ++info->cpu_cores;
774 }
775
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 50 times.
52 if (0 == gate_string_comp_ic(&key, &gate_os_cpu_key_vendor_id))
776 {
777 2 gate_str_print_text(info->cpu_vendor, sizeof(info->cpu_vendor), value.str, value.length);
778 }
779
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 50 times.
52 if (0 == gate_string_comp_ic(&key, &gate_os_cpu_key_model_name))
780 {
781 2 gate_str_print_text(info->cpu_name, sizeof(info->cpu_name), value.str, value.length);
782 2 gate_str_print_text(info->cpu_description, sizeof(info->cpu_description), value.str, value.length);
783 }
784
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 50 times.
52 if (0 == gate_string_comp_ic(&key, &gate_os_cpu_key_model_name))
785 {
786 2 gate_str_print_text(info->cpu_description, sizeof(info->cpu_description), value.str, value.length);
787 }
788
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 50 times.
52 if (0 == gate_string_comp_ic(&key, &gate_os_cpu_key_cpu_family))
789 {
790
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 if (0 != gate_str_parse_uint64(value.str, value.length, &ui64))
791 {
792 2 family = (gate_uint32_t)ui64;
793 }
794 }
795
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 50 times.
52 if (0 == gate_string_comp_ic(&key, &gate_os_cpu_key_model))
796 {
797
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 if (0 != gate_str_parse_uint64(value.str, value.length, &ui64))
798 {
799 2 model = (gate_uint32_t)ui64;
800 }
801 }
802
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 50 times.
52 if (0 == gate_string_comp_ic(&key, &gate_os_cpu_key_stepping))
803 {
804
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 if (0 != gate_str_parse_uint64(value.str, value.length, &ui64))
805 {
806 2 stepping = (gate_uint32_t)ui64;
807 }
808 }
809 /*
810 if(0 == gate_string_comp_ic(&key, &gate_os_cpu_key_flags))
811 {
812
813 }
814 */
815
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 50 times.
52 if (0 == gate_string_comp_ic(&key, &gate_os_cpu_key_cpu_mhz))
816 {
817
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 if (0 != gate_str_parse_uint64(value.str, value.length, &ui64))
818 {
819 2 info->cpu_speed_mhz = (gate_uint32_t)ui64;
820 }
821 }
822
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 50 times.
52 if (0 == gate_string_comp_ic(&key, &gate_os_cpu_key_cache_size))
823 {
824
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 if (0 != gate_str_parse_uint64(value.str, value.length, &ui64))
825 {
826 2 info->cpu_cache_bytes = (gate_uint32_t)(ui64 * 1024);
827 }
828 }
829 }
830 } // while(...readline...)
831 1 info->cpu_version = ((family & 0xff) << 24) | ((model & 0xff) << 16) | (stepping & 0xffff);
832
833 } while (0);
834
835 1 return ret;
836 }
837
838 gate_result_t gate_os_enum_cpu_features(gate_os_cpu_feature_callback_t callback, void* param)
839 {
840 gate_result_t ret = GATE_RESULT_NOTSUPPORTED;
841 return ret;
842 }
843
844 gate_result_t gate_os_get_process_cpu_affinity(gate_os_cpu_activation_t* affinity)
845 {
846 gate_result_t ret = GATE_RESULT_FAILED;
847 do
848 {
849 gate_mem_clear(affinity, sizeof(gate_os_cpu_activation_t));
850 } while (0);
851 return ret;
852 }
853 gate_result_t gate_os_set_process_cpu_affinity(gate_os_cpu_activation_t const* affinity)
854 {
855 gate_result_t ret = GATE_RESULT_FAILED;
856 do
857 {
858 } while (0);
859 return ret;
860 }
861
862
863
864 2 static gate_result_t gate_os_cpu_load(gate_int64_t* ptr_total, gate_int64_t* ptr_work)
865 {
866 gate_result_t ret;
867 static gate_string_t const procfs_stat = GATE_STRING_INIT_STATIC("/proc/stat");
868 char stat_buffer[4096];
869 2 gate_size_t stat_buffer_len = sizeof(stat_buffer);
870 gate_string_t data;
871 gate_string_t strvalues;
872 gate_string_t line;
873 gate_string_t tail;
874 gate_string_t value;
875 gate_size_t cnt;
876 gate_int64_t values[7];
877
878 do
879 {
880 2 ret = gate_file_get_content_buffer(&procfs_stat, stat_buffer, &stat_buffer_len);
881
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 GATE_BREAK_IF_FAILED(ret);
882
883 2 gate_string_create_static_len(&data, stat_buffer, stat_buffer_len);
884 2 ret = GATE_RESULT_FAILED;
885
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 while (NULL != gate_string_read_line(&line, &data, &tail))
886 {
887 2 data = tail;
888
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 if (gate_str_starts_with_ic(line.str, line.length, "cpu ", 4))
889 {
890 2 gate_string_substr(&strvalues, &line, 4, line.length - 4);
891
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 2 times.
16 for (cnt = 0; cnt != 7; ++cnt)
892 {
893
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 14 times.
14 if (NULL == gate_string_read_token(&value, &strvalues, &tail))
894 {
895 break;
896 }
897 14 values[cnt] = 0;
898 14 gate_str_parse_int64(value.str, value.length, &values[cnt]);
899 14 strvalues = tail;
900 }
901
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (cnt == 7)
902 {
903 2 *ptr_total = values[0] + values[1] + values[2] + values[3] + values[4] + values[5] + values[6];
904 2 *ptr_work = values[0] + values[1] + values[2];
905 2 ret = GATE_RESULT_OK;
906 }
907 2 break;
908 }
909 }
910 } while (0);
911 2 return ret;
912 }
913
914 1 gate_result_t gate_os_cpu_load_init(gate_os_cpu_load_state_t* state)
915 {
916 1 gate_int64_t* ptr_total = (gate_int64_t*)&state->records[0];
917 1 gate_int64_t* ptr_work = (gate_int64_t*)&state->records[4];
918
919 1 return gate_os_cpu_load(ptr_total, ptr_work);
920 }
921 1 gate_result_t gate_os_cpu_load_update(gate_os_cpu_load_state_t* state, gate_uint16_t* load65535)
922 {
923 gate_result_t ret;
924 1 gate_int64_t* ptr_total = (gate_int64_t*)&state->records[0];
925 1 gate_int64_t* ptr_work = (gate_int64_t*)&state->records[4];
926 gate_int64_t new_total;
927 gate_int64_t new_work;
928 gate_int64_t diff_total;
929 gate_int64_t diff_work;
930 gate_int64_t result;
931 1 ret = gate_os_cpu_load(&new_total, &new_work);
932
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (GATE_SUCCEEDED(ret))
933 {
934 1 diff_total = new_total - *ptr_total;
935 1 diff_work = new_work - *ptr_work;
936 1 *ptr_total = new_total;
937 1 *ptr_work = new_work;
938
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (diff_total > 0)
939 {
940 result = (diff_work * (gate_int64_t)65535 / diff_total);
941 *load65535 = (gate_uint16_t)(result > 65535 ? 65535 : result);
942 }
943 else
944 {
945 1 *load65535 = 65535;
946 }
947 }
948 1 return ret;
949 }
950 1 gate_result_t gate_os_cpu_load_uninit(gate_os_cpu_load_state_t* state)
951 {
952 1 return GATE_RESULT_OK;
953 }
954
955 static gate_string_t const filepath_proc_meminfo = GATE_STRING_INIT_STATIC("/proc/meminfo");
956
957 2 static gate_size_t gate_os_parse_meminfo_line(char const* data, gate_size_t data_len,
958 char const* key, gate_size_t key_len, char* value, gate_size_t value_len)
959 {
960 2 gate_size_t pos = gate_str_pos(data, data_len, key, key_len, 0);
961 gate_string_t line;
962 gate_string_t source;
963 gate_string_t tail;
964
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (pos != GATE_STR_NPOS)
965 {
966 2 gate_string_create_static_len(&source, data + pos + key_len, data_len - pos - key_len);
967
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 if (NULL != gate_string_read_line(&line, &source, &tail))
968 {
969 2 gate_string_trim(&line, &line);
970 2 return gate_string_to_buffer(&line, value, value_len);
971 }
972 }
973 return 0;
974 }
975 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)
976 {
977 char value[1024];
978 2 gate_size_t value_used = gate_os_parse_meminfo_line(data, data_len, key, key_len, value, sizeof(value));
979
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (value_used)
980 {
981 2 *num = 0;
982
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 if (gate_str_parse_uint64(value, value_used, num) > 0)
983 {
984 2 return true;
985 }
986 }
987 return false;
988 }
989
990
991 1 gate_result_t gate_os_get_physical_memory(gate_uint64_t* ptr_total, gate_uint64_t* ptr_available)
992 {
993 1 gate_result_t ret = GATE_RESULT_OK;
994 char buffer[8192];
995 1 gate_size_t buffer_len = sizeof(buffer);
996 1 gate_uint64_t total = 0;
997 1 gate_uint64_t available = 0;
998 1 gate_uint64_t pgsize
999 #if defined(_SC_PAGESIZE)
1000 1 = (gate_uint64_t)sysconf(_SC_PAGESIZE);
1001 #elif defined(_SC_PAGE_SIZE)
1002 = (gate_uint64_t)sysconf(_SC_PAGE_SIZE);
1003 #else
1004 = 4096;
1005 #endif
1006
1007 #if defined(_SC_PHYS_PAGES)
1008 1 long phys = sysconf(_SC_PHYS_PAGES);
1009 1 total = (gate_uint64_t)(phys) * (gate_uint64_t)(pgsize);
1010 #elif defined(_SC_AIX_REALMEM)
1011 total = (gate_uint64_t)(sysconf(_SC_AIX_REALMEM)) * 1024;
1012 #endif
1013
1014 #if defined(_SC_AVPHYS_PAGES)
1015 1 available = (gate_uint64_t)(sysconf(_SC_AVPHYS_PAGES)) * pgsize;
1016 #endif
1017
1018
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))
1019 {
1020 ret = gate_file_get_content_buffer(&filepath_proc_meminfo, buffer, &buffer_len);
1021 if (GATE_SUCCEEDED(ret))
1022 {
1023 if (total)
1024 {
1025 gate_os_parse_meminfo_num(buffer, buffer_len, "MemTotal:", 9, &total);
1026 total *= 1024;
1027 }
1028 if (available)
1029 {
1030 gate_os_parse_meminfo_num(buffer, buffer_len, "MemFree:", 8, &available);
1031 available *= 1024;
1032 }
1033 }
1034 }
1035
1036
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (ptr_total)
1037 {
1038 1 *ptr_total = total;
1039 }
1040
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (ptr_available)
1041 {
1042 1 *ptr_available = available;
1043 }
1044 1 return ret;
1045 }
1046 1 gate_result_t gate_os_get_virtual_memory(gate_uint64_t* ptr_total, gate_uint64_t* ptr_available)
1047 {
1048 1 gate_result_t ret = GATE_RESULT_NOTSUPPORTED;
1049 char buffer[8192];
1050 1 gate_uint64_t vmtotal = 0;
1051 1 gate_uint64_t vmused = 0;
1052 1 gate_size_t buffer_len = sizeof(buffer);
1053 1 ret = gate_file_get_content_buffer(&filepath_proc_meminfo, buffer, &buffer_len);
1054
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (GATE_SUCCEEDED(ret))
1055 {
1056 1 gate_os_parse_meminfo_num(buffer, buffer_len, "VmallocTotal:", 13, &vmtotal);
1057 1 gate_os_parse_meminfo_num(buffer, buffer_len, "VmallocUsed:", 12, &vmused);
1058
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (ptr_total)
1059 {
1060 1 *ptr_total = vmtotal * 1024;
1061 }
1062
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (ptr_available)
1063 {
1064 1 *ptr_available = (vmtotal - vmused) * 1024;
1065 }
1066 }
1067 1 return ret;
1068 }
1069
1070 #endif
1071
1072