add darwin placeholder. Not working yet.

Currently, test should be failed with NotImplementedError or something.
pull/4/head
Shirou WAKAYAMA 11 years ago
parent 594816dd1f
commit a199f2d854

@ -0,0 +1,20 @@
// +build darwin
package gopsutil
import (
"os/exec"
"strings"
)
func doSysctrl(mib string) ([]string, error) {
out, err := exec.Command("/usr/sbin/sysctl", "-n", mib).Output()
if err != nil {
return []string{}, err
}
v := strings.Replace(string(out), "{ ", "", 1)
v = strings.Replace(string(v), " }", "", 1)
values := strings.Fields(string(v))
return values, nil
}

@ -0,0 +1,87 @@
// +build darwin
package gopsutil
import (
"regexp"
"strconv"
"strings"
)
// sys/resource.h
const (
CP_USER = 0
CP_NICE = 1
CP_SYS = 2
CP_INTR = 3
CP_IDLE = 4
CPUSTATES = 5
)
// time.h
const (
CLOCKS_PER_SEC = 128
)
// TODO: get per cpus
func CPUTimes(percpu bool) ([]CPUTimesStat, error) {
var ret []CPUTimesStat
cpuTime, err := doSysctrl("kern.cp_time")
if err != nil {
return ret, err
}
user, _ := strconv.ParseFloat(cpuTime[CP_USER], 32)
nice, _ := strconv.ParseFloat(cpuTime[CP_NICE], 32)
sys, _ := strconv.ParseFloat(cpuTime[CP_SYS], 32)
idle, _ := strconv.ParseFloat(cpuTime[CP_IDLE], 32)
intr, _ := strconv.ParseFloat(cpuTime[CP_INTR], 32)
c := CPUTimesStat{
User: float32(user / CLOCKS_PER_SEC),
Nice: float32(nice / CLOCKS_PER_SEC),
System: float32(sys / CLOCKS_PER_SEC),
Idle: float32(idle / CLOCKS_PER_SEC),
Irq: float32(intr / CLOCKS_PER_SEC), // FIXME: correct?
}
ret = append(ret, c)
return ret, nil
}
// Returns only one CPUInfoStat on FreeBSD
func CPUInfo() ([]CPUInfoStat, error) {
filename := "/var/run/dmesg.boot"
lines, _ := readLines(filename)
var ret []CPUInfoStat
c := CPUInfoStat{}
for _, line := range lines {
if matches := regexp.MustCompile(`CPU:\s+(.+) \(([\d.]+).+\)`).FindStringSubmatch(line); matches != nil {
c.ModelName = matches[1]
c.Mhz = mustParseFloat64(matches[2])
} else if matches := regexp.MustCompile(`Origin = "(.+)" Id = (.+) Family = (.+) Model = (.+) Stepping = (.+)`).FindStringSubmatch(line); matches != nil {
c.VendorID = matches[1]
c.Family = matches[3]
c.Model = matches[4]
c.Stepping = mustParseInt32(matches[5])
} else if matches := regexp.MustCompile(`Features=.+<(.+)>`).FindStringSubmatch(line); matches != nil {
for _, v := range strings.Split(matches[1], ",") {
c.Flags = append(c.Flags, strings.ToLower(v))
}
} else if matches := regexp.MustCompile(`Features2=[a-f\dx]+<(.+)>`).FindStringSubmatch(line); matches != nil {
for _, v := range strings.Split(matches[1], ",") {
c.Flags = append(c.Flags, strings.ToLower(v))
}
} else if matches := regexp.MustCompile(`Logical CPUs per core: (\d+)`).FindStringSubmatch(line); matches != nil {
// FIXME: no this line?
c.Cores = mustParseInt32(matches[1])
}
}
return append(ret, c), nil
}

@ -0,0 +1,12 @@
// +build darwin
package gopsutil
func DiskPartitions(all bool) ([]DiskPartitionStat, error) {
return nil, NotImplementedError
}
func DiskIOCounters() (map[string]DiskIOCountersStat, error) {
return nil, NotImplementedError
}

