1
0
mirror of https://github.com/shirou/gopsutil.git synced 2025-04-26 13:48:59 +08:00
shirou_gopsutil/host/host_darwin.go
Tobias Klauser 28890b0482 Use common implementation for BootTime/Uptime on all BSDs
All BSDs use the same implementation to get BootTime{,WithContext} and
Uptime{,WithContext} based on the kern.boottime sysctl. Move this
implementation to a separate host/host_bsd.go file shared by darwin,
freebsd and openbsd. Also use SysctlTimeval to get
the boot time directly as a type Timeval instead of manually
extracting it using package unsafe. It will also allow for easier reuse
to support package host on e.g. Dragonfly BSD or NetBSD.

This requires updating the golang.org/x/sys/unix dependency to the
latest revision.

Signed-off-by: Tobias Klauser <tklauser@distanz.ch>
2020-07-23 13:23:20 +02:00

182 lines
3.6 KiB
Go

// +build darwin
package host
import (
"bytes"
"context"
"encoding/binary"
"io/ioutil"
"os"
"os/exec"
"runtime"
"strings"
"unsafe"
"github.com/shirou/gopsutil/internal/common"
"github.com/shirou/gopsutil/process"
"golang.org/x/sys/unix"
)
// from utmpx.h
const USER_PROCESS = 7
func Info() (*InfoStat, error) {
return InfoWithContext(context.Background())
}
func InfoWithContext(ctx context.Context) (*InfoStat, error) {
ret := &InfoStat{
OS: runtime.GOOS,
PlatformFamily: "darwin",
}
hostname, err := os.Hostname()
if err == nil {
ret.Hostname = hostname
}
kernelVersion, err := KernelVersionWithContext(ctx)
if err == nil {
ret.KernelVersion = kernelVersion
}
kernelArch, err := kernelArch()
if err == nil {
ret.KernelArch = kernelArch
}
platform, family, pver, err := PlatformInformation()
if err == nil {
ret.Platform = platform
ret.PlatformFamily = family
ret.PlatformVersion = pver
}
system, role, err := Virtualization()
if err == nil {
ret.VirtualizationSystem = system
ret.VirtualizationRole = role
}
boot, err := BootTime()
if err == nil {
ret.BootTime = boot
ret.Uptime = uptime(boot)
}
procs, err := process.Pids()
if err == nil {
ret.Procs = uint64(len(procs))
}
uuid, err := unix.Sysctl("kern.uuid")
if err == nil && uuid != "" {
ret.HostID = strings.ToLower(uuid)
}
return ret, nil
}
func Users() ([]UserStat, error) {
return UsersWithContext(context.Background())
}
func UsersWithContext(ctx context.Context) ([]UserStat, error) {
utmpfile := "/var/run/utmpx"
var ret []UserStat
file, err := os.Open(utmpfile)
if err != nil {
return ret, err
}
defer file.Close()
buf, err := ioutil.ReadAll(file)
if err != nil {
return ret, err
}
u := Utmpx{}
entrySize := int(unsafe.Sizeof(u))
count := len(buf) / entrySize
for i := 0; i < count; i++ {
b := buf[i*entrySize : i*entrySize+entrySize]
var u Utmpx
br := bytes.NewReader(b)
err := binary.Read(br, binary.LittleEndian, &u)
if err != nil {
continue
}
if u.Type != USER_PROCESS {
continue
}
user := UserStat{
User: common.IntToString(u.User[:]),
Terminal: common.IntToString(u.Line[:]),
Host: common.IntToString(u.Host[:]),
Started: int(u.Tv.Sec),
}
ret = append(ret, user)
}
return ret, nil
}
func PlatformInformation() (string, string, string, error) {
return PlatformInformationWithContext(context.Background())
}
func PlatformInformationWithContext(ctx context.Context) (string, string, string, error) {
platform := ""
family := ""
pver := ""
sw_vers, err := exec.LookPath("sw_vers")
if err != nil {
return "", "", "", err
}
p, err := unix.Sysctl("kern.ostype")
if err == nil {
platform = strings.ToLower(p)
}
out, err := invoke.CommandWithContext(ctx, sw_vers, "-productVersion")
if err == nil {
pver = strings.ToLower(strings.TrimSpace(string(out)))
}
// check if the macos server version file exists
_, err = os.Stat("/System/Library/CoreServices/ServerVersion.plist")
// server file doesn't exist
if os.IsNotExist(err) {
family = "Standalone Workstation"
} else {
family = "Server"
}
return platform, family, pver, nil
}
func Virtualization() (string, string, error) {
return VirtualizationWithContext(context.Background())
}
func VirtualizationWithContext(ctx context.Context) (string, string, error) {
return "", "", common.ErrNotImplementedError
}
func KernelVersion() (string, error) {
return KernelVersionWithContext(context.Background())
}
func KernelVersionWithContext(ctx context.Context) (string, error) {
version, err := unix.Sysctl("kern.osrelease")
return strings.ToLower(version), err
}