diff options
| author | Jeroen van Rijn <Kelimion@users.noreply.github.com> | 2022-09-01 02:06:05 +0200 |
|---|---|---|
| committer | Jeroen van Rijn <Kelimion@users.noreply.github.com> | 2022-09-01 02:06:05 +0200 |
| commit | 7479ac48e833a967881eb9bc8ddd2dfd76c25b8d (patch) | |
| tree | 84ef81778944912c119a939252a864898e0f6ebe /core/sys/info/platform_linux.odin | |
| parent | d5f94d73adb4aaa582cbe763ed1c8f0036398f9c (diff) | |
[sys/info] Parse kernel/distro info.
Diffstat (limited to 'core/sys/info/platform_linux.odin')
| -rw-r--r-- | core/sys/info/platform_linux.odin | 88 |
1 files changed, 85 insertions, 3 deletions
diff --git a/core/sys/info/platform_linux.odin b/core/sys/info/platform_linux.odin index 05f263094..d1f9ca599 100644 --- a/core/sys/info/platform_linux.odin +++ b/core/sys/info/platform_linux.odin @@ -4,11 +4,93 @@ package sysinfo import "core:c" import sys "core:sys/unix" import "core:intrinsics" -// import "core:fmt" +import "core:os" +import "core:strings" +import "core:strconv" + +@(private) +version_string_buf: [1024]u8 @(init, private) -init_os_version :: proc "c" () { - os_version = {} +init_os_version :: proc () { + os_version.platform = .Linux + + // Try to parse `/etc/os-release` for `PRETTY_NAME="Ubuntu 20.04.3 LTS` + fd, err := os.open("/etc/os-release", os.O_RDONLY, 0) + if err != 0 { + return + } + defer os.close(fd) + + os_release_buf: [2048]u8 + n, read_err := os.read(fd, os_release_buf[:]) + if read_err != 0 { + return + } + release := string(os_release_buf[:n]) + + NEEDLE :: "PRETTY_NAME=\"" + pretty_start := strings.index(release, NEEDLE) + + b := strings.builder_from_bytes(version_string_buf[:]) + + if pretty_start > 0 { + for r, i in release[pretty_start + len(NEEDLE):] { + if r == '"' { + strings.write_string(&b, release[pretty_start + len(NEEDLE):][:i]) + break + } else if r == '\r' || r == '\n' { + strings.write_string(&b, "Unknown Linux Distro") + break + } + } + } + + NEW_UTS_LEN :: 64 + UTS_Name :: struct { + sys_name: [NEW_UTS_LEN + 1]u8 `fmt:"s,0"`, + node_name: [NEW_UTS_LEN + 1]u8 `fmt:"s,0"`, + release: [NEW_UTS_LEN + 1]u8 `fmt:"s,0"`, + version: [NEW_UTS_LEN + 1]u8 `fmt:"s,0"`, + machine: [NEW_UTS_LEN + 1]u8 `fmt:"s,0"`, + domain_name: [NEW_UTS_LEN + 1]u8 `fmt:"s,0"`, + } + uts: UTS_Name + + // Grab kernel info using `uname()` syscall, https://linux.die.net/man/2/uname + if intrinsics.syscall(sys.SYS_uname, uintptr(&uts)) != 0 { + return + } + + strings.write_string(&b, ", ") + strings.write_string(&b, string(cstring(&uts.sys_name[0]))) + strings.write_rune(&b, ' ') + + l := strings.builder_len(b) + strings.write_string(&b, string(cstring(&uts.release[0]))) + + // Parse kernel version, as substrings of the version info in `version_string_buf` + version_bits := strings.split_n(strings.to_string(b)[l:], "-", 2, context.temp_allocator) + if len(version_bits) > 1 { + os_version.version = version_bits[1] + } + + // Parse major, minor, patch from release info + triplet := strings.split(version_bits[0], ".", context.temp_allocator) + if len(triplet) == 3 { + major, major_ok := strconv.parse_int(triplet[0]) + minor, minor_ok := strconv.parse_int(triplet[1]) + patch, patch_ok := strconv.parse_int(triplet[2]) + + if major_ok && minor_ok && patch_ok { + os_version.major = major + os_version.minor = minor + os_version.patch = patch + } + } + + // Finish the string + os_version.as_string = strings.to_string(b) } Sys_Info :: struct { |