Skip to content

Commit 6f94e85

Browse files
Merge pull request #8 from dreamer-coding/main
Upgrade Host Info
2 parents 34a5fcf + 68ab47d commit 6f94e85

File tree

7 files changed

+301
-11
lines changed

7 files changed

+301
-11
lines changed

code/logic/fossil/sys/hostinfo.h

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,32 @@ typedef struct {
2929
char os_name[128];
3030
char os_version[128];
3131
char kernel_version[128];
32+
char hostname[128];
33+
char username[128];
34+
char domain_name[128];
35+
char machine_type[128];
36+
char platform[128];
3237
} fossil_sys_hostinfo_system_t;
3338

39+
// Architecture information structure
40+
typedef struct {
41+
char architecture[128];
42+
char cpu[128];
43+
char cpu_cores[128];
44+
char cpu_threads[128];
45+
char cpu_frequency[128];
46+
char cpu_architecture[128];
47+
} fossil_sys_hostinfo_architecture_t;
48+
3449
// Memory information structure
3550
typedef struct {
36-
uint64_t total_memory; // in bytes
37-
uint64_t free_memory; // in bytes
51+
uint64_t total_memory; // in bytes
52+
uint64_t free_memory; // in bytes
53+
uint64_t used_memory; // in bytes
54+
uint64_t available_memory;// in bytes
55+
uint64_t total_swap; // in bytes
56+
uint64_t free_swap; // in bytes
57+
uint64_t used_swap; // in bytes
3858
} fossil_sys_hostinfo_memory_t;
3959