@ -1,4 +1,4 @@
// +build freebsd linux
// +build freebsd linux darwin
package gopsutil

@ -0,0 +1,148 @@
// +build darwin
package gopsutil
import (
"bytes"
"encoding/binary"
"io/ioutil"
"os"
"os/exec"
"runtime"
"strconv"
"strings"
"unsafe"
)
const (
UTX_USERSIZE = 256 /* include/NetBSD/utmpx.h */
UTX_IDSIZE = 4
UTX_LINESIZE = 32
UTX_HOSTSIZE = 256
)
type utmpx32 struct {
UtUser [UTX_USERSIZE]byte /* login name */
UtId [UTX_IDSIZE]byte /* id */
UtLine [UTX_LINESIZE]byte /* tty name */
//TODO UtPid pid_t /* process id creating the entry */
UtType [4]byte /* type of this entry */
//TODO UtTv timeval32 /* time entry was created */
UtHost [UTX_HOSTSIZE]byte /* host name */
UtPad [16]byte /* reserved for future use */
}
func HostInfo() (*HostInfoStat, error) {
ret := &HostInfoStat{
OS: runtime.GOOS,
PlatformFamily: "darwin",
}
hostname, err := os.Hostname()
if err != nil {
return ret, err
}
ret.Hostname = hostname
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
}
values, err := doSysctrl("kern.boottime")
if err == nil {
// ex: { sec = 1392261637, usec = 627534 } Thu Feb 13 12:20:37 2014
v := strings.Replace(values[2], ",", "", 1)
ret.Uptime = mustParseUint64(v)
}
return ret, nil
}
func BootTime() (int64, error) {
values, err := doSysctrl("kern.boottime")
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
}
return boottime, nil
}
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
}
u := utmpx32{}
entrySize := int(unsafe.Sizeof(u))
count := len(buf) / entrySize
for i := 0; i < count; i++ {
b := buf[i*entrySize : i*entrySize+entrySize]
var u utmpx32
br := bytes.NewReader(b)
err := binary.Read(br, binary.LittleEndian, &u)
if err != nil {
continue
}
user := UserStat{
User: byteToString(u.UtUser[:]),
// Terminal: byteToString(u.UtLine[:]),
Host: byteToString(u.UtHost[:]),
// Started: int(u.UtTime),
}
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
}

@ -0,0 +1,35 @@
// +build darwin
package gopsutil
import (
"strconv"
)
func LoadAvg() (*LoadAvgStat, error) {
values, err := doSysctrl("vm.loadavg")
if err != nil {
return nil, err
}
load1, err := strconv.ParseFloat(values[0], 64)
if err != nil {
return nil, err
}
load5, err := strconv.ParseFloat(values[1], 64)
if err != nil {
return nil, err
}
load15, err := strconv.ParseFloat(values[2], 64)
if err != nil {
return nil, err
}
ret := &LoadAvgStat{
Load1: float64(load1),
Load5: float64(load5),
Load15: float64(load15),
}
return ret, nil
}

