shirou_gopsutil/host_linux.go

251 lines
5.3 KiB
Go

// +build linux
package gopsutil
import (
"bytes"
"encoding/binary"
"io/ioutil"
"os"
"os/exec"
"runtime"
"strings"
"syscall"
"unsafe"
)
type LSB struct {
ID string
Release string
Codename string
Description string
}
func HostInfo() (*HostInfoStat, error) {
hostname, err := os.Hostname()
if err != nil {
return nil, err
}
ret := &HostInfoStat{
Hostname: hostname,
OS: runtime.GOOS,
}
platform, family, version, err := getPlatformInformation()
if err == nil {
ret.Platform = platform
ret.PlatformFamily = family
ret.PlatformVersion = version
}
return ret, nil
}
func BootTime() (int64, error) {
sysinfo := &syscall.Sysinfo_t{}
if err := syscall.Sysinfo(sysinfo); err != nil {
return 0, err
}
return int64(sysinfo.Uptime), nil
}
func Users() ([]UserStat, error) {
utmpfile := "/var/run/utmp"
file, err := os.Open(utmpfile)
if err != nil {
return nil, err
}
buf, err := ioutil.ReadAll(file)
if err != nil {
return nil, err
}
u := utmp{}
entrySize := int(unsafe.Sizeof(u))
count := len(buf) / entrySize
ret := make([]UserStat, 0, count)
for i := 0; i < count; i++ {
b := buf[i*entrySize : i*entrySize+entrySize]
var u utmp
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.UtTv.TvSec),
}
ret = append(ret, user)
}
return ret, nil
}
func getLSB() (*LSB, error) {
ret := &LSB{}
if pathExists("/etc/lsb-release") {
contents, err := readLines("/etc/lsb-release")
if err != nil {
return ret, err // return empty
}
for _, line := range contents {
field := strings.Split(line, "=")
if len(field) < 2 {
continue
}
switch field[0] {
case "DISTRIB_ID":
ret.ID = field[1]
case "DISTRIB_RELEASE":
ret.Release = field[1]
case "DISTRIB_CODENAME":
ret.Codename = field[1]
case "DISTRIB_DESCRIPTION":
ret.Description = field[1]
}
}
} else if pathExists("/usr/bin/lsb_release") {
out, err := exec.Command("/usr/bin/lsb_release").Output()
if err != nil {
return ret, err
}
for _, line := range strings.Split(string(out), "\n") {
field := strings.Split(line, ":")
if len(field) < 2 {
continue
}
switch field[0] {
case "Distributor ID":
ret.ID = field[1]
case "Release":
ret.Release = field[1]
case "Codename":
ret.Codename = field[1]
case "Description":
ret.Description = field[1]
}
}
}
return ret, nil
}
func getPlatformInformation() (string, string, string, error) {
platform := ""
family := ""
version := ""
lsb, _ := getLSB()
if pathExists("/etc/oracle-release") {
platform = "oracle"
contents, err := readLines("/etc/oracle-release")
if err == nil {
version, _ = getRedhatishVersion(contents)
}
} else if pathExists("/etc/enterprise-release") {
platform = "oracle"
contents, err := readLines("/etc/enterprise-release")
if err == nil {
version, _ = getRedhatishVersion(contents)
}
} else if pathExists("/etc/debian_version") {
if lsb.ID == "Ubuntu" {
platform = "ubuntu"
version = lsb.Release
} else if lsb.ID == "LinuxMint" {
platform = "linuxmint"
version = lsb.Release
} else {
if pathExists("/usr/bin/raspi-config") {
platform = "raspbian"
} else {
platform = "debian"
}
contents, err := readLines("/etc/debian_version")
if err == nil {
version = contents[0]
}
}
} else if pathExists("/etc/redhat-release") {
contents, err := readLines("/etc/redhat-release")
if err == nil {
version, _ = getRedhatishVersion(contents)
platform, _ = getRedhatishPlatform(contents)
}
} else if pathExists("/etc/system-release") {
contents, err := readLines("/etc/system-release")
if err == nil {
version, _ = getRedhatishVersion(contents)
platform, _ = getRedhatishPlatform(contents)
}
} else if pathExists("/etc/gentoo-release") {
platform = "gentoo"
contents, err := readLines("/etc/gentoo-release")
if err == nil {
version, _ = getRedhatishVersion(contents)
}
// TODO: suse detection
// TODO: slackware detecion
} else if pathExists("/etc/arch-release") {
platform = "arch"
// TODO: exherbo detection
} else if lsb.ID == "RedHat" {
platform = "redhat"
version = lsb.Release
} else if lsb.ID == "Amazon" {
platform = "amazon"
version = lsb.Release
} else if lsb.ID == "ScientificSL" {
platform = "scientific"
version = lsb.Release
} else if lsb.ID == "XenServer" {
platform = "xenserver"
version = lsb.Release
} else if lsb.ID != "" {
platform = strings.ToLower(lsb.ID)
version = lsb.Release
}
switch platform {
case "debian", "ubuntu", "linuxmint", "raspbian":
family = "debian"
case "fedora":
family = "fedora"
case "oracle", "centos", "redhat", "scientific", "enterpriseenterprise", "amazon", "xenserver", "cloudlinux", "ibm_powerkvm":
family = "rhel"
case "suse":
family = "suse"
case "gentoo":
family = "gentoo"
case "slackware":
family = "slackware"
case "arch":
family = "arch"
case "exherbo":
family = "exherbo"
}
return platform, family, version, nil
}
func getRedhatishVersion(contents []string) (string, error) {
return "", nil
}
func getRedhatishPlatform(contents []string) (string, error) {
return "", nil
}