Skip to content

Commit

Permalink
Add support for OpenBSD/amd64
Browse files Browse the repository at this point in the history
This code is based on the FreeBSD version
and implements roughly the same feature set.
  • Loading branch information
mpfz0r committed Nov 24, 2016
1 parent 110eb1f commit b4846b4
Show file tree
Hide file tree
Showing 27 changed files with 1,905 additions and 17 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@ build_test: ## test only buildable
# Supported operating systems
GOOS=linux go test ./... | $(BUILD_FAIL_PATTERN)
GOOS=freebsd go test ./... | $(BUILD_FAIL_PATTERN)
GOOS=openbsd go test ./... | $(BUILD_FAIL_PATTERN)
CGO_ENABLED=0 GOOS=darwin go test ./... | $(BUILD_FAIL_PATTERN)
CGO_ENABLED=1 GOOS=darwin go test ./... | $(BUILD_FAIL_PATTERN)
GOOS=windows go test ./... | $(BUILD_FAIL_PATTERN)
# Operating systems supported for building only (not implemented error if used)
GOOS=dragonfly go test ./... | $(BUILD_FAIL_PATTERN)
GOOS=netbsd go test ./... | $(BUILD_FAIL_PATTERN)
GOOS=openbsd go test ./... | $(BUILD_FAIL_PATTERN)
GOOS=solaris go test ./... | $(BUILD_FAIL_PATTERN)
@echo 'Successfully built on all known operating systems'
2 changes: 1 addition & 1 deletion cpu/cpu_fallback.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// +build !darwin,!linux,!freebsd,!windows
// +build !darwin,!linux,!freebsd,!openbsd,!windows

package cpu

Expand Down
110 changes: 110 additions & 0 deletions cpu/cpu_openbsd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
// +build openbsd

package cpu

import (
"bytes"
"encoding/binary"
"fmt"
"os/exec"
"strconv"
"strings"
"syscall"

"github.com/shirou/gopsutil/internal/common"
)

// sys/sched.h
const (
CPUser = 0
CPNice = 1
CPSys = 2
CPIntr = 3
CPIdle = 4
CPUStates = 5
)

// sys/sysctl.h
const (
CTLKern = 1 // "high kernel": proc, limits
KernCptime = 40 // KERN_CPTIME
KernCptime2 = 71 // KERN_CPTIME2
)

var ClocksPerSec = float64(128)

func init() {
getconf, err := exec.LookPath("/usr/bin/getconf")
if err != nil {
return
}
out, err := invoke.Command(getconf, "CLK_TCK")
// ignore errors
if err == nil {
i, err := strconv.ParseFloat(strings.TrimSpace(string(out)), 64)
if err == nil {
ClocksPerSec = float64(i)
}
}
}

func Times(percpu bool) ([]TimesStat, error) {
var ret []TimesStat

var ncpu int
if percpu {
ncpu, _ = Counts(true)
} else {
ncpu = 1
}

for i := 0; i < ncpu; i++ {
var cpuTimes [CPUStates]int64
var mib []int32
if percpu {
mib = []int32{CTLKern, KernCptime}
} else {
mib = []int32{CTLKern, KernCptime2, int32(i)}
}
buf, _, err := common.CallSyscall(mib)
if err != nil {
return ret, err
}

br := bytes.NewReader(buf)
err = binary.Read(br, binary.LittleEndian, &cpuTimes)
if err != nil {
return ret, err
}
c := TimesStat{
User: float64(cpuTimes[CPUser]) / ClocksPerSec,
Nice: float64(cpuTimes[CPNice]) / ClocksPerSec,
System: float64(cpuTimes[CPSys]) / ClocksPerSec,
Idle: float64(cpuTimes[CPIdle]) / ClocksPerSec,
Irq: float64(cpuTimes[CPIntr]) / ClocksPerSec,
}
if !percpu {
c.CPU = "cpu-total"
} else {
c.CPU = fmt.Sprintf("cpu%d", i)
}
ret = append(ret, c)
}

return ret, nil
}

// Returns only one (minimal) CPUInfoStat on OpenBSD
func Info() ([]InfoStat, error) {
var ret []InfoStat

c := InfoStat{}

v, err := syscall.Sysctl("hw.model")
if err != nil {
return nil, err
}
c.ModelName = v

return append(ret, c), nil
}
2 changes: 1 addition & 1 deletion disk/disk_fallback.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// +build !darwin,!linux,!freebsd,!windows
// +build !darwin,!linux,!freebsd,!openbsd,!windows

package disk

Expand Down
158 changes: 158 additions & 0 deletions disk/disk_openbsd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
// +build openbsd

package disk

import (
"bytes"
"encoding/binary"
"path"
"syscall"
"unsafe"

"github.com/shirou/gopsutil/internal/common"
)

func Partitions(all bool) ([]PartitionStat, error) {
var ret []PartitionStat

// get length
count, err := syscall.Getfsstat(nil, MNT_WAIT)
if err != nil {
return ret, err
}

fs := make([]Statfs, count)
_, err = Getfsstat(fs, MNT_WAIT)

for _, stat := range fs {
opts := "rw"
if stat.F_flags&MNT_RDONLY != 0 {
opts = "ro"
}
if stat.F_flags&MNT_SYNCHRONOUS != 0 {
opts += ",sync"
}
if stat.F_flags&MNT_NOEXEC != 0 {
opts += ",noexec"
}
if stat.F_flags&MNT_NOSUID != 0 {
opts += ",nosuid"
}
if stat.F_flags&MNT_NODEV != 0 {
opts += ",nodev"
}
if stat.F_flags&MNT_ASYNC != 0 {
opts += ",async"
}

d := PartitionStat{
Device: common.IntToString(stat.F_mntfromname[:]),
Mountpoint: common.IntToString(stat.F_mntonname[:]),
Fstype: common.IntToString(stat.F_fstypename[:]),
Opts: opts,
}
if all == false {
if !path.IsAbs(d.Device) || !common.PathExists(d.Device) {
continue
}
}

ret = append(ret, d)
}

return ret, nil
}