@ -0,0 +1,74 @@
// +build darwin
package gopsutil
import (
"os/exec"
"strings"
)
func getPageSize() (uint64, error) {
out, err := exec.Command("pagesize").Output()
if err != nil {
return 0, err
}
p := mustParseUint64(string(out))
return p, nil
}
// VirtualMemory returns VirtualmemoryStat.
func VirtualMemory() (*VirtualMemoryStat, error) {
p, _ := getPageSize()
total, _ := doSysctrl("hw.memsize")
free, _ := doSysctrl("vm.page_free_count")
/*
active, _ := doSysctrl("vm.stats.vm.v_active_count")
inactive, _ := doSysctrl("vm.pageout_inactive_used")
cache, _ := doSysctrl("vm.stats.vm.v_cache_count")
buffer, _ := doSysctrl("vfs.bufspace")
wired, _ := doSysctrl("vm.stats.vm.v_wire_count")
*/
ret := &VirtualMemoryStat{
Total: mustParseUint64(total[0]) * p,
Free: mustParseUint64(free[0]) * p,
/*
Active: mustParseUint64(active[0]) * p,
Inactive: mustParseUint64(inactive[0]) * p,
Cached: mustParseUint64(cache[0]) * p,
Buffers: mustParseUint64(buffer[0]),
Wired: mustParseUint64(wired[0]) * p,
*/
}
// TODO: platform independent (worked freebsd?)
ret.Available = ret.Free + ret.Buffers + ret.Cached
ret.Used = ret.Total - ret.Free
ret.UsedPercent = float64(ret.Total-ret.Available) / float64(ret.Total) * 100.0
return ret, nil
}
// SwapMemory returns swapinfo.
func SwapMemory() (*SwapMemoryStat, error) {
swapUsage, _ := doSysctrl("vm.swapusage")
var ret *SwapMemoryStat
total := strings.Replace(swapUsage[3], "M", "", 1)
used := strings.Replace(swapUsage[6], "M", "", 1)
free := strings.Replace(swapUsage[9], "M", "", 1)
u := "0"
ret = &SwapMemoryStat{
Total: mustParseUint64(total),
Used: mustParseUint64(used),
Free: mustParseUint64(free),
UsedPercent: mustParseFloat64(u),
}
return ret, nil
}

@ -0,0 +1,47 @@
// +build darwin
package gopsutil
import (
"os/exec"
"strings"
)
func NetIOCounters(pernic bool) ([]NetIOCountersStat, error) {
out, err := exec.Command("/usr/sbin/netstat", "-ibdn").Output()
if err != nil {
return nil, err
}
lines := strings.Split(string(out), "\n")
ret := make([]NetIOCountersStat, 0, len(lines)-1)
for _, line := range lines {
values := strings.Fields(line)
if len(values) < 1 || values[0] == "Name" {
continue
}
base := 1
// sometimes Address is ommitted
if len(values) < 13 {
base = 0
}
n := NetIOCountersStat{
Name: values[0],
PacketsRecv: mustParseUint64(values[base+3]),
Errin: mustParseUint64(values[base+4]),
Dropin: mustParseUint64(values[base+5]),
/*
BytesRecv: mustParseUint64(values[base+6]),
PacketsSent: mustParseUint64(values[base+7]),
Errout: mustParseUint64(values[base+8]),
BytesSent: mustParseUint64(values[base+9]),
Dropout: mustParseUint64(values[base+11]),
*/
}
ret = append(ret, n)
}
return ret, nil
}

