|
|
|
@ -9,7 +9,6 @@ package hostinfo |
|
|
|
|
|
|
|
|
|
|
|
import ( |
|
|
|
import ( |
|
|
|
"bytes" |
|
|
|
"bytes" |
|
|
|
"fmt" |
|
|
|
|
|
|
|
"io/ioutil" |
|
|
|
"io/ioutil" |
|
|
|
"os" |
|
|
|
"os" |
|
|
|
"strings" |
|
|
|
"strings" |
|
|
|
@ -21,14 +20,39 @@ import ( |
|
|
|
) |
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
func init() { |
|
|
|
func init() { |
|
|
|
osVersion = osVersionLinux |
|
|
|
osVersion = lazyOSVersion.Get |
|
|
|
packageType = packageTypeLinux |
|
|
|
packageType = packageTypeLinux |
|
|
|
|
|
|
|
distroName = distroNameLinux |
|
|
|
|
|
|
|
distroVersion = distroVersionLinux |
|
|
|
|
|
|
|
distroCodeName = distroCodeNameLinux |
|
|
|
if v := linuxDeviceModel(); v != "" { |
|
|
|
if v := linuxDeviceModel(); v != "" { |
|
|
|
SetDeviceModel(v) |
|
|
|
SetDeviceModel(v) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var ( |
|
|
|
|
|
|
|
lazyVersionMeta = &lazyAtomicValue[versionMeta]{f: ptrTo(linuxVersionMeta)} |
|
|
|
|
|
|
|
lazyOSVersion = &lazyAtomicValue[string]{f: ptrTo(osVersionLinux)} |
|
|
|
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
type versionMeta struct { |
|
|
|
|
|
|
|
DistroName string |
|
|
|
|
|
|
|
DistroVersion string |
|
|
|
|
|
|
|
DistroCodeName string // "jammy", etc (VERSION_CODENAME from /etc/os-release)
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func distroNameLinux() string { |
|
|
|
|
|
|
|
return lazyVersionMeta.Get().DistroName |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func distroVersionLinux() string { |
|
|
|
|
|
|
|
return lazyVersionMeta.Get().DistroVersion |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func distroCodeNameLinux() string { |
|
|
|
|
|
|
|
return lazyVersionMeta.Get().DistroCodeName |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func linuxDeviceModel() string { |
|
|
|
func linuxDeviceModel() string { |
|
|
|
for _, path := range []string{ |
|
|
|
for _, path := range []string{ |
|
|
|
// First try the Synology-specific location.
|
|
|
|
// First try the Synology-specific location.
|
|
|
|
@ -52,15 +76,22 @@ func linuxDeviceModel() string { |
|
|
|
func getQnapQtsVersion(versionInfo string) string { |
|
|
|
func getQnapQtsVersion(versionInfo string) string { |
|
|
|
for _, field := range strings.Fields(versionInfo) { |
|
|
|
for _, field := range strings.Fields(versionInfo) { |
|
|
|
if suffix, ok := strs.CutPrefix(field, "QTSFW_"); ok { |
|
|
|
if suffix, ok := strs.CutPrefix(field, "QTSFW_"); ok { |
|
|
|
return "QTS " + suffix |
|
|
|
return suffix |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
return "" |
|
|
|
return "" |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func osVersionLinux() string { |
|
|
|
func osVersionLinux() string { |
|
|
|
// TODO(bradfitz,dgentry): cache this, or make caller(s) cache it.
|
|
|
|
var un unix.Utsname |
|
|
|
|
|
|
|
unix.Uname(&un) |
|
|
|
|
|
|
|
return unix.ByteSliceToString(un.Release[:]) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func linuxVersionMeta() (meta versionMeta) { |
|
|
|
dist := distro.Get() |
|
|
|
dist := distro.Get() |
|
|
|
|
|
|
|
meta.DistroName = string(dist) |
|
|
|
|
|
|
|
|
|
|
|
propFile := "/etc/os-release" |
|
|
|
propFile := "/etc/os-release" |
|
|
|
switch dist { |
|
|
|
switch dist { |
|
|
|
case distro.Synology: |
|
|
|
case distro.Synology: |
|
|
|
@ -69,10 +100,12 @@ func osVersionLinux() string { |
|
|
|
propFile = "/etc/openwrt_release" |
|
|
|
propFile = "/etc/openwrt_release" |
|
|
|
case distro.WDMyCloud: |
|
|
|
case distro.WDMyCloud: |
|
|
|
slurp, _ := ioutil.ReadFile("/etc/version") |
|
|
|
slurp, _ := ioutil.ReadFile("/etc/version") |
|
|
|
return fmt.Sprintf("%s", string(bytes.TrimSpace(slurp))) |
|
|
|
meta.DistroVersion = string(bytes.TrimSpace(slurp)) |
|
|
|
|
|
|
|
return |
|
|
|
case distro.QNAP: |
|
|
|
case distro.QNAP: |
|
|
|
slurp, _ := ioutil.ReadFile("/etc/version_info") |
|
|
|
slurp, _ := ioutil.ReadFile("/etc/version_info") |
|
|
|
return getQnapQtsVersion(string(slurp)) |
|
|
|
meta.DistroVersion = getQnapQtsVersion(string(slurp)) |
|
|
|
|
|
|
|
return |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
m := map[string]string{} |
|
|
|
m := map[string]string{} |
|
|
|
@ -86,50 +119,45 @@ func osVersionLinux() string { |
|
|
|
return nil |
|
|
|
return nil |
|
|
|
}) |
|
|
|
}) |
|
|
|
|
|
|
|
|
|
|
|
var un unix.Utsname |
|
|
|
if v := m["VERSION_CODENAME"]; v != "" { |
|
|
|
unix.Uname(&un) |
|
|
|
meta.DistroCodeName = v |
|
|
|
|
|
|
|
|
|
|
|
var attrBuf strings.Builder |
|
|
|
|
|
|
|
attrBuf.WriteString("; kernel=") |
|
|
|
|
|
|
|
attrBuf.WriteString(unix.ByteSliceToString(un.Release[:])) |
|
|
|
|
|
|
|
if inContainer() { |
|
|
|
|
|
|
|
attrBuf.WriteString("; container") |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
if env := GetEnvType(); env != "" { |
|
|
|
if v := m["VERSION_ID"]; v != "" { |
|
|
|
fmt.Fprintf(&attrBuf, "; env=%s", env) |
|
|
|
meta.DistroVersion = v |
|
|
|
} |
|
|
|
} |
|
|
|
attr := attrBuf.String() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
id := m["ID"] |
|
|
|
id := m["ID"] |
|
|
|
|
|
|
|
if id != "" { |
|
|
|
|
|
|
|
meta.DistroName = id |
|
|
|
|
|
|
|
} |
|
|
|
switch id { |
|
|
|
switch id { |
|
|
|
case "debian": |
|
|
|
case "debian": |
|
|
|
|
|
|
|
// Debian's VERSION_ID is just like "11". But /etc/debian_version has "11.5" normally.
|
|
|
|
|
|
|
|
// Or "bookworm/sid" on sid/testing.
|
|
|
|
slurp, _ := ioutil.ReadFile("/etc/debian_version") |
|
|
|
slurp, _ := ioutil.ReadFile("/etc/debian_version") |
|
|
|
return fmt.Sprintf("Debian %s (%s)%s", bytes.TrimSpace(slurp), m["VERSION_CODENAME"], attr) |
|
|
|
if v := string(bytes.TrimSpace(slurp)); v != "" { |
|
|
|
case "ubuntu": |
|
|
|
if '0' <= v[0] && v[0] <= '9' { |
|
|
|
return fmt.Sprintf("Ubuntu %s%s", m["VERSION"], attr) |
|
|
|
meta.DistroVersion = v |
|
|
|
case "", "centos": // CentOS 6 has no /etc/os-release, so its id is ""
|
|
|
|
} else if meta.DistroCodeName == "" { |
|
|
|
if cr, _ := ioutil.ReadFile("/etc/centos-release"); len(cr) > 0 { // "CentOS release 6.10 (Final)
|
|
|
|
meta.DistroCodeName = v |
|
|
|
return fmt.Sprintf("%s%s", bytes.TrimSpace(cr), attr) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
fallthrough |
|
|
|
case "", "centos": // CentOS 6 has no /etc/os-release, so its id is ""
|
|
|
|
case "fedora", "rhel", "alpine", "nixos": |
|
|
|
if meta.DistroVersion == "" { |
|
|
|
// Their PRETTY_NAME is fine as-is for all versions I tested.
|
|
|
|
if cr, _ := ioutil.ReadFile("/etc/centos-release"); len(cr) > 0 { // "CentOS release 6.10 (Final)
|
|
|
|
fallthrough |
|
|
|
meta.DistroVersion = string(bytes.TrimSpace(cr)) |
|
|
|
default: |
|
|
|
} |
|
|
|
if v := m["PRETTY_NAME"]; v != "" { |
|
|
|
|
|
|
|
return fmt.Sprintf("%s%s", v, attr) |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if v := m["PRETTY_NAME"]; v != "" && meta.DistroVersion == "" && !strings.HasSuffix(v, "/sid") { |
|
|
|
|
|
|
|
meta.DistroVersion = v |
|
|
|
|
|
|
|
} |
|
|
|
switch dist { |
|
|
|
switch dist { |
|
|
|
case distro.Synology: |
|
|
|
case distro.Synology: |
|
|
|
return fmt.Sprintf("Synology %s%s", m["productversion"], attr) |
|
|
|
meta.DistroVersion = m["productversion"] |
|
|
|
case distro.OpenWrt: |
|
|
|
case distro.OpenWrt: |
|
|
|
return fmt.Sprintf("OpenWrt %s%s", m["DISTRIB_RELEASE"], attr) |
|
|
|
meta.DistroVersion = m["DISTRIB_RELEASE"] |
|
|
|
case distro.Gokrazy: |
|
|
|
|
|
|
|
return fmt.Sprintf("Gokrazy%s", attr) |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
return fmt.Sprintf("Other%s", attr) |
|
|
|
return |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func packageTypeLinux() string { |
|
|
|
func packageTypeLinux() string { |
|
|
|
|