ohmu
·
2026-10-15
1#include "common/sysctl.h"
2#include "common/debug.h"
3
4#include <errno.h>
5#include <stdlib.h>
6#include <string.h>
7
8#ifdef __OpenBSD__
9const char* ffSysctlGetString(int mib1, int mib2, FFstrbuf* result) {
10 size_t neededLength;
11 if (sysctl((int[]) { mib1, mib2 }, 2, nullptr, &neededLength, nullptr, 0) != 0 || neededLength == 1) { // neededLength is 1 for empty strings, because of the null terminator
12 FF_DEBUG("sysctl({%d, %d}) length query failed: %s", mib1, mib2, strerror(errno));
13 return "sysctl() length query failed";
14 }
15
16 ffStrbufEnsureFree(result, (uint32_t) neededLength - 1);
17
18 if (sysctl((int[]) { mib1, mib2 }, 2, result->chars + result->length, &neededLength, nullptr, 0) != 0) {
19 FF_DEBUG("sysctl({%d, %d}) failed to retrieve %zu bytes: %s", mib1, mib2, neededLength, strerror(errno));
20 return "sysctl() failed to retrieve string data";
21 }
22
23 result->length += (uint32_t) neededLength - 1;
24 result->chars[result->length] = '\0';
25
26 return nullptr;
27}
28
29int ffSysctlGetInt(int mib1, int mib2, int defaultValue) {
30 alignas(int) uint8_t result[sizeof(int)];
31 size_t neededLength = sizeof(result);
32 if (sysctl((int[]) { mib1, mib2 }, 2, &result, &neededLength, nullptr, 0) != 0) {
33 return defaultValue;
34 }
35 switch (neededLength) {
36 case sizeof(int32_t):
37 return *(int32_t*)result;
38 case sizeof(int16_t):
39 return *(int16_t*)result;
40 case sizeof(int8_t):
41 return *(int8_t*)result;
42 default:
43 return defaultValue;
44 }
45}
46
47int64_t ffSysctlGetInt64(int mib1, int mib2, int64_t defaultValue) {
48 alignas(int64_t) uint8_t result[sizeof(int64_t)];
49 size_t neededLength = sizeof(result);
50 if (sysctl((int[]) { mib1, mib2 }, 2, &result, &neededLength, nullptr, 0) != 0) {
51 return defaultValue;
52 }
53 switch (neededLength) {
54 case sizeof(int64_t):
55 return *(int64_t*)result;
56 case sizeof(int32_t):
57 return *(int32_t*)result;
58 case sizeof(int16_t):
59 return *(int16_t*)result;
60 case sizeof(int8_t):
61 return *(int8_t*)result;
62 default:
63 return defaultValue;
64 }
65}
66#else
67const char* ffSysctlGetString(const char* propName, FFstrbuf* result) {
68 size_t neededLength;
69 if (sysctlbyname(propName, nullptr, &neededLength, nullptr, 0) != 0 || neededLength == 1) { // neededLength is 1 for empty strings, because of the null terminator
70 FF_DEBUG("sysctlbyname(%s) length query failed: %s", propName, strerror(errno));
71 return "sysctlbyname() failed";
72 }
73
74 ffStrbufEnsureFree(result, (uint32_t) neededLength - 1);
75
76 if (sysctlbyname(propName, result->chars + result->length, &neededLength, nullptr, 0) != 0) {
77 FF_DEBUG("sysctlbyname(%s) failed to retrieve %zu bytes: %s", propName, neededLength, strerror(errno));
78 return "sysctlbyname() failed to retrieve string data";
79 }
80
81 result->length += (uint32_t) neededLength - 1;
82
83 result->chars[result->length] = '\0';
84
85 return nullptr;
86}
87
88int ffSysctlGetInt(const char* propName, int defaultValue) {
89 alignas(int) uint8_t result[sizeof(int)];
90 size_t neededLength = sizeof(result);
91 if (sysctlbyname(propName, &result, &neededLength, nullptr, 0) != 0) {
92 return defaultValue;
93 }
94 switch (neededLength) {
95 case sizeof(int32_t):
96 return *(int32_t*)result;
97 case sizeof(int16_t):
98 return *(int16_t*)result;
99 case sizeof(int8_t):
100 return *(int8_t*)result;
101 default:
102 return defaultValue;
103 }
104}
105
106int64_t ffSysctlGetInt64(const char* propName, int64_t defaultValue) {
107 alignas(int64_t) uint8_t result[sizeof(int64_t)];
108 size_t neededLength = sizeof(result);
109 if (sysctlbyname(propName, &result, &neededLength, nullptr, 0) != 0) {
110 return defaultValue;
111 }
112 switch (neededLength) {
113 case sizeof(int64_t):
114 return *(int64_t*)result;
115 case sizeof(int32_t):
116 return *(int32_t*)result;
117 case sizeof(int16_t):
118 return *(int16_t*)result;
119 case sizeof(int8_t):
120 return *(int8_t*)result;
121 default:
122 return defaultValue;
123 }
124}
125#endif // OpenBSD