host_darwin.go 2.67 KB
Newer Older
1 2
// +build darwin

Shirou WAKAYAMA's avatar
Shirou WAKAYAMA committed
3
package host
4 5 6 7 8 9 10 11 12 13

import (
	"bytes"
	"encoding/binary"
	"io/ioutil"
	"os"
	"os/exec"
	"runtime"
	"strconv"
	"strings"
14
	"time"
15
	"unsafe"
16

17
	"github.com/shirou/gopsutil/internal/common"
18 19
)

20 21 22
// from utmpx.h
const USER_PROCESS = 7

23 24 25 26 27 28 29
func HostInfo() (*HostInfoStat, error) {
	ret := &HostInfoStat{
		OS:             runtime.GOOS,
		PlatformFamily: "darwin",
	}

	hostname, err := os.Hostname()
30 31
	if err == nil {
		ret.Hostname = hostname
32 33 34 35 36 37 38 39 40 41 42 43 44 45
	}

	platform, family, version, err := GetPlatformInformation()
	if err == nil {
		ret.Platform = platform
		ret.PlatformFamily = family
		ret.PlatformVersion = version
	}
	system, role, err := GetVirtualization()
	if err == nil {
		ret.VirtualizationSystem = system
		ret.VirtualizationRole = role
	}

46
	boot, err := BootTime()
47
	if err == nil {
48 49
		ret.BootTime = boot
		ret.Uptime = uptime(boot)
50 51 52 53 54
	}

	return ret, nil
}

55
func BootTime() (uint64, error) {
56
	values, err := common.DoSysctrl("kern.boottime")
57 58 59 60 61 62 63 64 65 66
	if err != nil {
		return 0, err
	}
	// ex: { sec = 1392261637, usec = 627534 } Thu Feb 13 12:20:37 2014
	v := strings.Replace(values[2], ",", "", 1)
	boottime, err := strconv.ParseInt(v, 10, 64)
	if err != nil {
		return 0, err
	}

67
	return uint64(boottime), nil
68 69
}

70 71 72 73 74 75 76 77 78 79 80 81
func uptime(boot uint64) uint64 {
	return uint64(time.Now().Unix()) - boot
}

func Uptime() (uint64, error) {
	boot, err := BootTime()
	if err != nil {
		return 0, err
	}
	return uptime(boot), nil
}

82 83 84 85 86 87 88 89 90 91 92 93 94 95
func Users() ([]UserStat, error) {
	utmpfile := "/var/run/utmpx"
	var ret []UserStat

	file, err := os.Open(utmpfile)
	if err != nil {
		return ret, err
	}

	buf, err := ioutil.ReadAll(file)
	if err != nil {
		return ret, err
	}

96
	u := Utmpx{}
97 98 99 100 101 102
	entrySize := int(unsafe.Sizeof(u))
	count := len(buf) / entrySize

	for i := 0; i < count; i++ {
		b := buf[i*entrySize : i*entrySize+entrySize]

103
		var u Utmpx
104 105 106 107 108
		br := bytes.NewReader(b)
		err := binary.Read(br, binary.LittleEndian, &u)
		if err != nil {
			continue
		}
109
		if u.Type != USER_PROCESS {
110 111
			continue
		}
112
		user := UserStat{
113 114 115 116
			User:     common.IntToString(u.User[:]),
			Terminal: common.IntToString(u.Line[:]),
			Host:     common.IntToString(u.Host[:]),
			Started:  int(u.Tv.Sec),
117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
		}
		ret = append(ret, user)
	}

	return ret, nil

}

func GetPlatformInformation() (string, string, string, error) {
	platform := ""
	family := ""
	version := ""

	out, err := exec.Command("uname", "-s").Output()
	if err == nil {
		platform = strings.ToLower(strings.TrimSpace(string(out)))
	}

	out, err = exec.Command("uname", "-r").Output()
	if err == nil {
		version = strings.ToLower(strings.TrimSpace(string(out)))
	}

	return platform, family, version, nil
}

func GetVirtualization() (string, string, error) {
	system := ""
	role := ""

	return system, role, nil
}