pax_global_header00006660000000000000000000000064141131250630014506gustar00rootroot0000000000000052 comment=0d4cb7fb7f038c9c5fc6812873115265584a5f88 osinfo-1.0.3/000077500000000000000000000000001411312506300130045ustar00rootroot00000000000000osinfo-1.0.3/LICENSE000066400000000000000000000020461411312506300140130ustar00rootroot00000000000000Copyright (c) 2019-2020 Blackfire SAS Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. osinfo-1.0.3/README.md000066400000000000000000000047031411312506300142670ustar00rootroot00000000000000OS Info ======= This package provides a cross-platform way to identify the hardware your go code is running on. The following fields are provided by the `OSInfo` struct: | Field | Description | | ------------ | --------------------------------------- | | Family | The OS type as defined by `GOOS` | | Architecture | The architecture as defined by `GOARCH` | | ID | The OS ID as defined by the OS | | Name | The OS name as defined by the OS | | Codename | The release codename (if any) | | Version | The release version | | Build | The build number (if any) | Supported Operating Systems --------------------------- The following operating systems are currently supported: - Linux - FreeBSD - macOS - Windows If you wish to see another operating system supported (provided it is in [this list](https://github.com/golang/go/blob/master/src/go/build/syslist.go)), please open a pull request with the necessary changes and tests. Use one of the existing `getOSInfoXYZ()` functions as a guide (most commonly it involves parsing the output from a command or file). Usage ----- ```golang info, err := osinfo.GetOSInfo() if err != nil { // TODO: Handle this } fmt.Printf("Family: %v\n", info.Family) fmt.Printf("Architecture: %v\n", info.Architecture) fmt.Printf("ID: %v\n", info.ID) fmt.Printf("Name: %v\n", info.Name) fmt.Printf("Codename: %v\n", info.Codename) fmt.Printf("Version: %v\n", info.Version) fmt.Printf("Build: %v\n", info.Build) ``` ### Output on various platforms #### Ubuntu Linux ``` Family: linux Architecture: amd64 ID: ubuntu Name: Ubuntu Codename: eoan Version: 19.10 Build: ``` ### Alpine Linux ``` Family: linux Architecture: amd64 ID: alpine Name: Alpine Linux Codename: Version: 3.8.0 Build: ``` #### Windows ``` Family: windows Architecture: amd64 ID: windows Name: Windows 10 Pro Codename: 1903 Version: 10.0 Build: 18362 ``` #### FreeBSD ``` Family: freebsd Architecture: amd64 ID: freebsd Name: FreeBSD Codename: Version: 12.0-RELEASE Build: r341666 ``` #### Mac OS ``` Family: darwin Architecture: amd64 ID: darwin Name: Mac OS X Codename: Sierra Version: 10.12.6 Build: 16G2136 ``` osinfo-1.0.3/go.mod000066400000000000000000000000561411312506300141130ustar00rootroot00000000000000module github.com/blackfireio/osinfo go 1.11 osinfo-1.0.3/osinfo.go000066400000000000000000000204351411312506300146340ustar00rootroot00000000000000// Package osinfo provides a cross-platform way to identify the hardware your // code is running on. package osinfo // Copyright: (c) 2019 Blackfire SAS (https://blackfire.io) // License: MIT // Author: Karl Stenerud import ( "encoding/hex" "fmt" "io/ioutil" "regexp" "runtime" ) // Note: This must be updated with every new Mac OS release. // There is no other reliable way to get the "marketing" name from a mac. var macCodeNames = map[string]string{ // Mininum 10.10 (https://github.com/golang/go/wiki/MinimumRequirements) "10.10": "Yosemite", "10.11": "El Capitan", "10.12": "Sierra", "10.13": "High Sierra", "10.14": "Mojave", "10.15": "Catalina", "10.16": "Big Sur", // Big Sur is both 10.16 and 11.0 "11.0": "Big Sur", // See https://en.wikipedia.org/wiki/MacOS_Big_Sur#Development_history "12.0": "Monterey", } type OSInfo struct { Family string Architecture string ID string Name string Codename string Version string Build string } // GetOSInfo gets information about the current operating system. // The OSInfo object will always be valid, even on error. // If an error occurs, OSInfo will contain at least the Family and Architecture // fields, with a good chance that Name will also contain something. func GetOSInfo() (*OSInfo, error) { // To add support for a new system, create a new getOSInfoXYZ() function and // then add a case statement for its GOOS value, listed here: // https://github.com/golang/go/blob/master/src/go/build/syslist.go // getOSInfoXYZ() guidelines: // * Prefer text files (such as /etc/os-release) or /proc to commands. // * Prefer simple, well established commands (such as uname). // * Any command must work on a pristine system with nothing else installed. // * Always use the full path to a command for security reasons. switch runtime.GOOS { case "windows": return getOSInfoWindows() case "darwin": return getOSInfoMac() case "linux": return getOSInfoLinux() case "freebsd": return getOSInfoFreeBSD() default: return getOSInfoUnknown() } } func readTextFile(path string) (result string, err error) { var bytes []byte bytes, err = ioutil.ReadFile(path) if err == nil { result = string(bytes) } return } func hexToInt(hexString string) (int, error) { if len(hexString) < 3 || hexString[:2] != "0x" { return 0, fmt.Errorf("%v: Not a hex number", hexString) } hexString = hexString[2:] if len(hexString)&1 == 1 { hexString = "0" + hexString } dst := make([]byte, len(hexString)/2) bytesWritten, err := hex.Decode(dst, []byte(hexString)) if err != nil { return 0, err } dst = dst[:bytesWritten] accumulator := 0 for _, b := range dst { accumulator = accumulator<<8 | int(b) } return accumulator, nil } func extractRegistryString(id string, regCommandOutput string) (string, error) { rePortion := `.*\s+REG_\w+\s+(.+)` re := regexp.MustCompile(fmt.Sprintf("%v%v", id, rePortion)) found := re.FindStringSubmatch(regCommandOutput) if len(found) == 0 { return "", fmt.Errorf("Error: Could not parse reg query result: %v", regCommandOutput) } return found[1], nil } func extractRegistryInt(id string, regCommandOutput string) (int, error) { stringValue, err := extractRegistryString(id, regCommandOutput) if err != nil { return 0, err } return hexToInt(stringValue) } func getRegistryRaw(id string) (string, error) { return readCommandOutput(`C:\Windows\system32\reg.exe`, `query`, `HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion`, `/v`, id) } func populateFromRuntime(info *OSInfo) { info.Architecture = runtime.GOARCH info.Family = runtime.GOOS } func parseEtcOSRelease(info *OSInfo, contents string) { keyvalues := parseKeyValues(contents) if v, ok := keyvalues["ID"]; ok && info.ID == "" { info.ID = v } if v, ok := keyvalues["VERSION_ID"]; ok && info.Version == "" { info.Version = v } if v, ok := keyvalues["NAME"]; ok && info.Name == "" { info.Name = v } if v, ok := keyvalues["VERSION_CODENAME"]; ok && info.Codename == "" { info.Codename = v } } func parseEtcLSBRelease(info *OSInfo, contents string) { keyvalues := parseKeyValues(contents) if v, ok := keyvalues["DISTRIB_ID"]; ok && info.ID == "" { info.ID = v } if v, ok := keyvalues["DISTRIB_RELEASE"]; ok && info.Version == "" { info.Version = v } if v, ok := keyvalues["DISTRIB_CODENAME"]; ok && info.Codename == "" { info.Codename = v } if v, ok := keyvalues["DISTRIB_DESCRIPTION"]; ok && info.Name == "" { info.Name = v } } func parseKeyValues(contents string) (kvmap map[string]string) { kvmap = make(map[string]string) re := regexp.MustCompile(`\b(.+)="?([^"\n]*)"?`) for _, found := range re.FindAllStringSubmatch(contents, -1) { kvmap[found[1]] = found[2] } return } func parseMacSWVers(info *OSInfo, productVersion, buildVersion string) error { info.Version = productVersion info.Build = buildVersion re := regexp.MustCompile(`\d+\.\d+`) version := re.FindString(info.Version) if len(version) == 0 { return fmt.Errorf("Could not parse product version [%v]", info.Version) } codeName, ok := macCodeNames[version] if ok { info.Codename = codeName } else { info.Codename = "unknown" } return nil } func parseFreeBSDUname(info *OSInfo, unameV string) error { re := regexp.MustCompile(`(\S+)\s+(\S+)\s+(\S+).*`) found := re.FindStringSubmatch(unameV) if len(found) == 0 { return fmt.Errorf("Error: Could not parse result from uname -v [%v]", unameV) } info.Name = found[1] info.Version = found[2] info.Build = found[3] return nil } func getRegistryString(id string) (string, error) { raw, err := getRegistryRaw(id) if err != nil { return "", err } return extractRegistryString(id, raw) } func getRegistryInt(id string) (int, error) { raw, err := getRegistryRaw(id) if err != nil { return 0, err } return extractRegistryInt(id, raw) } func getOSInfoWindows() (info *OSInfo, err error) { info = new(OSInfo) populateFromRuntime(info) info.ID = "windows" var versionMajor int var versionMinor int // Only Windows 10+ has this versionMinor, err = getRegistryInt("CurrentMinorVersionNumber") versionMajor, err = getRegistryInt("CurrentMajorVersionNumber") if err != nil { err = nil versionMajor = 0 versionMinor = 0 } info.Name, err = getRegistryString("ProductName") if err != nil { return } var servicePack string servicePack, err = getRegistryString("CSDVersion") if err == nil { info.Name = info.Name + " " + servicePack } if versionMajor == 0 { info.Version, err = getRegistryString("CurrentVersion") if err != nil { return } } else { info.Version = fmt.Sprintf("%v.%v", versionMajor, versionMinor) } info.Codename, err = getRegistryString("ReleaseID") if err != nil { info.Codename = "" } info.Build, err = getRegistryString("CurrentBuild") return } func getOSInfoLinux() (info *OSInfo, err error) { info = new(OSInfo) populateFromRuntime(info) var contents string if contents, err = readTextFile("/etc/os-release"); err == nil { parseEtcOSRelease(info, contents) } lastError := err if contents, err = readTextFile("/etc/lsb-release"); err == nil { parseEtcLSBRelease(info, contents) } // Only propagate an error if both files failed to load if lastError == nil { err = nil } return } func getOSInfoFreeBSD() (info *OSInfo, err error) { info = new(OSInfo) populateFromRuntime(info) info.ID = "freebsd" var contents string contents, err = readCommandOutput("/usr/bin/uname", "-v") if err != nil { return } err = parseFreeBSDUname(info, contents) return } func getOSInfoMac() (info *OSInfo, err error) { info = new(OSInfo) populateFromRuntime(info) info.ID = "darwin" info.Name = "Mac OS X" var productVersion string productVersion, err = readCommandOutput("/usr/bin/sw_vers", "-productVersion") if err != nil { return } var buildVersion string buildVersion, err = readCommandOutput("/usr/bin/sw_vers", "-buildVersion") if err != nil { return } err = parseMacSWVers(info, productVersion, buildVersion) return } func getOSInfoUnknown() (info *OSInfo, err error) { info = new(OSInfo) populateFromRuntime(info) info.ID = "unknown" info.Name = "unknown" info.Version = "unknown" // Try to fill with contents of `uname`. var contents string contents, err = readCommandOutput("/usr/bin/uname") if err == nil { info.Name = contents } err = fmt.Errorf("%v: Unhandled OS", runtime.GOOS) return } osinfo-1.0.3/osinfo_defaultos.go000066400000000000000000000004771411312506300167060ustar00rootroot00000000000000// +build !windows package osinfo import ( "os/exec" "strings" ) func readCommandOutput(cmd string, arg ...string) (result string, err error) { command := exec.Command(cmd, arg...) var bytes []byte bytes, err = command.CombinedOutput() if err == nil { result = strings.TrimSpace(string(bytes)) } return } osinfo-1.0.3/osinfo_test.go000066400000000000000000000233301411312506300156700ustar00rootroot00000000000000package osinfo import ( "fmt" "testing" ) func expectEqualStrings(t *testing.T, expected, actual string) { if expected != actual { t.Errorf("Expected [%v] but got [%v]", expected, actual) } } func expectEqualInts(t *testing.T, expected, actual int) { if expected != actual { t.Errorf("Expected [%v] but got [%v]", expected, actual) } } func TestAlpine(t *testing.T) { osRelease := `NAME="Alpine Linux" ID=alpine VERSION_ID=3.8.0 PRETTY_NAME="Alpine Linux v3.8" HOME_URL="http://alpinelinux.org" BUG_REPORT_URL="http://bugs.alpinelinux.org" ` info := new(OSInfo) parseEtcOSRelease(info, osRelease) // Alpine has no /etc/lsb-release expectEqualStrings(t, "alpine", info.ID) expectEqualStrings(t, "3.8.0", info.Version) expectEqualStrings(t, "Alpine Linux", info.Name) expectEqualStrings(t, "", info.Codename) } func TestCentos(t *testing.T) { osRelease := `NAME="CentOS Linux" VERSION="8 (Core)" ID="centos" ID_LIKE="rhel fedora" VERSION_ID="8" PLATFORM_ID="platform:el8" PRETTY_NAME="CentOS Linux 8 (Core)" ANSI_COLOR="0;31" CPE_NAME="cpe:/o:centos:centos:8" HOME_URL="https://www.centos.org/" BUG_REPORT_URL="https://bugs.centos.org/" CENTOS_MANTISBT_PROJECT="CentOS-8" CENTOS_MANTISBT_PROJECT_VERSION="8" REDHAT_SUPPORT_PRODUCT="centos" REDHAT_SUPPORT_PRODUCT_VERSION="8" ` info := new(OSInfo) parseEtcOSRelease(info, osRelease) // CentOS has no /etc/lsb-release expectEqualStrings(t, "centos", info.ID) expectEqualStrings(t, "8", info.Version) expectEqualStrings(t, "CentOS Linux", info.Name) expectEqualStrings(t, "", info.Codename) } func TestDebian(t *testing.T) { osRelease := `PRETTY_NAME="Debian GNU/Linux 9 (stretch)" NAME="Debian GNU/Linux" VERSION_ID="9" VERSION="9 (stretch)" VERSION_CODENAME=stretch ID=debian HOME_URL="https://www.debian.org/" SUPPORT_URL="https://www.debian.org/support" BUG_REPORT_URL="https://bugs.debian.org/" ` info := new(OSInfo) parseEtcOSRelease(info, osRelease) // Debian has no /etc/lsb-release expectEqualStrings(t, "debian", info.ID) expectEqualStrings(t, "9", info.Version) expectEqualStrings(t, "Debian GNU/Linux", info.Name) expectEqualStrings(t, "stretch", info.Codename) } func TestFedora(t *testing.T) { osRelease := `NAME=Fedora VERSION="31 (Container Image)" ID=fedora VERSION_ID=31 VERSION_CODENAME="" PLATFORM_ID="platform:f31" PRETTY_NAME="Fedora 31 (Container Image)" ANSI_COLOR="0;34" LOGO=fedora-logo-icon CPE_NAME="cpe:/o:fedoraproject:fedora:31" HOME_URL="https://fedoraproject.org/" DOCUMENTATION_URL="https://docs.fedoraproject.org/en-US/fedora/f31/system-administrators-guide/" SUPPORT_URL="https://fedoraproject.org/wiki/Communicating_and_getting_help" BUG_REPORT_URL="https://bugzilla.redhat.com/" REDHAT_BUGZILLA_PRODUCT="Fedora" REDHAT_BUGZILLA_PRODUCT_VERSION=31 REDHAT_SUPPORT_PRODUCT="Fedora" REDHAT_SUPPORT_PRODUCT_VERSION=31 PRIVACY_POLICY_URL="https://fedoraproject.org/wiki/Legal:PrivacyPolicy" VARIANT="Container Image" VARIANT_ID=container ` info := new(OSInfo) parseEtcOSRelease(info, osRelease) // Fedora has no /etc/lsb-release expectEqualStrings(t, "fedora", info.ID) expectEqualStrings(t, "31", info.Version) expectEqualStrings(t, "Fedora", info.Name) expectEqualStrings(t, "", info.Codename) } func TestGentoo(t *testing.T) { osRelease := `NAME=Gentoo ID=gentoo PRETTY_NAME="Gentoo/Linux" ANSI_COLOR="1;32" HOME_URL="https://www.gentoo.org/" SUPPORT_URL="https://www.gentoo.org/support/" BUG_REPORT_URL="https://bugs.gentoo.org/" ` info := new(OSInfo) parseEtcOSRelease(info, osRelease) // Gentoo has no /etc/lsb-release expectEqualStrings(t, "gentoo", info.ID) expectEqualStrings(t, "", info.Version) expectEqualStrings(t, "Gentoo", info.Name) expectEqualStrings(t, "", info.Codename) } func TestKali(t *testing.T) { osRelease := `PRETTY_NAME="Kali GNU/Linux Rolling" NAME="Kali GNU/Linux" ID=kali VERSION="2020.2" VERSION_ID="2020.2" VERSION_CODENAME="kali-rolling" ID_LIKE=debian ANSI_COLOR="1;31" HOME_URL="https://www.kali.org/" SUPPORT_URL="https://forums.kali.org/" BUG_REPORT_URL="https://bugs.kali.org/" ` info := new(OSInfo) parseEtcOSRelease(info, osRelease) // Kali has no /etc/lsb-release expectEqualStrings(t, "kali", info.ID) expectEqualStrings(t, "2020.2", info.Version) expectEqualStrings(t, "Kali GNU/Linux", info.Name) expectEqualStrings(t, "kali-rolling", info.Codename) } func TestManjaro(t *testing.T) { osRelease := `NAME="Manjaro Linux" ID=manjaro ID_LIKE=arch PRETTY_NAME="Manjaro Linux" ANSI_COLOR="1;32" HOME_URL="https://www.manjaro.org/" SUPPORT_URL="https://www.manjaro.org/" BUG_REPORT_URL="https://bugs.manjaro.org/" LOGO=manjarolinux ` lsbRelease := `DISTRIB_ID=ManjaroLinux DISTRIB_RELEASE=19.0.2 DISTRIB_CODENAME=Kyria DISTRIB_DESCRIPTION="Manjaro Linux" ` info := new(OSInfo) parseEtcOSRelease(info, osRelease) parseEtcLSBRelease(info, lsbRelease) expectEqualStrings(t, "manjaro", info.ID) expectEqualStrings(t, "19.0.2", info.Version) expectEqualStrings(t, "Manjaro Linux", info.Name) expectEqualStrings(t, "Kyria", info.Codename) } func TestOpenSUSE(t *testing.T) { osRelease := `NAME="openSUSE Leap" VERSION="15.1" ID="opensuse-leap" ID_LIKE="suse opensuse" VERSION_ID="15.1" PRETTY_NAME="openSUSE Leap 15.1" ANSI_COLOR="0;32" CPE_NAME="cpe:/o:opensuse:leap:15.1" BUG_REPORT_URL="https://bugs.opensuse.org" HOME_URL="https://www.opensuse.org/" ` info := new(OSInfo) parseEtcOSRelease(info, osRelease) // OpenSUSE has no /etc/lsb-release expectEqualStrings(t, "opensuse-leap", info.ID) expectEqualStrings(t, "15.1", info.Version) expectEqualStrings(t, "openSUSE Leap", info.Name) expectEqualStrings(t, "", info.Codename) } func TestOracle(t *testing.T) { osRelease := `NAME="Oracle Linux Server" VERSION="8.1" ID="ol" ID_LIKE="fedora" VARIANT="Server" VARIANT_ID="server" VERSION_ID="8.1" PLATFORM_ID="platform:el8" PRETTY_NAME="Oracle Linux Server 8.1" ANSI_COLOR="0;31" CPE_NAME="cpe:/o:oracle:linux:8:1:server" HOME_URL="https://linux.oracle.com/" BUG_REPORT_URL="https://bugzilla.oracle.com/" ORACLE_BUGZILLA_PRODUCT="Oracle Linux 8" ORACLE_BUGZILLA_PRODUCT_VERSION=8.1 ORACLE_SUPPORT_PRODUCT="Oracle Linux" ORACLE_SUPPORT_PRODUCT_VERSION=8.1 ` info := new(OSInfo) parseEtcOSRelease(info, osRelease) // Oracle has no /etc/lsb-release expectEqualStrings(t, "ol", info.ID) expectEqualStrings(t, "8.1", info.Version) expectEqualStrings(t, "Oracle Linux Server", info.Name) expectEqualStrings(t, "", info.Codename) } func TestUbuntu(t *testing.T) { osRelease := `NAME="Ubuntu" VERSION="19.10 (Eoan Ermine)" ID=ubuntu ID_LIKE=debian PRETTY_NAME="Ubuntu 19.10" VERSION_ID="19.10" HOME_URL="https://www.ubuntu.com/" SUPPORT_URL="https://help.ubuntu.com/" BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/" PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy" VERSION_CODENAME=eoan UBUNTU_CODENAME=eoan ` lsbRelease := `DISTRIB_ID=Ubuntu DISTRIB_RELEASE=19.10 DISTRIB_CODENAME=eoan DISTRIB_DESCRIPTION="Ubuntu 19.10" ` info := new(OSInfo) parseEtcOSRelease(info, osRelease) parseEtcLSBRelease(info, lsbRelease) expectEqualStrings(t, "ubuntu", info.ID) expectEqualStrings(t, "19.10", info.Version) expectEqualStrings(t, "Ubuntu", info.Name) expectEqualStrings(t, "eoan", info.Codename) } func TestMacOSSierra(t *testing.T) { info := new(OSInfo) productVersion := "10.12.6" buildVersion := "16G1815" err := parseMacSWVers(info, productVersion, buildVersion) if err != nil { t.Error(err) } expectEqualStrings(t, "10.12.6", info.Version) expectEqualStrings(t, "Sierra", info.Codename) expectEqualStrings(t, "16G1815", info.Build) } func TestFreeBSD(t *testing.T) { info := new(OSInfo) unameV := "FreeBSD 12.0-RELEASE r341666 GENERIC" err := parseFreeBSDUname(info, unameV) if err != nil { t.Error(err) } expectEqualStrings(t, "12.0-RELEASE", info.Version) expectEqualStrings(t, "r341666", info.Build) expectEqualStrings(t, "FreeBSD", info.Name) } func expectRegistryString(t *testing.T, expected string, id string, regOutput string) { result, err := extractRegistryString(id, regOutput) if err != nil { t.Error(err) } expectEqualStrings(t, expected, result) } func expectRegistryInt(t *testing.T, expected int, id string, regOutput string) { result, err := extractRegistryInt(id, regOutput) if err != nil { t.Error(err) } expectEqualInts(t, expected, result) } func TestWindowsExtractProductName(t *testing.T) { expectRegistryString(t, "Windows 10 Pro", "ProductName", ` HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion ProductName REG_SZ Windows 10 Pro `) } func TestWindowsExtractCurrentVersion(t *testing.T) { expectRegistryString(t, "6.3", "CurrentVersion", ` HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion CurrentVersion REG_SZ 6.3 `) } func TestWindowsExtractMajorVersion(t *testing.T) { expectRegistryInt(t, 10, "CurrentMajorVersionNumber", ` HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion CurrentMajorVersionNumber REG_DWORD 0xa `) } func TestWindowsExtractMinorVersion(t *testing.T) { expectRegistryInt(t, 0, "CurrentMinorVersionNumber", ` HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion CurrentMinorVersionNumber REG_DWORD 0x0 `) } func TestWindowsExtractCurrentBuild(t *testing.T) { expectRegistryString(t, "18362", "CurrentBuild", ` HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion CurrentBuild REG_SZ 18362 `) } func TestDemonstrate(t *testing.T) { info, err := GetOSInfo() if err != nil { t.Errorf("Error while getting OS info: %v", err) } fmt.Printf("Family: %v\n", info.Family) fmt.Printf("Architecture: %v\n", info.Architecture) fmt.Printf("ID: %v\n", info.ID) fmt.Printf("Name: %v\n", info.Name) fmt.Printf("Codename: %v\n", info.Codename) fmt.Printf("Version: %v\n", info.Version) fmt.Printf("Build: %v\n", info.Build) } osinfo-1.0.3/osinfo_windows.go000066400000000000000000000006411411312506300164030ustar00rootroot00000000000000package osinfo import ( "fmt" "os/exec" "strings" ) func readCommandOutput(cmd string, arg ...string) (result string, err error) { command := exec.Command(cmd, arg...) var bytes []byte bytes, err = command.CombinedOutput() if err == nil { result = strings.TrimSpace(string(bytes)) } else { if len(bytes) > 0 && err.Error() == "exit status 1" { err = fmt.Errorf("%v", string(bytes)) } } return }