summaryrefslogtreecommitdiff
path: root/vendor/github.com/shirou/gopsutil/v4/internal
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/shirou/gopsutil/v4/internal')
-rw-r--r--vendor/github.com/shirou/gopsutil/v4/internal/common/binary.go638
-rw-r--r--vendor/github.com/shirou/gopsutil/v4/internal/common/common.go474
-rw-r--r--vendor/github.com/shirou/gopsutil/v4/internal/common/common_darwin.go402
-rw-r--r--vendor/github.com/shirou/gopsutil/v4/internal/common/common_freebsd.go82
-rw-r--r--vendor/github.com/shirou/gopsutil/v4/internal/common/common_linux.go356
-rw-r--r--vendor/github.com/shirou/gopsutil/v4/internal/common/common_netbsd.go66
-rw-r--r--vendor/github.com/shirou/gopsutil/v4/internal/common/common_openbsd.go66
-rw-r--r--vendor/github.com/shirou/gopsutil/v4/internal/common/common_unix.go42
-rw-r--r--vendor/github.com/shirou/gopsutil/v4/internal/common/common_windows.go304
-rw-r--r--vendor/github.com/shirou/gopsutil/v4/internal/common/endian.go11
-rw-r--r--vendor/github.com/shirou/gopsutil/v4/internal/common/sleep.go22
-rw-r--r--vendor/github.com/shirou/gopsutil/v4/internal/common/warnings.go31
12 files changed, 2494 insertions, 0 deletions
diff --git a/vendor/github.com/shirou/gopsutil/v4/internal/common/binary.go b/vendor/github.com/shirou/gopsutil/v4/internal/common/binary.go
new file mode 100644
index 0000000..6e75e74
--- /dev/null
+++ b/vendor/github.com/shirou/gopsutil/v4/internal/common/binary.go
@@ -0,0 +1,638 @@
+// SPDX-License-Identifier: BSD-3-Clause
+package common
+
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package binary implements simple translation between numbers and byte
+// sequences and encoding and decoding of varints.
+//
+// Numbers are translated by reading and writing fixed-size values.
+// A fixed-size value is either a fixed-size arithmetic
+// type (int8, uint8, int16, float32, complex64, ...)
+// or an array or struct containing only fixed-size values.
+//
+// The varint functions encode and decode single integer values using
+// a variable-length encoding; smaller values require fewer bytes.
+// For a specification, see
+// http://code.google.com/apis/protocolbuffers/docs/encoding.html.
+//
+// This package favors simplicity over efficiency. Clients that require
+// high-performance serialization, especially for large data structures,
+// should look at more advanced solutions such as the encoding/gob
+// package or protocol buffers.
+
+import (
+ "errors"
+ "io"
+ "math"
+ "reflect"
+)
+
+// A ByteOrder specifies how to convert byte sequences into
+// 16-, 32-, or 64-bit unsigned integers.
+type ByteOrder interface {
+ Uint16([]byte) uint16
+ Uint32([]byte) uint32
+ Uint64([]byte) uint64
+ PutUint16([]byte, uint16)
+ PutUint32([]byte, uint32)
+ PutUint64([]byte, uint64)
+ String() string
+}
+
+// LittleEndian is the little-endian implementation of ByteOrder.
+var LittleEndian littleEndian
+
+// BigEndian is the big-endian implementation of ByteOrder.
+var BigEndian bigEndian
+
+type littleEndian struct{}
+
+func (littleEndian) Uint16(b []byte) uint16 { return uint16(b[0]) | uint16(b[1])<<8 }
+
+func (littleEndian) PutUint16(b []byte, v uint16) {
+ b[0] = byte(v)
+ b[1] = byte(v >> 8)
+}
+
+func (littleEndian) Uint32(b []byte) uint32 {
+ return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24
+}
+
+func (littleEndian) PutUint32(b []byte, v uint32) {
+ b[0] = byte(v)
+ b[1] = byte(v >> 8)
+ b[2] = byte(v >> 16)
+ b[3] = byte(v >> 24)
+}
+
+func (littleEndian) Uint64(b []byte) uint64 {
+ return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 |
+ uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56
+}
+
+func (littleEndian) PutUint64(b []byte, v uint64) {
+ b[0] = byte(v)
+ b[1] = byte(v >> 8)
+ b[2] = byte(v >> 16)
+ b[3] = byte(v >> 24)
+ b[4] = byte(v >> 32)
+ b[5] = byte(v >> 40)
+ b[6] = byte(v >> 48)
+ b[7] = byte(v >> 56)
+}
+
+func (littleEndian) String() string { return "LittleEndian" }
+
+func (littleEndian) GoString() string { return "binary.LittleEndian" }
+
+type bigEndian struct{}
+
+func (bigEndian) Uint16(b []byte) uint16 { return uint16(b[1]) | uint16(b[0])<<8 }
+
+func (bigEndian) PutUint16(b []byte, v uint16) {
+ b[0] = byte(v >> 8)
+ b[1] = byte(v)
+}
+
+func (bigEndian) Uint32(b []byte) uint32 {
+ return uint32(b[3]) | uint32(b[2])<<8 | uint32(b[1])<<16 | uint32(b[0])<<24
+}
+
+func (bigEndian) PutUint32(b []byte, v uint32) {
+ b[0] = byte(v >> 24)
+ b[1] = byte(v >> 16)
+ b[2] = byte(v >> 8)
+ b[3] = byte(v)
+}
+
+func (bigEndian) Uint64(b []byte) uint64 {
+ return uint64(b[7]) | uint64(b[6])<<8 | uint64(b[5])<<16 | uint64(b[4])<<24 |
+ uint64(b[3])<<32 | uint64(b[2])<<40 | uint64(b[1])<<48 | uint64(b[0])<<56
+}
+
+func (bigEndian) PutUint64(b []byte, v uint64) {
+ b[0] = byte(v >> 56)
+ b[1] = byte(v >> 48)
+ b[2] = byte(v >> 40)
+ b[3] = byte(v >> 32)
+ b[4] = byte(v >> 24)
+ b[5] = byte(v >> 16)
+ b[6] = byte(v >> 8)
+ b[7] = byte(v)
+}
+
+func (bigEndian) String() string { return "BigEndian" }
+
+func (bigEndian) GoString() string { return "binary.BigEndian" }
+
+// Read reads structured binary data from r into data.
+// Data must be a pointer to a fixed-size value or a slice
+// of fixed-size values.
+// Bytes read from r are decoded using the specified byte order
+// and written to successive fields of the data.
+// When reading into structs, the field data for fields with
+// blank (_) field names is skipped; i.e., blank field names
+// may be used for padding.
+// When reading into a struct, all non-blank fields must be exported.
+func Read(r io.Reader, order ByteOrder, data interface{}) error {
+ // Fast path for basic types and slices.
+ if n := intDataSize(data); n != 0 {
+ var b [8]byte
+ var bs []byte
+ if n > len(b) {
+ bs = make([]byte, n)
+ } else {
+ bs = b[:n]
+ }
+ if _, err := io.ReadFull(r, bs); err != nil {
+ return err
+ }
+ switch data := data.(type) {
+ case *int8:
+ *data = int8(b[0])
+ case *uint8:
+ *data = b[0]
+ case *int16:
+ *data = int16(order.Uint16(bs))
+ case *uint16:
+ *data = order.Uint16(bs)
+ case *int32:
+ *data = int32(order.Uint32(bs))
+ case *uint32:
+ *data = order.Uint32(bs)
+ case *int64:
+ *data = int64(order.Uint64(bs))
+ case *uint64:
+ *data = order.Uint64(bs)
+ case []int8:
+ for i, x := range bs { // Easier to loop over the input for 8-bit values.
+ data[i] = int8(x)
+ }
+ case []uint8:
+ copy(data, bs)
+ case []int16:
+ for i := range data {
+ data[i] = int16(order.Uint16(bs[2*i:]))
+ }
+ case []uint16:
+ for i := range data {
+ data[i] = order.Uint16(bs[2*i:])
+ }
+ case []int32:
+ for i := range data {
+ data[i] = int32(order.Uint32(bs[4*i:]))
+ }
+ case []uint32:
+ for i := range data {
+ data[i] = order.Uint32(bs[4*i:])
+ }
+ case []int64:
+ for i := range data {
+ data[i] = int64(order.Uint64(bs[8*i:]))
+ }
+ case []uint64:
+ for i := range data {
+ data[i] = order.Uint64(bs[8*i:])
+ }
+ }
+ return nil
+ }
+
+ // Fallback to reflect-based decoding.
+ v := reflect.ValueOf(data)
+ size := -1
+ switch v.Kind() {
+ case reflect.Ptr:
+ v = v.Elem()
+ size = dataSize(v)
+ case reflect.Slice:
+ size = dataSize(v)
+ }
+ if size < 0 {
+ return errors.New("binary.Read: invalid type " + reflect.TypeOf(data).String())
+ }
+ d := &decoder{order: order, buf: make([]byte, size)}
+ if _, err := io.ReadFull(r, d.buf); err != nil {
+ return err
+ }
+ d.value(v)
+ return nil
+}
+
+// Write writes the binary representation of data into w.
+// Data must be a fixed-size value or a slice of fixed-size
+// values, or a pointer to such data.
+// Bytes written to w are encoded using the specified byte order
+// and read from successive fields of the data.
+// When writing structs, zero values are written for fields
+// with blank (_) field names.
+func Write(w io.Writer, order ByteOrder, data interface{}) error {
+ // Fast path for basic types and slices.
+ if n := intDataSize(data); n != 0 {
+ var b [8]byte
+ var bs []byte
+ if n > len(b) {
+ bs = make([]byte, n)
+ } else {
+ bs = b[:n]
+ }
+ switch v := data.(type) {
+ case *int8:
+ bs = b[:1]
+ b[0] = byte(*v)
+ case int8:
+ bs = b[:1]
+ b[0] = byte(v)
+ case []int8:
+ for i, x := range v {
+ bs[i] = byte(x)
+ }
+ case *uint8:
+ bs = b[:1]
+ b[0] = *v
+ case uint8:
+ bs = b[:1]
+ b[0] = byte(v)
+ case []uint8:
+ bs = v
+ case *int16:
+ bs = b[:2]
+ order.PutUint16(bs, uint16(*v))
+ case int16:
+ bs = b[:2]
+ order.PutUint16(bs, uint16(v))
+ case []int16:
+ for i, x := range v {
+ order.PutUint16(bs[2*i:], uint16(x))
+ }
+ case *uint16:
+ bs = b[:2]
+ order.PutUint16(bs, *v)
+ case uint16:
+ bs = b[:2]
+ order.PutUint16(bs, v)
+ case []uint16:
+ for i, x := range v {
+ order.PutUint16(bs[2*i:], x)
+ }
+ case *int32:
+ bs = b[:4]
+ order.PutUint32(bs, uint32(*v))
+ case int32:
+ bs = b[:4]
+ order.PutUint32(bs, uint32(v))
+ case []int32:
+ for i, x := range v {
+ order.PutUint32(bs[4*i:], uint32(x))
+ }
+ case *uint32:
+ bs = b[:4]
+ order.PutUint32(bs, *v)
+ case uint32:
+ bs = b[:4]
+ order.PutUint32(bs, v)
+ case []uint32:
+ for i, x := range v {
+ order.PutUint32(bs[4*i:], x)
+ }
+ case *int64:
+ bs = b[:8]
+ order.PutUint64(bs, uint64(*v))
+ case int64:
+ bs = b[:8]
+ order.PutUint64(bs, uint64(v))
+ case []int64:
+ for i, x := range v {
+ order.PutUint64(bs[8*i:], uint64(x))
+ }
+ case *uint64:
+ bs = b[:8]
+ order.PutUint64(bs, *v)
+ case uint64:
+ bs = b[:8]
+ order.PutUint64(bs, v)
+ case []uint64:
+ for i, x := range v {
+ order.PutUint64(bs[8*i:], x)
+ }
+ }
+ _, err := w.Write(bs)
+ return err
+ }
+
+ // Fallback to reflect-based encoding.
+ v := reflect.Indirect(reflect.ValueOf(data))
+ size := dataSize(v)
+ if size < 0 {
+ return errors.New("binary.Write: invalid type " + reflect.TypeOf(data).String())
+ }
+ buf := make([]byte, size)
+ e := &encoder{order: order, buf: buf}
+ e.value(v)
+ _, err := w.Write(buf)
+ return err
+}
+
+// Size returns how many bytes Write would generate to encode the value v, which
+// must be a fixed-size value or a slice of fixed-size values, or a pointer to such data.
+// If v is neither of these, Size returns -1.
+func Size(v interface{}) int {
+ return dataSize(reflect.Indirect(reflect.ValueOf(v)))
+}
+
+// dataSize returns the number of bytes the actual data represented by v occupies in memory.
+// For compound structures, it sums the sizes of the elements. Thus, for instance, for a slice
+// it returns the length of the slice times the element size and does not count the memory
+// occupied by the header. If the type of v is not acceptable, dataSize returns -1.
+func dataSize(v reflect.Value) int {
+ if v.Kind() == reflect.Slice {
+ if s := sizeof(v.Type().Elem()); s >= 0 {
+ return s * v.Len()
+ }
+ return -1
+ }
+ return sizeof(v.Type())
+}
+
+// sizeof returns the size >= 0 of variables for the given type or -1 if the type is not acceptable.
+func sizeof(t reflect.Type) int {
+ switch t.Kind() {
+ case reflect.Array:
+ if s := sizeof(t.Elem()); s >= 0 {
+ return s * t.Len()
+ }
+
+ case reflect.Struct:
+ sum := 0
+ for i, n := 0, t.NumField(); i < n; i++ {
+ s := sizeof(t.Field(i).Type)
+ if s < 0 {
+ return -1
+ }
+ sum += s
+ }
+ return sum
+
+ case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
+ reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
+ reflect.Float32, reflect.Float64, reflect.Complex64, reflect.Complex128, reflect.Ptr:
+ return int(t.Size())
+ }
+
+ return -1
+}
+
+type coder struct {
+ order ByteOrder
+ buf []byte
+}
+
+type (
+ decoder coder
+ encoder coder
+)
+
+func (d *decoder) uint8() uint8 {
+ x := d.buf[0]
+ d.buf = d.buf[1:]
+ return x
+}
+
+func (e *encoder) uint8(x uint8) {
+ e.buf[0] = x
+ e.buf = e.buf[1:]
+}
+
+func (d *decoder) uint16() uint16 {
+ x := d.order.Uint16(d.buf[0:2])
+ d.buf = d.buf[2:]
+ return x
+}
+
+func (e *encoder) uint16(x uint16) {
+ e.order.PutUint16(e.buf[0:2], x)
+ e.buf = e.buf[2:]
+}
+
+func (d *decoder) uint32() uint32 {
+ x := d.order.Uint32(d.buf[0:4])
+ d.buf = d.buf[4:]
+ return x
+}
+
+func (e *encoder) uint32(x uint32) {
+ e.order.PutUint32(e.buf[0:4], x)
+ e.buf = e.buf[4:]
+}
+
+func (d *decoder) uint64() uint64 {
+ x := d.order.Uint64(d.buf[0:8])
+ d.buf = d.buf[8:]
+ return x
+}
+
+func (e *encoder) uint64(x uint64) {
+ e.order.PutUint64(e.buf[0:8], x)
+ e.buf = e.buf[8:]
+}
+
+func (d *decoder) int8() int8 { return int8(d.uint8()) }
+
+func (e *encoder) int8(x int8) { e.uint8(uint8(x)) }
+
+func (d *decoder) int16() int16 { return int16(d.uint16()) }
+
+func (e *encoder) int16(x int16) { e.uint16(uint16(x)) }
+
+func (d *decoder) int32() int32 { return int32(d.uint32()) }
+
+func (e *encoder) int32(x int32) { e.uint32(uint32(x)) }
+
+func (d *decoder) int64() int64 { return int64(d.uint64()) }
+
+func (e *encoder) int64(x int64) { e.uint64(uint64(x)) }
+
+func (d *decoder) value(v reflect.Value) {
+ switch v.Kind() {
+ case reflect.Array:
+ l := v.Len()
+ for i := 0; i < l; i++ {
+ d.value(v.Index(i))
+ }
+
+ case reflect.Struct:
+ t := v.Type()
+ l := v.NumField()
+ for i := 0; i < l; i++ {
+ // Note: Calling v.CanSet() below is an optimization.
+ // It would be sufficient to check the field name,
+ // but creating the StructField info for each field is
+ // costly (run "go test -bench=ReadStruct" and compare
+ // results when making changes to this code).
+ if v := v.Field(i); v.CanSet() || t.Field(i).Name != "_" {
+ d.value(v)
+ } else {
+ d.skip(v)
+ }
+ }
+
+ case reflect.Slice:
+ l := v.Len()
+ for i := 0; i < l; i++ {
+ d.value(v.Index(i))
+ }
+
+ case reflect.Int8:
+ v.SetInt(int64(d.int8()))
+ case reflect.Int16:
+ v.SetInt(int64(d.int16()))
+ case reflect.Int32:
+ v.SetInt(int64(d.int32()))
+ case reflect.Int64:
+ v.SetInt(d.int64())
+
+ case reflect.Uint8:
+ v.SetUint(uint64(d.uint8()))
+ case reflect.Uint16:
+ v.SetUint(uint64(d.uint16()))
+ case reflect.Uint32:
+ v.SetUint(uint64(d.uint32()))
+ case reflect.Uint64:
+ v.SetUint(d.uint64())
+
+ case reflect.Float32:
+ v.SetFloat(float64(math.Float32frombits(d.uint32())))
+ case reflect.Float64:
+ v.SetFloat(math.Float64frombits(d.uint64()))
+
+ case reflect.Complex64:
+ v.SetComplex(complex(
+ float64(math.Float32frombits(d.uint32())),
+ float64(math.Float32frombits(d.uint32())),
+ ))
+ case reflect.Complex128:
+ v.SetComplex(complex(
+ math.Float64frombits(d.uint64()),
+ math.Float64frombits(d.uint64()),
+ ))
+ }
+}
+
+func (e *encoder) value(v reflect.Value) {
+ switch v.Kind() {
+ case reflect.Array:
+ l := v.Len()
+ for i := 0; i < l; i++ {
+ e.value(v.Index(i))
+ }
+
+ case reflect.Struct:
+ t := v.Type()
+ l := v.NumField()
+ for i := 0; i < l; i++ {
+ // see comment for corresponding code in decoder.value()
+ if v := v.Field(i); v.CanSet() || t.Field(i).Name != "_" {
+ e.value(v)
+ } else {
+ e.skip(v)
+ }
+ }
+
+ case reflect.Slice:
+ l := v.Len()
+ for i := 0; i < l; i++ {
+ e.value(v.Index(i))
+ }
+
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ switch v.Type().Kind() {
+ case reflect.Int8:
+ e.int8(int8(v.Int()))
+ case reflect.Int16:
+ e.int16(int16(v.Int()))
+ case reflect.Int32:
+ e.int32(int32(v.Int()))
+ case reflect.Int64:
+ e.int64(v.Int())
+ }
+
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+ switch v.Type().Kind() {
+ case reflect.Uint8:
+ e.uint8(uint8(v.Uint()))
+ case reflect.Uint16:
+ e.uint16(uint16(v.Uint()))
+ case reflect.Uint32:
+ e.uint32(uint32(v.Uint()))
+ case reflect.Uint64:
+ e.uint64(v.Uint())
+ }
+
+ case reflect.Float32, reflect.Float64:
+ switch v.Type().Kind() {
+ case reflect.Float32:
+ e.uint32(math.Float32bits(float32(v.Float())))
+ case reflect.Float64:
+ e.uint64(math.Float64bits(v.Float()))
+ }
+
+ case reflect.Complex64, reflect.Complex128:
+ switch v.Type().Kind() {
+ case reflect.Complex64:
+ x := v.Complex()
+ e.uint32(math.Float32bits(float32(real(x))))
+ e.uint32(math.Float32bits(float32(imag(x))))
+ case reflect.Complex128:
+ x := v.Complex()
+ e.uint64(math.Float64bits(real(x)))
+ e.uint64(math.Float64bits(imag(x)))
+ }
+ }
+}
+
+func (d *decoder) skip(v reflect.Value) {
+ d.buf = d.buf[dataSize(v):]
+}
+
+func (e *encoder) skip(v reflect.Value) {
+ n := dataSize(v)
+ for i := range e.buf[0:n] {
+ e.buf[i] = 0
+ }
+ e.buf = e.buf[n:]
+}
+
+// intDataSize returns the size of the data required to represent the data when encoded.
+// It returns zero if the type cannot be implemented by the fast path in Read or Write.
+func intDataSize(data interface{}) int {
+ switch data := data.(type) {
+ case int8, *int8, *uint8:
+ return 1
+ case []int8:
+ return len(data)
+ case []uint8:
+ return len(data)
+ case int16, *int16, *uint16:
+ return 2
+ case []int16:
+ return 2 * len(data)
+ case []uint16:
+ return 2 * len(data)
+ case int32, *int32, *uint32:
+ return 4
+ case []int32:
+ return 4 * len(data)
+ case []uint32:
+ return 4 * len(data)
+ case int64, *int64, *uint64:
+ return 8
+ case []int64:
+ return 8 * len(data)
+ case []uint64:
+ return 8 * len(data)
+ }
+ return 0
+}
diff --git a/vendor/github.com/shirou/gopsutil/v4/internal/common/common.go b/vendor/github.com/shirou/gopsutil/v4/internal/common/common.go
new file mode 100644
index 0000000..868ea4d
--- /dev/null
+++ b/vendor/github.com/shirou/gopsutil/v4/internal/common/common.go
@@ -0,0 +1,474 @@
+// SPDX-License-Identifier: BSD-3-Clause
+package common
+
+//
+// gopsutil is a port of psutil(http://pythonhosted.org/psutil/).
+// This covers these architectures.
+// - linux (amd64, arm)
+// - freebsd (amd64)
+// - windows (amd64)
+
+import (
+ "bufio"
+ "bytes"
+ "context"
+ "errors"
+ "fmt"
+ "io"
+ "math"
+ "net/url"
+ "os"
+ "os/exec"
+ "path"
+ "path/filepath"
+ "reflect"
+ "runtime"
+ "strconv"
+ "strings"
+ "time"
+
+ "github.com/shirou/gopsutil/v4/common"
+)
+
+var (
+ Timeout = 3 * time.Second
+ ErrTimeout = errors.New("command timed out")
+)
+
+type Invoker interface {
+ Command(string, ...string) ([]byte, error)
+ CommandWithContext(context.Context, string, ...string) ([]byte, error)
+}
+
+type Invoke struct{}
+
+func (i Invoke) Command(name string, arg ...string) ([]byte, error) {
+ ctx, cancel := context.WithTimeout(context.Background(), Timeout)
+ defer cancel()
+ return i.CommandWithContext(ctx, name, arg...)
+}
+
+func (i Invoke) CommandWithContext(ctx context.Context, name string, arg ...string) ([]byte, error) {
+ cmd := exec.CommandContext(ctx, name, arg...)
+
+ var buf bytes.Buffer
+ cmd.Stdout = &buf
+ cmd.Stderr = &buf
+
+ if err := cmd.Start(); err != nil {
+ return buf.Bytes(), err
+ }
+
+ if err := cmd.Wait(); err != nil {
+ return buf.Bytes(), err
+ }
+
+ return buf.Bytes(), nil
+}
+
+type FakeInvoke struct {
+ Suffix string // Suffix species expected file name suffix such as "fail"
+ Error error // If Error specified, return the error.
+}
+
+// Command in FakeInvoke returns from expected file if exists.
+func (i FakeInvoke) Command(name string, arg ...string) ([]byte, error) {
+ if i.Error != nil {
+ return []byte{}, i.Error
+ }
+
+ arch := runtime.GOOS
+
+ commandName := filepath.Base(name)
+
+ fname := strings.Join(append([]string{commandName}, arg...), "")
+ fname = url.QueryEscape(fname)
+ fpath := path.Join("testdata", arch, fname)
+ if i.Suffix != "" {
+ fpath += "_" + i.Suffix
+ }
+ if PathExists(fpath) {
+ return os.ReadFile(fpath)
+ }
+ return []byte{}, fmt.Errorf("could not find testdata: %s", fpath)
+}
+
+func (i FakeInvoke) CommandWithContext(ctx context.Context, name string, arg ...string) ([]byte, error) {
+ return i.Command(name, arg...)
+}
+
+var ErrNotImplementedError = errors.New("not implemented yet")
+
+// ReadFile reads contents from a file
+func ReadFile(filename string) (string, error) {
+ content, err := os.ReadFile(filename)
+ if err != nil {
+ return "", err
+ }
+
+ return string(content), nil
+}
+
+// ReadLines reads contents from a file and splits them by new lines.
+// A convenience wrapper to ReadLinesOffsetN(filename, 0, -1).
+func ReadLines(filename string) ([]string, error) {
+ return ReadLinesOffsetN(filename, 0, -1)
+}
+
+// ReadLine reads a file and returns the first occurrence of a line that is prefixed with prefix.
+func ReadLine(filename string, prefix string) (string, error) {
+ f, err := os.Open(filename)
+ if err != nil {
+ return "", err
+ }
+ defer f.Close()
+ r := bufio.NewReader(f)
+ for {
+ line, err := r.ReadString('\n')
+ if err != nil {
+ if err == io.EOF {
+ break
+ }
+ return "", err
+ }
+ if strings.HasPrefix(line, prefix) {
+ return line, nil
+ }
+ }
+
+ return "", nil
+}
+
+// ReadLinesOffsetN reads contents from file and splits them by new line.
+// The offset tells at which line number to start.
+// The count determines the number of lines to read (starting from offset):
+// n >= 0: at most n lines
+// n < 0: whole file
+func ReadLinesOffsetN(filename string, offset uint, n int) ([]string, error) {
+ f, err := os.Open(filename)
+ if err != nil {
+ return []string{""}, err
+ }
+ defer f.Close()
+
+ var ret []string
+
+ r := bufio.NewReader(f)
+ for i := uint(0); i < uint(n)+offset || n < 0; i++ {
+ line, err := r.ReadString('\n')
+ if err != nil {
+ if err == io.EOF && len(line) > 0 {
+ ret = append(ret, strings.Trim(line, "\n"))
+ }
+ break
+ }
+ if i < offset {
+ continue
+ }
+ ret = append(ret, strings.Trim(line, "\n"))
+ }
+
+ return ret, nil
+}
+
+func IntToString(orig []int8) string {
+ ret := make([]byte, len(orig))
+ size := -1
+ for i, o := range orig {
+ if o == 0 {
+ size = i
+ break
+ }
+ ret[i] = byte(o)
+ }
+ if size == -1 {
+ size = len(orig)
+ }
+
+ return string(ret[0:size])
+}
+
+func UintToString(orig []uint8) string {
+ ret := make([]byte, len(orig))
+ size := -1
+ for i, o := range orig {
+ if o == 0 {
+ size = i
+ break
+ }
+ ret[i] = byte(o)
+ }
+ if size == -1 {
+ size = len(orig)
+ }
+
+ return string(ret[0:size])
+}
+
+func ByteToString(orig []byte) string {
+ n := -1
+ l := -1
+ for i, b := range orig {
+ // skip left side null
+ if l == -1 && b == 0 {
+ continue
+ }
+ if l == -1 {
+ l = i
+ }
+
+ if b == 0 {
+ break
+ }
+ n = i + 1
+ }
+ if n == -1 {
+ return string(orig)
+ }
+ return string(orig[l:n])
+}
+
+// ReadInts reads contents from single line file and returns them as []int32.
+func ReadInts(filename string) ([]int64, error) {
+ f, err := os.Open(filename)
+ if err != nil {
+ return []int64{}, err
+ }
+ defer f.Close()
+
+ var ret []int64
+
+ r := bufio.NewReader(f)
+
+ // The int files that this is concerned with should only be one liners.
+ line, err := r.ReadString('\n')
+ if err != nil {
+ return []int64{}, err
+ }
+
+ i, err := strconv.ParseInt(strings.Trim(line, "\n"), 10, 32)
+ if err != nil {
+ return []int64{}, err
+ }
+ ret = append(ret, i)
+
+ return ret, nil
+}
+
+// Parse Hex to uint32 without error
+func HexToUint32(hex string) uint32 {
+ vv, _ := strconv.ParseUint(hex, 16, 32)
+ return uint32(vv)
+}
+
+// Parse to int32 without error
+func mustParseInt32(val string) int32 {
+ vv, _ := strconv.ParseInt(val, 10, 32)
+ return int32(vv)
+}
+
+// Parse to uint64 without error
+func mustParseUint64(val string) uint64 {
+ vv, _ := strconv.ParseInt(val, 10, 64)
+ return uint64(vv)
+}
+
+// Parse to Float64 without error
+func mustParseFloat64(val string) float64 {
+ vv, _ := strconv.ParseFloat(val, 64)
+ return vv
+}
+
+// StringsHas checks the target string slice contains src or not
+func StringsHas(target []string, src string) bool {
+ for _, t := range target {
+ if strings.TrimSpace(t) == src {
+ return true
+ }
+ }
+ return false
+}
+
+// StringsContains checks the src in any string of the target string slice
+func StringsContains(target []string, src string) bool {
+ for _, t := range target {
+ if strings.Contains(t, src) {
+ return true
+ }
+ }
+ return false
+}
+
+// IntContains checks the src in any int of the target int slice.
+func IntContains(target []int, src int) bool {
+ for _, t := range target {
+ if src == t {
+ return true
+ }
+ }
+ return false
+}
+
+// get struct attributes.
+// This method is used only for debugging platform dependent code.
+func attributes(m interface{}) map[string]reflect.Type {
+ typ := reflect.TypeOf(m)
+ if typ.Kind() == reflect.Ptr {
+ typ = typ.Elem()
+ }
+
+ attrs := make(map[string]reflect.Type)
+ if typ.Kind() != reflect.Struct {
+ return nil
+ }
+
+ for i := 0; i < typ.NumField(); i++ {
+ p := typ.Field(i)
+ if !p.Anonymous {
+ attrs[p.Name] = p.Type
+ }
+ }
+
+ return attrs
+}
+
+func PathExists(filename string) bool {
+ if _, err := os.Stat(filename); err == nil {
+ return true
+ }
+ return false
+}
+
+// PathExistsWithContents returns the filename exists and it is not empty
+func PathExistsWithContents(filename string) bool {
+ info, err := os.Stat(filename)
+ if err != nil {
+ return false
+ }
+ 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.
+// The context may optionally contain a map superseding os.EnvKey.
+func GetEnvWithContext(ctx context.Context, key string, dfault string, combineWith ...string) string {
+ var value string
+ if env, ok := ctx.Value(common.EnvKey).(common.EnvMap); ok {
+ value = env[common.EnvKeyType(key)]
+ }
+ if value == "" {
+ value = os.Getenv(key)
+ }
+ if value == "" {
+ value = dfault
+ }
+
+ return combine(value, combineWith)
+}
+
+// GetEnv retrieves the environment variable key. If it does not exist it returns the default.
+func GetEnv(key string, dfault string, combineWith ...string) string {
+ value := os.Getenv(key)
+ if value == "" {
+ value = dfault
+ }
+
+ return combine(value, combineWith)
+}
+
+func combine(value string, combineWith []string) string {
+ switch len(combineWith) {
+ case 0:
+ return value
+ case 1:
+ return filepath.Join(value, combineWith[0])
+ default:
+ all := make([]string, len(combineWith)+1)
+ all[0] = value
+ copy(all[1:], combineWith)
+ return filepath.Join(all...)
+ }
+}
+
+func HostProc(combineWith ...string) string {
+ return GetEnv("HOST_PROC", "/proc", combineWith...)
+}
+
+func HostSys(combineWith ...string) string {
+ return GetEnv("HOST_SYS", "/sys", combineWith...)
+}
+
+func HostEtc(combineWith ...string) string {
+ return GetEnv("HOST_ETC", "/etc", combineWith...)
+}
+
+func HostVar(combineWith ...string) string {
+ return GetEnv("HOST_VAR", "/var", combineWith...)
+}
+
+func HostRun(combineWith ...string) string {
+ return GetEnv("HOST_RUN", "/run", combineWith...)
+}
+
+func HostDev(combineWith ...string) string {
+ return GetEnv("HOST_DEV", "/dev", combineWith...)
+}
+
+func HostRoot(combineWith ...string) string {
+ return GetEnv("HOST_ROOT", "/", combineWith...)
+}
+
+func HostProcWithContext(ctx context.Context, combineWith ...string) string {
+ return GetEnvWithContext(ctx, "HOST_PROC", "/proc", combineWith...)
+}
+
+func HostProcMountInfoWithContext(ctx context.Context, combineWith ...string) string {
+ return GetEnvWithContext(ctx, "HOST_PROC_MOUNTINFO", "", combineWith...)
+}
+
+func HostSysWithContext(ctx context.Context, combineWith ...string) string {
+ return GetEnvWithContext(ctx, "HOST_SYS", "/sys", combineWith...)
+}
+
+func HostEtcWithContext(ctx context.Context, combineWith ...string) string {
+ return GetEnvWithContext(ctx, "HOST_ETC", "/etc", combineWith...)
+}
+
+func HostVarWithContext(ctx context.Context, combineWith ...string) string {
+ return GetEnvWithContext(ctx, "HOST_VAR", "/var", combineWith...)
+}
+
+func HostRunWithContext(ctx context.Context, combineWith ...string) string {
+ return GetEnvWithContext(ctx, "HOST_RUN", "/run", combineWith...)
+}
+
+func HostDevWithContext(ctx context.Context, combineWith ...string) string {
+ return GetEnvWithContext(ctx, "HOST_DEV", "/dev", combineWith...)
+}
+
+func HostRootWithContext(ctx context.Context, combineWith ...string) string {
+ return GetEnvWithContext(ctx, "HOST_ROOT", "/", combineWith...)
+}
+
+// getSysctrlEnv sets LC_ALL=C in a list of env vars for use when running
+// sysctl commands (see DoSysctrl).
+func getSysctrlEnv(env []string) []string {
+ foundLC := false
+ for i, line := range env {
+ if strings.HasPrefix(line, "LC_ALL") {
+ env[i] = "LC_ALL=C"
+ foundLC = true
+ }
+ }
+ if !foundLC {
+ env = append(env, "LC_ALL=C")
+ }
+ return env
+}
+
+// Round places rounds the number 'val' to 'n' decimal places
+func Round(val float64, n int) float64 {
+ // Calculate the power of 10 to the n
+ pow10 := math.Pow(10, float64(n))
+ // Multiply the value by pow10, round it, then divide it by pow10
+ return math.Round(val*pow10) / pow10
+}
diff --git a/vendor/github.com/shirou/gopsutil/v4/internal/common/common_darwin.go b/vendor/github.com/shirou/gopsutil/v4/internal/common/common_darwin.go
new file mode 100644
index 0000000..2de3bb1
--- /dev/null
+++ b/vendor/github.com/shirou/gopsutil/v4/internal/common/common_darwin.go
@@ -0,0 +1,402 @@
+// SPDX-License-Identifier: BSD-3-Clause
+//go:build darwin
+
+package common
+
+import (
+ "context"
+ "fmt"
+ "os"
+ "os/exec"
+ "strings"
+ "unsafe"
+
+ "github.com/ebitengine/purego"
+ "golang.org/x/sys/unix"
+)
+
+func DoSysctrlWithContext(ctx context.Context, mib string) ([]string, error) {
+ cmd := exec.CommandContext(ctx, "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) {
+ miblen := uint64(len(mib))
+
+ // get required buffer size
+ length := uint64(0)
+ _, _, err := unix.Syscall6(
+ 202, // unix.SYS___SYSCTL https://github.com/golang/sys/blob/76b94024e4b621e672466e8db3d7f084e7ddcad2/unix/zsysnum_darwin_amd64.go#L146
+ 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 = unix.Syscall6(
+ 202, // unix.SYS___SYSCTL https://github.com/golang/sys/blob/76b94024e4b621e672466e8db3d7f084e7ddcad2/unix/zsysnum_darwin_amd64.go#L146
+ 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
+}
+
+// Library represents a dynamic library loaded by purego.
+type Library struct {
+ addr uintptr
+ path string
+ close func()
+}
+
+// library paths
+const (
+ IOKit = "/System/Library/Frameworks/IOKit.framework/IOKit"
+ CoreFoundation = "/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation"
+ System = "/usr/lib/libSystem.B.dylib"
+)
+
+func NewLibrary(path string) (*Library, error) {
+ lib, err := purego.Dlopen(path, purego.RTLD_LAZY|purego.RTLD_GLOBAL)
+ if err != nil {
+ return nil, err
+ }
+
+ closeFunc := func() {
+ purego.Dlclose(lib)
+ }
+
+ return &Library{
+ addr: lib,
+ path: path,
+ close: closeFunc,
+ }, nil
+}
+
+func (lib *Library) Dlsym(symbol string) (uintptr, error) {
+ return purego.Dlsym(lib.addr, symbol)
+}
+
+func GetFunc[T any](lib *Library, symbol string) T {
+ var fptr T
+ purego.RegisterLibFunc(&fptr, lib.addr, symbol)
+ return fptr
+}
+
+func (lib *Library) Close() {
+ lib.close()
+}
+
+// status codes
+const (
+ KERN_SUCCESS = 0
+)
+
+// IOKit functions and symbols.
+type (
+ IOServiceGetMatchingServiceFunc func(mainPort uint32, matching uintptr) uint32
+ IOServiceGetMatchingServicesFunc func(mainPort uint32, matching uintptr, existing *uint32) int
+ IOServiceMatchingFunc func(name string) unsafe.Pointer
+ IOServiceOpenFunc func(service, owningTask, connType uint32, connect *uint32) int
+ IOServiceCloseFunc func(connect uint32) int
+ IOIteratorNextFunc func(iterator uint32) uint32
+ IORegistryEntryGetNameFunc func(entry uint32, name CStr) int
+ IORegistryEntryGetParentEntryFunc func(entry uint32, plane string, parent *uint32) int
+ IORegistryEntryCreateCFPropertyFunc func(entry uint32, key, allocator uintptr, options uint32) unsafe.Pointer
+ IORegistryEntryCreateCFPropertiesFunc func(entry uint32, properties unsafe.Pointer, allocator uintptr, options uint32) int
+ IOObjectConformsToFunc func(object uint32, className string) bool
+ IOObjectReleaseFunc func(object uint32) int
+ IOConnectCallStructMethodFunc func(connection, selector uint32, inputStruct, inputStructCnt, outputStruct uintptr, outputStructCnt *uintptr) int
+
+ IOHIDEventSystemClientCreateFunc func(allocator uintptr) unsafe.Pointer
+ IOHIDEventSystemClientSetMatchingFunc func(client, match uintptr) int
+ IOHIDServiceClientCopyEventFunc func(service uintptr, eventType int64,
+ options int32, timeout int64) unsafe.Pointer
+ IOHIDServiceClientCopyPropertyFunc func(service, property uintptr) unsafe.Pointer
+ IOHIDEventGetFloatValueFunc func(event uintptr, field int32) float64
+ IOHIDEventSystemClientCopyServicesFunc func(client uintptr) unsafe.Pointer
+)
+
+const (
+ IOServiceGetMatchingServiceSym = "IOServiceGetMatchingService"
+ IOServiceGetMatchingServicesSym = "IOServiceGetMatchingServices"
+ IOServiceMatchingSym = "IOServiceMatching"
+ IOServiceOpenSym = "IOServiceOpen"
+ IOServiceCloseSym = "IOServiceClose"
+ IOIteratorNextSym = "IOIteratorNext"
+ IORegistryEntryGetNameSym = "IORegistryEntryGetName"
+ IORegistryEntryGetParentEntrySym = "IORegistryEntryGetParentEntry"
+ IORegistryEntryCreateCFPropertySym = "IORegistryEntryCreateCFProperty"
+ IORegistryEntryCreateCFPropertiesSym = "IORegistryEntryCreateCFProperties"
+ IOObjectConformsToSym = "IOObjectConformsTo"
+ IOObjectReleaseSym = "IOObjectRelease"
+ IOConnectCallStructMethodSym = "IOConnectCallStructMethod"
+
+ IOHIDEventSystemClientCreateSym = "IOHIDEventSystemClientCreate"
+ IOHIDEventSystemClientSetMatchingSym = "IOHIDEventSystemClientSetMatching"
+ IOHIDServiceClientCopyEventSym = "IOHIDServiceClientCopyEvent"
+ IOHIDServiceClientCopyPropertySym = "IOHIDServiceClientCopyProperty"
+ IOHIDEventGetFloatValueSym = "IOHIDEventGetFloatValue"
+ IOHIDEventSystemClientCopyServicesSym = "IOHIDEventSystemClientCopyServices"
+)
+
+const (
+ KIOMainPortDefault = 0
+
+ KIOHIDEventTypeTemperature = 15
+
+ KNilOptions = 0
+)
+
+const (
+ KIOMediaWholeKey = "Media"
+ KIOServicePlane = "IOService"
+)
+
+// CoreFoundation functions and symbols.
+type (
+ CFGetTypeIDFunc func(cf uintptr) int32
+ CFNumberCreateFunc func(allocator uintptr, theType int32, valuePtr uintptr) unsafe.Pointer
+ CFNumberGetValueFunc func(num uintptr, theType int32, valuePtr uintptr) bool
+ CFDictionaryCreateFunc func(allocator uintptr, keys, values *unsafe.Pointer, numValues int32,
+ keyCallBacks, valueCallBacks uintptr) unsafe.Pointer
+ CFDictionaryAddValueFunc func(theDict, key, value uintptr)
+ CFDictionaryGetValueFunc func(theDict, key uintptr) unsafe.Pointer
+ CFArrayGetCountFunc func(theArray uintptr) int32
+ CFArrayGetValueAtIndexFunc func(theArray uintptr, index int32) unsafe.Pointer
+ CFStringCreateMutableFunc func(alloc uintptr, maxLength int32) unsafe.Pointer
+ CFStringGetLengthFunc func(theString uintptr) int32
+ CFStringGetCStringFunc func(theString uintptr, buffer CStr, bufferSize int32, encoding uint32)
+ CFStringCreateWithCStringFunc func(alloc uintptr, cStr string, encoding uint32) unsafe.Pointer
+ CFDataGetLengthFunc func(theData uintptr) int32
+ CFDataGetBytePtrFunc func(theData uintptr) unsafe.Pointer
+ CFReleaseFunc func(cf uintptr)
+)
+
+const (
+ CFGetTypeIDSym = "CFGetTypeID"
+ CFNumberCreateSym = "CFNumberCreate"
+ CFNumberGetValueSym = "CFNumberGetValue"
+ CFDictionaryCreateSym = "CFDictionaryCreate"
+ CFDictionaryAddValueSym = "CFDictionaryAddValue"
+ CFDictionaryGetValueSym = "CFDictionaryGetValue"
+ CFArrayGetCountSym = "CFArrayGetCount"
+ CFArrayGetValueAtIndexSym = "CFArrayGetValueAtIndex"
+ CFStringCreateMutableSym = "CFStringCreateMutable"
+ CFStringGetLengthSym = "CFStringGetLength"
+ CFStringGetCStringSym = "CFStringGetCString"
+ CFStringCreateWithCStringSym = "CFStringCreateWithCString"
+ CFDataGetLengthSym = "CFDataGetLength"
+ CFDataGetBytePtrSym = "CFDataGetBytePtr"
+ CFReleaseSym = "CFRelease"
+)
+
+const (
+ KCFStringEncodingUTF8 = 0x08000100
+ KCFNumberSInt64Type = 4
+ KCFNumberIntType = 9
+ KCFAllocatorDefault = 0
+)
+
+// Kernel functions and symbols.
+type MachTimeBaseInfo struct {
+ Numer uint32
+ Denom uint32
+}
+
+type (
+ HostProcessorInfoFunc func(host uint32, flavor int32, outProcessorCount *uint32, outProcessorInfo uintptr,
+ outProcessorInfoCnt *uint32) int
+ HostStatisticsFunc func(host uint32, flavor int32, hostInfoOut uintptr, hostInfoOutCnt *uint32) int
+ MachHostSelfFunc func() uint32
+ MachTaskSelfFunc func() uint32
+ MachTimeBaseInfoFunc func(info uintptr) int
+ VMDeallocateFunc func(targetTask uint32, vmAddress, vmSize uintptr) int
+)
+
+const (
+ HostProcessorInfoSym = "host_processor_info"
+ HostStatisticsSym = "host_statistics"
+ MachHostSelfSym = "mach_host_self"
+ MachTaskSelfSym = "mach_task_self"
+ MachTimeBaseInfoSym = "mach_timebase_info"
+ VMDeallocateSym = "vm_deallocate"
+)
+
+const (
+ CTL_KERN = 1
+ KERN_ARGMAX = 8
+ KERN_PROCARGS2 = 49
+
+ HOST_VM_INFO = 2
+ HOST_CPU_LOAD_INFO = 3
+
+ HOST_VM_INFO_COUNT = 0xf
+)
+
+// System functions and symbols.
+type (
+ ProcPidPathFunc func(pid int32, buffer uintptr, bufferSize uint32) int32
+ ProcPidInfoFunc func(pid, flavor int32, arg uint64, buffer uintptr, bufferSize int32) int32
+)
+
+const (
+ SysctlSym = "sysctl"
+ ProcPidPathSym = "proc_pidpath"
+ ProcPidInfoSym = "proc_pidinfo"
+)
+
+const (
+ MAXPATHLEN = 1024
+ PROC_PIDPATHINFO_MAXSIZE = 4 * MAXPATHLEN
+ PROC_PIDTASKINFO = 4
+ PROC_PIDVNODEPATHINFO = 9
+)
+
+// SMC represents a SMC instance.
+type SMC struct {
+ lib *Library
+ conn uint32
+ callStruct IOConnectCallStructMethodFunc
+}
+
+const ioServiceSMC = "AppleSMC"
+
+const (
+ KSMCUserClientOpen = 0
+ KSMCUserClientClose = 1
+ KSMCHandleYPCEvent = 2
+ KSMCReadKey = 5
+ KSMCWriteKey = 6
+ KSMCGetKeyCount = 7
+ KSMCGetKeyFromIndex = 8
+ KSMCGetKeyInfo = 9
+)
+
+const (
+ KSMCSuccess = 0
+ KSMCError = 1
+ KSMCKeyNotFound = 132
+)
+
+func NewSMC(ioKit *Library) (*SMC, error) {
+ if ioKit.path != IOKit {
+ return nil, fmt.Errorf("library is not IOKit")
+ }
+
+ ioServiceGetMatchingService := GetFunc[IOServiceGetMatchingServiceFunc](ioKit, IOServiceGetMatchingServiceSym)
+ ioServiceMatching := GetFunc[IOServiceMatchingFunc](ioKit, IOServiceMatchingSym)
+ ioServiceOpen := GetFunc[IOServiceOpenFunc](ioKit, IOServiceOpenSym)
+ ioObjectRelease := GetFunc[IOObjectReleaseFunc](ioKit, IOObjectReleaseSym)
+ machTaskSelf := GetFunc[MachTaskSelfFunc](ioKit, MachTaskSelfSym)
+
+ ioConnectCallStructMethod := GetFunc[IOConnectCallStructMethodFunc](ioKit, IOConnectCallStructMethodSym)
+
+ service := ioServiceGetMatchingService(0, uintptr(ioServiceMatching(ioServiceSMC)))
+ if service == 0 {
+ return nil, fmt.Errorf("ERROR: %s NOT FOUND", ioServiceSMC)
+ }
+
+ var conn uint32
+ if result := ioServiceOpen(service, machTaskSelf(), 0, &conn); result != 0 {
+ return nil, fmt.Errorf("ERROR: IOServiceOpen failed")
+ }
+
+ ioObjectRelease(service)
+ return &SMC{
+ lib: ioKit,
+ conn: conn,
+ callStruct: ioConnectCallStructMethod,
+ }, nil
+}
+
+func (s *SMC) CallStruct(selector uint32, inputStruct, inputStructCnt, outputStruct uintptr, outputStructCnt *uintptr) int {
+ return s.callStruct(s.conn, selector, inputStruct, inputStructCnt, outputStruct, outputStructCnt)
+}
+
+func (s *SMC) Close() error {
+ ioServiceClose := GetFunc[IOServiceCloseFunc](s.lib, IOServiceCloseSym)
+
+ if result := ioServiceClose(s.conn); result != 0 {
+ return fmt.Errorf("ERROR: IOServiceClose failed")
+ }
+ return nil
+}
+
+type CStr []byte
+
+func NewCStr(length int32) CStr {
+ return make(CStr, length)
+}
+
+func (s CStr) Length() int32 {
+ // Include null terminator to make CFStringGetCString properly functions
+ return int32(len(s)) + 1
+}
+
+func (s CStr) Ptr() *byte {
+ if len(s) < 1 {
+ return nil
+ }
+
+ return &s[0]
+}
+
+func (c CStr) Addr() uintptr {
+ return uintptr(unsafe.Pointer(c.Ptr()))
+}
+
+func (s CStr) GoString() string {
+ if s == nil {
+ return ""
+ }
+
+ var length int
+ for _, char := range s {
+ if char == '\x00' {
+ break
+ }
+ length++
+ }
+ return string(s[:length])
+}
+
+// https://github.com/ebitengine/purego/blob/main/internal/strings/strings.go#L26
+func GoString(cStr *byte) string {
+ if cStr == nil {
+ return ""
+ }
+ var length int
+ for {
+ if *(*byte)(unsafe.Add(unsafe.Pointer(cStr), uintptr(length))) == '\x00' {
+ break
+ }
+ length++
+ }
+ return string(unsafe.Slice(cStr, length))
+}
diff --git a/vendor/github.com/shirou/gopsutil/v4/internal/common/common_freebsd.go b/vendor/github.com/shirou/gopsutil/v4/internal/common/common_freebsd.go
new file mode 100644
index 0000000..53cdcee
--- /dev/null
+++ b/vendor/github.com/shirou/gopsutil/v4/internal/common/common_freebsd.go
@@ -0,0 +1,82 @@
+// SPDX-License-Identifier: BSD-3-Clause
+//go:build freebsd || openbsd
+
+package common
+
+import (
+ "fmt"
+ "os"
+ "os/exec"
+ "strings"
+ "unsafe"
+
+ "golang.org/x/sys/unix"
+)
+
+func SysctlUint(mib string) (uint64, error) {
+ buf, err := unix.SysctlRaw(mib)
+ if err != nil {
+ return 0, err
+ }
+ if len(buf) == 8 { // 64 bit
+ return *(*uint64)(unsafe.Pointer(&buf[0])), nil
+ }
+ if len(buf) == 4 { // 32bit
+ t := *(*uint32)(unsafe.Pointer(&buf[0]))
+ return uint64(t), nil
+ }
+ return 0, fmt.Errorf("unexpected size: %s, %d", mib, len(buf))
+}
+
+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
+}
diff --git a/vendor/github.com/shirou/gopsutil/v4/internal/common/common_linux.go b/vendor/github.com/shirou/gopsutil/v4/internal/common/common_linux.go
new file mode 100644
index 0000000..277034f
--- /dev/null
+++ b/vendor/github.com/shirou/gopsutil/v4/internal/common/common_linux.go
@@ -0,0 +1,356 @@
+// SPDX-License-Identifier: BSD-3-Clause
+//go:build linux
+
+package common
+
+import (
+ "context"
+ "errors"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "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())
+ 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 NumProcs() (uint64, error) {
+ return NumProcsWithContext(context.Background())
+}
+
+func NumProcsWithContext(ctx context.Context) (uint64, error) {
+ f, err := os.Open(HostProcWithContext(ctx))
+ if err != nil {
+ return 0, err
+ }
+ defer f.Close()
+
+ list, err := f.Readdirnames(-1)
+ if err != nil {
+ return 0, err
+ }
+ var cnt uint64
+
+ for _, v := range list {
+ if _, err = strconv.ParseUint(v, 10, 64); err == nil {
+ cnt++
+ }
+ }
+
+ return cnt, nil
+}
+
+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
+ }
+
+ useStatFile := true
+ if system == "lxc" && role == "guest" {
+ // if lxc, /proc/uptime is used.
+ useStatFile = false
+ } else if system == "docker" && role == "guest" {
+ // also docker, guest
+ useStatFile = false
+ }
+
+ if useStatFile {
+ t, err := readBootTimeStat(ctx)
+ if err != nil {
+ return 0, err
+ }
+ if enableCache {
+ atomic.StoreUint64(&cachedBootTime, t)
+ }
+
+ return t, nil
+ }
+
+ filename := HostProcWithContext(ctx, "uptime")
+ lines, err := ReadLines(filename)
+ if err != nil {
+ return handleBootTimeFileReadErr(err)
+ }
+ currentTime := float64(time.Now().UnixNano()) / float64(time.Second)
+
+ if len(lines) != 1 {
+ return 0, errors.New("wrong uptime format")
+ }
+ f := strings.Fields(lines[0])
+ b, err := strconv.ParseFloat(f[0], 64)
+ if err != nil {
+ return 0, err
+ }
+ t := currentTime - b
+
+ if enableCache {
+ atomic.StoreUint64(&cachedBootTime, uint64(t))
+ }
+
+ return uint64(t), nil
+}
+
+func handleBootTimeFileReadErr(err error) (uint64, error) {
+ if os.IsPermission(err) {
+ var info syscall.Sysinfo_t
+ err := syscall.Sysinfo(&info)
+ if err != nil {
+ return 0, err
+ }
+
+ currentTime := time.Now().UnixNano() / int64(time.Second)
+ t := currentTime - int64(info.Uptime)
+ return uint64(t), nil
+ }
+ return 0, err
+}
+
+func readBootTimeStat(ctx context.Context) (uint64, error) {
+ filename := HostProcWithContext(ctx, "stat")
+ line, err := ReadLine(filename, "btime")
+ if err != nil {
+ return handleBootTimeFileReadErr(err)
+ }
+ if strings.HasPrefix(line, "btime") {
+ f := strings.Fields(line)
+ if len(f) != 2 {
+ return 0, errors.New("wrong btime format")
+ }
+ b, err := strconv.ParseInt(f[1], 10, 64)
+ if err != nil {
+ return 0, err
+ }
+ t := uint64(b)
+ return t, nil
+ }
+ return 0, errors.New("could not find btime")
+}
+
+func Virtualization() (string, string, error) {
+ return VirtualizationWithContext(context.Background())
+}
+
+// required variables for concurrency safe virtualization caching
+var (
+ cachedVirtMap map[string]string
+ cachedVirtMutex sync.RWMutex
+ cachedVirtOnce sync.Once
+)
+
+func VirtualizationWithContext(ctx context.Context) (string, string, error) {
+ var system, role string
+
+ // if cached already, return from cache
+ cachedVirtMutex.RLock() // unlock won't be deferred so concurrent reads don't wait for long
+ if cachedVirtMap != nil {
+ cachedSystem, cachedRole := cachedVirtMap["system"], cachedVirtMap["role"]
+ cachedVirtMutex.RUnlock()
+ return cachedSystem, cachedRole, nil
+ }
+ cachedVirtMutex.RUnlock()
+
+ filename := HostProcWithContext(ctx, "xen")
+ if PathExists(filename) {
+ system = "xen"
+ role = "guest" // assume guest
+
+ if PathExists(filepath.Join(filename, "capabilities")) {
+ contents, err := ReadLines(filepath.Join(filename, "capabilities"))
+ if err == nil {
+ if StringsContains(contents, "control_d") {
+ role = "host"
+ }
+ }
+ }
+ }
+
+ filename = HostProcWithContext(ctx, "modules")
+ if PathExists(filename) {
+ contents, err := ReadLines(filename)
+ if err == nil {
+ if StringsContains(contents, "kvm") {
+ system = "kvm"
+ role = "host"
+ } else if StringsContains(contents, "hv_util") {
+ system = "hyperv"
+ role = "guest"
+ } else if StringsContains(contents, "vboxdrv") {
+ system = "vbox"
+ role = "host"
+ } else if StringsContains(contents, "vboxguest") {
+ system = "vbox"
+ role = "guest"
+ } else if StringsContains(contents, "vmware") {
+ system = "vmware"
+ role = "guest"
+ }
+ }
+ }
+
+ filename = HostProcWithContext(ctx, "cpuinfo")
+ if PathExists(filename) {
+ contents, err := ReadLines(filename)
+ if err == nil {
+ if StringsContains(contents, "QEMU Virtual CPU") ||
+ StringsContains(contents, "Common KVM processor") ||
+ StringsContains(contents, "Common 32-bit KVM processor") {
+ system = "kvm"
+ role = "guest"
+ }
+ }
+ }
+
+ filename = HostProcWithContext(ctx, "bus/pci/devices")
+ if PathExists(filename) {
+ contents, err := ReadLines(filename)
+ if err == nil {
+ if StringsContains(contents, "virtio-pci") {
+ role = "guest"
+ }
+ }
+ }
+
+ filename = HostProcWithContext(ctx)
+ if PathExists(filepath.Join(filename, "bc", "0")) {
+ system = "openvz"
+ role = "host"
+ } else if PathExists(filepath.Join(filename, "vz")) {
+ system = "openvz"
+ role = "guest"
+ }
+
+ // not use dmidecode because it requires root
+ if PathExists(filepath.Join(filename, "self", "status")) {
+ contents, err := ReadLines(filepath.Join(filename, "self", "status"))
+ if err == nil {
+ if StringsContains(contents, "s_context:") ||
+ StringsContains(contents, "VxID:") {
+ system = "linux-vserver"
+ }
+ // TODO: guest or host
+ }
+ }
+
+ if PathExists(filepath.Join(filename, "1", "environ")) {
+ contents, err := ReadFile(filepath.Join(filename, "1", "environ"))
+
+ if err == nil {
+ if strings.Contains(contents, "container=lxc") {
+ system = "lxc"
+ role = "guest"
+ }
+ }
+ }
+
+ if PathExists(filepath.Join(filename, "self", "cgroup")) {
+ contents, err := ReadLines(filepath.Join(filename, "self", "cgroup"))
+ if err == nil {
+ if StringsContains(contents, "lxc") {
+ system = "lxc"
+ role = "guest"
+ } else if StringsContains(contents, "docker") {
+ system = "docker"
+ role = "guest"
+ } else if StringsContains(contents, "machine-rkt") {
+ system = "rkt"
+ role = "guest"
+ } else if PathExists("/usr/bin/lxc-version") {
+ system = "lxc"
+ role = "host"
+ }
+ }
+ }
+
+ if PathExists(HostEtcWithContext(ctx, "os-release")) {
+ p, _, err := GetOSReleaseWithContext(ctx)
+ if err == nil && p == "coreos" {
+ system = "rkt" // Is it true?
+ role = "host"
+ }
+ }
+
+ if PathExists(HostRootWithContext(ctx, ".dockerenv")) {
+ system = "docker"
+ role = "guest"
+ }
+
+ // before returning for the first time, cache the system and role
+ cachedVirtOnce.Do(func() {
+ cachedVirtMutex.Lock()
+ defer cachedVirtMutex.Unlock()
+ cachedVirtMap = map[string]string{
+ "system": system,
+ "role": role,
+ }
+ })
+
+ return system, role, nil
+}
+
+func GetOSRelease() (platform string, version string, err error) {
+ return GetOSReleaseWithContext(context.Background())
+}
+
+func GetOSReleaseWithContext(ctx context.Context) (platform string, version string, err error) {
+ contents, err := ReadLines(HostEtcWithContext(ctx, "os-release"))
+ if err != nil {
+ return "", "", nil // return empty
+ }
+ for _, line := range contents {
+ field := strings.Split(line, "=")
+ if len(field) < 2 {
+ continue
+ }
+ switch field[0] {
+ case "ID": // use ID for lowercase
+ platform = trimQuotes(field[1])
+ case "VERSION_ID":
+ version = trimQuotes(field[1])
+ }
+ }
+
+ // cleanup amazon ID
+ if platform == "amzn" {
+ platform = "amazon"
+ }
+
+ return platform, version, nil
+}
+
+// Remove quotes of the source string
+func trimQuotes(s string) string {
+ if len(s) >= 2 {
+ if s[0] == '"' && s[len(s)-1] == '"' {
+ return s[1 : len(s)-1]
+ }
+ }
+ return s
+}
diff --git a/vendor/github.com/shirou/gopsutil/v4/internal/common/common_netbsd.go b/vendor/github.com/shirou/gopsutil/v4/internal/common/common_netbsd.go
new file mode 100644
index 0000000..2065321
--- /dev/null
+++ b/vendor/github.com/shirou/gopsutil/v4/internal/common/common_netbsd.go
@@ -0,0 +1,66 @@
+// SPDX-License-Identifier: BSD-3-Clause
+//go: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
+}
diff --git a/vendor/github.com/shirou/gopsutil/v4/internal/common/common_openbsd.go b/vendor/github.com/shirou/gopsutil/v4/internal/common/common_openbsd.go
new file mode 100644
index 0000000..00fa19a
--- /dev/null
+++ b/vendor/github.com/shirou/gopsutil/v4/internal/common/common_openbsd.go
@@ -0,0 +1,66 @@
+// SPDX-License-Identifier: BSD-3-Clause
+//go:build openbsd
+
+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
+}
diff --git a/vendor/github.com/shirou/gopsutil/v4/internal/common/common_unix.go b/vendor/github.com/shirou/gopsutil/v4/internal/common/common_unix.go
new file mode 100644
index 0000000..c9f91b1
--- /dev/null
+++ b/vendor/github.com/shirou/gopsutil/v4/internal/common/common_unix.go
@@ -0,0 +1,42 @@
+// SPDX-License-Identifier: BSD-3-Clause
+//go:build linux || freebsd || darwin || openbsd
+
+package common
+
+import (
+ "context"
+ "errors"
+ "os/exec"
+ "strconv"
+ "strings"
+)
+
+func CallLsofWithContext(ctx context.Context, invoke Invoker, pid int32, args ...string) ([]string, error) {
+ var cmd []string
+ if pid == 0 { // will get from all processes.
+ cmd = []string{"-a", "-n", "-P"}
+ } else {
+ cmd = []string{"-a", "-n", "-P", "-p", strconv.Itoa(int(pid))}
+ }
+ cmd = append(cmd, args...)
+ out, err := invoke.CommandWithContext(ctx, "lsof", cmd...)
+ if err != nil {
+ if errors.Is(err, exec.ErrNotFound) {
+ return []string{}, err
+ }
+ // if no pid found, lsof returns code 1.
+ if err.Error() == "exit status 1" && len(out) == 0 {
+ return []string{}, nil
+ }
+ }
+ lines := strings.Split(string(out), "\n")
+
+ var ret []string
+ for _, l := range lines[1:] {
+ if len(l) == 0 {
+ continue
+ }
+ ret = append(ret, l)
+ }
+ return ret, nil
+}
diff --git a/vendor/github.com/shirou/gopsutil/v4/internal/common/common_windows.go b/vendor/github.com/shirou/gopsutil/v4/internal/common/common_windows.go
new file mode 100644
index 0000000..766ed2f
--- /dev/null
+++ b/vendor/github.com/shirou/gopsutil/v4/internal/common/common_windows.go
@@ -0,0 +1,304 @@
+// SPDX-License-Identifier: BSD-3-Clause
+//go:build windows
+
+package common
+
+import (
+ "context"
+ "fmt"
+ "path/filepath"
+ "reflect"
+ "strings"
+ "syscall"
+ "unsafe"
+
+ "github.com/yusufpapurcu/wmi"
+ "golang.org/x/sys/windows"
+)
+
+// for double values
+type PDH_FMT_COUNTERVALUE_DOUBLE struct {
+ CStatus uint32
+ DoubleValue float64
+}
+
+// for 64 bit integer values
+type PDH_FMT_COUNTERVALUE_LARGE struct {
+ CStatus uint32
+ LargeValue int64
+}
+
+// for long values
+type PDH_FMT_COUNTERVALUE_LONG struct {
+ CStatus uint32
+ LongValue int32
+ padding [4]byte
+}
+
+// windows system const
+const (
+ ERROR_SUCCESS = 0
+ ERROR_FILE_NOT_FOUND = 2
+ DRIVE_REMOVABLE = 2
+ DRIVE_FIXED = 3
+ HKEY_LOCAL_MACHINE = 0x80000002
+ RRF_RT_REG_SZ = 0x00000002
+ RRF_RT_REG_DWORD = 0x00000010
+ PDH_FMT_LONG = 0x00000100
+ PDH_FMT_DOUBLE = 0x00000200
+ PDH_FMT_LARGE = 0x00000400
+ PDH_INVALID_DATA = 0xc0000bc6
+ PDH_INVALID_HANDLE = 0xC0000bbc
+ PDH_NO_DATA = 0x800007d5
+
+ STATUS_BUFFER_OVERFLOW = 0x80000005
+ STATUS_BUFFER_TOO_SMALL = 0xC0000023
+ STATUS_INFO_LENGTH_MISMATCH = 0xC0000004
+)
+
+const (
+ ProcessBasicInformation = 0
+ ProcessWow64Information = 26
+ ProcessQueryInformation = windows.PROCESS_DUP_HANDLE | windows.PROCESS_QUERY_INFORMATION
+
+ SystemExtendedHandleInformationClass = 64
+)
+
+var (
+ Modkernel32 = windows.NewLazySystemDLL("kernel32.dll")
+ ModNt = windows.NewLazySystemDLL("ntdll.dll")
+ ModPdh = windows.NewLazySystemDLL("pdh.dll")
+ ModPsapi = windows.NewLazySystemDLL("psapi.dll")
+
+ ProcGetSystemTimes = Modkernel32.NewProc("GetSystemTimes")
+ ProcNtQuerySystemInformation = ModNt.NewProc("NtQuerySystemInformation")
+ ProcRtlGetNativeSystemInformation = ModNt.NewProc("RtlGetNativeSystemInformation")
+ ProcRtlNtStatusToDosError = ModNt.NewProc("RtlNtStatusToDosError")
+ ProcNtQueryInformationProcess = ModNt.NewProc("NtQueryInformationProcess")
+ ProcNtReadVirtualMemory = ModNt.NewProc("NtReadVirtualMemory")
+ ProcNtWow64QueryInformationProcess64 = ModNt.NewProc("NtWow64QueryInformationProcess64")
+ ProcNtWow64ReadVirtualMemory64 = ModNt.NewProc("NtWow64ReadVirtualMemory64")
+
+ PdhOpenQuery = ModPdh.NewProc("PdhOpenQuery")
+ PdhAddEnglishCounterW = ModPdh.NewProc("PdhAddEnglishCounterW")
+ PdhCollectQueryData = ModPdh.NewProc("PdhCollectQueryData")
+ PdhGetFormattedCounterValue = ModPdh.NewProc("PdhGetFormattedCounterValue")
+ PdhCloseQuery = ModPdh.NewProc("PdhCloseQuery")
+
+ procQueryDosDeviceW = Modkernel32.NewProc("QueryDosDeviceW")
+)
+
+type FILETIME struct {
+ DwLowDateTime uint32
+ DwHighDateTime uint32
+}
+
+// borrowed from net/interface_windows.go
+func BytePtrToString(p *uint8) string {
+ a := (*[10000]uint8)(unsafe.Pointer(p))
+ i := 0
+ for a[i] != 0 {
+ i++
+ }
+ return string(a[:i])
+}
+
+// CounterInfo struct is used to track a windows performance counter
+// copied from https://github.com/mackerelio/mackerel-agent/
+type CounterInfo struct {
+ PostName string
+ CounterName string
+ Counter windows.Handle
+}
+
+// CreateQuery with a PdhOpenQuery call
+// copied from https://github.com/mackerelio/mackerel-agent/
+func CreateQuery() (windows.Handle, error) {
+ var query windows.Handle
+ r, _, err := PdhOpenQuery.Call(0, 0, uintptr(unsafe.Pointer(&query)))
+ if r != 0 {
+ return 0, err
+ }
+ return query, nil
+}
+
+// CreateCounter with a PdhAddEnglishCounterW call
+func CreateCounter(query windows.Handle, pname, cname string) (*CounterInfo, error) {
+ var counter windows.Handle
+ r, _, err := PdhAddEnglishCounterW.Call(
+ uintptr(query),
+ uintptr(unsafe.Pointer(windows.StringToUTF16Ptr(cname))),
+ 0,
+ uintptr(unsafe.Pointer(&counter)))
+ if r != 0 {
+ return nil, err
+ }
+ return &CounterInfo{
+ PostName: pname,
+ CounterName: cname,
+ Counter: counter,
+ }, nil
+}
+
+// GetCounterValue get counter value from handle
+// adapted from https://github.com/mackerelio/mackerel-agent/
+func GetCounterValue(counter windows.Handle) (float64, error) {
+ var value PDH_FMT_COUNTERVALUE_DOUBLE
+ r, _, err := PdhGetFormattedCounterValue.Call(uintptr(counter), PDH_FMT_DOUBLE, uintptr(0), uintptr(unsafe.Pointer(&value)))
+ if r != 0 && r != PDH_INVALID_DATA {
+ return 0.0, err
+ }
+ return value.DoubleValue, nil
+}
+
+type Win32PerformanceCounter struct {
+ PostName string
+ CounterName string
+ Query windows.Handle
+ Counter windows.Handle
+}
+
+func NewWin32PerformanceCounter(postName, counterName string) (*Win32PerformanceCounter, error) {
+ query, err := CreateQuery()
+ if err != nil {
+ return nil, err
+ }
+ counter := Win32PerformanceCounter{
+ Query: query,
+ PostName: postName,
+ CounterName: counterName,
+ }
+ r, _, err := PdhAddEnglishCounterW.Call(
+ uintptr(counter.Query),
+ uintptr(unsafe.Pointer(windows.StringToUTF16Ptr(counter.CounterName))),
+ 0,
+ uintptr(unsafe.Pointer(&counter.Counter)),
+ )
+ if r != 0 {
+ return nil, err
+ }
+ return &counter, nil
+}
+
+func (w *Win32PerformanceCounter) GetValue() (float64, error) {
+ r, _, err := PdhCollectQueryData.Call(uintptr(w.Query))
+ if r != 0 && err != nil {
+ if r == PDH_NO_DATA {
+ return 0.0, fmt.Errorf("%w: this counter has not data", err)
+ }
+ return 0.0, err
+ }
+
+ return GetCounterValue(w.Counter)
+}
+
+func ProcessorQueueLengthCounter() (*Win32PerformanceCounter, error) {
+ return NewWin32PerformanceCounter("processor_queue_length", `\System\Processor Queue Length`)
+}
+
+// WMIQueryWithContext - wraps wmi.Query with a timed-out context to avoid hanging
+func WMIQueryWithContext(ctx context.Context, query string, dst interface{}, connectServerArgs ...interface{}) error {
+ if _, ok := ctx.Deadline(); !ok {
+ ctxTimeout, cancel := context.WithTimeout(ctx, Timeout)
+ defer cancel()
+ ctx = ctxTimeout
+ }
+
+ errChan := make(chan error, 1)
+ go func() {
+ errChan <- wmi.Query(query, dst, connectServerArgs...)
+ }()
+
+ select {
+ case <-ctx.Done():
+ return ctx.Err()
+ case err := <-errChan:
+ return err
+ }
+}
+
+// Convert paths using native DOS format like:
+//
+// "\Device\HarddiskVolume1\Windows\systemew\file.txt"
+//
+// into:
+//
+// "C:\Windows\systemew\file.txt"
+func ConvertDOSPath(p string) string {
+ rawDrive := strings.Join(strings.Split(p, `\`)[:3], `\`)
+
+ for d := 'A'; d <= 'Z'; d++ {
+ szDeviceName := string(d) + ":"
+ szTarget := make([]uint16, 512)
+ ret, _, _ := procQueryDosDeviceW.Call(uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(szDeviceName))),
+ uintptr(unsafe.Pointer(&szTarget[0])),
+ uintptr(len(szTarget)))
+ if ret != 0 && windows.UTF16ToString(szTarget[:]) == rawDrive {
+ return filepath.Join(szDeviceName, p[len(rawDrive):])
+ }
+ }
+ return p
+}
+
+type NtStatus uint32
+
+func (s NtStatus) Error() error {
+ if s == 0 {
+ return nil
+ }
+ return fmt.Errorf("NtStatus 0x%08x", uint32(s))
+}
+
+func (s NtStatus) IsError() bool {
+ return s>>30 == 3
+}
+
+type SystemExtendedHandleTableEntryInformation struct {
+ Object uintptr
+ UniqueProcessId uintptr
+ HandleValue uintptr
+ GrantedAccess uint32
+ CreatorBackTraceIndex uint16
+ ObjectTypeIndex uint16
+ HandleAttributes uint32
+ Reserved uint32
+}
+
+type SystemExtendedHandleInformation struct {
+ NumberOfHandles uintptr
+ Reserved uintptr
+ Handles [1]SystemExtendedHandleTableEntryInformation
+}
+
+// CallWithExpandingBuffer https://github.com/hillu/go-ntdll
+func CallWithExpandingBuffer(fn func() NtStatus, buf *[]byte, resultLength *uint32) NtStatus {
+ for {
+ if st := fn(); st == STATUS_BUFFER_OVERFLOW || st == STATUS_BUFFER_TOO_SMALL || st == STATUS_INFO_LENGTH_MISMATCH {
+ if int(*resultLength) <= cap(*buf) {
+ (*reflect.SliceHeader)(unsafe.Pointer(buf)).Len = int(*resultLength)
+ } else {
+ *buf = make([]byte, int(*resultLength))
+ }
+ continue
+ } else {
+ if !st.IsError() {
+ *buf = (*buf)[:int(*resultLength)]
+ }
+ return st
+ }
+ }
+}
+
+func NtQuerySystemInformation(
+ SystemInformationClass uint32,
+ SystemInformation *byte,
+ SystemInformationLength uint32,
+ ReturnLength *uint32,
+) NtStatus {
+ r0, _, _ := ProcNtQuerySystemInformation.Call(
+ uintptr(SystemInformationClass),
+ uintptr(unsafe.Pointer(SystemInformation)),
+ uintptr(SystemInformationLength),
+ uintptr(unsafe.Pointer(ReturnLength)))
+ return NtStatus(r0)
+}
diff --git a/vendor/github.com/shirou/gopsutil/v4/internal/common/endian.go b/vendor/github.com/shirou/gopsutil/v4/internal/common/endian.go
new file mode 100644
index 0000000..113ff2e
--- /dev/null
+++ b/vendor/github.com/shirou/gopsutil/v4/internal/common/endian.go
@@ -0,0 +1,11 @@
+// SPDX-License-Identifier: BSD-3-Clause
+package common
+
+import "unsafe"
+
+// IsLittleEndian checks if the current platform uses little-endian.
+// copied from https://github.com/ntrrg/ntgo/blob/v0.8.0/runtime/infrastructure.go#L16 (MIT License)
+func IsLittleEndian() bool {
+ var x int16 = 0x0011
+ return *(*byte)(unsafe.Pointer(&x)) == 0x11
+}
diff --git a/vendor/github.com/shirou/gopsutil/v4/internal/common/sleep.go b/vendor/github.com/shirou/gopsutil/v4/internal/common/sleep.go
new file mode 100644
index 0000000..504f13f
--- /dev/null
+++ b/vendor/github.com/shirou/gopsutil/v4/internal/common/sleep.go
@@ -0,0 +1,22 @@
+// SPDX-License-Identifier: BSD-3-Clause
+package common
+
+import (
+ "context"
+ "time"
+)
+
+// Sleep awaits for provided interval.
+// Can be interrupted by context cancellation.
+func Sleep(ctx context.Context, interval time.Duration) error {
+ timer := time.NewTimer(interval)
+ select {
+ case <-ctx.Done():
+ if !timer.Stop() {
+ <-timer.C
+ }
+ return ctx.Err()
+ case <-timer.C:
+ return nil
+ }
+}
diff --git a/vendor/github.com/shirou/gopsutil/v4/internal/common/warnings.go b/vendor/github.com/shirou/gopsutil/v4/internal/common/warnings.go
new file mode 100644
index 0000000..888cc57
--- /dev/null
+++ b/vendor/github.com/shirou/gopsutil/v4/internal/common/warnings.go
@@ -0,0 +1,31 @@
+// SPDX-License-Identifier: BSD-3-Clause
+package common
+
+import "fmt"
+
+type Warnings struct {
+ List []error
+ Verbose bool
+}
+
+func (w *Warnings) Add(err error) {
+ w.List = append(w.List, err)
+}
+
+func (w *Warnings) Reference() error {
+ if len(w.List) > 0 {
+ return w
+ }
+ return nil
+}
+
+func (w *Warnings) Error() string {
+ if w.Verbose {
+ str := ""
+ for i, e := range w.List {
+ str += fmt.Sprintf("\tError %d: %s\n", i, e.Error())
+ }
+ return str
+ }
+ return fmt.Sprintf("Number of warnings: %v", len(w.List))
+}