1// +build freebsd 2 3package host 4 5import ( 6 "bytes" 7 "context" 8 "encoding/binary" 9 "io/ioutil" 10 "math" 11 "os" 12 "strings" 13 "unsafe" 14 15 "github.com/shirou/gopsutil/v3/internal/common" 16 "github.com/shirou/gopsutil/v3/process" 17 "golang.org/x/sys/unix" 18) 19 20const ( 21 UTNameSize = 16 /* see MAXLOGNAME in <sys/param.h> */ 22 UTLineSize = 8 23 UTHostSize = 16 24) 25 26func HostIDWithContext(ctx context.Context) (string, error) { 27 uuid, err := unix.Sysctl("kern.hostuuid") 28 if err != nil { 29 return "", err 30 } 31 return strings.ToLower(uuid), err 32} 33 34func numProcs(ctx context.Context) (uint64, error) { 35 procs, err := process.PidsWithContext(ctx) 36 if err != nil { 37 return 0, err 38 } 39 return uint64(len(procs)), nil 40} 41 42func UsersWithContext(ctx context.Context) ([]UserStat, error) { 43 utmpfile := "/var/run/utx.active" 44 if !common.PathExists(utmpfile) { 45 utmpfile = "/var/run/utmp" // before 9.0 46 return getUsersFromUtmp(utmpfile) 47 } 48 49 var ret []UserStat 50 file, err := os.Open(utmpfile) 51 if err != nil { 52 return ret, err 53 } 54 defer file.Close() 55 56 buf, err := ioutil.ReadAll(file) 57 if err != nil { 58 return ret, err 59 } 60 61 entrySize := sizeOfUtmpx 62 count := len(buf) / entrySize 63 64 for i := 0; i < count; i++ { 65 b := buf[i*sizeOfUtmpx : (i+1)*sizeOfUtmpx] 66 var u Utmpx 67 br := bytes.NewReader(b) 68 err := binary.Read(br, binary.BigEndian, &u) 69 if err != nil || u.Type != 4 { 70 continue 71 } 72 sec := math.Floor(float64(u.Tv) / 1000000) 73 user := UserStat{ 74 User: common.IntToString(u.User[:]), 75 Terminal: common.IntToString(u.Line[:]), 76 Host: common.IntToString(u.Host[:]), 77 Started: int(sec), 78 } 79 80 ret = append(ret, user) 81 } 82 83 return ret, nil 84 85} 86 87func PlatformInformationWithContext(ctx context.Context) (string, string, string, error) { 88 platform, err := unix.Sysctl("kern.ostype") 89 if err != nil { 90 return "", "", "", err 91 } 92 93 version, err := unix.Sysctl("kern.osrelease") 94 if err != nil { 95 return "", "", "", err 96 } 97 98 return strings.ToLower(platform), "", strings.ToLower(version), nil 99} 100 101func VirtualizationWithContext(ctx context.Context) (string, string, error) { 102 return "", "", common.ErrNotImplementedError 103} 104 105// before 9.0 106func getUsersFromUtmp(utmpfile string) ([]UserStat, error) { 107 var ret []UserStat 108 file, err := os.Open(utmpfile) 109 if err != nil { 110 return ret, err 111 } 112 defer file.Close() 113 114 buf, err := ioutil.ReadAll(file) 115 if err != nil { 116 return ret, err 117 } 118 119 u := Utmp{} 120 entrySize := int(unsafe.Sizeof(u)) 121 count := len(buf) / entrySize 122 123 for i := 0; i < count; i++ { 124 b := buf[i*entrySize : i*entrySize+entrySize] 125 var u Utmp 126 br := bytes.NewReader(b) 127 err := binary.Read(br, binary.LittleEndian, &u) 128 if err != nil || u.Time == 0 { 129 continue 130 } 131 user := UserStat{ 132 User: common.IntToString(u.Name[:]), 133 Terminal: common.IntToString(u.Line[:]), 134 Host: common.IntToString(u.Host[:]), 135 Started: int(u.Time), 136 } 137 138 ret = append(ret, user) 139 } 140 141 return ret, nil 142} 143 144func SensorsTemperaturesWithContext(ctx context.Context) ([]TemperatureStat, error) { 145 return []TemperatureStat{}, common.ErrNotImplementedError 146} 147 148func KernelVersionWithContext(ctx context.Context) (string, error) { 149 _, _, version, err := PlatformInformationWithContext(ctx) 150 return version, err 151} 152