GCC Code Coverage Report


Directory: src/gate/
File: src/gate/system/os_posix.c
Date: 2025-09-14 13:10:38
Exec Total Coverage
Lines: 123 363 33.9%
Functions: 11 29 37.9%
Branches: 45 200 22.5%

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