@ -0,0 +1,306 @@
// +build darwin
package gopsutil
import (
"bytes"
"encoding/binary"
"syscall"
"unsafe"
)
// MemoryInfoExStat is different between OSes
type MemoryInfoExStat struct {
}
type MemoryMapsStat struct {
}
func Pids() ([]int32, error) {
var ret []int32
procs, err := processes()
if err != nil {
return ret, nil
}
for _, p := range procs {
ret = append(ret, p.Pid)
}
return ret, nil
}
func (p *Process) Ppid() (int32, error) {
return 0, NotImplementedError
k, err := p.getKProc()
if err != nil {
return 0, err
}
return k.KiPpid, nil
}
func (p *Process) Name() (string, error) {
k, err := p.getKProc()
if err != nil {
return "", err
}
return string(k.KiComm[:]), nil
}
func (p *Process) Exe() (string, error) {
return "", NotImplementedError
}
func (p *Process) Cmdline() (string, error) {
return "", NotImplementedError
}
func (p *Process) CreateTime() (int64, error) {
return 0, NotImplementedError
}
func (p *Process) Cwd() (string, error) {
return "", NotImplementedError
}
func (p *Process) Parent() (*Process, error) {
return p, NotImplementedError
}
func (p *Process) Status() (string, error) {
k, err := p.getKProc()
if err != nil {
return "", err
}
return string(k.KiStat[:]), nil
}
func (p *Process) Username() (string, error) {
return "", NotImplementedError
}
func (p *Process) Uids() ([]int32, error) {
k, err := p.getKProc()
if err != nil {
return nil, err
}
uids := make([]int32, 0, 3)
uids = append(uids, int32(k.KiRuid), int32(k.KiUID), int32(k.KiSvuid))
return uids, nil
}
func (p *Process) Gids() ([]int32, error) {
k, err := p.getKProc()
if err != nil {
return nil, err
}
gids := make([]int32, 0, 3)
gids = append(gids, int32(k.KiRgid), int32(k.KiNgroups[0]), int32(k.KiSvuid))
return gids, nil
}
func (p *Process) Terminal() (string, error) {
k, err := p.getKProc()
if err != nil {
return "", err
}
ttyNr := uint64(k.KiTdev)
termmap, err := getTerminalMap()
if err != nil {
return "", err
}
return termmap[ttyNr], nil
}
func (p *Process) Nice() (int32, error) {
return 0, NotImplementedError
}
func (p *Process) IOnice() (int32, error) {
return 0, NotImplementedError
}
func (p *Process) Rlimit() ([]RlimitStat, error) {
var rlimit []RlimitStat
return rlimit, NotImplementedError
}
func (p *Process) IOCounters() (*IOCountersStat, error) {
return nil, NotImplementedError
}
func (p *Process) NumCtxSwitches() (*NumCtxSwitchesStat, error) {
return nil, NotImplementedError
}
func (p *Process) NumFDs() (int32, error) {
return 0, NotImplementedError
}
func (p *Process) NumThreads() (int32, error) {
k, err := p.getKProc()
if err != nil {
return 0, err
}
return k.KiNumthreads, nil
}
func (p *Process) Threads() (map[string]string, error) {
ret := make(map[string]string, 0)
return ret, NotImplementedError
}
func (p *Process) CPUTimes() (*CPUTimesStat, error) {
return nil, NotImplementedError
}
func (p *Process) CPUPercent() (int32, error) {
return 0, NotImplementedError
}
func (p *Process) CPUAffinity() ([]int32, error) {
return nil, NotImplementedError
}
func (p *Process) MemoryInfo() (*MemoryInfoStat, error) {
k, err := p.getKProc()
if err != nil {
return nil, err
}
ret := &MemoryInfoStat{
RSS: uint64(k.KiRssize),
VMS: uint64(k.KiSize),
}
return ret, nil
}
func (p *Process) MemoryInfoEx() (*MemoryInfoExStat, error) {
return nil, NotImplementedError
}
func (p *Process) MemoryPercent() (float32, error) {
return 0, NotImplementedError
}
func (p *Process) Children() ([]*Process, error) {
return nil, NotImplementedError
}
func (p *Process) OpenFiles() ([]OpenFilesStat, error) {
return nil, NotImplementedError
}
func (p *Process) Connections() ([]NetConnectionStat, error) {
return nil, NotImplementedError
}
func (p *Process) IsRunning() (bool, error) {
return true, NotImplementedError
}
func (p *Process) MemoryMaps(grouped bool) (*[]MemoryMapsStat, error) {
var ret []MemoryMapsStat
return &ret, NotImplementedError
}
func copyParams(k *KinfoProc, p *Process) error {
return nil
}
func processes() ([]Process, error) {
results := make([]Process, 0, 50)
mib := []int32{CTL_KERN, KERN_PROC, KERN_PROC_PROC, 0}
buf, length, err := callSyscall(mib)
if err != nil {
return results, err
}
// get kinfo_proc size
k := KinfoProc{}
procinfoLen := int(unsafe.Sizeof(k))
count := int(length / uint64(procinfoLen))
// parse buf to procs
for i := 0; i < count; i++ {
b := buf[i*procinfoLen : i*procinfoLen+procinfoLen]
k, err := parseKinfoProc(b)
if err != nil {
continue
}
p, err := NewProcess(int32(k.KiPid))
if err != nil {
continue
}
copyParams(&k, p)
results = append(results, *p)
}
return results, nil
}
func parseKinfoProc(buf []byte) (KinfoProc, error) {
var k KinfoProc
br := bytes.NewReader(buf)
err := binary.Read(br, binary.LittleEndian, &k)
if err != nil {
return k, err
}
return k, nil
}
func callSyscall(mib []int32) ([]byte, uint64, error) {
miblen := uint64(len(mib))
// get required buffer size
length := uint64(0)
_, _, err := syscall.Syscall6(
syscall.SYS___SYSCTL,
uintptr(unsafe.Pointer(&mib[0])),
uintptr(miblen),
0,
uintptr(unsafe.Pointer(&length)),
0,
0)
if err != 0 {
var b []byte
return b, length, err
}
if length == 0 {
var b []byte
return b, length, err
}
// get proc info itself
buf := make([]byte, length)
_, _, err = syscall.Syscall6(
syscall.SYS___SYSCTL,
uintptr(unsafe.Pointer(&mib[0])),
uintptr(miblen),
uintptr(unsafe.Pointer(&buf[0])),
uintptr(unsafe.Pointer(&length)),
0,
0)
if err != 0 {
return buf, length, err
}
return buf, length, nil
}
func (p *Process) getKProc() (*KinfoProc, error) {
mib := []int32{CTL_KERN, KERN_PROC, KERN_PROC_PID, p.Pid}
buf, length, err := callSyscall(mib)
if err != nil {
return nil, err
}
procK := KinfoProc{}
if length != uint64(unsafe.Sizeof(procK)) {
return nil, err
}
k, err := parseKinfoProc(buf)
if err != nil {
return nil, err
}
return &k, nil
}
func NewProcess(pid int32) (*Process, error) {
p := &Process{Pid: pid}
return p, nil
}

