From 98c779765ff887604786e139d7cda986aac516a4 Mon Sep 17 00:00:00 2001
From: Lomanic <Lomanic@users.noreply.github.com>
Date: Wed, 7 Aug 2019 22:34:36 +0200
Subject: [PATCH 1/2] [host] go-fmt and propagate context on Windows in Info()

---
 host/host_windows.go | 8 ++++----
 host/types.go        | 4 ++--
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/host/host_windows.go b/host/host_windows.go
index d89e191..512b63c 100644
--- a/host/host_windows.go
+++ b/host/host_windows.go
@@ -77,7 +77,7 @@ func InfoWithContext(ctx context.Context) (*InfoStat, error) {
 	}
 
 	{
-		boot, err := BootTime()
+		boot, err := BootTimeWithContext(ctx)
 		if err == nil {
 			ret.BootTime = boot
 			ret.Uptime, _ = Uptime()
@@ -87,12 +87,12 @@ func InfoWithContext(ctx context.Context) (*InfoStat, error) {
 	{
 		hostID, err := getMachineGuid()
 		if err == nil {
-			ret.HostID = strings.ToLower(hostID)
+			ret.HostID = hostID
 		}
 	}
 
 	{
-		procs, err := process.Pids()
+		procs, err := process.PidsWithContext(ctx)
 		if err == nil {
 			ret.Procs = uint64(len(procs))
 		}
@@ -128,7 +128,7 @@ func getMachineGuid() (string, error) {
 		return "", fmt.Errorf("HostID incorrect: %q\n", hostID)
 	}
 
-	return hostID, nil
+	return strings.ToLower(hostID), nil
 }
 
 func Uptime() (uint64, error) {
diff --git a/host/types.go b/host/types.go
index 1766e7e..1eff475 100644
--- a/host/types.go
+++ b/host/types.go
@@ -5,7 +5,7 @@ import (
 )
 
 type Warnings struct {
-    List []error
+	List []error
 }
 
 func (w *Warnings) Add(err error) {
@@ -21,5 +21,5 @@ func (w *Warnings) Reference() error {
 }
 
 func (w *Warnings) Error() string {
-    return fmt.Sprintf("Number of warnings: %v", len(w.List))
+	return fmt.Sprintf("Number of warnings: %v", len(w.List))
 }

From 4bf185067dfdaedade4d07b259b4741fb66eb000 Mon Sep 17 00:00:00 2001
From: Lomanic <Lomanic@users.noreply.github.com>
Date: Wed, 7 Aug 2019 23:59:43 +0200
Subject: [PATCH 2/2] [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
+}