Merge remote-tracking branch 'downstream/master' into elfrucool/fix-windows-load-avg

pull/1358/head
elfrucool 1 year ago
commit e787f1a2b3

@ -22,17 +22,17 @@ jobs:
runs-on: ubuntu-22.04
steps:
- name: Install Go
uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0
with:
go-version: ${{ matrix.go-version }}
- name: Checkout code
uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- id: cache-paths
run: |
echo "::set-output name=cache::$(go env GOCACHE)"
echo "::set-output name=mod-cache::$(go env GOMODCACHE)"
- name: Cache go modules
uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 # v3.3.1
uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 # v4.0.0
with:
path: |
${{ steps.cache-paths.outputs.cache }}

@ -16,13 +16,14 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Setup go
uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0
with:
go-version: 1.17
cache: false
- name: Checkout repository
uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Setup golangci-lint
uses: golangci/golangci-lint-action@3a919529898de77ec3da873e3063ca4b10e7f5cc # v3.7.0
uses: golangci/golangci-lint-action@3cfe3a4abbb849e10058ce4af15d205b6da42804 # v4.0.0
with:
args: --verbose
version: latest

@ -10,6 +10,6 @@ jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Release
run: make release

@ -13,13 +13,13 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- uses: advanced-security/sbom-generator-action@375dee8e6144d9fd0ec1f5667b4f6fb4faacefed # v0.0.1
id: sbom
env:
GITHUB_TOKEN: ${{ github.token }}
- uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
- uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
with:
path: ${{steps.sbom.outputs.fileName }}
name: "SBOM"

@ -8,6 +8,6 @@ jobs:
name: Shellcheck
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Run ShellCheck
uses: ludeeus/action-shellcheck@00cae500b08a931fb5698e11e79bfbd38e612a38 # v2.0.0

@ -19,21 +19,21 @@ jobs:
fail-fast: false
matrix:
go-version: ${{fromJson(needs.go-versions.outputs.versions)}}
os: [ubuntu-22.04, ubuntu-20.04, windows-2022, windows-2019, macos-11, macos-12]
os: [ubuntu-22.04, ubuntu-20.04, windows-2022, windows-2019, macos-11, macos-12, macos-13, macos-14]
runs-on: ${{ matrix.os }}
steps:
- name: Install Go
uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0
with:
go-version: ${{ matrix.go-version }}
- name: Checkout code
uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- id: go-env
run: |
echo "::set-output name=cache::$(go env GOCACHE)"
echo "::set-output name=mod-cache::$(go env GOMODCACHE)"
- name: Cache go modules
uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 # v3.3.1
uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 # v4.0.0
with:
path: |
${{ steps.go-env.outputs.cache }}

@ -1,21 +1,21 @@
issues:
max-same-issues: 0
exclude-rules:
- linters:
- gosec
text: "G204"
- linters:
- revive
text: "var-naming"
- linters:
- revive
text: "exported"
- linters:
- revive
text: "empty-block"
- linters:
- revive
text: "unused-parameter"
exclude-rules:
- linters:
- gosec
text: "G204"
- linters:
- revive
text: "var-naming"
- linters:
- revive
text: "exported"
- linters:
- revive
text: "empty-block"
- linters:
- revive
text: "unused-parameter"
linters:
enable:
- asciicheck
@ -26,6 +26,7 @@ linters:
- gofmt
- gofumpt
- goimports
- gomodguard
- gosec
- gosimple
- importas
@ -46,10 +47,16 @@ linters:
- structcheck
- unused
- varcheck
linters-settings:
gci:
sections:
- standard
- default
- prefix(github.com/shirou)
- standard
- default
- prefix(github.com/shirou)
gomodguard:
blocked:
modules:
- io/ioutil:
recommandations:
- io
- os

@ -20,6 +20,7 @@ build_test: ## test only buildable
GOOS=linux GOARCH=loong64 go test ./... | $(BUILD_FAIL_PATTERN)
GOOS=linux GOARCH=riscv64 go test ./... | $(BUILD_FAIL_PATTERN)
GOOS=linux GOARCH=s390x go test ./... | $(BUILD_FAIL_PATTERN)
GOOS=linux GOARCH=mips go test ./... | $(BUILD_FAIL_PATTERN)
GOOS=freebsd GOARCH=amd64 go test ./... | $(BUILD_FAIL_PATTERN)
GOOS=freebsd GOARCH=386 go test ./... | $(BUILD_FAIL_PATTERN)
GOOS=freebsd GOARCH=arm go test ./... | $(BUILD_FAIL_PATTERN)

