github.com/isyscore/isc-gobase@v1.5.3-0.20231218061332-cbc7451899e9/system/host/host_darwin.go (about) 1 //go:build darwin 2 3 package host 4 5 import ( 6 "bytes" 7 "context" 8 "encoding/binary" 9 "errors" 10 "github.com/isyscore/isc-gobase/system/common" 11 "github.com/isyscore/isc-gobase/system/process" 12 "golang.org/x/sys/unix" 13 "io" 14 "os" 15 "os/exec" 16 "strings" 17 "unsafe" 18 ) 19 20 // USER_PROCESS from tmpl.h 21 const USER_PROCESS = 7 22 23 func HostIDWithContext(ctx context.Context) (string, error) { 24 ioreg, err := exec.LookPath("ioreg") 25 if err != nil { 26 return "", err 27 } 28 29 out, err := invoke.CommandWithContext(ctx, ioreg, "-rd1", "-c", "IOPlatformExpertDevice") 30 if err != nil { 31 return "", err 32 } 33 34 for _, line := range strings.Split(string(out), "\n") { 35 if strings.Contains(line, "IOPlatformUUID") { 36 parts := strings.SplitAfter(line, `" = "`) 37 if len(parts) == 2 { 38 uuid := strings.TrimRight(parts[1], `"`) 39 return strings.ToLower(uuid), nil 40 } 41 } 42 } 43 44 return "", errors.New("cannot find host id") 45 } 46 47 func numProcs(ctx context.Context) (uint64, error) { 48 procs, err := process.PidsWithContext(ctx) 49 if err != nil { 50 return 0, err 51 } 52 return uint64(len(procs)), nil 53 } 54 55 func UsersWithContext(ctx context.Context) ([]UserStat, error) { 56 utmpfile := "/var/run/utmpx" 57 var ret []UserStat 58 59 file, err := os.Open(utmpfile) 60 if err != nil { 61 return ret, err 62 } 63 defer func(file *os.File) { 64 _ = file.Close() 65 }(file) 66 67 buf, err := io.ReadAll(file) 68 if err != nil { 69 return ret, err 70 } 71 72 u := Utmpx{} 73 entrySize := int(unsafe.Sizeof(u)) 74 count := len(buf) / entrySize 75 76 for i := 0; i < count; i++ { 77 b := buf[i*entrySize : i*entrySize+entrySize] 78 79 var u Utmpx 80 br := bytes.NewReader(b) 81 err := binary.Read(br, binary.LittleEndian, &u) 82 if err != nil { 83 continue 84 } 85 if u.Type != USER_PROCESS { 86 continue 87 } 88 user := UserStat{ 89 User: common.IntToString(u.User[:]), 90 Terminal: common.IntToString(u.Line[:]), 91 Host: common.IntToString(u.Host[:]), 92 Started: int(u.Tv.Sec), 93 } 94 ret = append(ret, user) 95 } 96 97 return ret, nil 98 99 } 100 101 func PlatformInformationWithContext(ctx context.Context) (string, string, string, error) { 102 platform := "" 103 family := "" 104 pver := "" 105 106 sw_vers, err := exec.LookPath("sw_vers") 107 if err != nil { 108 return "", "", "", err 109 } 110 111 p, err := unix.Sysctl("kern.ostype") 112 if err == nil { 113 platform = strings.ToLower(p) 114 } 115 116 out, err := invoke.CommandWithContext(ctx, sw_vers, "-productVersion") 117 if err == nil { 118 pver = strings.ToLower(strings.TrimSpace(string(out))) 119 } 120 121 // check if the macos server version file exists 122 _, err = os.Stat("/System/Library/CoreServices/ServerVersion.plist") 123 124 // server file doesn't exist 125 if os.IsNotExist(err) { 126 family = "Standalone Workstation" 127 } else { 128 family = "Server" 129 } 130 131 return platform, family, pver, nil 132 } 133 134 func VirtualizationWithContext(ctx context.Context) (string, string, error) { 135 return "", "", common.ErrNotImplementedError 136 } 137 138 func KernelVersionWithContext(ctx context.Context) (string, error) { 139 version, err := unix.Sysctl("kern.osrelease") 140 return strings.ToLower(version), err 141 }