4060
// Endianness information structure
@@ -50,6 +70,14 @@ typedef struct {
5070
*/
5171
int fossil_sys_hostinfo_get_system(fossil_sys_hostinfo_system_t *info);
5272

73+
/**
74+
* Retrieve architecture information.
75+
*
76+
* @param info A pointer to a structure that will be filled with architecture information.
77+
* @return 0 on success, or a negative error code on failure.
78+
*/
79+
int fossil_sys_hostinfo_get_architecture(fossil_sys_hostinfo_architecture_t *info);
80+
5381
/**
5482
* Retrieve memory information.
5583
*
@@ -96,6 +124,17 @@ namespace fossil {
96124
return info;
97125
}
98126

127+
/**
128+
* Get architecture information.
129+
*
130+
* @return A structure containing architecture information.
131+
*/
132+
static fossil_sys_hostinfo_architecture_t get_architecture() {
133+
fossil_sys_hostinfo_architecture_t info;
134+
fossil_sys_hostinfo_get_architecture(&info);
135+
return info;
136+
}
137+
99138
/**
100139
* Get memory information.
101140
*

code/logic/hostinfo.c

Lines changed: 230 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,19 +14,22 @@
1414
#include "fossil/sys/hostinfo.h"
1515
#include <stdio.h>
1616
#include <string.h>
17+
#include <stdlib.h>
1718

1819
#ifdef _WIN32
1920
#include <windows.h>
2021
#elif defined(__APPLE__)
22+
#define _DARWIN_C_SOURCE
2123
#include <sys/utsname.h>
22-
#include <sys/types.h>
2324
#include <unistd.h>
25+
#include <sys/types.h>
2426
#include <sys/sysctl.h>
2527
#else
2628
#include <sys/utsname.h>
2729
#include <sys/sysinfo.h>
2830
#include <sys/types.h>
2931
#include <unistd.h>
32+
#include <netdb.h> // for gethostname
3033
#endif
3134

3235
int fossil_sys_hostinfo_get_system(fossil_sys_hostinfo_system_t *info) {
@@ -38,19 +41,228 @@ int fossil_sys_hostinfo_get_system(fossil_sys_hostinfo_system_t *info) {
3841
snprintf(info->os_name, sizeof(info->os_name), "Windows");
3942
snprintf(info->os_version, sizeof(info->os_version), "%lu.%lu", osvi.dwMajorVersion, osvi.dwMinorVersion);
4043
snprintf(info->kernel_version, sizeof(info->kernel_version), "%lu", osvi.dwBuildNumber);
44+
45+
DWORD size = sizeof(info->hostname);
46+
GetComputerNameA(info->hostname, &size);
47+
48+
size = sizeof(info->username);
49+
GetUserNameA(info->username, &size);
50+
51+
// Domain name
52+
size = sizeof(info->domain_name);
53+
if (!GetEnvironmentVariableA("USERDOMAIN", info->domain_name, size)) {
54+
strncpy(info->domain_name, "Unknown", sizeof(info->domain_name) - 1);
55+
info->domain_name[sizeof(info->domain_name) - 1] = '\0';
56+
}
57+
58+
SYSTEM_INFO sysinfo;
59+
GetSystemInfo(&sysinfo);
60+
snprintf(info->machine_type, sizeof(info->machine_type), "%u", sysinfo.wProcessorArchitecture);
61+
snprintf(info->platform, sizeof(info->platform), "Win32");
62+
4163
#elif defined(__APPLE__)
4264
struct utsname sysinfo;
4365
if (uname(&sysinfo) != 0) return -1;
4466
strncpy(info->os_name, sysinfo.sysname, sizeof(info->os_name) - 1);
67+
info->os_name[sizeof(info->os_name) - 1] = '\0';
4568
strncpy(info->os_version, sysinfo.version, sizeof(info->os_version) - 1);
69+
info->os_version[sizeof(info->os_version) - 1] = '\0';
4670
strncpy(info->kernel_version, sysinfo.release, sizeof(info->kernel_version) - 1);
71+
info->kernel_version[sizeof(info->kernel_version) - 1] = '\0';
72+
73+
if (gethostname(info->hostname, sizeof(info->hostname)) != 0)
74+
strncpy(info->hostname, "Unknown", sizeof(info->hostname) - 1);
75+
info->hostname[sizeof(info->hostname) - 1] = '\0';
76+
77+
const char *user = getenv("USER");
78+
if (user)
79+
strncpy(info->username, user, sizeof(info->username) - 1);
80+
else
81+
strncpy(info->username, "Unknown", sizeof(info->username) - 1);
82+
info->username[sizeof(info->username) - 1] = '\0';
83+
84+
strncpy(info->domain_name, "Unknown", sizeof(info->domain_name) - 1);
85+
info->domain_name[sizeof(info->domain_name) - 1] = '\0';
86+
87+
strncpy(info->machine_type, sysinfo.machine, sizeof(info->machine_type) - 1);
88+
info->machine_type[sizeof(info->machine_type) - 1] = '\0';
89+
90+
strncpy(info->platform, "Apple", sizeof(info->platform) - 1);
91+
info->platform[sizeof(info->platform) - 1] = '\0';
92+
4793
#else
4894
struct utsname sysinfo;
4995
if (uname(&sysinfo) != 0) return -1;
5096
strncpy(info->os_name, sysinfo.sysname, sizeof(info->os_name) - 1);
97+
info->os_name[sizeof(info->os_name) - 1] = '\0';
5198
strncpy(info->os_version, sysinfo.version, sizeof(info->os_version) - 1);
99+
info->os_version[sizeof(info->os_version) - 1] = '\0';
52100
strncpy(info->kernel_version, sysinfo.release, sizeof(info->kernel_version) - 1);
101+
info->kernel_version[sizeof(info->kernel_version) - 1] = '\0';
102+
103+
if (gethostname(info->hostname, sizeof(info->hostname)) != 0)
104+
strncpy(info->hostname, "Unknown", sizeof(info->hostname) - 1);
105+
info->hostname[sizeof(info->hostname) - 1] = '\0';
106+
107+
const char *user = getenv("USER");
108+
if (user)
109+
strncpy(info->username, user, sizeof(info->username) - 1);
110+
else
111+
strncpy(info->username, "Unknown", sizeof(info->username) - 1);
112+
info->username[sizeof(info->username) - 1] = '\0';
113+
114+
const char *domain = getenv("DOMAINNAME");
115+
if (domain)
116+
strncpy(info->domain_name, domain, sizeof(info->domain_name) - 1);
117+
else
118+
strncpy(info->domain_name, "Unknown", sizeof(info->domain_name) - 1);
119+
info->domain_name[sizeof(info->domain_name) - 1] = '\0';
120+
121+
strncpy(info->machine_type, sysinfo.machine, sizeof(info->machine_type) - 1);
122+
info->machine_type[sizeof(info->machine_type) - 1] = '\0';
123+
124+
strncpy(info->platform, "Unix", sizeof(info->platform) - 1);
125+
info->platform[sizeof(info->platform) - 1] = '\0';
126+
127+
#endif
128+
return 0;
129+
}
130+
131+
int fossil_sys_hostinfo_get_architecture(fossil_sys_hostinfo_architecture_t *info) {
132+
if (!info) return -1;
133+
134+
#ifdef _WIN32
135+
SYSTEM_INFO sysinfo;
136+
GetSystemInfo(&sysinfo);
137+
138+
// Architecture
139+
switch (sysinfo.wProcessorArchitecture) {
140+
case PROCESSOR_ARCHITECTURE_AMD64:
141+
strncpy(info->architecture, "x86_64", sizeof(info->architecture) - 1);
142+
break;
143+
case PROCESSOR_ARCHITECTURE_INTEL:
144+
strncpy(info->architecture, "x86", sizeof(info->architecture) - 1);
145+
break;
146+
case PROCESSOR_ARCHITECTURE_ARM:
147+
strncpy(info->architecture, "ARM", sizeof(info->architecture) - 1);
148+
break;
149+
default:
150+
strncpy(info->architecture, "Unknown", sizeof(info->architecture) - 1);
151+
break;
152+
}
153+
info->architecture[sizeof(info->architecture) - 1] = '\0';
154+
155+
// CPU info (limited on Windows)
156+
strncpy(info->cpu, "Unknown", sizeof(info->cpu) - 1);
157+
info->cpu[sizeof(info->cpu) - 1] = '\0';
158+
159+
snprintf(info->cpu_cores, sizeof(info->cpu_cores), "%lu", sysinfo.dwNumberOfProcessors);
160+
strncpy(info->cpu_threads, "Unknown", sizeof(info->cpu_threads) - 1);
161+
info->cpu_threads[sizeof(info->cpu_threads) - 1] = '\0';
162+
strncpy(info->cpu_frequency, "Unknown", sizeof(info->cpu_frequency) - 1);
163+
info->cpu_frequency[sizeof(info->cpu_frequency) - 1] = '\0';
164+
strncpy(info->cpu_architecture, info->architecture, sizeof(info->cpu_architecture) - 1);
165+
info->cpu_architecture[sizeof(info->cpu_architecture) - 1] = '\0';
166+
167+
#elif defined(__APPLE__)
168+
size_t size = sizeof(info->architecture);
169+
if (sysctlbyname("hw.machine", info->architecture, &size, NULL, 0) != 0)
170+
strncpy(info->architecture, "Unknown", sizeof(info->architecture) - 1);
171+
info->architecture[sizeof(info->architecture) - 1] = '\0';
172+
173+
size = sizeof(info->cpu);
174+
if (sysctlbyname("machdep.cpu.brand_string", info->cpu, &size, NULL, 0) != 0)
175+
strncpy(info->cpu, "Unknown", sizeof(info->cpu) - 1);
176+
info->cpu[sizeof(info->cpu) - 1] = '\0';
177+
178+
int cores = 0;
179+
size = sizeof(cores);
180+
if (sysctlbyname("hw.physicalcpu", &cores, &size, NULL, 0) == 0)
181+
snprintf(info->cpu_cores, sizeof(info->cpu_cores), "%d", cores);
182+
else
183+
strncpy(info->cpu_cores, "Unknown", sizeof(info->cpu_cores) - 1);
184+
info->cpu_cores[sizeof(info->cpu_cores) - 1] = '\0';
185+
186+
int threads = 0;
187+
size = sizeof(threads);
188+
if (sysctlbyname("hw.logicalcpu", &threads, &size, NULL, 0) == 0)
189+
snprintf(info->cpu_threads, sizeof(info->cpu_threads), "%d", threads);
190+
else
191+
strncpy(info->cpu_threads, "Unknown", sizeof(info->cpu_threads) - 1);
192+
info->cpu_threads[sizeof(info->cpu_threads) - 1] = '\0';
193+
194+
uint64_t freq = 0;
195+
size = sizeof(freq);
196+
if (sysctlbyname("hw.cpufrequency", &freq, &size, NULL, 0) == 0)
197+
snprintf(info->cpu_frequency, sizeof(info->cpu_frequency), "%llu", (unsigned long long)freq);
198+
else
199+
strncpy(info->cpu_frequency, "Unknown", sizeof(info->cpu_frequency) - 1);
200+
info->cpu_frequency[sizeof(info->cpu_frequency) - 1] = '\0';
201+
202+
strncpy(info->cpu_architecture, info->architecture, sizeof(info->cpu_architecture) - 1);
203+
info->cpu_architecture[sizeof(info->cpu_architecture) - 1] = '\0';
204+
205+
#else
206+
struct utsname sysinfo;
207+
if (uname(&sysinfo) != 0) return -1;
208+
209+
strncpy(info->architecture, sysinfo.machine, sizeof(info->architecture) - 1);
210+
info->architecture[sizeof(info->architecture) - 1] = '\0';
211+
212+
FILE *fp = fopen("/proc/cpuinfo", "r");
213+
if (fp) {
214+
char line[256];
215+
while (fgets(line, sizeof(line), fp)) {
216+
if (strncmp(line, "model name", 10) == 0) {
217+
char *colon = strchr(line, ':');
218+
if (colon) {
219+
colon++;
220+
while (*colon == ' ') colon++;
221+
strncpy(info->cpu, colon, sizeof(info->cpu) - 1);
222+
info->cpu[sizeof(info->cpu) - 1] = '\0';
223+
}
224+
} else if (strncmp(line, "cpu cores", 9) == 0) {
225+
char *colon = strchr(line, ':');
226+
if (colon) {
227+
colon++;
228+
while (*colon == ' ') colon++;
229+
strncpy(info->cpu_cores, colon, sizeof(info->cpu_cores) - 1);
230+
info->cpu_cores[sizeof(info->cpu_cores) - 1] = '\0';
231+
}
232+
} else if (strncmp(line, "siblings", 8) == 0) {
233+
char *colon = strchr(line, ':');
234+
if (colon) {
235+
colon++;
236+
while (*colon == ' ') colon++;
237+
strncpy(info->cpu_threads, colon, sizeof(info->cpu_threads) - 1);
238+
info->cpu_threads[sizeof(info->cpu_threads) - 1] = '\0';
239+
}
240+
} else if (strncmp(line, "cpu MHz", 7) == 0) {
241+
char *colon = strchr(line, ':');
242+
if (colon) {
243+
colon++;
244+
while (*colon == ' ') colon++;
245+
strncpy(info->cpu_frequency, colon, sizeof(info->cpu_frequency) - 1);
246+
info->cpu_frequency[sizeof(info->cpu_frequency) - 1] = '\0';
247+
}
248+
}
249+
}
250+
fclose(fp);
251+
} else {
252+
strncpy(info->cpu, "Unknown", sizeof(info->cpu) - 1);
253+
info->cpu[sizeof(info->cpu) - 1] = '\0';
254+
strncpy(info->cpu_cores, "Unknown", sizeof(info->cpu_cores) - 1);
255+
info->cpu_cores[sizeof(info->cpu_cores) - 1] = '\0';
256+
strncpy(info->cpu_threads, "Unknown", sizeof(info->cpu_threads) - 1);
257+
info->cpu_threads[sizeof(info->cpu_threads) - 1] = '\0';
258+
strncpy(info->cpu_frequency, "Unknown", sizeof(info->cpu_frequency) - 1);
259+
info->cpu_frequency[sizeof(info->cpu_frequency) - 1] = '\0';
260+
}
261+
262+
strncpy(info->cpu_architecture, info->architecture, sizeof(info->cpu_architecture) - 1);
263+
info->cpu_architecture[sizeof(info->cpu_architecture) - 1] = '\0';
53264
#endif
265+
54266
return 0;
55267
}
56268

@@ -62,17 +274,32 @@ int fossil_sys_hostinfo_get_memory(fossil_sys_hostinfo_memory_t *info) {
62274
if (!GlobalMemoryStatusEx(&statex)) return -1;
63275
info->total_memory = statex.ullTotalPhys;
64276
info->free_memory = statex.ullAvailPhys;
277+
info->used_memory = statex.ullTotalPhys - statex.ullAvailPhys;
278+
info->available_memory = statex.ullAvailPhys;
279+
info->total_swap = statex.ullTotalPageFile;
280+
info->free_swap = statex.ullAvailPageFile;
281+
info->used_swap = statex.ullTotalPageFile - statex.ullAvailPageFile;
65282
#elif defined(__APPLE__)
66283
int64_t memsize;
67284
size_t len = sizeof(memsize);
68285
if (sysctlbyname("hw.memsize", &memsize, &len, NULL, 0) != 0) return -1;
69286
info->total_memory = memsize;
70287
info->free_memory = 0; // macOS does not provide free memory info in the same way
288+
info->used_memory = 0;
289+
info->available_memory = 0;
290+
info->total_swap = 0;
291+
info->free_swap = 0;
292+
info->used_swap = 0;
71293
#else
72294
struct sysinfo sys_info;
73295
if (sysinfo(&sys_info) != 0) return -1;
74-
info->total_memory = sys_info.totalram;
75-
info->free_memory = sys_info.freeram;
296+
info->total_memory = sys_info.totalram * sys_info.mem_unit;
297+
info->free_memory = sys_info.freeram * sys_info.mem_unit;
298+
info->used_memory = (sys_info.totalram - sys_info.freeram) * sys_info.mem_unit;
299+
info->available_memory = sys_info.freeram * sys_info.mem_unit;
300+
info->total_swap = sys_info.totalswap * sys_info.mem_unit;
301+
info->free_swap = sys_info.freeswap * sys_info.mem_unit;
302+
info->used_swap = (sys_info.totalswap - sys_info.freeswap) * sys_info.mem_unit;
76303
#endif
77304
return 0;
78305
}

code/logic/meson.build

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
dir = include_directories('.')
2+
add_project_arguments('-D_POSIX_C_SOURCE=200112L', language: 'c')
3+
add_project_arguments('-D_POSIX_C_SOURCE=200112L', language: 'cpp')
24

35
fossil_sys_lib = library('fossil_sys',
46
files('memory.c', 'datetime.c', 'hostinfo.c', 'syscall.c', 'bitwise.c'),

code/tests/cases/test_hostinfo.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,18 @@ FOSSIL_TEST(c_test_hostinfo_get_memory) {
6060
ASSUME_ITS_TRUE(info.free_memory <= info.total_memory);
6161
}
6262

63+
FOSSIL_TEST(c_test_hostinfo_get_architecture) {
64+
fossil_sys_hostinfo_architecture_t info;
65+
int result = fossil_sys_hostinfo_get_architecture(&info);
66+
ASSUME_ITS_TRUE(result == 0);
67+
ASSUME_ITS_TRUE(strlen(info.architecture) > 0);
68+
ASSUME_ITS_TRUE(strlen(info.cpu) > 0);
69+
ASSUME_ITS_TRUE(strlen(info.cpu_cores) > 0);
70+
ASSUME_ITS_TRUE(strlen(info.cpu_threads) > 0);
71+
ASSUME_ITS_TRUE(strlen(info.cpu_frequency) > 0);
72+
ASSUME_ITS_TRUE(strlen(info.cpu_architecture) > 0);
73+
}
74+
6375
FOSSIL_TEST(c_test_hostinfo_get_endianness) {
6476
fossil_sys_hostinfo_endianness_t info;
6577
int result = fossil_sys_hostinfo_get_endianness(&info);
@@ -75,6 +87,7 @@ FOSSIL_TEST(c_test_hostinfo_get_endianness) {
7587
FOSSIL_TEST_GROUP(c_hostinfo_tests) {
7688
FOSSIL_TEST_ADD(c_hostinfo_suite, c_test_hostinfo_get_system);
7789
FOSSIL_TEST_ADD(c_hostinfo_suite, c_test_hostinfo_get_memory);
90+
FOSSIL_TEST_ADD(c_hostinfo_suite, c_test_hostinfo_get_architecture);
7891
FOSSIL_TEST_ADD(c_hostinfo_suite, c_test_hostinfo_get_endianness);
7992

8093
FOSSIL_TEST_REGISTER(c_hostinfo_suite);

0 commit comments

Comments
 (0)