@ -32,7 +32,7 @@ can be skipped.
- Linux i386/amd64/arm(raspberry pi)
- Windows i386/amd64/arm/arm64
- Darwin amd64/arm64
- OpenBSD amd64 (Thank you @mpfz0r!)
- OpenBSD i386/amd64/armv7/arm64/riscv64 (Thank you @mpfz0r!)
- Solaris amd64 (developed and tested on SmartOS/Illumos, Thank you
@jen20!)
@ -109,6 +109,17 @@ As of v3.23.6, it is now possible to pass a path location using `context`: impor
First priority is given to the value set in `context`, then the value from the environment variable, and finally the default location.
### Caching
As of v3.24.1, it is now possible to cached some values. These values default to false, not cached.
Be very careful that enabling the cache may cause inconsistencies. For example, if you enable caching of boottime on Linux, be aware that unintended values may be returned if [the boottime is changed by NTP after booted](https://github.com/shirou/gopsutil/issues/1070#issuecomment-842512782).
- `host`
- EnableBootTimeCache
- `process`
- EnableBootTimeCache
## Documentation
See https://pkg.go.dev/github.com/shirou/gopsutil/v3 or https://godocs.io/github.com/shirou/gopsutil/v3
@ -190,7 +201,7 @@ Some code is ported from Ohai. Many thanks.
|users |x |x |x |x |x | | |
|pids |x |x |x |x |x | | |
|pid\_exists |x |x |x |x |x | | |
|net\_connections |x | |x |x | | | |
|net\_connections |x |x |x |x | | | |
|net\_protocols |x | | | | | | |
|net\_if\_addrs | | | | | | | |
|net\_if\_stats | | | | | | | |
@ -207,7 +218,7 @@ Some code is ported from Ohai. Many thanks.
|cmdline |x |x | |x |x |
|create\_time |x | | |x |x |
|status |x |x |x |x | |
|cwd |x | | |x | |
|cwd |x | | |x |x |
|exe |x |x |x | |x |
|uids |x |x |x |x | |
|gids |x |x |x |x | |

@ -5,15 +5,12 @@ package cpu
import (
"context"
"regexp"
"strconv"
"strings"
"github.com/shirou/gopsutil/v3/internal/common"
)
var whiteSpaces = regexp.MustCompile(`\s+`)
func TimesWithContext(ctx context.Context, percpu bool) ([]TimesStat, error) {
if percpu {
return []TimesStat{}, common.ErrNotImplementedError
@ -28,8 +25,8 @@ func TimesWithContext(ctx context.Context, percpu bool) ([]TimesStat, error) {
}
ret := TimesStat{CPU: "cpu-total"}
h := whiteSpaces.Split(lines[len(lines)-3], -1) // headers
v := whiteSpaces.Split(lines[len(lines)-2], -1) // values
h := strings.Fields(lines[len(lines)-3]) // headers
v := strings.Fields(lines[len(lines)-2]) // values
for i, header := range h {
if t, err := strconv.ParseFloat(v[i], 64); err == nil {
switch header {
@ -58,14 +55,14 @@ func InfoWithContext(ctx context.Context) ([]InfoStat, error) {
ret := InfoStat{}
for _, line := range strings.Split(string(out), "\n") {
if strings.HasPrefix(line, "Number Of Processors:") {
p := whiteSpaces.Split(line, 4)
p := strings.Fields(line)
if len(p) > 3 {
if t, err := strconv.ParseUint(p[3], 10, 64); err == nil {
ret.Cores = int32(t)
}
}
} else if strings.HasPrefix(line, "Processor Clock Speed:") {
p := whiteSpaces.Split(line, 5)
p := strings.Fields(line)
if len(p) > 4 {
if t, err := strconv.ParseFloat(p[3], 64); err == nil {
switch strings.ToUpper(p[4]) {

@ -4,6 +4,7 @@
package cpu
import (
"os"
"testing"
"github.com/shoenig/go-m1cpu"
@ -23,7 +24,7 @@ func Test_CpuInfo_AppleSilicon(t *testing.T) {
if vv.ModelName == "" {
t.Errorf("could not get CPU info: %v", vv)
}
if vv.Mhz <= 0 {
if vv.Mhz <= 0 && os.Getenv("CI") != "true" {
t.Errorf("could not get frequency of: %s", vv.ModelName)
}
if vv.Mhz > 6000 {

@ -1,5 +1,5 @@
//go:build !darwin && !linux && !freebsd && !openbsd && !solaris && !windows && !dragonfly && !plan9 && !aix
// +build !darwin,!linux,!freebsd,!openbsd,!solaris,!windows,!dragonfly,!plan9,!aix
//go:build !darwin && !linux && !freebsd && !openbsd && !netbsd && !solaris && !windows && !dragonfly && !plan9 && !aix
// +build !darwin,!linux,!freebsd,!openbsd,!netbsd,!solaris,!windows,!dragonfly,!plan9,!aix
package cpu

@ -309,7 +309,7 @@ func InfoWithContext(ctx context.Context) ([]InfoStat, error) {
func parseStatLine(line string) (*TimesStat, error) {
fields := strings.Fields(line)
if len(fields) == 0 {
if len(fields) < 8 {
return nil, errors.New("stat does not contain cpu info")
}

@ -0,0 +1,119 @@
//go:build netbsd
// +build netbsd
package cpu
import (
"context"
"fmt"
"runtime"
"unsafe"
"github.com/shirou/gopsutil/v3/internal/common"
"github.com/tklauser/go-sysconf"
"golang.org/x/sys/unix"
)
const (
// sys/sysctl.h
ctlKern = 1 // "high kernel": proc, limits
ctlHw = 6 // CTL_HW
kernCpTime = 51 // KERN_CPTIME
)
var ClocksPerSec = float64(100)
func init() {
clkTck, err := sysconf.Sysconf(sysconf.SC_CLK_TCK)
// ignore errors
if err == nil {
ClocksPerSec = float64(clkTck)
}
}
func Times(percpu bool) ([]TimesStat, error) {
return TimesWithContext(context.Background(), percpu)
}
func TimesWithContext(ctx context.Context, percpu bool) (ret []TimesStat, err error) {
if !percpu {
mib := []int32{ctlKern, kernCpTime}
buf, _, err := common.CallSyscall(mib)
if err != nil {
return ret, err
}
times := (*cpuTimes)(unsafe.Pointer(&buf[0]))
stat := TimesStat{
CPU: "cpu-total",
User: float64(times.User),
Nice: float64(times.Nice),
System: float64(times.Sys),
Idle: float64(times.Idle),
Irq: float64(times.Intr),
}
return []TimesStat{stat}, nil
}
ncpu, err := unix.SysctlUint32("hw.ncpu")
if err != nil {
return
}
var i uint32
for i = 0; i < ncpu; i++ {
mib := []int32{ctlKern, kernCpTime, int32(i)}
buf, _, err := common.CallSyscall(mib)
if err != nil {
return ret, err
}
stats := (*cpuTimes)(unsafe.Pointer(&buf[0]))
ret = append(ret, TimesStat{
CPU: fmt.Sprintf("cpu%d", i),
User: float64(stats.User),
Nice: float64(stats.Nice),
System: float64(stats.Sys),
Idle: float64(stats.Idle),
Irq: float64(stats.Intr),
})
}
return ret, nil
}
// Returns only one (minimal) CPUInfoStat on NetBSD
func Info() ([]InfoStat, error) {
return InfoWithContext(context.Background())
}
func InfoWithContext(ctx context.Context) ([]InfoStat, error) {
var ret []InfoStat
var err error
c := InfoStat{}
mhz, err := unix.Sysctl("machdep.dmi.processor-frequency")
if err != nil {
return nil, err
}
_, err = fmt.Sscanf(mhz, "%f", &c.Mhz)
if err != nil {
return nil, err
}
ncpu, err := unix.SysctlUint32("hw.ncpuonline")
if err != nil {
return nil, err
}
c.Cores = int32(ncpu)
if c.ModelName, err = unix.Sysctl("machdep.dmi.processor-version"); err != nil {
return nil, err
}
return append(ret, c), nil
}
func CountsWithContext(ctx context.Context, logical bool) (int, error) {
return runtime.NumCPU(), nil
}

@ -0,0 +1,9 @@
package cpu
type cpuTimes struct {
User uint64
Nice uint64
Sys uint64
Intr uint64
Idle uint64
}

@ -0,0 +1,9 @@
package cpu
type cpuTimes struct {
User uint64
Nice uint64
Sys uint64
Intr uint64
Idle uint64
}

@ -0,0 +1,10 @@
package cpu
type cpuTimes struct {
User uint64
Nice uint64
Sys uint64
Spin uint64
Intr uint64
Idle uint64
}

@ -36,6 +36,8 @@ func Times(percpu bool) ([]TimesStat, error) {
return TimesWithContext(context.Background(), percpu)
}
var kstatSplit = regexp.MustCompile(`[:\s]+`)
func TimesWithContext(ctx context.Context, percpu bool) ([]TimesStat, error) {
kstatSysOut, err := invoke.CommandWithContext(ctx, "kstat", "-p", "cpu_stat:*:*:/^idle$|^user$|^kernel$|^iowait$|^swap$/")
if err != nil {
@ -47,9 +49,8 @@ func TimesWithContext(ctx context.Context, percpu bool) ([]TimesStat, error) {
kern := make(map[float64]float64)
iowt := make(map[float64]float64)
// swap := make(map[float64]float64)
re := regexp.MustCompile(`[:\s]+`)
for _, line := range strings.Split(string(kstatSysOut), "\n") {
fields := re.Split(line, -1)
fields := kstatSplit.Split(line, -1)
if fields[0] != "cpu_stat" {
continue
}

@ -1,7 +1,7 @@
package cpu
import (
"io/ioutil"
"os"
"path/filepath"
"reflect"
"sort"
@ -49,7 +49,7 @@ func TestParseISAInfo(t *testing.T) {
}
for _, tc := range cases {
content, err := ioutil.ReadFile(filepath.Join("testdata", "solaris", tc.filename))
content, err := os.ReadFile(filepath.Join("testdata", "solaris", tc.filename))
if err != nil {
t.Errorf("cannot read test case: %s", err)
}
@ -138,7 +138,7 @@ func TestParseProcessorInfo(t *testing.T) {
}
for _, tc := range cases {
content, err := ioutil.ReadFile(filepath.Join("testdata", "solaris", tc.filename))
content, err := os.ReadFile(filepath.Join("testdata", "solaris", tc.filename))
if err != nil {
t.Errorf("cannot read test case: %s", err)
}

@ -12,7 +12,6 @@ import (
"golang.org/x/sys/unix"
)
var whiteSpaces = regexp.MustCompile(`\s+`)
var startBlank = regexp.MustCompile(`^\s+`)
var ignoreFSType = map[string]bool{"procfs": true}
@ -60,7 +59,7 @@ func PartitionsWithContext(ctx context.Context, all bool) ([]PartitionStat, erro
if startBlank.MatchString(line) {
line = "localhost" + line
}
p := whiteSpaces.Split(lines[idx], 6)
p := strings.Fields(lines[idx])
if len(p) < 5 || ignoreFSType[p[colidx["vfs"]]] {
continue
}

@ -1,5 +1,5 @@
//go:build !darwin && !linux && !freebsd && !openbsd && !windows && !solaris && !aix
// +build !darwin,!linux,!freebsd,!openbsd,!windows,!solaris,!aix
//go:build !darwin && !linux && !freebsd && !openbsd && !netbsd && !windows && !solaris && !aix
// +build !darwin,!linux,!freebsd,!openbsd,!netbsd,!windows,!solaris,!aix
package disk

@ -5,11 +5,9 @@ package disk
import (
"bufio"
"bytes"
"context"
"errors"
"fmt"
"io/ioutil"
"os"
"path"
"path/filepath"
@ -486,32 +484,42 @@ func IOCountersWithContext(ctx context.Context, names ...string) (map[string]IOC
return ret, nil
}
func udevData(ctx context.Context, major uint32, minor uint32, name string) (string, error) {
udevDataPath := common.HostRunWithContext(ctx, fmt.Sprintf("udev/data/b%d:%d", major, minor))
if f, err := os.Open(udevDataPath); err == nil {
defer f.Close()
scanner := bufio.NewScanner(f)
for scanner.Scan() {
values := strings.SplitN(scanner.Text(), "=", 3)
if len(values) == 2 && values[0] == name {
return values[1], nil
}
}
return "", scanner.Err()
} else if !os.IsNotExist(err) {
return "", err
}
return "", nil
}
func SerialNumberWithContext(ctx context.Context, name string) (string, error) {
var stat unix.Stat_t
err := unix.Stat(name, &stat)
if err != nil {
if err := unix.Stat(name, &stat); err != nil {
return "", err
}
major := unix.Major(uint64(stat.Rdev))
minor := unix.Minor(uint64(stat.Rdev))
// Try to get the serial from udev data
udevDataPath := common.HostRunWithContext(ctx, fmt.Sprintf("udev/data/b%d:%d", major, minor))
if udevdata, err := ioutil.ReadFile(udevDataPath); err == nil {
scanner := bufio.NewScanner(bytes.NewReader(udevdata))
for scanner.Scan() {
values := strings.Split(scanner.Text(), "=")
if len(values) == 2 && values[0] == "E:ID_SERIAL" {
return values[1], nil
}
}
sserial, _ := udevData(ctx, major, minor, "E:ID_SERIAL")
if sserial != "" {
return sserial, nil
}
// Try to get the serial from sysfs, look at the disk device (minor 0) directly
// because if it is a partition it is not going to contain any device information
devicePath := common.HostSysWithContext(ctx, fmt.Sprintf("dev/block/%d:0/device", major))
model, _ := ioutil.ReadFile(filepath.Join(devicePath, "model"))
serial, _ := ioutil.ReadFile(filepath.Join(devicePath, "serial"))
model, _ := os.ReadFile(filepath.Join(devicePath, "model"))
serial, _ := os.ReadFile(filepath.Join(devicePath, "serial"))
if len(model) > 0 && len(serial) > 0 {
return fmt.Sprintf("%s_%s", string(model), string(serial)), nil
}
@ -521,16 +529,26 @@ func SerialNumberWithContext(ctx context.Context, name string) (string, error) {
func LabelWithContext(ctx context.Context, name string) (string, error) {
// Try label based on devicemapper name
dmname_filename := common.HostSysWithContext(ctx, fmt.Sprintf("block/%s/dm/name", name))
if !common.PathExists(dmname_filename) {
return "", nil
// Could errors.Join errs with Go >= 1.20
if common.PathExists(dmname_filename) {
dmname, err := os.ReadFile(dmname_filename)
if err == nil {
return strings.TrimSpace(string(dmname)), nil
}
}
// Try udev data
var stat unix.Stat_t
if err := unix.Stat(common.HostDevWithContext(ctx, name), &stat); err != nil {
return "", err
}
major := unix.Major(uint64(stat.Rdev))
minor := unix.Minor(uint64(stat.Rdev))
dmname, err := ioutil.ReadFile(dmname_filename)
label, err := udevData(ctx, major, minor, "E:ID_FS_LABEL")
if err != nil {
return "", err
}
return strings.TrimSpace(string(dmname)), nil
return label, nil
}
func getFsType(stat unix.Statfs_t) string {

@ -0,0 +1,152 @@
//go:build netbsd
// +build netbsd
package disk
import (
"context"
"unsafe"
"github.com/shirou/gopsutil/v3/internal/common"
"golang.org/x/sys/unix"
)
const (
// see sys/fstypes.h and `man 5 statvfs`
MNT_RDONLY = 0x00000001 /* read only filesystem */
MNT_SYNCHRONOUS = 0x00000002 /* file system written synchronously */
MNT_NOEXEC = 0x00000004 /* can't exec from filesystem */
MNT_NOSUID = 0x00000008 /* don't honor setuid bits on fs */
MNT_NODEV = 0x00000010 /* don't interpret special files */
MNT_ASYNC = 0x00000040 /* file system written asynchronously */
MNT_NOATIME = 0x04000000 /* Never update access times in fs */
MNT_SOFTDEP = 0x80000000 /* Use soft dependencies */
)
func PartitionsWithContext(ctx context.Context, all bool) ([]PartitionStat, error) {
var ret []PartitionStat
flag := uint64(1) // ST_WAIT/MNT_WAIT, see sys/fstypes.h
// get required buffer size
emptyBufSize := 0
r, _, err := unix.Syscall(
483, // SYS___getvfsstat90 syscall
uintptr(unsafe.Pointer(nil)),
uintptr(unsafe.Pointer(&emptyBufSize)),
uintptr(unsafe.Pointer(&flag)),
)
if err != 0 {
return ret, err
}
mountedFsCount := uint64(r)
// calculate the buffer size
bufSize := sizeOfStatvfs * mountedFsCount
buf := make([]Statvfs, mountedFsCount)
// request agian to get desired mount data
_, _, err = unix.Syscall(
483, // SYS___getvfsstat90 syscall
uintptr(unsafe.Pointer(&buf[0])),
uintptr(unsafe.Pointer(&bufSize)),
uintptr(unsafe.Pointer(&flag)),
)
if err != 0 {
return ret, err
}
for _, stat := range buf {
opts := []string{"rw"}
if stat.Flag&MNT_RDONLY != 0 {
opts = []string{"rw"}
}
if stat.Flag&MNT_SYNCHRONOUS != 0 {
opts = append(opts, "sync")
}
if stat.Flag&MNT_NOEXEC != 0 {
opts = append(opts, "noexec")
}
if stat.Flag&MNT_NOSUID != 0 {
opts = append(opts, "nosuid")
}
if stat.Flag&MNT_NODEV != 0 {
opts = append(opts, "nodev")
}
if stat.Flag&MNT_ASYNC != 0 {
opts = append(opts, "async")
}
if stat.Flag&MNT_SOFTDEP != 0 {
opts = append(opts, "softdep")
}
if stat.Flag&MNT_NOATIME != 0 {
opts = append(opts, "noatime")
}
d := PartitionStat{
Device: common.ByteToString([]byte(stat.Mntfromname[:])),
Mountpoint: common.ByteToString([]byte(stat.Mntonname[:])),
Fstype: common.ByteToString([]byte(stat.Fstypename[:])),
Opts: opts,
}
ret = append(ret, d)
}
return ret, nil
}
func IOCountersWithContext(ctx context.Context, names ...string) (map[string]IOCountersStat, error) {
ret := make(map[string]IOCountersStat)
return ret, common.ErrNotImplementedError
}
func UsageWithContext(ctx context.Context, path string) (*UsageStat, error) {
stat := Statvfs{}
flag := uint64(1) // ST_WAIT/MNT_WAIT, see sys/fstypes.h
_path, e := unix.BytePtrFromString(path)
if e != nil {
return nil, e
}
_, _, err := unix.Syscall(
484, // SYS___statvfs190, see sys/syscall.h
uintptr(unsafe.Pointer(_path)),
uintptr(unsafe.Pointer(&stat)),
uintptr(unsafe.Pointer(&flag)),
)
if err != 0 {
return nil, err
}
// frsize is the real block size on NetBSD. See discuss here: https://bugzilla.samba.org/show_bug.cgi?id=11810
bsize := stat.Frsize
ret := &UsageStat{
Path: path,
Fstype: getFsType(stat),
Total: (uint64(stat.Blocks) * uint64(bsize)),
Free: (uint64(stat.Bavail) * uint64(bsize)),
InodesTotal: (uint64(stat.Files)),
InodesFree: (uint64(stat.Ffree)),
}
ret.InodesUsed = (ret.InodesTotal - ret.InodesFree)
ret.InodesUsedPercent = (float64(ret.InodesUsed) / float64(ret.InodesTotal)) * 100.0
ret.Used = (uint64(stat.Blocks) - uint64(stat.Bfree)) * uint64(bsize)
ret.UsedPercent = (float64(ret.Used) / float64(ret.Total)) * 100.0
return ret, nil
}
func getFsType(stat Statvfs) string {
return common.ByteToString(stat.Fstypename[:])
}
func SerialNumberWithContext(ctx context.Context, name string) (string, error) {
return "", common.ErrNotImplementedError
}
func LabelWithContext(ctx context.Context, name string) (string, error) {
return "", common.ErrNotImplementedError
}

@ -0,0 +1,45 @@
//go:build netbsd && amd64
// +build netbsd,amd64
// Code generated by cmd/cgo -godefs; DO NOT EDIT.
// cgo -godefs types_netbsd.go
package disk
const (
sizeOfStatvfs = 0xce0
)
type (
Statvfs struct {
Flag uint64
Bsize uint64
Frsize uint64
Iosize uint64
Blocks uint64
Bfree uint64
Bavail uint64
Bresvd uint64
Files uint64
Ffree uint64
Favail uint64
Fresvd uint64
Syncreads uint64
Syncwrites uint64
Asyncreads uint64
Asyncwrites uint64
Fsidx _Ctype_struct___0
Fsid uint64
Namemax uint64
Owner uint32
Spare [4]uint64
Fstypename [32]uint8
Mntonname [1024]uint8
Mntfromname [1024]uint8
Mntfromlabel [1024]uint8
}
)
type _Ctype_struct___0 struct {
FsidVal [2]int32
}

@ -0,0 +1,45 @@
//go:build netbsd && arm64
// +build netbsd,arm64
// Code generated by cmd/cgo -godefs; DO NOT EDIT.
// cgo -godefs types_netbsd.go
package disk
const (
sizeOfStatvfs = 0xce0
)
type (
Statvfs struct {
Flag uint64
Bsize uint64
Frsize uint64
Iosize uint64
Blocks uint64
Bfree uint64
Bavail uint64
Bresvd uint64
Files uint64
Ffree uint64
Favail uint64
Fresvd uint64
Syncreads uint64
Syncwrites uint64
Asyncreads uint64
Asyncwrites uint64
Fsidx _Ctype_struct___0
Fsid uint64
Namemax uint64
Owner uint32
Spare [4]uint64
Fstypename [32]uint8
Mntonname [1024]uint8
Mntfromname [1024]uint8
Mntfromlabel [1024]uint8
}
)
type _Ctype_struct___0 struct {
FsidVal [2]int32
}

@ -0,0 +1,40 @@
//go:build openbsd && riscv64
// +build openbsd,riscv64
// Code generated by cmd/cgo -godefs; DO NOT EDIT.
// cgo -godefs disk/types_openbsd.go
package disk
const (
devstat_NO_DATA = 0x00
devstat_READ = 0x01
devstat_WRITE = 0x02
devstat_FREE = 0x03
)
const (
sizeOfDiskstats = 0x70
)
type (
Diskstats struct {
Name [16]int8
Busy int32
Rxfer uint64
Wxfer uint64
Seek uint64
Rbytes uint64
Wbytes uint64
Attachtime Timeval
Timestamp Timeval
Time Timeval
}
Timeval struct {
Sec int64
Usec int64
}
)
type Diskstat struct{}
type bintime struct{}

@ -83,6 +83,8 @@ func PartitionsWithContext(ctx context.Context, all bool) ([]PartitionStat, erro
return ret, err
}
var kstatSplit = regexp.MustCompile(`[:\s]+`)
func IOCountersWithContext(ctx context.Context, names ...string) (map[string]IOCountersStat, error) {
var issolaris bool
if runtime.GOOS == "illumos" {
@ -107,7 +109,6 @@ func IOCountersWithContext(ctx context.Context, names ...string) (map[string]IOC
writesarr := make(map[string]uint64)
rtimearr := make(map[string]uint64)
wtimearr := make(map[string]uint64)
re := regexp.MustCompile(`[:\s]+`)
// in case the name is "/dev/sda1", then convert to "sda1"
for i, name := range names {
@ -115,7 +116,7 @@ func IOCountersWithContext(ctx context.Context, names ...string) (map[string]IOC
}
for _, line := range lines {
fields := re.Split(line, -1)
fields := kstatSplit.Split(line, -1)
if len(fields) == 0 {
continue
}

@ -0,0 +1,30 @@
//go:build ignore
// +build ignore
// Hand writing: _Ctype_struct___0
/*
Input to cgo -godefs.
*/
package disk
/*
#include <sys/types.h>
#include <sys/statvfs.h>
#include <sys/cdefs.h>
#include <sys/featuretest.h>
#include <sys/stdint.h>
#include <machine/ansi.h>
#include <sys/ansi.h>
*/
import "C"
const (
sizeOfStatvfs = C.sizeof_struct_statvfs
)
type (
Statvfs C.struct_statvfs
)

@ -3,14 +3,14 @@ module github.com/shirou/gopsutil/v3
go 1.15
require (
github.com/google/go-cmp v0.5.9
github.com/google/go-cmp v0.6.0
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c
github.com/shoenig/go-m1cpu v0.1.6
github.com/stretchr/testify v1.8.4
github.com/tklauser/go-sysconf v0.3.12
github.com/yusufpapurcu/wmi v1.2.3
golang.org/x/sys v0.11.0
github.com/yusufpapurcu/wmi v1.2.4
golang.org/x/sys v0.17.0
)
retract v3.22.11

@ -4,8 +4,9 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4=
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
@ -27,13 +28,14 @@ github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFA
github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI=
github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk=
github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY=
github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw=
github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM=
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=

@ -62,6 +62,13 @@ func (t TemperatureStat) String() string {
return string(s)
}
var enableBootTimeCache bool
// EnableBootTimeCache change cache behavior of BootTime. If true, cache BootTime value. Default is false.
func EnableBootTimeCache(enable bool) {
enableBootTimeCache = enable
}
func Info() (*InfoStat, error) {
return InfoWithContext(context.Background())
}

@ -1,5 +1,5 @@
//go:build darwin || freebsd || openbsd
// +build darwin freebsd openbsd
//go:build darwin || freebsd || openbsd || netbsd
// +build darwin freebsd openbsd netbsd
package host
@ -14,16 +14,20 @@ import (
var cachedBootTime uint64
func BootTimeWithContext(ctx context.Context) (uint64, error) {
t := atomic.LoadUint64(&cachedBootTime)
if t != 0 {
return t, nil
if enableBootTimeCache {
t := atomic.LoadUint64(&cachedBootTime)
if t != 0 {
return t, nil
}
}
tv, err := unix.SysctlTimeval("kern.boottime")
if err != nil {
return 0, err
}
atomic.StoreUint64(&cachedBootTime, uint64(tv.Sec))
if enableBootTimeCache {
atomic.StoreUint64(&cachedBootTime, uint64(tv.Sec))
}
return uint64(tv.Sec), nil
}

@ -8,7 +8,7 @@ import (
"context"
"encoding/binary"
"errors"
"io/ioutil"
"io"
"os"
"strings"
"unsafe"
@ -59,11 +59,14 @@ func UsersWithContext(ctx context.Context) ([]UserStat, error) {
}
defer file.Close()
buf, err := ioutil.ReadAll(file)
buf, err := io.ReadAll(file)
if err != nil {
return ret, err
}
// Skip macOS utmpx header part
buf = buf[604:]
u := Utmpx{}
entrySize := int(unsafe.Sizeof(u))
count := len(buf) / entrySize

@ -1,5 +1,5 @@
//go:build !darwin && !linux && !freebsd && !openbsd && !solaris && !windows
// +build !darwin,!linux,!freebsd,!openbsd,!solaris,!windows
//go:build !darwin && !linux && !freebsd && !openbsd && !netbsd && !solaris && !windows
// +build !darwin,!linux,!freebsd,!openbsd,!netbsd,!solaris,!windows
package host

@ -7,7 +7,7 @@ import (
"bytes"
"context"
"encoding/binary"
"io/ioutil"
"io"
"math"
"os"
"strings"
@ -54,7 +54,7 @@ func UsersWithContext(ctx context.Context) ([]UserStat, error) {
}
defer file.Close()
buf, err := ioutil.ReadAll(file)
buf, err := io.ReadAll(file)
if err != nil {
return ret, err
}
@ -111,7 +111,7 @@ func getUsersFromUtmp(utmpfile string) ([]UserStat, error) {
}
defer file.Close()
buf, err := ioutil.ReadAll(file)
buf, err := io.ReadAll(file)
if err != nil {
return ret, err
}

@ -8,7 +8,7 @@ import (
"context"
"encoding/binary"
"fmt"
"io/ioutil"
"io"
"os"
"path/filepath"
"regexp"
@ -71,7 +71,7 @@ func numProcs(ctx context.Context) (uint64, error) {
}
func BootTimeWithContext(ctx context.Context) (uint64, error) {
return common.BootTimeWithContext(ctx)
return common.BootTimeWithContext(ctx, enableBootTimeCache)
}
func UptimeWithContext(ctx context.Context) (uint64, error) {
@ -91,7 +91,7 @@ func UsersWithContext(ctx context.Context) ([]UserStat, error) {
}
defer file.Close()
buf, err := ioutil.ReadAll(file)
buf, err := io.ReadAll(file)
if err != nil {
return nil, err
}
@ -212,6 +212,12 @@ func PlatformInformationWithContext(ctx context.Context) (platform string, famil
} else if lsb.ID == `"Cumulus Linux"` {
platform = "cumuluslinux"
version = lsb.Release
} else if lsb.ID == "uos" {
platform = "uos"
version = lsb.Release
} else if lsb.ID == "Deepin" {
platform = "Deepin"
version = lsb.Release
} else {
if common.PathExistsWithContents("/usr/bin/raspi-config") {
platform = "raspbian"
@ -223,47 +229,47 @@ func PlatformInformationWithContext(ctx context.Context) (platform string, famil
version = contents[0]
}
}
} else if common.PathExists(common.HostEtcWithContext(ctx, "neokylin-release")) {
} else if common.PathExistsWithContents(common.HostEtcWithContext(ctx, "neokylin-release")) {
contents, err := common.ReadLines(common.HostEtcWithContext(ctx, "neokylin-release"))
if err == nil {
version = getRedhatishVersion(contents)
platform = getRedhatishPlatform(contents)
}
} else if common.PathExists(common.HostEtcWithContext(ctx, "redhat-release")) {
} else if common.PathExistsWithContents(common.HostEtcWithContext(ctx, "redhat-release")) {
contents, err := common.ReadLines(common.HostEtcWithContext(ctx, "redhat-release"))
if err == nil {
version = getRedhatishVersion(contents)
platform = getRedhatishPlatform(contents)
}
} else if common.PathExists(common.HostEtcWithContext(ctx, "system-release")) {
} else if common.PathExistsWithContents(common.HostEtcWithContext(ctx, "system-release")) {
contents, err := common.ReadLines(common.HostEtcWithContext(ctx, "system-release"))
if err == nil {
version = getRedhatishVersion(contents)
platform = getRedhatishPlatform(contents)
}
} else if common.PathExists(common.HostEtcWithContext(ctx, "gentoo-release")) {
} else if common.PathExistsWithContents(common.HostEtcWithContext(ctx, "gentoo-release")) {
platform = "gentoo"
contents, err := common.ReadLines(common.HostEtcWithContext(ctx, "gentoo-release"))
if err == nil {
version = getRedhatishVersion(contents)
}
} else if common.PathExists(common.HostEtcWithContext(ctx, "SuSE-release")) {
} else if common.PathExistsWithContents(common.HostEtcWithContext(ctx, "SuSE-release")) {
contents, err := common.ReadLines(common.HostEtcWithContext(ctx, "SuSE-release"))
if err == nil {
version = getSuseVersion(contents)
platform = getSusePlatform(contents)
}
// TODO: slackware detecion
} else if common.PathExists(common.HostEtcWithContext(ctx, "arch-release")) {
} else if common.PathExistsWithContents(common.HostEtcWithContext(ctx, "arch-release")) {
platform = "arch"
version = lsb.Release
} else if common.PathExists(common.HostEtcWithContext(ctx, "alpine-release")) {
} else if common.PathExistsWithContents(common.HostEtcWithContext(ctx, "alpine-release")) {
platform = "alpine"
contents, err := common.ReadLines(common.HostEtcWithContext(ctx, "alpine-release"))
if err == nil && len(contents) > 0 && contents[0] != "" {
version = contents[0]
}
} else if common.PathExists(common.HostEtcWithContext(ctx, "os-release")) {
} else if common.PathExistsWithContents(common.HostEtcWithContext(ctx, "os-release")) {
p, v, err := common.GetOSReleaseWithContext(ctx)
if err == nil {
platform = p
@ -289,7 +295,7 @@ func PlatformInformationWithContext(ctx context.Context) (platform string, famil
platform = strings.Trim(platform, `"`)
switch platform {
case "debian", "ubuntu", "linuxmint", "raspbian", "Kylin", "cumuluslinux":
case "debian", "ubuntu", "linuxmint", "raspbian", "Kylin", "cumuluslinux", "uos", "Deepin":
family = "debian"
case "fedora":
family = "fedora"
@ -333,13 +339,15 @@ func getSlackwareVersion(contents []string) string {
return c
}
var redhatishReleaseMatch = regexp.MustCompile(`release (\w[\d.]*)`)
func getRedhatishVersion(contents []string) string {
c := strings.ToLower(strings.Join(contents, ""))
if strings.Contains(c, "rawhide") {
return "rawhide"
}
if matches := regexp.MustCompile(`release (\w[\d.]*)`).FindStringSubmatch(c); matches != nil {
if matches := redhatishReleaseMatch.FindStringSubmatch(c); matches != nil {
return matches[1]
}
return ""
@ -356,12 +364,17 @@ func getRedhatishPlatform(contents []string) string {
return f[0]
}
var (
suseVersionMatch = regexp.MustCompile(`VERSION = ([\d.]+)`)
susePatchLevelMatch = regexp.MustCompile(`PATCHLEVEL = (\d+)`)
)
func getSuseVersion(contents []string) string {
version := ""
for _, line := range contents {
if matches := regexp.MustCompile(`VERSION = ([\d.]+)`).FindStringSubmatch(line); matches != nil {
if matches := suseVersionMatch.FindStringSubmatch(line); matches != nil {
version = matches[1]
} else if matches := regexp.MustCompile(`PATCHLEVEL = ([\d]+)`).FindStringSubmatch(line); matches != nil {
} else if matches = susePatchLevelMatch.FindStringSubmatch(line); matches != nil {
version = version + "." + matches[1]
}
}
@ -411,13 +424,13 @@ func SensorsTemperaturesWithContext(ctx context.Context) ([]TemperatureStat, err
}
for _, file := range files {
// Get the name of the temperature you are reading
name, err := ioutil.ReadFile(filepath.Join(file, "type"))
name, err := os.ReadFile(filepath.Join(file, "type"))
if err != nil {
warns.Add(err)
continue
}
// Get the temperature reading
current, err := ioutil.ReadFile(filepath.Join(file, "temp"))
current, err := os.ReadFile(filepath.Join(file, "temp"))
if err != nil {
warns.Add(err)
continue
@ -461,13 +474,13 @@ func SensorsTemperaturesWithContext(ctx context.Context) ([]TemperatureStat, err
// Get the label of the temperature you are reading
label := ""
if raw, _ = ioutil.ReadFile(basepath + "_label"); len(raw) != 0 {
if raw, _ = os.ReadFile(basepath + "_label"); len(raw) != 0 {
// Format the label from "Core 0" to "core_0"
label = strings.Join(strings.Split(strings.TrimSpace(strings.ToLower(string(raw))), " "), "_")
}
// Get the name of the temperature you are reading
if raw, err = ioutil.ReadFile(filepath.Join(directory, "name")); err != nil {
if raw, err = os.ReadFile(filepath.Join(directory, "name")); err != nil {
warns.Add(err)
continue
}
@ -479,7 +492,7 @@ func SensorsTemperaturesWithContext(ctx context.Context) ([]TemperatureStat, err
}
// Get the temperature reading
if raw, err = ioutil.ReadFile(file); err != nil {
if raw, err = os.ReadFile(file); err != nil {
warns.Add(err)
continue
}
@ -513,7 +526,7 @@ func optionalValueReadFromFile(filename string) float64 {
return 0
}
if raw, err = ioutil.ReadFile(filename); err != nil {
if raw, err = os.ReadFile(filename); err != nil {
return 0
}

@ -0,0 +1,55 @@
//go:build netbsd
// +build netbsd
package host
import (
"context"
"strings"
"github.com/shirou/gopsutil/v3/internal/common"
"golang.org/x/sys/unix"
)
func HostIDWithContext(ctx context.Context) (string, error) {
return "", common.ErrNotImplementedError
}
func numProcs(ctx context.Context) (uint64, error) {
return 0, common.ErrNotImplementedError
}
func PlatformInformationWithContext(ctx context.Context) (string, string, string, error) {
platform := ""
family := ""
version := ""
p, err := unix.Sysctl("kern.ostype")
if err == nil {
platform = strings.ToLower(p)
}
v, err := unix.Sysctl("kern.osrelease")
if err == nil {
version = strings.ToLower(v)
}
return platform, family, version, nil
}
func VirtualizationWithContext(ctx context.Context) (string, string, error) {
return "", "", common.ErrNotImplementedError
}
func UsersWithContext(ctx context.Context) ([]UserStat, error) {
var ret []UserStat
return ret, common.ErrNotImplementedError
}
func SensorsTemperaturesWithContext(ctx context.Context) ([]TemperatureStat, error) {
return []TemperatureStat{}, common.ErrNotImplementedError
}
func KernelVersionWithContext(ctx context.Context) (string, error) {
_, _, version, err := PlatformInformationWithContext(ctx)
return version, err
}

@ -7,7 +7,7 @@ import (
"bytes"
"context"
"encoding/binary"
"io/ioutil"
"io"
"os"
"strings"
"unsafe"
@ -65,7 +65,7 @@ func UsersWithContext(ctx context.Context) ([]UserStat, error) {
}
defer file.Close()
buf, err := ioutil.ReadAll(file)
buf, err := io.ReadAll(file)
if err != nil {
return ret, err
}

@ -0,0 +1,36 @@
//go:build openbsd && riscv64
// +build openbsd,riscv64
// Code generated by cmd/cgo -godefs; DO NOT EDIT.
// cgo -godefs host/types_openbsd.go
package host
const (
sizeofPtr = 0x8
sizeofShort = 0x2
sizeofInt = 0x4
sizeofLong = 0x8
sizeofLongLong = 0x8
sizeOfUtmp = 0x130
)
type (
_C_short int16
_C_int int32
_C_long int64
_C_long_long int64
)
type (
Utmp struct {
Line [8]int8
Name [32]int8
Host [256]int8
Time int64
}
Timeval struct {
Sec int64
Usec int64
}
)

@ -1,5 +1,5 @@
//go:build linux || freebsd || openbsd || darwin || solaris
// +build linux freebsd openbsd darwin solaris
//go:build linux || freebsd || openbsd || netbsd || darwin || solaris
// +build linux freebsd openbsd netbsd darwin solaris
package host

@ -7,7 +7,6 @@ import (
"encoding/csv"
"fmt"
"io"
"io/ioutil"
"os"
"regexp"
"strconv"
@ -60,7 +59,7 @@ func HostIDWithContext(ctx context.Context) (string, error) {
// Count number of processes based on the number of entries in /proc
func numProcs(ctx context.Context) (uint64, error) {
dirs, err := ioutil.ReadDir("/proc")
dirs, err := os.ReadDir("/proc")
if err != nil {
return 0, err
}
@ -138,7 +137,7 @@ func VirtualizationWithContext(ctx context.Context) (string, string, error) {
// Find distribution name from /etc/release
func parseReleaseFile() (string, error) {
b, err := ioutil.ReadFile("/etc/release")
b, err := os.ReadFile("/etc/release")
if err != nil {
return "", err
}

@ -89,6 +89,7 @@ func TestUsers(t *testing.T) {
if u == empty {
t.Errorf("Could not Users %v", v)
}
t.Log(u)
}
}
@ -194,3 +195,17 @@ func TestPlatformInformation(t *testing.T) {
t.Logf("PlatformInformation(): %v, %v, %v", platform, family, version)
}
func BenchmarkBootTimeWithCache(b *testing.B) {
EnableBootTimeCache(true)
for i := 0; i < b.N; i++ {
BootTime()
}
}
func BenchmarkBootTimeWithoutCache(b *testing.B) {
EnableBootTimeCache(false)
for i := 0; i < b.N; i++ {
BootTime()
}
}

@ -127,16 +127,20 @@ func uptimeMillis() (uint64, error) {
var cachedBootTime uint64
func BootTimeWithContext(ctx context.Context) (uint64, error) {
t := atomic.LoadUint64(&cachedBootTime)
if t != 0 {
return t, nil
if enableBootTimeCache {
t := atomic.LoadUint64(&cachedBootTime)
if t != 0 {
return t, nil
}
}
up, err := uptimeMillis()
if err != nil {
return 0, err
}
t = uint64((time.Duration(timeSinceMillis(up)) * time.Millisecond).Seconds())
atomic.StoreUint64(&cachedBootTime, t)
t := uint64((time.Duration(timeSinceMillis(up)) * time.Millisecond).Seconds())
if enableBootTimeCache {
atomic.StoreUint64(&cachedBootTime, t)
}
return t, nil
}

@ -14,7 +14,6 @@ import (
"errors"
"fmt"
"io"
"io/ioutil"
"net/url"
"os"
"os/exec"
@ -87,7 +86,7 @@ func (i FakeInvoke) Command(name string, arg ...string) ([]byte, error) {
fpath += "_" + i.Suffix
}
if PathExists(fpath) {
return ioutil.ReadFile(fpath)
return os.ReadFile(fpath)
}
return []byte{}, fmt.Errorf("could not find testdata: %s", fpath)
}
@ -100,7 +99,7 @@ var ErrNotImplementedError = errors.New("not implemented yet")
// ReadFile reads contents from a file
func ReadFile(filename string) (string, error) {
content, err := ioutil.ReadFile(filename)
content, err := os.ReadFile(filename)
if err != nil {
return "", err
}
@ -344,7 +343,7 @@ func PathExistsWithContents(filename string) bool {
if err != nil {
return false
}
return info.Size() > 4 // at least 4 bytes
return info.Size() > 4 && !info.IsDir() // at least 4 bytes
}
// GetEnvWithContext retrieves the environment variable key. If it does not exist it returns the default.

@ -12,10 +12,14 @@ import (
"strconv"
"strings"
"sync"
"sync/atomic"
"syscall"
"time"
)
// cachedBootTime must be accessed via atomic.Load/StoreUint64
var cachedBootTime uint64
func DoSysctrl(mib string) ([]string, error) {
cmd := exec.Command("sysctl", "-n", mib)
cmd.Env = getSysctrlEnv(os.Environ())
@ -56,7 +60,14 @@ func NumProcsWithContext(ctx context.Context) (uint64, error) {
return cnt, nil
}
func BootTimeWithContext(ctx context.Context) (uint64, error) {
func BootTimeWithContext(ctx context.Context, enableCache bool) (uint64, error) {
if enableCache {
t := atomic.LoadUint64(&cachedBootTime)
if t != 0 {
return t, nil
}
}
system, role, err := VirtualizationWithContext(ctx)
if err != nil {
return 0, err
@ -72,7 +83,13 @@ func BootTimeWithContext(ctx context.Context) (uint64, error) {
}
if useStatFile {
return readBootTimeStat(ctx)
t, err := readBootTimeStat(ctx)
if err != nil {
return 0, err
}
if enableCache {
atomic.StoreUint64(&cachedBootTime, t)
}
}
filename := HostProcWithContext(ctx, "uptime")
@ -90,6 +107,11 @@ func BootTimeWithContext(ctx context.Context) (uint64, error) {
}
currentTime := float64(time.Now().UnixNano()) / float64(time.Second)
t := currentTime - b
if enableCache {
atomic.StoreUint64(&cachedBootTime, uint64(t))
}
return uint64(t), nil
}
@ -307,7 +329,7 @@ func GetOSReleaseWithContext(ctx context.Context) (platform string, version stri
switch field[0] {
case "ID": // use ID for lowercase
platform = trimQuotes(field[1])
case "VERSION":
case "VERSION_ID":
version = trimQuotes(field[1])
}
}

@ -0,0 +1,66 @@
//go:build netbsd
// +build netbsd
package common
import (
"os"
"os/exec"
"strings"
"unsafe"
"golang.org/x/sys/unix"
)
func DoSysctrl(mib string) ([]string, error) {
cmd := exec.Command("sysctl", "-n", mib)
cmd.Env = getSysctrlEnv(os.Environ())
out, err := cmd.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
}
func CallSyscall(mib []int32) ([]byte, uint64, error) {
mibptr := unsafe.Pointer(&mib[0])
miblen := uint64(len(mib))
// get required buffer size
length := uint64(0)
_, _, err := unix.Syscall6(
unix.SYS___SYSCTL,
uintptr(mibptr),
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 = unix.Syscall6(
unix.SYS___SYSCTL,
uintptr(mibptr),
uintptr(miblen),
uintptr(unsafe.Pointer(&buf[0])),
uintptr(unsafe.Pointer(&length)),
0,
0)
if err != 0 {
return buf, length, err
}
return buf, length, nil
}

@ -5,7 +5,7 @@ package load
import (
"context"
"io/ioutil"
"os"
"strconv"
"strings"
"syscall"
@ -76,7 +76,7 @@ func Misc() (*MiscStat, error) {
func MiscWithContext(ctx context.Context) (*MiscStat, error) {
filename := common.HostProcWithContext(ctx, "stat")
out, err := ioutil.ReadFile(filename)
out, err := os.ReadFile(filename)
if err != nil {
return nil, err
}
@ -126,7 +126,7 @@ func getProcsTotal(ctx context.Context) (int64, error) {
func readLoadAvgFromFile(ctx context.Context) ([]string, error) {
loadavgFilename := common.HostProcWithContext(ctx, "loadavg")
line, err := ioutil.ReadFile(loadavgFilename)
line, err := os.ReadFile(loadavgFilename)
if err != nil {
return nil, err
}

@ -5,7 +5,6 @@ package load
import (
"context"
"log"
"math"
"sync"
"time"
@ -47,6 +46,7 @@ func loadAvgGoroutine(ctx context.Context) {
}
loadAvgMutex.Lock()
loadErr = err
loadAvg1M = loadAvg1M*loadAvgFactor1M + currentLoad*(1-loadAvgFactor1M)
loadAvg5M = loadAvg5M*loadAvgFactor5M + currentLoad*(1-loadAvgFactor5M)
loadAvg15M = loadAvg15M*loadAvgFactor15M + currentLoad*(1-loadAvgFactor15M)

@ -50,6 +50,7 @@ type VirtualMemoryStat struct {
// https://www.centos.org/docs/5/html/5.1/Deployment_Guide/s2-proc-meminfo.html
// https://www.kernel.org/doc/Documentation/filesystems/proc.txt
// https://www.kernel.org/doc/Documentation/vm/overcommit-accounting
// https://www.kernel.org/doc/Documentation/vm/transhuge.txt
Buffers uint64 `json:"buffers"`
Cached uint64 `json:"cached"`
WriteBack uint64 `json:"writeBack"`
@ -78,6 +79,7 @@ type VirtualMemoryStat struct {
HugePagesRsvd uint64 `json:"hugePagesRsvd"`
HugePagesSurp uint64 `json:"hugePagesSurp"`
HugePageSize uint64 `json:"hugePageSize"`
AnonHugePages uint64 `json:"anonHugePages"`
}
type SwapMemoryStat struct {

@ -5,15 +5,12 @@ package mem
import (
"context"
"regexp"
"strconv"
"strings"
"github.com/shirou/gopsutil/v3/internal/common"
)
var whiteSpaces = regexp.MustCompile(`\s+`)
func VirtualMemoryWithContext(ctx context.Context) (*VirtualMemoryStat, error) {
vmem, swap, err := callSVMon(ctx)
if err != nil {
@ -49,7 +46,7 @@ func callSVMon(ctx context.Context) (*VirtualMemoryStat, *SwapMemoryStat, error)
swap := &SwapMemoryStat{}
for _, line := range strings.Split(string(out), "\n") {
if strings.HasPrefix(line, "memory") {
p := whiteSpaces.Split(line, 7)
p := strings.Fields(line)
if len(p) > 2 {
if t, err := strconv.ParseUint(p[1], 10, 64); err == nil {
vmem.Total = t * pagesize
@ -65,7 +62,7 @@ func callSVMon(ctx context.Context) (*VirtualMemoryStat, *SwapMemoryStat, error)
}
}
} else if strings.HasPrefix(line, "pg space") {
p := whiteSpaces.Split(line, 4)
p := strings.Fields(line)
if len(p) > 3 {
if t, err := strconv.ParseUint(p[2], 10, 64); err == nil {
swap.Total = t * pagesize

@ -1,5 +1,5 @@
//go:build freebsd || openbsd
// +build freebsd openbsd
//go:build freebsd || openbsd || netbsd
// +build freebsd openbsd netbsd
package mem

@ -1,5 +1,5 @@
//go:build !darwin && !linux && !freebsd && !openbsd && !solaris && !windows && !plan9 && !aix
// +build !darwin,!linux,!freebsd,!openbsd,!solaris,!windows,!plan9,!aix
//go:build !darwin && !linux && !freebsd && !openbsd && !solaris && !windows && !plan9 && !aix && !netbsd
// +build !darwin,!linux,!freebsd,!openbsd,!solaris,!windows,!plan9,!aix,!netbsd
package mem

@ -311,6 +311,12 @@ func fillFromMeminfoWithContext(ctx context.Context) (*VirtualMemoryStat, *Virtu
return ret, retEx, err
}
ret.HugePageSize = t * 1024
case "AnonHugePages":
t, err := strconv.ParseUint(value, 10, 64)
if err != nil {
return ret, retEx, err
}
ret.AnonHugePages = t * 1024
}
}

@ -108,6 +108,16 @@ var virtualMemoryTests = []struct {
HugePageSize: 0,
},
},
{
"anonhugepages", &VirtualMemoryStat{
Total: 260799420 * 1024,
Available: 127880216 * 1024,
Free: 119443248 * 1024,
AnonHugePages: 50409472 * 1024,
Used: 144748720128,
UsedPercent: 54.20110673559013,
},
},
}
func TestVirtualMemoryLinux(t *testing.T) {

@ -0,0 +1,87 @@
//go:build netbsd
// +build netbsd
package mem
import (
"context"
"errors"
"fmt"
"golang.org/x/sys/unix"
)
func GetPageSize() (uint64, error) {
return GetPageSizeWithContext(context.Background())
}
func GetPageSizeWithContext(ctx context.Context) (uint64, error) {
uvmexp, err := unix.SysctlUvmexp("vm.uvmexp2")
if err != nil {
return 0, err
}
return uint64(uvmexp.Pagesize), nil
}
func VirtualMemory() (*VirtualMemoryStat, error) {
return VirtualMemoryWithContext(context.Background())
}
func VirtualMemoryWithContext(ctx context.Context) (*VirtualMemoryStat, error) {
uvmexp, err := unix.SysctlUvmexp("vm.uvmexp2")
if err != nil {
return nil, err
}
p := uint64(uvmexp.Pagesize)
ret := &VirtualMemoryStat{
Total: uint64(uvmexp.Npages) * p,
Free: uint64(uvmexp.Free) * p,
Active: uint64(uvmexp.Active) * p,
Inactive: uint64(uvmexp.Inactive) * p,
Cached: 0, // not available
Wired: uint64(uvmexp.Wired) * p,
}
ret.Available = ret.Inactive + ret.Cached + ret.Free
ret.Used = ret.Total - ret.Available
ret.UsedPercent = float64(ret.Used) / float64(ret.Total) * 100.0
// Get buffers from vm.bufmem sysctl
ret.Buffers, err = unix.SysctlUint64("vm.bufmem")
if err != nil {
return nil, err
}
return ret, nil
}
// Return swapctl summary info
func SwapMemory() (*SwapMemoryStat, error) {
return SwapMemoryWithContext(context.Background())
}
func SwapMemoryWithContext(ctx context.Context) (*SwapMemoryStat, error) {
out, err := invoke.CommandWithContext(ctx, "swapctl", "-sk")
if err != nil {
return &SwapMemoryStat{}, nil
}
line := string(out)
var total, used, free uint64
_, err = fmt.Sscanf(line,
"total: %d 1K-blocks allocated, %d used, %d available",
&total, &used, &free)
if err != nil {
return nil, errors.New("failed to parse swapctl output")
}
percent := float64(used) / float64(total) * 100
return &SwapMemoryStat{
Total: total * 1024,
Used: used * 1024,
Free: free * 1024,
UsedPercent: percent,
}, nil
}

@ -0,0 +1,38 @@
//go:build openbsd && riscv64
// +build openbsd,riscv64
// Code generated by cmd/cgo -godefs; DO NOT EDIT.
// cgo -godefs mem/types_openbsd.go
package mem
const (
CTLVfs = 10
VfsGeneric = 0
VfsBcacheStat = 3
)
const (
sizeOfBcachestats = 0x90
)
type Bcachestats struct {
Numbufs int64
Numbufpages int64
Numdirtypages int64
Numcleanpages int64
Pendingwrites int64
Pendingreads int64
Numwrites int64
Numreads int64
Cachehits int64
Busymapped int64
Dmapages int64
Highpages int64
Delwribufs int64
Kvaslots int64
Avail int64
Highflips int64
Highflops int64
Dmaflips int64
}

@ -89,7 +89,7 @@ func TestVirtualMemoryStat_String(t *testing.T) {
Free: 40,
}
t.Log(v)
e := `{"total":10,"available":20,"used":30,"usedPercent":30.1,"free":40,"active":0,"inactive":0,"wired":0,"laundry":0,"buffers":0,"cached":0,"writeBack":0,"dirty":0,"writeBackTmp":0,"shared":0,"slab":0,"sreclaimable":0,"sunreclaim":0,"pageTables":0,"swapCached":0,"commitLimit":0,"committedAS":0,"highTotal":0,"highFree":0,"lowTotal":0,"lowFree":0,"swapTotal":0,"swapFree":0,"mapped":0,"vmallocTotal":0,"vmallocUsed":0,"vmallocChunk":0,"hugePagesTotal":0,"hugePagesFree":0,"hugePagesRsvd":0,"hugePagesSurp":0,"hugePageSize":0}`
e := `{"total":10,"available":20,"used":30,"usedPercent":30.1,"free":40,"active":0,"inactive":0,"wired":0,"laundry":0,"buffers":0,"cached":0,"writeBack":0,"dirty":0,"writeBackTmp":0,"shared":0,"slab":0,"sreclaimable":0,"sunreclaim":0,"pageTables":0,"swapCached":0,"commitLimit":0,"committedAS":0,"highTotal":0,"highFree":0,"lowTotal":0,"lowFree":0,"swapTotal":0,"swapFree":0,"mapped":0,"vmallocTotal":0,"vmallocUsed":0,"vmallocChunk":0,"hugePagesTotal":0,"hugePagesFree":0,"hugePagesRsvd":0,"hugePagesSurp":0,"hugePageSize":0,"anonHugePages":0}`
if e != fmt.Sprintf("%v", v) {
t.Errorf("VirtualMemoryStat string is invalid: %v", v)
}

@ -0,0 +1,4 @@
MemTotal: 260799420 kB
MemFree: 119443248 kB
MemAvailable: 127880216 kB
AnonHugePages: 50409472 kB

@ -10,7 +10,6 @@ import (
"errors"
"fmt"
"io"
"io/ioutil"
"net"
"os"
"strconv"
@ -643,7 +642,7 @@ func (p *process) getUids(ctx context.Context) ([]int32, error) {
func (p *process) fillFromStatus(ctx context.Context) error {
pid := p.Pid
statPath := common.HostProcWithContext(ctx, strconv.Itoa(int(pid)), "status")
contents, err := ioutil.ReadFile(statPath)
contents, err := os.ReadFile(statPath)
if err != nil {
return err
}
@ -784,7 +783,7 @@ func processInetWithContext(ctx context.Context, file string, kind netConnection
// This minimizes duplicates in the returned connections
// For more info:
// https://github.com/shirou/gopsutil/pull/361
contents, err := ioutil.ReadFile(file)
contents, err := os.ReadFile(file)
if err != nil {
return nil, err
}
@ -845,7 +844,7 @@ func processUnix(file string, kind netConnectionKindType, inodes map[string][]in
// This minimizes duplicates in the returned connections
// For more info:
// https://github.com/shirou/gopsutil/pull/361
contents, err := ioutil.ReadFile(file)
contents, err := os.ReadFile(file)
if err != nil {
return nil, err
}

@ -3,7 +3,6 @@ package net
import (
"context"
"fmt"
"io/ioutil"
"net"
"os"
"strings"
@ -17,7 +16,7 @@ import (
func TestIOCountersByFileParsing(t *testing.T) {
// Prpare a temporary file, which will be read during the test
tmpfile, err := ioutil.TempFile("", "proc_dev_net")
tmpfile, err := os.CreateTemp("", "proc_dev_net")
defer os.Remove(tmpfile.Name()) // clean up
assert.Nil(t, err, "Temporary file creation failed: ", err)
@ -195,7 +194,7 @@ func TestReverse(t *testing.T) {
}
func TestConntrackStatFileParsing(t *testing.T) {
tmpfile, err := ioutil.TempFile("", "proc_net_stat_conntrack")
tmpfile, err := os.CreateTemp("", "proc_net_stat_conntrack")
defer os.Remove(tmpfile.Name())
assert.Nil(t, err, "Temporary file creation failed: ", err)

@ -23,6 +23,8 @@ func IOCounters(pernic bool) ([]IOCountersStat, error) {
return IOCountersWithContext(context.Background(), pernic)
}
var kstatSplit = regexp.MustCompile(`[:\s]+`)
func IOCountersWithContext(ctx context.Context, pernic bool) ([]IOCountersStat, error) {
// collect all the net class's links with below statistics
filterstr := "/^(?!vnic)/::phys:/^rbytes64$|^ipackets64$|^idrops64$|^ierrors$|^obytes64$|^opackets64$|^odrops64$|^oerrors$/"
@ -47,9 +49,8 @@ func IOCountersWithContext(ctx context.Context, pernic bool) ([]IOCountersStat,
odrops64arr := make(map[string]uint64)
oerrorsarr := make(map[string]uint64)
re := regexp.MustCompile(`[:\s]+`)
for _, line := range lines {
fields := re.Split(line, -1)
fields := kstatSplit.Split(line, -1)
interfaceName := fields[0]
instance := fields[1]
switch fields[3] {

@ -171,6 +171,13 @@ func (p NumCtxSwitchesStat) String() string {
return string(s)
}
var enableBootTimeCache bool
// EnableBootTimeCache change cache behavior of BootTime. If true, cache BootTime value. Default is false.
func EnableBootTimeCache(enable bool) {
enableBootTimeCache = enable
}
// Pids returns a slice of process ID list which are running now.
func Pids() ([]int32, error) {
return PidsWithContext(context.Background())

@ -286,11 +286,11 @@ func (p *Process) ChildrenWithContext(ctx context.Context) ([]*Process, error) {
}
func (p *Process) ConnectionsWithContext(ctx context.Context) ([]net.ConnectionStat, error) {
return nil, common.ErrNotImplementedError
return net.ConnectionsPidWithContext(ctx, "all", p.Pid)
}
func (p *Process) ConnectionsMaxWithContext(ctx context.Context, max int) ([]net.ConnectionStat, error) {
return nil, common.ErrNotImplementedError
return net.ConnectionsPidMaxWithContext(ctx, "all", p.Pid, max)
}
func ProcessesWithContext(ctx context.Context) ([]*Process, error) {

@ -9,7 +9,6 @@ import (
"context"
"encoding/json"
"fmt"
"io/ioutil"
"math"
"os"
"path/filepath"
@ -136,7 +135,7 @@ func (p *Process) ForegroundWithContext(ctx context.Context) (bool, error) {
// see https://github.com/shirou/gopsutil/issues/596#issuecomment-432707831 for implementation details
pid := p.Pid
statPath := common.HostProcWithContext(ctx, strconv.Itoa(int(pid)), "stat")
contents, err := ioutil.ReadFile(statPath)
contents, err := os.ReadFile(statPath)
if err != nil {
return false, err
}
@ -391,7 +390,7 @@ func (p *Process) MemoryMapsWithContext(ctx context.Context, grouped bool) (*[]M
smapsPath = smapsRollupPath
}
}
contents, err := ioutil.ReadFile(smapsPath)
contents, err := os.ReadFile(smapsPath)
if err != nil {
return nil, err
}
@ -484,7 +483,7 @@ func (p *Process) MemoryMapsWithContext(ctx context.Context, grouped bool) (*[]M
func (p *Process) EnvironWithContext(ctx context.Context) ([]string, error) {
environPath := common.HostProcWithContext(ctx, strconv.Itoa(int(p.Pid)), "environ")
environContent, err := ioutil.ReadFile(environPath)
environContent, err := os.ReadFile(environPath)
if err != nil {
return nil, err
}
@ -668,7 +667,7 @@ func (p *Process) fillFromExeWithContext(ctx context.Context) (string, error) {
func (p *Process) fillFromCmdlineWithContext(ctx context.Context) (string, error) {
pid := p.Pid
cmdPath := common.HostProcWithContext(ctx, strconv.Itoa(int(pid)), "cmdline")
cmdline, err := ioutil.ReadFile(cmdPath)
cmdline, err := os.ReadFile(cmdPath)
if err != nil {
return "", err
}
@ -682,7 +681,7 @@ func (p *Process) fillFromCmdlineWithContext(ctx context.Context) (string, error
func (p *Process) fillSliceFromCmdlineWithContext(ctx context.Context) ([]string, error) {
pid := p.Pid
cmdPath := common.HostProcWithContext(ctx, strconv.Itoa(int(pid)), "cmdline")
cmdline, err := ioutil.ReadFile(cmdPath)
cmdline, err := os.ReadFile(cmdPath)
if err != nil {
return nil, err
}
@ -705,7 +704,7 @@ func (p *Process) fillSliceFromCmdlineWithContext(ctx context.Context) ([]string
func (p *Process) fillFromIOWithContext(ctx context.Context) (*IOCountersStat, error) {
pid := p.Pid
ioPath := common.HostProcWithContext(ctx, strconv.Itoa(int(pid)), "io")
ioline, err := ioutil.ReadFile(ioPath)
ioline, err := os.ReadFile(ioPath)
if err != nil {
return nil, err
}
@ -741,7 +740,7 @@ func (p *Process) fillFromIOWithContext(ctx context.Context) (*IOCountersStat, e
func (p *Process) fillFromStatmWithContext(ctx context.Context) (*MemoryInfoStat, *MemoryInfoExStat, error) {
pid := p.Pid
memPath := common.HostProcWithContext(ctx, strconv.Itoa(int(pid)), "statm")
contents, err := ioutil.ReadFile(memPath)
contents, err := os.ReadFile(memPath)
if err != nil {
return nil, nil, err
}
@ -802,7 +801,7 @@ func (p *Process) fillNameWithContext(ctx context.Context) error {
func (p *Process) fillFromCommWithContext(ctx context.Context) error {
pid := p.Pid
statPath := common.HostProcWithContext(ctx, strconv.Itoa(int(pid)), "comm")
contents, err := ioutil.ReadFile(statPath)
contents, err := os.ReadFile(statPath)
if err != nil {
return err
}
@ -819,7 +818,7 @@ func (p *Process) fillFromStatus() error {
func (p *Process) fillFromStatusWithContext(ctx context.Context) error {
pid := p.Pid
statPath := common.HostProcWithContext(ctx, strconv.Itoa(int(pid)), "status")
contents, err := ioutil.ReadFile(statPath)
contents, err := os.ReadFile(statPath)
if err != nil {
return err
}
@ -1026,7 +1025,7 @@ func (p *Process) fillFromTIDStatWithContext(ctx context.Context, tid int32) (ui
statPath = common.HostProcWithContext(ctx, strconv.Itoa(int(pid)), "task", strconv.Itoa(int(tid)), "stat")
}
contents, err := ioutil.ReadFile(statPath)
contents, err := os.ReadFile(statPath)
if err != nil {
return 0, 0, nil, 0, 0, 0, nil, err
}
@ -1072,7 +1071,7 @@ func (p *Process) fillFromTIDStatWithContext(ctx context.Context, tid int32) (ui
Iowait: iotime / float64(clockTicks),
}
bootTime, _ := common.BootTimeWithContext(ctx)
bootTime, _ := common.BootTimeWithContext(ctx, enableBootTimeCache)
t, err := strconv.ParseUint(fields[22], 10, 64)
if err != nil {
return 0, 0, nil, 0, 0, 0, nil, err

@ -6,7 +6,6 @@ package process
import (
"context"
"fmt"
"io/ioutil"
"os"
"strconv"
"strings"
@ -58,7 +57,7 @@ func Test_Process_splitProcStat(t *testing.T) {
}
func Test_Process_splitProcStat_fromFile(t *testing.T) {
pids, err := ioutil.ReadDir("testdata/linux/")
pids, err := os.ReadDir("testdata/linux/")
if err != nil {
t.Error(err)
}
@ -72,7 +71,7 @@ func Test_Process_splitProcStat_fromFile(t *testing.T) {
if _, err := os.Stat(statFile); err != nil {
continue
}
contents, err := ioutil.ReadFile(statFile)
contents, err := os.ReadFile(statFile)
assert.NoError(t, err)
pidStr := strconv.Itoa(int(pid))
@ -94,7 +93,7 @@ func Test_Process_splitProcStat_fromFile(t *testing.T) {
}
func Test_fillFromCommWithContext(t *testing.T) {
pids, err := ioutil.ReadDir("testdata/linux/")
pids, err := os.ReadDir("testdata/linux/")
if err != nil {
t.Error(err)
}
@ -115,7 +114,7 @@ func Test_fillFromCommWithContext(t *testing.T) {
}
func Test_fillFromStatusWithContext(t *testing.T) {
pids, err := ioutil.ReadDir("testdata/linux/")
pids, err := os.ReadDir("testdata/linux/")
if err != nil {
t.Error(err)
}
@ -154,7 +153,7 @@ func Benchmark_fillFromStatusWithContext(b *testing.B) {
}
func Test_fillFromTIDStatWithContext_lx_brandz(t *testing.T) {
pids, err := ioutil.ReadDir("testdata/lx_brandz/")
pids, err := os.ReadDir("testdata/lx_brandz/")
if err != nil {
t.Error(err)
}

@ -0,0 +1,204 @@
//go:build openbsd && riscv64
// +build openbsd,riscv64
// Code generated by cmd/cgo -godefs; DO NOT EDIT.
// cgo -godefs process/types_openbsd.go
package process
const (
CTLKern = 1
KernProc = 66
KernProcAll = 0
KernProcPID = 1
KernProcProc = 8
KernProcPathname = 12
KernProcArgs = 55
KernProcArgv = 1
KernProcEnv = 3
)
const (
ArgMax = 256 * 1024
)
const (
sizeofPtr = 0x8
sizeofShort = 0x2
sizeofInt = 0x4
sizeofLong = 0x8
sizeofLongLong = 0x8
)
const (
sizeOfKinfoVmentry = 0x50
sizeOfKinfoProc = 0x288
)
const (
SIDL = 1
SRUN = 2
SSLEEP = 3
SSTOP = 4
SZOMB = 5
SDEAD = 6
SONPROC = 7
)
type (
_C_short int16
_C_int int32
_C_long int64
_C_long_long int64
)
type Timespec struct {
Sec int64
Nsec int64
}
type Timeval struct {
Sec int64
Usec int64
}
type Rusage struct {
Utime Timeval
Stime Timeval
Maxrss int64
Ixrss int64
Idrss int64
Isrss int64
Minflt int64
Majflt int64
Nswap int64
Inblock int64
Oublock int64
Msgsnd int64
Msgrcv int64
Nsignals int64
Nvcsw int64
Nivcsw int64
}
type Rlimit struct {
Cur uint64
Max uint64
}
type KinfoProc struct {
Forw uint64
Back uint64
Paddr uint64
Addr uint64
Fd uint64
Stats uint64
Limit uint64
Vmspace uint64
Sigacts uint64
Sess uint64
Tsess uint64
Ru uint64
Eflag int32
Exitsig int32
Flag int32
Pid int32
Ppid int32
Sid int32
X_pgid int32
Tpgid int32
Uid uint32
Ruid uint32
Gid uint32
Rgid uint32
Groups [16]uint32
Ngroups int16
Jobc int16
Tdev uint32
Estcpu uint32
Rtime_sec uint32
Rtime_usec uint32
Cpticks int32
Pctcpu uint32
Swtime uint32
Slptime uint32
Schedflags int32
Uticks uint64
Sticks uint64
Iticks uint64
Tracep uint64
Traceflag int32
Holdcnt int32
Siglist int32
Sigmask uint32
Sigignore uint32
Sigcatch uint32
Stat int8
Priority uint8
Usrpri uint8
Nice uint8
Xstat uint16
Spare uint16
Comm [24]int8
Wmesg [8]uint8
Wchan uint64
Login [32]uint8
Vm_rssize int32
Vm_tsize int32
Vm_dsize int32
Vm_ssize int32
Uvalid int64
Ustart_sec uint64
Ustart_usec uint32
Uutime_sec uint32
Uutime_usec uint32
Ustime_sec uint32
Ustime_usec uint32
Uru_maxrss uint64
Uru_ixrss uint64
Uru_idrss uint64
Uru_isrss uint64
Uru_minflt uint64
Uru_majflt uint64
Uru_nswap uint64
Uru_inblock uint64
Uru_oublock uint64
Uru_msgsnd uint64
Uru_msgrcv uint64
Uru_nsignals uint64
Uru_nvcsw uint64
Uru_nivcsw uint64
Uctime_sec uint32
Uctime_usec uint32
Psflags uint32
Acflag uint32
Svuid uint32
Svgid uint32
Emul [8]uint8
Rlim_rss_cur uint64
Cpuid uint64
Vm_map_size uint64
Tid int32
Rtableid uint32
Pledge uint64
Name [24]uint8
}
type Priority struct{}
type KinfoVmentry struct {
Start uint64
End uint64
Guard uint64
Fspace uint64
Fspace_augment uint64
Offset uint64
Wired_count int32
Etype int32
Protection int32
Max_protection int32
Advice int32
Inheritance int32
Flags uint8
Pad_cgo_0 [7]byte
}

@ -3,7 +3,6 @@ package process
import (
"bytes"
"context"
"io/ioutil"
"os"
"strconv"
"strings"
@ -232,7 +231,7 @@ func (p *Process) fillFromPathAOutWithContext(ctx context.Context) (string, erro
func (p *Process) fillFromExecnameWithContext(ctx context.Context) (string, error) {
pid := p.Pid
execNamePath := common.HostProcWithContext(ctx, strconv.Itoa(int(pid)), "execname")
exe, err := ioutil.ReadFile(execNamePath)
exe, err := os.ReadFile(execNamePath)
if err != nil {
return "", err
}
@ -242,7 +241,7 @@ func (p *Process) fillFromExecnameWithContext(ctx context.Context) (string, erro
func (p *Process) fillFromCmdlineWithContext(ctx context.Context) (string, error) {
pid := p.Pid
cmdPath := common.HostProcWithContext(ctx, strconv.Itoa(int(pid)), "cmdline")
cmdline, err := ioutil.ReadFile(cmdPath)
cmdline, err := os.ReadFile(cmdPath)
if err != nil {
return "", err
}
@ -259,7 +258,7 @@ func (p *Process) fillFromCmdlineWithContext(ctx context.Context) (string, error
func (p *Process) fillSliceFromCmdlineWithContext(ctx context.Context) ([]string, error) {
pid := p.Pid
cmdPath := common.HostProcWithContext(ctx, strconv.Itoa(int(pid)), "cmdline")
cmdline, err := ioutil.ReadFile(cmdPath)
cmdline, err := os.ReadFile(cmdPath)
if err != nil {
return nil, err
}

@ -4,7 +4,7 @@ import (
"bufio"
"errors"
"fmt"
"io/ioutil"
"io"
"net"
"os"
"os/exec"
@ -227,6 +227,11 @@ func Test_Process_NumCtx(t *testing.T) {
func Test_Process_Nice(t *testing.T) {
p := testGetProcess()
// https://github.com/shirou/gopsutil/issues/1532
if os.Getenv("CI") == "true" && runtime.GOOS == "darwin" {
t.Skip("Skip CI")
}
n, err := p.Nice()
skipIfNotImplementedErr(t, err)
if err != nil {
@ -302,7 +307,7 @@ func Test_Process_Name(t *testing.T) {
}
func Test_Process_Long_Name_With_Spaces(t *testing.T) {
tmpdir, err := ioutil.TempDir("", "")
tmpdir, err := os.MkdirTemp("", "")
if err != nil {
t.Fatalf("unable to create temp dir %v", err)
}
@ -348,7 +353,7 @@ func Test_Process_Long_Name_With_Spaces(t *testing.T) {
}
func Test_Process_Long_Name(t *testing.T) {
tmpdir, err := ioutil.TempDir("", "")
tmpdir, err := os.MkdirTemp("", "")
if err != nil {
t.Fatalf("unable to create temp dir %v", err)
}
@ -405,7 +410,7 @@ func Test_Process_Name_Against_Python(t *testing.T) {
t.Skipf("psutil not found for %s: %s", py3Path, out)
}
tmpdir, err := ioutil.TempDir("", "")
tmpdir, err := os.MkdirTemp("", "")
if err != nil {
t.Fatalf("unable to create temp dir %v", err)
}
@ -571,7 +576,7 @@ func Test_Connections(t *testing.T) {
defer conn.Close()
serverEstablished <- struct{}{}
_, err = ioutil.ReadAll(conn)
_, err = io.ReadAll(conn)
if err != nil {
panic(err)
}
@ -774,7 +779,7 @@ func Test_IsRunning(t *testing.T) {
}
func Test_Process_Environ(t *testing.T) {
tmpdir, err := ioutil.TempDir("", "")
tmpdir, err := os.MkdirTemp("", "")
if err != nil {
t.Fatalf("unable to create temp dir %v", err)
}

@ -253,7 +253,7 @@ func pidsWithContext(ctx context.Context) ([]int32, error) {
if err := windows.EnumProcesses(ps, &read); err != nil {
return nil, err
}
if uint32(len(ps)) == read { // ps buffer was too small to host every results, retry with a bigger one
if uint32(len(ps)) == read/dwordSize { // ps buffer was too small to host every results, retry with a bigger one
psSize += 1024
continue
}

Loading…
Cancel
Save