From 4bf185067dfdaedade4d07b259b4741fb66eb000 Mon Sep 17 00:00:00 2001 From: Lomanic Date: Wed, 7 Aug 2019 23:59:43 +0200 Subject: [PATCH] [host] Fix #737 add KernelArch field in InfoStat struct returning 'uname -m' result --- host/host.go | 1 + host/host_darwin.go | 5 +++++ host/host_freebsd.go | 5 +++++ host/host_linux.go | 5 +++++ host/host_openbsd.go | 5 +++++ host/host_posix.go | 13 +++++++++++++ host/host_solaris.go | 5 +++++ host/host_windows.go | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 93 insertions(+) create mode 100644 host/host_posix.go diff --git a/host/host.go b/host/host.go index 1e9e9bb..e100bc5 100644 --- a/host/host.go +++ b/host/host.go @@ -20,6 +20,7 @@ type InfoStat struct { PlatformFamily string `json:"platformFamily"` // ex: debian, rhel PlatformVersion string `json:"platformVersion"` // version of the complete OS KernelVersion string `json:"kernelVersion"` // version of the OS kernel (if available) + KernelArch string `json:"kernelArch"` // native cpu architecture queried at runtime, as returned by `uname -m` or empty string in case of error VirtualizationSystem string `json:"virtualizationSystem"` VirtualizationRole string `json:"virtualizationRole"` // guest or host HostID string `json:"hostid"` // ex: uuid diff --git a/host/host_darwin.go b/host/host_darwin.go index de8277f..d40457c 100644 --- a/host/host_darwin.go +++ b/host/host_darwin.go @@ -43,6 +43,11 @@ func InfoWithContext(ctx context.Context) (*InfoStat, error) { ret.KernelVersion = kernelVersion } + kernelArch, err := kernelArch() + if err == nil { + ret.KernelArch = kernelArch + } + platform, family, pver, err := PlatformInformation() if err == nil { ret.Platform = platform diff --git a/host/host_freebsd.go b/host/host_freebsd.go index 9cf654e..6dc4bc1 100644 --- a/host/host_freebsd.go +++ b/host/host_freebsd.go @@ -50,6 +50,11 @@ func InfoWithContext(ctx context.Context) (*InfoStat, error) { ret.KernelVersion = version } + kernelArch, err := kernelArch() + if err == nil { + ret.KernelArch = kernelArch + } + system, role, err := Virtualization() if err == nil { ret.VirtualizationSystem = system diff --git a/host/host_linux.go b/host/host_linux.go index 02ff554..0d1dabd 100644 --- a/host/host_linux.go +++ b/host/host_linux.go @@ -55,6 +55,11 @@ func InfoWithContext(ctx context.Context) (*InfoStat, error) { ret.KernelVersion = kernelVersion } + kernelArch, err := kernelArch() + if err == nil { + ret.KernelArch = kernelArch + } + system, role, err := Virtualization() if err == nil { ret.VirtualizationSystem = system diff --git a/host/host_openbsd.go b/host/host_openbsd.go index 90d1fd3..d1501e9 100644 --- a/host/host_openbsd.go +++ b/host/host_openbsd.go @@ -40,6 +40,11 @@ func InfoWithContext(ctx context.Context) (*InfoStat, error) { ret.Hostname = hostname } + kernelArch, err := kernelArch() + if err == nil { + ret.KernelArch = kernelArch + } + platform, family, version, err := PlatformInformation() if err == nil { ret.Platform = platform diff --git a/host/host_posix.go b/host/host_posix.go new file mode 100644 index 0000000..a16e5a1 --- /dev/null +++ b/host/host_posix.go @@ -0,0 +1,13 @@ +// +build linux freebsd openbsd darwin solaris + +package host + +import ( + "golang.org/x/sys/unix" +) + +func kernelArch() (string, error) { + var utsname unix.Utsname + err := unix.Uname(&utsname) + return string(utsname.Machine[:]), err +} diff --git a/host/host_solaris.go b/host/host_solaris.go index f3c7ad6..c6061b8 100644 --- a/host/host_solaris.go +++ b/host/host_solaris.go @@ -54,6 +54,11 @@ func InfoWithContext(ctx context.Context) (*InfoStat, error) { result.PlatformVersion = fields[2] } + kernelArch, err := kernelArch() + if err == nil { + result.KernelArch = kernelArch + } + // Find distribution name from /etc/release fh, err := os.Open("/etc/release") if err != nil { diff --git a/host/host_windows.go b/host/host_windows.go index 512b63c..f9e1a16 100644 --- a/host/host_windows.go +++ b/host/host_windows.go @@ -24,6 +24,7 @@ var ( procGetSystemTimeAsFileTime = common.Modkernel32.NewProc("GetSystemTimeAsFileTime") procGetTickCount32 = common.Modkernel32.NewProc("GetTickCount") procGetTickCount64 = common.Modkernel32.NewProc("GetTickCount64") + procGetNativeSystemInfo = common.Modkernel32.NewProc("GetNativeSystemInfo") procRtlGetVersion = common.ModNt.NewProc("RtlGetVersion") ) @@ -42,6 +43,20 @@ type osVersionInfoExW struct { wReserved uint8 } +type systemInfo struct { + wProcessorArchitecture uint16 + wReserved uint16 + dwPageSize uint32 + lpMinimumApplicationAddress uintptr + lpMaximumApplicationAddress uintptr + dwActiveProcessorMask uintptr + dwNumberOfProcessors uint32 + dwProcessorType uint32 + dwAllocationGranularity uint32 + wProcessorLevel uint16 + wProcessorRevision uint16 +} + type msAcpi_ThermalZoneTemperature struct { Active bool CriticalTripPoint uint32 @@ -77,6 +92,13 @@ func InfoWithContext(ctx context.Context) (*InfoStat, error) { } { + kernelArch, err := kernelArch() + if err == nil { + ret.KernelArch = kernelArch + } + } + + { boot, err := BootTimeWithContext(ctx) if err == nil { ret.BootTime = boot @@ -293,3 +315,35 @@ func KernelVersionWithContext(ctx context.Context) (string, error) { _, _, version, err := PlatformInformation() return version, err } + +func kernelArch() (string, error) { + var systemInfo systemInfo + procGetNativeSystemInfo.Call(uintptr(unsafe.Pointer(&systemInfo))) + + const ( + PROCESSOR_ARCHITECTURE_INTEL = 0 + PROCESSOR_ARCHITECTURE_ARM = 5 + PROCESSOR_ARCHITECTURE_ARM64 = 12 + PROCESSOR_ARCHITECTURE_IA64 = 6 + PROCESSOR_ARCHITECTURE_AMD64 = 9 + ) + switch systemInfo.wProcessorArchitecture { + case PROCESSOR_ARCHITECTURE_INTEL: + if systemInfo.wProcessorLevel < 3 { + return "i386", nil + } + if systemInfo.wProcessorLevel > 6 { + return "i686", nil + } + return fmt.Sprintf("i%d86", systemInfo.wProcessorLevel), nil + case PROCESSOR_ARCHITECTURE_ARM: + return "arm", nil + case PROCESSOR_ARCHITECTURE_ARM64: + return "aarch64", nil + case PROCESSOR_ARCHITECTURE_IA64: + return "ia64", nil + case PROCESSOR_ARCHITECTURE_AMD64: + return "x86_64", nil + } + return "", nil +}