func IOCounters() (map[string]IOCountersStat, error) {
ret := make(map[string]IOCountersStat)

r, err := syscall.Sysctl("hw.diskstats")
if err != nil {
return nil, err
}
buf := []byte(r)
length := len(buf)

count := int(uint64(length) / uint64(sizeOfDiskstats))

// parse buf to Diskstats
for i := 0; i < count; i++ {
b := buf[i*sizeOfDiskstats : i*sizeOfDiskstats+sizeOfDiskstats]
d, err := parseDiskstats(b)
if err != nil {
continue
}
name := common.IntToString(d.Name[:])

ds := IOCountersStat{
ReadCount: d.Rxfer,
WriteCount: d.Wxfer,
ReadBytes: d.Rbytes,
WriteBytes: d.Wbytes,
Name: name,
}
ret[name] = ds
}

return ret, nil
}

// BT2LD(time) ((long double)(time).sec + (time).frac * BINTIME_SCALE)

// Getfsstat is borrowed from pkg/syscall/syscall_freebsd.go
// change Statfs_t to Statfs in order to get more information
func Getfsstat(buf []Statfs, flags int) (n int, err error) {
var _p0 unsafe.Pointer
var bufsize uintptr
if len(buf) > 0 {
_p0 = unsafe.Pointer(&buf[0])
bufsize = unsafe.Sizeof(Statfs{}) * uintptr(len(buf))
}
r0, _, e1 := syscall.Syscall(syscall.SYS_GETFSSTAT, uintptr(_p0), bufsize, uintptr(flags))
n = int(r0)
if e1 != 0 {
err = e1
}
return
}

func parseDiskstats(buf []byte) (Diskstats, error) {
var ds Diskstats
br := bytes.NewReader(buf)
// err := binary.Read(br, binary.LittleEndian, &ds)
err := common.Read(br, binary.LittleEndian, &ds)
if err != nil {
return ds, err
}

return ds, nil
}

func Usage(path string) (*UsageStat, error) {
stat := syscall.Statfs_t{}
err := syscall.Statfs(path, &stat)
if err != nil {
return nil, err
}
bsize := stat.F_bsize

ret := &UsageStat{
Path: path,
Fstype: getFsType(stat),
Total: (uint64(stat.F_blocks) * uint64(bsize)),
Free: (uint64(stat.F_bavail) * uint64(bsize)),
InodesTotal: (uint64(stat.F_files)),
InodesFree: (uint64(stat.F_ffree)),
}

ret.InodesUsed = (ret.InodesTotal - ret.InodesFree)
ret.InodesUsedPercent = (float64(ret.InodesUsed) / float64(ret.InodesTotal)) * 100.0
ret.Used = (uint64(stat.F_blocks) - uint64(stat.F_bfree)) * uint64(bsize)
ret.UsedPercent = (float64(ret.Used) / float64(ret.Total)) * 100.0

return ret, nil
}

func getFsType(stat syscall.Statfs_t) string {
return common.IntToString(stat.F_fstypename[:])
}
91 changes: 91 additions & 0 deletions disk/disk_openbsd_amd64.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
// Created by cgo -godefs - DO NOT EDIT
// cgo -godefs types_openbsd.go

package disk

const (
sizeofPtr = 0x8
sizeofShort = 0x2
sizeofInt = 0x4
sizeofLong = 0x8
sizeofLongLong = 0x8
sizeofLongDouble = 0x8

DEVSTAT_NO_DATA = 0x00
DEVSTAT_READ = 0x01
DEVSTAT_WRITE = 0x02
DEVSTAT_FREE = 0x03

MNT_RDONLY = 0x00000001
MNT_SYNCHRONOUS = 0x00000002
MNT_NOEXEC = 0x00000004
MNT_NOSUID = 0x00000008
MNT_NODEV = 0x00000010
MNT_ASYNC = 0x00000040

MNT_WAIT = 1
MNT_NOWAIT = 2
MNT_LAZY = 3
)

const (
sizeOfDiskstats = 0x70
)

type (
_C_short int16
_C_int int32
_C_long int64
_C_long_long int64
_C_long_double int64
)

type Statfs struct {
F_flags uint32
F_bsize uint32
F_iosize uint32
Pad_cgo_0 [4]byte
F_blocks uint64
F_bfree uint64
F_bavail int64
F_files uint64
F_ffree uint64
F_favail int64
F_syncwrites uint64
F_syncreads uint64
F_asyncwrites uint64
F_asyncreads uint64
F_fsid Fsid
F_namemax uint32
F_owner uint32
F_ctime uint64
F_fstypename [16]int8
F_mntonname [90]int8
F_mntfromname [90]int8
F_mntfromspec [90]int8
Pad_cgo_1 [2]byte
Mount_info [160]byte
}
type Diskstats struct {
Name [16]int8
Busy int32
Pad_cgo_0 [4]byte
Rxfer uint64
Wxfer uint64
Seek uint64
Rbytes uint64
Wbytes uint64
Attachtime Timeval
Timestamp Timeval
Time Timeval
}
type Fsid struct {
Val [2]int32
}
type Timeval struct {
Sec int64
Usec int64
}

type Diskstat struct{}
type Bintime struct{}
Loading

0 comments on commit b4846b4

Please sign in to comment.