@ -0,0 +1,96 @@
// +build darwin
// +build amd64
package gopsutil
// copied from sys/sysctl.h
const (
CTL_KERN = 1 // "high kernel": proc, limits
KERN_PROC = 14 // struct: process entries
KERN_PROC_PID = 1 // by process id
KERN_PROC_PROC = 8 // only return procs
KERN_PROC_PATHNAME = 12 // path to executable
)
// copied from sys/user.h
type KinfoProc struct {
KiStructsize int32
KiLayout int32
KiArgs int64
KiPaddr int64
KiAddr int64
KiTracep int64
KiTextvp int64
KiFd int64
KiVmspace int64
KiWchan int64
KiPid int32
KiPpid int32
KiPgid int32
KiTpgid int32
KiSid int32
KiTsid int32
KiJobc [2]byte
KiSpareShort1 [2]byte
KiTdev int32
KiSiglist [16]byte
KiSigmask [16]byte
KiSigignore [16]byte
KiSigcatch [16]byte
KiUID int32
KiRuid int32
KiSvuid int32
KiRgid int32
KiSvgid int32
KiNgroups [2]byte
KiSpareShort2 [2]byte
KiGroups [64]byte
KiSize int64
KiRssize int64
KiSwrss int64
KiTsize int64
KiDsize int64
KiSsize int64
KiXstat [2]byte
KiAcflag [2]byte
KiPctcpu int32
KiEstcpu int32
KiSlptime int32
KiSwtime int32
KiCow int32
KiRuntime int64
KiStart [16]byte
KiChildtime [16]byte
KiFlag int64
KiKflag int64
KiTraceflag int32
KiStat [1]byte
KiNice [1]byte
KiLock [1]byte
KiRqindex [1]byte
KiOncpu [1]byte
KiLastcpu [1]byte
KiOcomm [17]byte
KiWmesg [9]byte
KiLogin [18]byte
KiLockname [9]byte
KiComm [20]byte
KiEmul [17]byte
KiSparestrings [68]byte
KiSpareints [36]byte
KiCrFlags int32
KiJid int32
KiNumthreads int32
KiTid int32
KiPri int32
KiRusage [144]byte
KiRusageCh [144]byte
KiPcb int64
KiKstack int64
KiUdata int64
KiTdaddr int64
KiSpareptrs [48]byte
KiSpareint64s [96]byte
KiSflag int64
KiTdflags int64
}

@ -1,4 +1,4 @@
// +build linux freebsd
// +build linux freebsd darwin
package gopsutil

Loading…
Cancel
Save