@@ -19,9 +19,19 @@ package linux
1919
2020import (
2121"fmt"
22+ "os"
23+ "strings"
2224"syscall"
2325)
2426
27+ const (
28+ procSysKernelArch = "/proc/sys/kernel/arch"
29+ procVersion = "/proc/version"
30+ archAmd64 = "amd64"
31+ archArm64 = "arm64"
32+ archAarch64 = "aarch64"
33+ )
34+
2535func Architecture () (string , error ) {
2636var uname syscall.Utsname
2737if err := syscall .Uname (& uname ); err != nil {
@@ -38,3 +48,38 @@ func Architecture() (string, error) {
3848
3949return string (data ), nil
4050}
51+
52+ func NativeArchitecture () (string , error ) {
53+ // /proc/sys/kernel/arch was introduced in Kernel 6.1
54+ // https://www.kernel.org/doc/html/v6.1/admin-guide/sysctl/kernel.html#arch
55+ // It's the same as uname -m, except that for a process running in emulation
56+ // machine returned from syscall reflects the emulated machine, whilst /proc
57+ // filesystem is read as file so its value is not emulated
58+ data , err := os .ReadFile (procSysKernelArch )
59+ if err != nil {
60+ if os .IsNotExist (err ) {
61+ // fallback to checking version string for older kernels
62+ version , err := os .ReadFile (procVersion )
63+ if err != nil {
64+ return "" , nil
65+ }
66+
67+ versionStr := string (version )
68+ if strings .Contains (versionStr , archAmd64 ) {
69+ return archAmd64 , nil
70+ } else if strings .Contains (versionStr , archArm64 ) {
71+ // for parity with Architecture() and /proc/sys/kernel/arch
72+ // as aarch64 and arm64 are used interchangeably
73+ return archAarch64 , nil
74+ }
75+ return "" , nil
76+ }
77+
78+ return "" , fmt .Errorf ("failed to read kernel arch: %w" , err )
79+ }
80+
81+ nativeArch := string (data )
82+ nativeArch = strings .TrimRight (nativeArch , "\n " )
83+
84+ return string (data ), nil
85+ }
0 commit comments