diff --git a/core/sys/info/platform_linux.odin b/core/sys/info/platform_linux.odin index e7588f9ec..3933d9f5c 100644 --- a/core/sys/info/platform_linux.odin +++ b/core/sys/info/platform_linux.odin @@ -1,10 +1,9 @@ package sysinfo import "base:intrinsics" -import "base:runtime" -import "core:strings" -import "core:strconv" +import "core:strconv" +import "core:strings" import "core:sys/linux" @(private) @@ -13,32 +12,37 @@ version_string_buf: [1024]u8 @(init, private) init_os_version :: proc () { os_version.platform = .Linux - // Try to parse `/etc/os-release` for `PRETTY_NAME="Ubuntu 20.04.3 LTS` - fd, errno := linux.open("/etc/os-release", {.RDONLY}, {}) - assert(errno == .NONE, "Failed to read /etc/os-release") - defer { - cerrno := linux.close(fd) - assert(cerrno == .NONE, "Failed to close the file descriptor") - } - os_release_buf: [2048]u8 - n, read_errno := linux.read(fd, os_release_buf[:]) - assert(read_errno == .NONE, "Failed to read data from /etc/os-release") - release := string(os_release_buf[:n]) - // Search the line in the file until we find "PRETTY_NAME=" - 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 + + // Try to parse `/etc/os-release` for `PRETTY_NAME="Ubuntu 20.04.3 LTS` + { + fd, errno := linux.open("/etc/os-release", {}) + assert(errno == .NONE, "Failed to read /etc/os-release") + defer { + cerrno := linux.close(fd) + assert(cerrno == .NONE, "Failed to close the file descriptor") + } + + os_release_buf: [2048]u8 + n, read_errno := linux.read(fd, os_release_buf[:]) + assert(read_errno == .NONE, "Failed to read data from /etc/os-release") + release := string(os_release_buf[:n]) + + // Search the line in the file until we find "PRETTY_NAME=" + NEEDLE :: "PRETTY_NAME=\"" + _, _, post := strings.partition(release, NEEDLE) + if len(post) > 0 { + end := strings.index_any(post, "\"\n") + if end > -1 && post[end] == '"' { + strings.write_string(&b, post[:end]) } } + if strings.builder_len(b) == 0 { + strings.write_string(&b, "Unknown Linux Distro") + } } + // Grab kernel info using `uname()` syscall, https://linux.die.net/man/2/uname uts: linux.UTS_Name uname_errno := linux.uname(&uts) @@ -47,28 +51,36 @@ init_os_version :: proc () { strings.write_string(&b, ", ") strings.write_string(&b, string(cstring(&uts.sysname[0]))) strings.write_rune(&b, ' ') - l := strings.builder_len(b) + + release_i := 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` - runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD() - 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 + release_str := string(b.buf[release_i:]) + + os_version.as_string = strings.to_string(b) + + // Parse the Linux version out of the release string + { + version_num, _, version_suffix := strings.partition(release_str, "-") + os_version.version = version_suffix + + i: int + for part in strings.split_iterator(&version_num, ".") { + defer i += 1 + + dst: ^int + switch i { + case 0: dst = &os_version.major + case 1: dst = &os_version.minor + case 2: dst = &os_version.patch + case: break + } + + num, ok := strconv.parse_int(part) + if !ok { break } + + dst^ = num } } - // Finish the string - os_version.as_string = strings.to_string(b) } @(init) @@ -83,4 +95,4 @@ init_ram :: proc() { total_swap = int(sys_info.totalswap) * int(sys_info.mem_unit), free_swap = int(sys_info.freeswap) * int(sys_info.mem_unit), } -} \ No newline at end of file +}