1
2
3 package host
4
5 import (
6 "bytes"
7 "context"
8 "encoding/binary"
9 "io/ioutil"
10 "math"
11 "os"
12 "strings"
13 "unsafe"
14
15 "github.com/shirou/gopsutil/internal/common"
16 "github.com/shirou/gopsutil/process"
17 "golang.org/x/sys/unix"
18 )
19
20 const (
21 UTNameSize = 16
22 UTLineSize = 8
23 UTHostSize = 16
24 )
25
26 func 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
34 func 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
42 func UsersWithContext(ctx context.Context) ([]UserStat, error) {
43 utmpfile := "/var/run/utx.active"
44 if !common.PathExists(utmpfile) {
45 utmpfile = "/var/run/utmp"
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
87 func 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
101 func VirtualizationWithContext(ctx context.Context) (string, string, error) {
102 return "", "", common.ErrNotImplementedError
103 }
104
105
106 func 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
144 func SensorsTemperaturesWithContext(ctx context.Context) ([]TemperatureStat, error) {
145 return []TemperatureStat{}, common.ErrNotImplementedError
146 }
147
148 func KernelVersionWithContext(ctx context.Context) (string, error) {
149 _, _, version, err := PlatformInformationWithContext(ctx)
150 return version, err
151 }
152
View as plain text