pull/1769/head
Mingyang Zheng 1 week ago
commit 0be0ec4e46

4
.gitattributes vendored

@ -0,0 +1,4 @@
# ensure that line endings for Windows builds are properly formatted
# see https://github.com/golangci/golangci-lint-action?tab=readme-ov-file#how-to-use
# at "Multiple OS Example" section
*.go text eol=lf

@ -1,5 +1,15 @@
on: [push, pull_request]
name: Build Test
on:
push:
branches:
- master
pull_request:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
@ -21,24 +31,12 @@ jobs:
go-version: ${{fromJson(needs.go-versions.outputs.versions)}}
runs-on: ubuntu-22.04
steps:
- name: Install Go
uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0
with:
go-version: ${{ matrix.go-version }}
- name: Checkout code
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- 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@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
- name: Install Go
uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5.3.0
with:
path: |
${{ steps.cache-paths.outputs.cache }}
${{ steps.cache-paths.outputs.mod-cache }}
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
restore-keys: ${{ runner.os }}-go-
go-version: ${{ matrix.go-version }}
- name: Build Test v3
run: |
make build_test

@ -1,6 +1,7 @@
name: "Pull Request Labeler"
on:
- pull_request_target
pull_request_target:
permissions:
contents: read

@ -2,28 +2,66 @@ name: Golangci-lint
on:
push:
branches:
- master
pull_request:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
jobs:
golangci:
strategy:
fail-fast: false
matrix:
include:
- {os: macos-latest, GOOS: darwin, GOARCH: amd64}
- {os: macos-latest, GOOS: darwin, GOARCH: arm64}
- {os: ubuntu-latest, GOOS: dragonfly, GOARCH: amd64}
- {os: ubuntu-latest, GOOS: freebsd, GOARCH: amd64}
- {os: ubuntu-latest, GOOS: freebsd, GOARCH: 386}
- {os: ubuntu-latest, GOOS: freebsd, GOARCH: arm}
- {os: ubuntu-latest, GOOS: linux, GOARCH: 386}
- {os: ubuntu-latest, GOOS: linux, GOARCH: amd64}
- {os: ubuntu-latest, GOOS: linux, GOARCH: arm64}
- {os: ubuntu-latest, GOOS: linux, GOARCH: arm}
- {os: ubuntu-latest, GOOS: linux, GOARCH: mips64}
- {os: ubuntu-latest, GOOS: linux, GOARCH: mips64le}
- {os: ubuntu-latest, GOOS: linux, GOARCH: mips}
- {os: ubuntu-latest, GOOS: linux, GOARCH: mipsle}
- {os: ubuntu-latest, GOOS: linux, GOARCH: ppc64le}
- {os: ubuntu-latest, GOOS: linux, GOARCH: ppc64}
- {os: ubuntu-latest, GOOS: linux, GOARCH: riscv64}
- {os: ubuntu-latest, GOOS: linux, GOARCH: s390x}
- {os: ubuntu-latest, GOOS: netbsd, GOARCH: amd64}
- {os: ubuntu-latest, GOOS: openbsd, GOARCH: 386}
- {os: ubuntu-latest, GOOS: openbsd, GOARCH: amd64}
- {os: ubuntu-latest, GOOS: plan9, GOARCH: amd64}
- {os: ubuntu-latest, GOOS: plan9, GOARCH: 386}
- {os: ubuntu-latest, GOOS: solaris, GOARCH: amd64}
- {os: windows-latest, GOOS: windows, GOARCH: amd64}
- {os: windows-latest, GOOS: windows, GOARCH: 386}
permissions:
contents: read # for actions/checkout to fetch code
pull-requests: read # for golangci/golangci-lint-action to fetch pull requests
name: lint
runs-on: ubuntu-latest
runs-on: ${{ matrix.os }}
env:
GOARCH: ${{ matrix.GOARCH }}
GOOS: ${{ matrix.GOOS }}
steps:
- name: Setup go
uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0
with:
go-version: 1.17
cache: false
- name: Checkout repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Setup go
uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5.3.0
with:
go-version-file: go.mod
- name: Setup golangci-lint
uses: golangci/golangci-lint-action@971e284b6050e8a5849b72094c50ab08da042db8 # v6.1.1
uses: golangci/golangci-lint-action@2226d7cb06a077cd73e56eedd38eecad18e5d837 # v6.5.0
with:
args: --verbose
version: latest

@ -1,8 +1,9 @@
name: Release
on:
schedule:
- cron: '0 1 1 * *' # UTC 01:00 on the first day of the Month
name: Release
permissions:
contents: write

@ -2,8 +2,8 @@ name: SBOM Generator
on:
push:
branches: [ "master" ]
branches:
- master
workflow_dispatch:
permissions: read-all
@ -11,15 +11,13 @@ permissions: read-all
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: advanced-security/sbom-generator-action@375dee8e6144d9fd0ec1f5667b4f6fb4faacefed # v0.0.1
- uses: advanced-security/sbom-generator-action@6fe43abf522b2e7a19bc769aec1e6c848614b517 # v0.0.2
id: sbom
env:
GITHUB_TOKEN: ${{ github.token }}
- uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0
- uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
with:
path: ${{steps.sbom.outputs.fileName }}
name: "SBOM"

@ -1,5 +1,15 @@
on: [push, pull_request]
name: Shellcheck
on:
push:
branches:
- master
pull_request:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read

@ -1,5 +1,15 @@
on: [push, pull_request]
name: Test
on:
push:
branches:
- master
pull_request:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
@ -22,24 +32,12 @@ jobs:
os: [ubuntu-22.04, ubuntu-20.04, ubuntu-24.04, windows-2022, windows-2019, macos-13, macos-14, macos-15]
runs-on: ${{ matrix.os }}
steps:
- name: Install Go
uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0
with:
go-version: ${{ matrix.go-version }}
- name: Checkout code
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- 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@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
- name: Install Go
uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5.3.0
with:
path: |
${{ steps.go-env.outputs.cache }}
${{ steps.go-env.outputs.mod-cache }}
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
restore-keys: ${{ runner.os }}-go-
go-version: ${{ matrix.go-version }}
- name: Test
run: |
go test -coverprofile='coverage.out' -covermode=atomic ./...

@ -1,21 +1,6 @@
issues:
max-same-issues: 0
exclude-rules:
- linters:
- gosec
text: G115
- linters:
- revive
text: var-naming
- linters:
- revive
text: exported
- linters:
- revive
text: empty-block
- linters:
- revive
text: unused-parameter
exclude-rules: []
linters:
enable:
- asciicheck
@ -55,9 +40,12 @@ linters-settings:
blocked:
modules:
- io/ioutil:
recommandations:
recommendations:
- io
- os
gosec:
excludes:
- G115
perfsprint:
# Optimizes even if it requires an int or uint type cast.
int-conversion: true
@ -69,5 +57,47 @@ linters-settings:
sprintf1: true
# Optimizes into strings concatenation.
strconcat: true
revive:
rules:
- name: blank-imports
- name: context-as-argument
arguments:
- allowTypesBefore: "*testing.T"
- name: context-keys-type
- name: dot-imports
- name: duplicated-imports
- name: early-return
arguments:
- "preserveScope"
- name: empty-block
disabled: true
- name: error-naming
- name: error-return
- name: error-strings
- name: exported
disabled: true
- name: errorf
- name: increment-decrement
- name: indent-error-flow
arguments:
- "preserveScope"
- name: range
- name: receiver-naming
- name: redefines-builtin-id
- name: redundant-import-alias
- name: superfluous-else
arguments:
- "preserveScope"
- name: time-naming
- name: unexported-return
- name: unnecessary-stmt
disabled: true
- name: unreachable-code
- name: unused-parameter
disabled: true
- name: use-any
- name: var-declaration
- name: var-naming
disabled: true
testifylint:
enable-all: true

@ -34,6 +34,7 @@ build_test: ## test only buildable
GOOS=netbsd go test ./... | $(BUILD_FAIL_PATTERN)
GOOS=openbsd go test ./... | $(BUILD_FAIL_PATTERN)
GOOS=plan9 go test ./... | $(BUILD_FAIL_PATTERN)
CGO_ENABLED=0 GOOS=aix GOARCH=ppc64 go test ./... | $(BUILD_FAIL_PATTERN)
ifeq ($(shell uname -s), Darwin)
CGO_ENABLED=1 GOOS=darwin go test ./... | $(BUILD_FAIL_PATTERN)
@ -77,6 +78,8 @@ vet:
GOOS=plan9 GOARCH=amd64 go vet ./...
GOOS=plan9 GOARCH=386 go vet ./...
CGO_ENABLED=0 GOOS=aix GOARCH=ppc64 go vet ./...
macos_test:
CGO_ENABLED=0 GOOS=darwin go test ./... | $(BUILD_FAIL_PATTERN)
CGO_ENABLED=1 GOOS=darwin go test ./... | $(BUILD_FAIL_PATTERN)

@ -11,9 +11,10 @@ import (
"strings"
"unsafe"
"github.com/shirou/gopsutil/v4/internal/common"
"github.com/tklauser/go-sysconf"
"golang.org/x/sys/unix"
"github.com/shirou/gopsutil/v4/internal/common"
)
var (
@ -135,7 +136,7 @@ func parseDmesgBoot(fileName string) (InfoStat, error) {
c.VendorID = matches[1]
t, err := strconv.ParseInt(matches[2], 10, 32)
if err != nil {
return c, fmt.Errorf("unable to parse DragonflyBSD CPU stepping information from %q: %v", line, err)
return c, fmt.Errorf("unable to parse DragonflyBSD CPU stepping information from %q: %w", line, err)
}
c.Stepping = int32(t)
} else if matches := featuresMatch.FindStringSubmatch(line); matches != nil {

@ -57,7 +57,7 @@ func TimesWithContext(ctx context.Context, percpu bool) (ret []TimesStat, err er
ncpu, err := unix.SysctlUint32("hw.ncpu")
if err != nil {
return
return //nolint:nakedret //FIXME
}
var i uint32

@ -9,9 +9,10 @@ import (
"runtime"
"unsafe"
"github.com/shirou/gopsutil/v4/internal/common"
"github.com/tklauser/go-sysconf"
"golang.org/x/sys/unix"
"github.com/shirou/gopsutil/v4/internal/common"
)
const (
@ -74,7 +75,7 @@ func TimesWithContext(ctx context.Context, percpu bool) (ret []TimesStat, err er
ncpu, err := unix.SysctlUint32("hw.ncpu")
if err != nil {
return
return //nolint:nakedret //FIXME
}
var i uint32

@ -9,6 +9,7 @@ import (
"runtime"
stats "github.com/lufia/plan9stats"
"github.com/shirou/gopsutil/v4/internal/common"
)

@ -42,7 +42,7 @@ 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 {
return nil, fmt.Errorf("cannot execute kstat: %s", err)
return nil, fmt.Errorf("cannot execute kstat: %w", err)
}
cpu := make(map[float64]float64)
idle := make(map[float64]float64)
@ -57,29 +57,29 @@ func TimesWithContext(ctx context.Context, percpu bool) ([]TimesStat, error) {
}
cpuNumber, err := strconv.ParseFloat(fields[1], 64)
if err != nil {
return nil, fmt.Errorf("cannot parse cpu number: %s", err)
return nil, fmt.Errorf("cannot parse cpu number: %w", err)
}
cpu[cpuNumber] = cpuNumber
switch fields[3] {
case "idle":
idle[cpuNumber], err = strconv.ParseFloat(fields[4], 64)
if err != nil {
return nil, fmt.Errorf("cannot parse idle: %s", err)
return nil, fmt.Errorf("cannot parse idle: %w", err)
}
case "user":
user[cpuNumber], err = strconv.ParseFloat(fields[4], 64)
if err != nil {
return nil, fmt.Errorf("cannot parse user: %s", err)
return nil, fmt.Errorf("cannot parse user: %w", err)
}
case "kernel":
kern[cpuNumber], err = strconv.ParseFloat(fields[4], 64)
if err != nil {
return nil, fmt.Errorf("cannot parse kernel: %s", err)
return nil, fmt.Errorf("cannot parse kernel: %w", err)
}
case "iowait":
iowt[cpuNumber], err = strconv.ParseFloat(fields[4], 64)
if err != nil {
return nil, fmt.Errorf("cannot parse iowait: %s", err)
return nil, fmt.Errorf("cannot parse iowait: %w", err)
}
//not sure how this translates, don't report, add to kernel, something else?
/*case "swap":
@ -121,22 +121,22 @@ func Info() ([]InfoStat, error) {
func InfoWithContext(ctx context.Context) ([]InfoStat, error) {
psrInfoOut, err := invoke.CommandWithContext(ctx, "psrinfo", "-p", "-v")
if err != nil {
return nil, fmt.Errorf("cannot execute psrinfo: %s", err)
return nil, fmt.Errorf("cannot execute psrinfo: %w", err)
}
procs, err := parseProcessorInfo(string(psrInfoOut))
if err != nil {
return nil, fmt.Errorf("error parsing psrinfo output: %s", err)
return nil, fmt.Errorf("error parsing psrinfo output: %w", err)
}
isaInfoOut, err := invoke.CommandWithContext(ctx, "isainfo", "-b", "-v")
if err != nil {
return nil, fmt.Errorf("cannot execute isainfo: %s", err)
return nil, fmt.Errorf("cannot execute isainfo: %w", err)
}
flags, err := parseISAInfo(string(isaInfoOut))
if err != nil {
return nil, fmt.Errorf("error parsing isainfo output: %s", err)
return nil, fmt.Errorf("error parsing isainfo output: %w", err)
}
result := make([]InfoStat, 0, len(flags))
@ -160,7 +160,7 @@ func parseISAInfo(cmdOutput string) ([]string, error) {
}
flags := make([]string, len(words)-4)
for i, val := range words[4:] {
for i, val := range words[4:] { //nolint:gosimple //FIXME
flags[i] = val
}
sort.Strings(flags)
@ -194,7 +194,7 @@ func parseProcessorInfo(cmdOutput string) ([]InfoStat, error) {
if physicalCPU[psrStepOffset] != "" {
stepParsed, err := strconv.ParseInt(physicalCPU[psrStepOffset], 10, 32)
if err != nil {
return nil, fmt.Errorf("cannot parse value %q for step as 32-bit integer: %s", physicalCPU[9], err)
return nil, fmt.Errorf("cannot parse value %q for step as 32-bit integer: %w", physicalCPU[9], err)
}
step = int32(stepParsed)
}
@ -202,7 +202,7 @@ func parseProcessorInfo(cmdOutput string) ([]InfoStat, error) {
if physicalCPU[psrClockOffset] != "" {
clockParsed, err := strconv.ParseInt(physicalCPU[psrClockOffset], 10, 64)
if err != nil {
return nil, fmt.Errorf("cannot parse value %q for clock as 32-bit integer: %s", physicalCPU[10], err)
return nil, fmt.Errorf("cannot parse value %q for clock as 32-bit integer: %w", physicalCPU[10], err)
}
clock = float64(clockParsed)
}
@ -214,7 +214,7 @@ func parseProcessorInfo(cmdOutput string) ([]InfoStat, error) {
case physicalCPU[psrNumCoresOffset] != "":
numCores, err = strconv.ParseInt(physicalCPU[psrNumCoresOffset], 10, 32)
if err != nil {
return nil, fmt.Errorf("cannot parse value %q for core count as 32-bit integer: %s", physicalCPU[1], err)
return nil, fmt.Errorf("cannot parse value %q for core count as 32-bit integer: %w", physicalCPU[1], err)
}
for i := 0; i < int(numCores); i++ {
@ -235,12 +235,12 @@ func parseProcessorInfo(cmdOutput string) ([]InfoStat, error) {
case physicalCPU[psrNumCoresHTOffset] != "":
numCores, err = strconv.ParseInt(physicalCPU[psrNumCoresHTOffset], 10, 32)
if err != nil {
return nil, fmt.Errorf("cannot parse value %q for core count as 32-bit integer: %s", physicalCPU[3], err)
return nil, fmt.Errorf("cannot parse value %q for core count as 32-bit integer: %w", physicalCPU[3], err)
}
numHT, err = strconv.ParseInt(physicalCPU[psrNumHTOffset], 10, 32)
if err != nil {
return nil, fmt.Errorf("cannot parse value %q for hyperthread count as 32-bit integer: %s", physicalCPU[4], err)
return nil, fmt.Errorf("cannot parse value %q for hyperthread count as 32-bit integer: %w", physicalCPU[4], err)
}
for i := 0; i < int(numCores); i++ {

@ -6,11 +6,13 @@ package cpu
import (
"context"
"fmt"
"strconv"
"unsafe"
"github.com/shirou/gopsutil/v4/internal/common"
"github.com/yusufpapurcu/wmi"
"golang.org/x/sys/windows"
"github.com/shirou/gopsutil/v4/internal/common"
)
var procGetNativeSystemInfo = common.Modkernel32.NewProc("GetNativeSystemInfo")
@ -110,7 +112,7 @@ func InfoWithContext(ctx context.Context) ([]InfoStat, error) {
cpu := InfoStat{
CPU: int32(i),
Family: fmt.Sprintf("%d", l.Family),
Family: strconv.FormatUint(uint64(l.Family), 10),
VendorID: l.Manufacturer,
ModelName: l.Name,
Cores: int32(l.NumberOfLogicalProcessors),

@ -222,7 +222,7 @@ func (i *ioCounters) getDriveStat(d uint32) (*IOCountersStat, error) {
defer i.ioObjectRelease(parent)
if !ioObjectConformsTo(parent, "IOBlockStorageDriver") {
//return nil, fmt.Errorf("ERROR: the object is not of the IOBlockStorageDriver class")
// return nil, fmt.Errorf("ERROR: the object is not of the IOBlockStorageDriver class")
return nil, nil
}

@ -8,8 +8,9 @@ import (
"context"
"encoding/binary"
"github.com/shirou/gopsutil/v4/internal/common"
"golang.org/x/sys/unix"
"github.com/shirou/gopsutil/v4/internal/common"
)
func PartitionsWithContext(ctx context.Context, all bool) ([]PartitionStat, error) {

@ -7,6 +7,7 @@ import (
"bufio"
"bytes"
"context"
"errors"
"fmt"
"math"
"os"
@ -16,8 +17,9 @@ import (
"strconv"
"strings"
"github.com/shirou/gopsutil/v4/internal/common"
"golang.org/x/sys/unix"
"github.com/shirou/gopsutil/v4/internal/common"
)
const (
@ -100,7 +102,7 @@ func IOCountersWithContext(ctx context.Context, names ...string) (map[string]IOC
}
lines := strings.Split(strings.TrimSpace(string(kstatSysOut)), "\n")
if len(lines) == 0 {
return nil, fmt.Errorf("no disk class found")
return nil, errors.New("no disk class found")
}
dnamearr := make(map[string]string)
nreadarr := make(map[string]uint64)

@ -6,13 +6,14 @@ package disk
import (
"bytes"
"context"
"fmt"
"errors"
"syscall"
"unsafe"
"github.com/shirou/gopsutil/v4/internal/common"
"golang.org/x/sys/windows"
"golang.org/x/sys/windows/registry"
"github.com/shirou/gopsutil/v4/internal/common"
)
var (
@ -202,11 +203,11 @@ func IOCountersWithContext(ctx context.Context, names ...string) (map[string]IOC
if typeret != windows.DRIVE_FIXED {
continue
}
szDevice := fmt.Sprintf(`\\.\%s`, path)
szDevice := `\\.\` + path
const IOCTL_DISK_PERFORMANCE = 0x70020
h, err := windows.CreateFile(syscall.StringToUTF16Ptr(szDevice), 0, windows.FILE_SHARE_READ|windows.FILE_SHARE_WRITE, nil, windows.OPEN_EXISTING, 0, 0)
if err != nil {
if err == windows.ERROR_FILE_NOT_FOUND {
if errors.Is(err, windows.ERROR_FILE_NOT_FOUND) {
continue
}
return drivemap, err

@ -13,7 +13,7 @@ import (
"strconv"
"strings"
cpu "github.com/shirou/gopsutil/v4/cpu"
"github.com/shirou/gopsutil/v4/cpu"
"github.com/shirou/gopsutil/v4/internal/common"
)

@ -3,8 +3,8 @@ module github.com/shirou/gopsutil/v4
go 1.18
require (
github.com/ebitengine/purego v0.8.1
github.com/google/go-cmp v0.6.0
github.com/ebitengine/purego v0.8.2
github.com/google/go-cmp v0.7.0
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c
github.com/stretchr/testify v1.10.0

@ -1,12 +1,12 @@
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/ebitengine/purego v0.8.1 h1:sdRKd6plj7KYW33EH5As6YKfe8m9zbN9JMrOjNVF/BE=
github.com/ebitengine/purego v0.8.1/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ=
github.com/ebitengine/purego v0.8.2 h1:jPPGWs2sZ1UgOSgD2bClL0MJIqu58nOmIcBuXr62z1I=
github.com/ebitengine/purego v0.8.2/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ=
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.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
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=

@ -110,7 +110,7 @@ func parseUptime(uptime string) uint64 {
if err != nil {
return 0
}
case ut[3] == "mins," || ut[3] == "mins,":
case ut[3] == "mins,":
mins, err = strconv.ParseUint(ut[2], 10, 64)
if err != nil {
return 0

@ -12,9 +12,10 @@ import (
"strings"
"unsafe"
"golang.org/x/sys/unix"
"github.com/shirou/gopsutil/v4/internal/common"
"github.com/shirou/gopsutil/v4/process"
"golang.org/x/sys/unix"
)
const (

@ -7,6 +7,7 @@ import (
"bufio"
"bytes"
"context"
"errors"
"fmt"
"os"
"regexp"
@ -31,14 +32,13 @@ func HostIDWithContext(ctx context.Context) (string, error) {
line := sc.Text()
// If we're in the global zone, rely on the hostname.
if line == "global" {
if line != "global" {
return strings.TrimSpace(line), nil
}
hostname, err := os.Hostname()
if err == nil {
return hostname, nil
}
} else {
return strings.TrimSpace(line), nil
}
}
}
}
@ -84,7 +84,7 @@ func BootTimeWithContext(ctx context.Context) (uint64, error) {
}
func UptimeWithContext(ctx context.Context) (uint64, error) {
bootTime, err := BootTime()
bootTime, err := BootTime() //nolint:contextcheck //FIXME
if err != nil {
return 0, err
}
@ -139,7 +139,7 @@ func parseUnameOutput(ctx context.Context) (string, string, string, error) {
fields := strings.Fields(string(out))
if len(fields) < 3 {
return "", "", "", fmt.Errorf("malformed `uname` output")
return "", "", "", errors.New("malformed `uname` output")
}
return fields[0], fields[1], fields[2], nil

@ -13,9 +13,10 @@ import (
"time"
"unsafe"
"golang.org/x/sys/windows"
"github.com/shirou/gopsutil/v4/internal/common"
"github.com/shirou/gopsutil/v4/process"
"golang.org/x/sys/windows"
)
var (
@ -79,7 +80,7 @@ func HostIDWithContext(ctx context.Context) (string, error) {
hostID := windows.UTF16ToString(regBuf[:])
hostIDLen := len(hostID)
if hostIDLen != uuidLen {
return "", fmt.Errorf("HostID incorrect: %q\n", hostID)
return "", fmt.Errorf("HostID incorrect: %q\n", hostID) //nolint:revive //FIXME
}
return strings.ToLower(hostID), nil
@ -135,15 +136,15 @@ func BootTimeWithContext(ctx context.Context) (uint64, error) {
return t, nil
}
func PlatformInformationWithContext(ctx context.Context) (platform string, family string, version string, err error) {
platform, family, _, displayVersion, err := platformInformation(ctx)
func PlatformInformationWithContext(_ context.Context) (platform string, family string, version string, err error) {
platform, family, _, displayVersion, err := platformInformation()
if err != nil {
return "", "", "", err
}
return platform, family, displayVersion, nil
}
func platformInformation(ctx context.Context) (platform, family, version, displayVersion string, err error) {
func platformInformation() (platform, family, version, displayVersion string, err error) {
// GetVersionEx lies on Windows 8.1 and returns as Windows 8 if we don't declare compatibility in manifest
// RtlGetVersion bypasses this lying layer and returns the true Windows version
// https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/wdm/nf-wdm-rtlgetversion
@ -152,26 +153,26 @@ func platformInformation(ctx context.Context) (platform, family, version, displa
osInfo.dwOSVersionInfoSize = uint32(unsafe.Sizeof(osInfo))
ret, _, err := procRtlGetVersion.Call(uintptr(unsafe.Pointer(&osInfo)))
if ret != 0 {
return
return //nolint:nakedret //FIXME
}
// Platform
var h windows.Handle // like HostIDWithContext(), we query the registry using the raw windows.RegOpenKeyEx/RegQueryValueEx
err = windows.RegOpenKeyEx(windows.HKEY_LOCAL_MACHINE, windows.StringToUTF16Ptr(`SOFTWARE\Microsoft\Windows NT\CurrentVersion`), 0, windows.KEY_READ|windows.KEY_WOW64_64KEY, &h)
if err != nil {
return
return //nolint:nakedret //FIXME
}
defer windows.RegCloseKey(h)
var bufLen uint32
var valType uint32
err = windows.RegQueryValueEx(h, windows.StringToUTF16Ptr(`ProductName`), nil, &valType, nil, &bufLen)
if err != nil {
return
return //nolint:nakedret //FIXME
}
regBuf := make([]uint16, bufLen/2+1)
err = windows.RegQueryValueEx(h, windows.StringToUTF16Ptr(`ProductName`), nil, &valType, (*byte)(unsafe.Pointer(&regBuf[0])), &bufLen)
if err != nil {
return
return //nolint:nakedret //FIXME
}
platform = windows.UTF16ToString(regBuf[:])
if strings.Contains(platform, "Windows 10") { // check build number to determine whether it's actually Windows 11
@ -243,8 +244,8 @@ func VirtualizationWithContext(ctx context.Context) (string, string, error) {
return "", "", common.ErrNotImplementedError
}
func KernelVersionWithContext(ctx context.Context) (string, error) {
_, _, version, _, err := platformInformation(ctx)
func KernelVersionWithContext(_ context.Context) (string, error) {
_, _, version, _, err := platformInformation()
return version, err
}

@ -137,7 +137,7 @@ func (bigEndian) GoString() string { return "binary.BigEndian" }
// 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 {
func Read(r io.Reader, order ByteOrder, data any) error {
// Fast path for basic types and slices.
if n := intDataSize(data); n != 0 {
var b [8]byte
@ -229,7 +229,7 @@ func Read(r io.Reader, order ByteOrder, data interface{}) error {
// 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 {
func Write(w io.Writer, order ByteOrder, data any) error {
// Fast path for basic types and slices.
if n := intDataSize(data); n != 0 {
var b [8]byte
@ -339,7 +339,7 @@ func Write(w io.Writer, order ByteOrder, data interface{}) error {
// 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 {
func Size(v any) int {
return dataSize(reflect.Indirect(reflect.ValueOf(v)))
}
@ -607,7 +607,7 @@ func (e *encoder) skip(v reflect.Value) {
// 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 {
func intDataSize(data any) int {
switch data := data.(type) {
case int8, *int8, *uint8:
return 1

@ -311,7 +311,7 @@ func IntContains(target []int, src int) bool {
// get struct attributes.
// This method is used only for debugging platform dependent code.
func attributes(m interface{}) map[string]reflect.Type {
func attributes(m any) map[string]reflect.Type {
typ := reflect.TypeOf(m)
if typ.Kind() == reflect.Ptr {
typ = typ.Elem()

@ -5,6 +5,7 @@ package common
import (
"context"
"errors"
"fmt"
"os"
"os/exec"
@ -306,7 +307,7 @@ const (
func NewSMC(ioKit *Library) (*SMC, error) {
if ioKit.path != IOKit {
return nil, fmt.Errorf("library is not IOKit")
return nil, errors.New("library is not IOKit")
}
ioServiceGetMatchingService := GetFunc[IOServiceGetMatchingServiceFunc](ioKit, IOServiceGetMatchingServiceSym)
@ -324,7 +325,7 @@ func NewSMC(ioKit *Library) (*SMC, error) {
var conn uint32
if result := ioServiceOpen(service, machTaskSelf(), 0, &conn); result != 0 {
return nil, fmt.Errorf("ERROR: IOServiceOpen failed")
return nil, errors.New("ERROR: IOServiceOpen failed")
}
ioObjectRelease(service)
@ -343,7 +344,7 @@ 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 errors.New("ERROR: IOServiceClose failed")
}
return nil
}
@ -367,8 +368,8 @@ func (s CStr) Ptr() *byte {
return &s[0]
}
func (c CStr) Addr() uintptr {
return uintptr(unsafe.Pointer(c.Ptr()))
func (s CStr) Addr() uintptr {
return uintptr(unsafe.Pointer(s.Ptr()))
}
func (s CStr) GoString() string {

@ -197,7 +197,7 @@ func ProcessorQueueLengthCounter() (*Win32PerformanceCounter, error) {
}
// WMIQueryWithContext - wraps wmi.Query with a timed-out context to avoid hanging
func WMIQueryWithContext(ctx context.Context, query string, dst interface{}, connectServerArgs ...interface{}) error {
func WMIQueryWithContext(ctx context.Context, query string, dst any, connectServerArgs ...any) error {
if _, ok := ctx.Deadline(); !ok {
ctxTimeout, cancel := context.WithTimeout(ctx, Timeout)
defer cancel()
@ -273,20 +273,20 @@ type SystemExtendedHandleInformation struct {
// 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 {
st := fn()
if 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(

@ -14,9 +14,9 @@ import (
var (
loadErr error
loadAvg1M float64 = 0.0
loadAvg5M float64 = 0.0
loadAvg15M float64 = 0.0
loadAvg1M = 0.0
loadAvg5M = 0.0
loadAvg15M = 0.0
loadAvgMutex sync.RWMutex
loadAvgGoroutineOnce sync.Once
)
@ -27,10 +27,10 @@ var (
// code https://github.com/giampaolo/psutil/blob/8415355c8badc9c94418b19bdf26e622f06f0cce/psutil/arch/windows/wmi.c
func loadAvgGoroutine(ctx context.Context) {
var (
samplingFrequency time.Duration = 5 * time.Second
loadAvgFactor1M float64 = 1 / math.Exp(samplingFrequency.Seconds()/time.Minute.Seconds())
loadAvgFactor5M float64 = 1 / math.Exp(samplingFrequency.Seconds()/(5*time.Minute).Seconds())
loadAvgFactor15M float64 = 1 / math.Exp(samplingFrequency.Seconds()/(15*time.Minute).Seconds())
samplingFrequency = 5 * time.Second
loadAvgFactor1M = 1 / math.Exp(samplingFrequency.Seconds()/time.Minute.Seconds())
loadAvgFactor5M = 1 / math.Exp(samplingFrequency.Seconds()/(5*time.Minute).Seconds())
loadAvgFactor15M = 1 / math.Exp(samplingFrequency.Seconds()/(15*time.Minute).Seconds())
currentLoad float64
)

@ -7,6 +7,7 @@ import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
const validFreeBSD = `Device: 1kB-blocks Used:
@ -24,33 +25,31 @@ const invalid = `Device: 512-blocks Used:
`
func TestParseSwapctlOutput_FreeBSD(t *testing.T) {
assert := assert.New(t)
stats, err := parseSwapctlOutput(validFreeBSD)
assert.NoError(err)
require.NoError(t, err)
assert.Equal(*stats[0], SwapDevice{
assert.Equal(t, SwapDevice{
Name: "/dev/gpt/swapfs",
UsedBytes: 1263616,
FreeBytes: 1072478208,
})
}, *stats[0])
assert.Equal(*stats[1], SwapDevice{
assert.Equal(t, SwapDevice{
Name: "/dev/md0",
UsedBytes: 681984,
FreeBytes: 1073059840,
})
}, *stats[1])
}
func TestParseSwapctlOutput_OpenBSD(t *testing.T) {
assert := assert.New(t)
stats, err := parseSwapctlOutput(validOpenBSD)
assert.NoError(err)
require.NoError(t, err)
assert.Equal(*stats[0], SwapDevice{
assert.Equal(t, SwapDevice{
Name: "/dev/wd0b",
UsedBytes: 1234 * 1024,
FreeBytes: 653791 * 1024,
})
}, *stats[0])
}
func TestParseSwapctlOutput_Invalid(t *testing.T) {

@ -9,39 +9,40 @@ import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestVirtualMemoryDarwin(t *testing.T) {
v, err := VirtualMemory()
assert.Nil(t, err)
require.NoError(t, err)
outBytes, err := invoke.Command("/usr/sbin/sysctl", "hw.memsize")
assert.Nil(t, err)
require.NoError(t, err)
outString := string(outBytes)
outString = strings.TrimSpace(outString)
outParts := strings.Split(outString, " ")
actualTotal, err := strconv.ParseInt(outParts[1], 10, 64)
assert.Nil(t, err)
require.NoError(t, err)
assert.Equal(t, uint64(actualTotal), v.Total)
assert.True(t, v.Available > 0)
assert.Positive(t, v.Available)
assert.Equal(t, v.Available, v.Free+v.Inactive, "%v", v)
assert.True(t, v.Used > 0)
assert.True(t, v.Used < v.Total)
assert.Positive(t, v.Used)
assert.Less(t, v.Used, v.Total)
assert.True(t, v.UsedPercent > 0)
assert.True(t, v.UsedPercent < 100)
assert.Positive(t, v.UsedPercent)
assert.Less(t, v.UsedPercent, 100.0)
assert.True(t, v.Free > 0)
assert.True(t, v.Free < v.Available)
assert.Positive(t, v.Free)
assert.Less(t, v.Free, v.Available)
assert.True(t, v.Active > 0)
assert.True(t, v.Active < v.Total)
assert.Positive(t, v.Active)
assert.Less(t, v.Active, v.Total)
assert.True(t, v.Inactive > 0)
assert.True(t, v.Inactive < v.Total)
assert.Positive(t, v.Inactive)
assert.Less(t, v.Inactive, v.Total)
assert.True(t, v.Wired > 0)
assert.True(t, v.Wired < v.Total)
assert.Positive(t, v.Wired)
assert.Less(t, v.Wired, v.Total)
}

@ -151,17 +151,16 @@ const invalidFile = `INVALID Type Size Used Priority
`
func TestParseSwapsFile_ValidFile(t *testing.T) {
assert := assert.New(t)
stats, err := parseSwapsFile(context.Background(), strings.NewReader(validFile))
require.NoError(t, err)
assert.Equal(SwapDevice{
assert.Equal(t, SwapDevice{
Name: "/dev/dm-2",
UsedBytes: 502566912,
FreeBytes: 68128825344,
}, *stats[0])
assert.Equal(SwapDevice{
assert.Equal(t, SwapDevice{
Name: "/swapfile",
UsedBytes: 1024,
FreeBytes: 1024,

@ -10,8 +10,9 @@ import (
"errors"
"fmt"
"github.com/shirou/gopsutil/v4/internal/common"
"golang.org/x/sys/unix"
"github.com/shirou/gopsutil/v4/internal/common"
)
func GetPageSize() (uint64, error) {

@ -8,6 +8,7 @@ import (
"os"
stats "github.com/lufia/plan9stats"
"github.com/shirou/gopsutil/v4/internal/common"
)

@ -11,8 +11,9 @@ import (
"strconv"
"strings"
"github.com/shirou/gopsutil/v4/internal/common"
"github.com/tklauser/go-sysconf"
"github.com/shirou/gopsutil/v4/internal/common"
)
// VirtualMemory for Solaris is a minimal implementation which only returns
@ -24,17 +25,17 @@ func VirtualMemory() (*VirtualMemoryStat, error) {
func VirtualMemoryWithContext(ctx context.Context) (*VirtualMemoryStat, error) {
result := &VirtualMemoryStat{}
zoneName, err := zoneName()
zoneName, err := zoneName() //nolint:contextcheck //FIXME
if err != nil {
return nil, err
}
if zoneName == "global" {
cap, err := globalZoneMemoryCapacity()
capacity, err := globalZoneMemoryCapacity() //nolint:contextcheck //FIXME
if err != nil {
return nil, err
}
result.Total = cap
result.Total = capacity
freemem, err := globalZoneFreeMemory(ctx)
if err != nil {
return nil, err
@ -43,11 +44,11 @@ func VirtualMemoryWithContext(ctx context.Context) (*VirtualMemoryStat, error) {
result.Free = freemem
result.Used = result.Total - result.Free
} else {
cap, err := nonGlobalZoneMemoryCapacity()
capacity, err := nonGlobalZoneMemoryCapacity() //nolint:contextcheck //FIXME
if err != nil {
return nil, err
}
result.Total = cap
result.Total = capacity
}
return result, nil

@ -7,6 +7,7 @@ import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
const validFile = `swapfile dev swaplo blocks free
@ -18,21 +19,20 @@ const invalidFile = `swapfile dev swaplo INVALID free
/dev/dsk/c0t0d0s1 136,1 16 1638608 1600528`
func TestParseSwapsCommandOutput_Valid(t *testing.T) {
assert := assert.New(t)
stats, err := parseSwapsCommandOutput(validFile)
assert.NoError(err)
require.NoError(t, err)
assert.Equal(*stats[0], SwapDevice{
assert.Equal(t, SwapDevice{
Name: "/dev/zvol/dsk/rpool/swap",
UsedBytes: 0,
FreeBytes: 1058800 * 512,
})
}, *stats[0])
assert.Equal(*stats[1], SwapDevice{
assert.Equal(t, SwapDevice{
Name: "/dev/dsk/c0t0d0s1",
UsedBytes: 38080 * 512,
FreeBytes: 1600528 * 512,
})
}, *stats[1])
}
func TestParseSwapsCommandOutput_Invalid(t *testing.T) {

@ -9,8 +9,9 @@ import (
"syscall"
"unsafe"
"github.com/shirou/gopsutil/v4/internal/common"
"golang.org/x/sys/windows"
"github.com/shirou/gopsutil/v4/internal/common"
)
var (

@ -255,7 +255,7 @@ func InterfacesWithContext(ctx context.Context) (InterfaceStatList, error) {
return ret, nil
}
func getIOCountersAll(n []IOCountersStat) ([]IOCountersStat, error) {
func getIOCountersAll(n []IOCountersStat) []IOCountersStat {
r := IOCountersStat{
Name: "all",
}
@ -270,7 +270,7 @@ func getIOCountersAll(n []IOCountersStat) ([]IOCountersStat, error) {
r.Dropout += nic.Dropout
}
return []IOCountersStat{r}, nil
return []IOCountersStat{r}
}
// NetIOCounters returns network I/O statistics for every network

@ -30,7 +30,7 @@ func IOCountersWithContext(ctx context.Context, pernic bool) ([]IOCountersStat,
iocounters = append(iocounters, n)
}
if pernic == false {
return getIOCountersAll(iocounters)
return getIOCountersAll(iocounters), nil
}
return iocounters, nil
}

@ -89,7 +89,7 @@ func IOCountersWithContext(ctx context.Context, pernic bool) ([]IOCountersStat,
return nil, err
}
if pernic == false {
return getIOCountersAll(iocounters)
return getIOCountersAll(iocounters), nil
}
return iocounters, nil
}

@ -30,14 +30,14 @@ func parseNetstatLine(line string) (stat *IOCountersStat, linkID *uint, err erro
if columns[0] == "Name" {
err = errNetstatHeader
return
return //nolint:nakedret //FIXME
}
// try to extract the numeric value from <Link#123>
if subMatch := netstatLinkRegexp.FindStringSubmatch(columns[2]); len(subMatch) == 2 {
numericValue, err = strconv.ParseUint(subMatch[1], 10, 64)
if err != nil {
return
return //nolint:nakedret //FIXME
}
linkIDUint := uint(numericValue)
linkID = &linkIDUint
@ -51,7 +51,7 @@ func parseNetstatLine(line string) (stat *IOCountersStat, linkID *uint, err erro
}
if numberColumns < 11 || numberColumns > 13 {
err = fmt.Errorf("Line %q do have an invalid number of columns %d", line, numberColumns)
return
return //nolint:nakedret //FIXME
}
parsed := make([]uint64, 0, 7)
@ -74,7 +74,7 @@ func parseNetstatLine(line string) (stat *IOCountersStat, linkID *uint, err erro
}
if numericValue, err = strconv.ParseUint(target, 10, 64); err != nil {
return
return //nolint:nakedret //FIXME
}
parsed = append(parsed, numericValue)
}
@ -91,7 +91,7 @@ func parseNetstatLine(line string) (stat *IOCountersStat, linkID *uint, err erro
if len(parsed) == 7 {
stat.Dropout = parsed[6]
}
return
return //nolint:nakedret //FIXME
}
type netstatInterface struct {
@ -249,7 +249,7 @@ func IOCountersWithContext(ctx context.Context, pernic bool) ([]IOCountersStat,
}
if !pernic {
return getIOCountersAll(ret)
return getIOCountersAll(ret), nil
}
return ret, nil
}

@ -137,5 +137,5 @@ func TestParseNetstatTruncated(t *testing.T) {
mapUsage := newMapInterfaceNameUsage(nsInterfaces)
assert.True(t, mapUsage.isTruncated())
assert.Equal(t, 3, len(mapUsage.notTruncated()), "en0, gif0 and stf0")
assert.Len(t, mapUsage.notTruncated(), 3, "en0, gif0 and stf0")
}

@ -85,7 +85,7 @@ func IOCountersWithContext(ctx context.Context, pernic bool) ([]IOCountersStat,
}
if !pernic {
return getIOCountersAll(ret)
return getIOCountersAll(ret), nil
}
return ret, nil

@ -128,7 +128,7 @@ func IOCountersByFileWithContext(ctx context.Context, pernic bool, filename stri
}
if !pernic {
return getIOCountersAll(ret)
return getIOCountersAll(ret), nil
}
return ret, nil

@ -138,8 +138,6 @@ type AddrTest struct {
}
func TestDecodeAddress(t *testing.T) {
assert := assert.New(t)
addr := map[string]AddrTest{
"11111:0035": {
Error: true,
@ -182,11 +180,11 @@ func TestDecodeAddress(t *testing.T) {
}
addr, err := decodeAddress(uint32(family), src)
if dst.Error {
assert.Error(err, src)
assert.Error(t, err, src)
} else {
require.NoError(t, err, src)
assert.Equal(dst.IP, addr.IP, src)
assert.Equal(dst.Port, int(addr.Port), src)
assert.Equal(t, dst.IP, addr.IP, src)
assert.Equal(t, dst.Port, int(addr.Port), src)
}
}
}

@ -150,15 +150,15 @@ func IOCountersWithContext(ctx context.Context, pernic bool) ([]IOCountersStat,
ret = append(ret, ioc)
}
if pernic == false {
return getIOCountersAll(ret)
if !pernic {
return getIOCountersAll(ret), nil
}
return ret, nil
}
func IOCountersByFileWithContext(ctx context.Context, pernic bool, filename string) ([]IOCountersStat, error) {
return IOCounters(pernic)
return IOCounters(pernic) //nolint:contextcheck //FIXME
}
func FilterCountersWithContext(ctx context.Context) ([]FilterStat, error) {

@ -5,6 +5,7 @@ package net
import (
"context"
"errors"
"fmt"
"regexp"
"runtime"
@ -29,7 +30,7 @@ func IOCountersWithContext(ctx context.Context, pernic bool) ([]IOCountersStat,
lines := strings.Split(strings.TrimSpace(string(kstatSysOut)), "\n")
if len(lines) == 0 {
return nil, fmt.Errorf("no interface found")
return nil, errors.New("no interface found")
}
rbytes64arr := make(map[string]uint64)
ipackets64arr := make(map[string]uint64)
@ -104,7 +105,7 @@ func IOCountersWithContext(ctx context.Context, pernic bool) ([]IOCountersStat,
}
if !pernic {
return getIOCountersAll(ret)
return getIOCountersAll(ret), nil
}
return ret, nil

@ -133,11 +133,7 @@ func TestGetNetIOCountersAll(t *testing.T) {
Errin: 10,
},
}
ret, err := getIOCountersAll(n)
skipIfNotImplementedErr(t, err)
if err != nil {
t.Error(err)
}
ret := getIOCountersAll(n)
if len(ret) != 1 {
t.Errorf("invalid return count")
}

@ -5,14 +5,16 @@ package net
import (
"context"
"errors"
"fmt"
"net"
"os"
"syscall"
"unsafe"
"github.com/shirou/gopsutil/v4/internal/common"
"golang.org/x/sys/windows"
"github.com/shirou/gopsutil/v4/internal/common"
)
var (
@ -191,13 +193,13 @@ func IOCountersWithContext(ctx context.Context, pernic bool) ([]IOCountersStat,
}
if !pernic {
return getIOCountersAll(counters)
return getIOCountersAll(counters), nil
}
return counters, nil
}
func IOCountersByFileWithContext(ctx context.Context, pernic bool, filename string) ([]IOCountersStat, error) {
return IOCounters(pernic)
return IOCounters(pernic) //nolint:contextcheck //FIXME
}
func ConnectionsWithContext(ctx context.Context, kind string) ([]ConnectionStat, error) {
@ -238,7 +240,7 @@ func getProcInet(kinds []netConnectionKindType, pid int32) ([]ConnectionStat, er
func getNetStatWithKind(kindType netConnectionKindType) ([]ConnectionStat, error) {
if kindType.filename == "" {
return nil, fmt.Errorf("kind filename must be required")
return nil, errors.New("kind filename must be required")
}
switch kindType.filename {
@ -326,7 +328,7 @@ func getTableUintptr(family uint32, buf []byte) uintptr {
return p
}
func getTableInfo(filename string, table interface{}) (index, step, length int) {
func getTableInfo(filename string, table any) (index, step, length int) {
switch filename {
case kindTCP4.filename:
index = int(unsafe.Sizeof(table.(pmibTCPTableOwnerPidAll).DwNumEntries))
@ -360,7 +362,7 @@ func getTCPConnections(family uint32) ([]ConnectionStat, error) {
)
if family == 0 {
return nil, fmt.Errorf("faimly must be required")
return nil, errors.New("faimly must be required")
}
for {
@ -390,7 +392,7 @@ func getTCPConnections(family uint32) ([]ConnectionStat, error) {
if err == nil {
break
}
if err != windows.ERROR_INSUFFICIENT_BUFFER {
if !errors.Is(err, windows.ERROR_INSUFFICIENT_BUFFER) {
return nil, err
}
buf = make([]byte, size)
@ -441,7 +443,7 @@ func getUDPConnections(family uint32) ([]ConnectionStat, error) {
)
if family == 0 {
return nil, fmt.Errorf("faimly must be required")
return nil, errors.New("faimly must be required")
}
for {
@ -473,7 +475,7 @@ func getUDPConnections(family uint32) ([]ConnectionStat, error) {
if err == nil {
break
}
if err != windows.ERROR_INSUFFICIENT_BUFFER {
if !errors.Is(err, windows.ERROR_INSUFFICIENT_BUFFER) {
return nil, err
}
buf = make([]byte, size)

@ -409,6 +409,11 @@ func (p *Process) Cmdline() (string, error) {
// CmdlineSlice returns the command line arguments of the process as a slice with each
// element being an argument.
//
// On Windows, this assumes the command line is encoded according to the convention accepted by
// [golang.org/x/sys/windows.CmdlineToArgv] (the most common convention). If this is not suitable,
// you should instead use [Process.Cmdline] and parse the command line according to your specific
// requirements.
func (p *Process) CmdlineSlice() ([]string, error) {
return p.CmdlineSliceWithContext(context.Background())
}

@ -7,6 +7,7 @@ import (
"bytes"
"context"
"encoding/binary"
"errors"
"fmt"
"path/filepath"
"runtime"
@ -348,7 +349,7 @@ func (p *Process) CwdWithContext(ctx context.Context) (string, error) {
ret := procPidInfo(p.Pid, common.PROC_PIDVNODEPATHINFO, 0, uintptr(unsafe.Pointer(&vpi)), vpiSize)
errno, _ := lib.Dlsym("errno")
err = *(**unix.Errno)(unsafe.Pointer(&errno))
if err == unix.EPERM {
if errors.Is(err, unix.EPERM) {
return "", ErrorNotPermitted
}
@ -373,11 +374,11 @@ func procArgs(pid int32) ([]byte, int, error) {
return procargs, int(binary.LittleEndian.Uint32(nargs)), nil
}
func (p *Process) CmdlineSliceWithContext(ctx context.Context) ([]string, error) {
return p.cmdlineSliceWithContext(ctx, true)
func (p *Process) CmdlineSliceWithContext(_ context.Context) ([]string, error) {
return p.cmdlineSlice()
}
func (p *Process) cmdlineSliceWithContext(ctx context.Context, fallback bool) ([]string, error) {
func (p *Process) cmdlineSlice() ([]string, error) {
pargs, nargs, err := procArgs(p.Pid)
if err != nil {
return nil, err
@ -408,8 +409,8 @@ func (p *Process) cmdlineSliceWithContext(ctx context.Context, fallback bool) ([
}
// cmdNameWithContext returns the command name (including spaces) without any arguments
func (p *Process) cmdNameWithContext(ctx context.Context) (string, error) {
r, err := p.cmdlineSliceWithContext(ctx, false)
func (p *Process) cmdNameWithContext(_ context.Context) (string, error) {
r, err := p.cmdlineSlice()
if err != nil {
return "", err
}

@ -8,7 +8,6 @@ import (
"context"
"encoding/binary"
"errors"
"fmt"
"io"
"path/filepath"
"sort"
@ -16,11 +15,12 @@ import (
"strings"
"unsafe"
cpu "github.com/shirou/gopsutil/v4/cpu"
"github.com/shirou/gopsutil/v4/internal/common"
mem "github.com/shirou/gopsutil/v4/mem"
net "github.com/shirou/gopsutil/v4/net"
"golang.org/x/sys/unix"
"github.com/shirou/gopsutil/v4/cpu"
"github.com/shirou/gopsutil/v4/internal/common"
"github.com/shirou/gopsutil/v4/mem"
"github.com/shirou/gopsutil/v4/net"
)
func pidsWithContext(ctx context.Context) ([]int32, error) {
@ -130,7 +130,7 @@ func readPtr(r io.Reader) (uintptr, error) {
}
return uintptr(p), nil
default:
return 0, fmt.Errorf("unsupported pointer size")
return 0, errors.New("unsupported pointer size")
}
}

@ -247,10 +247,7 @@ func (p *Process) fillFromCmdlineWithContext(ctx context.Context) (string, error
return "", err
}
ret := strings.FieldsFunc(string(cmdline), func(r rune) bool {
if r == '\u0000' {
return true
}
return false
return r == '\u0000'
})
return strings.Join(ret, " "), nil

@ -12,16 +12,16 @@ import (
"os"
"path/filepath"
"reflect"
"strings"
"syscall"
"time"
"unicode/utf16"
"unsafe"
"golang.org/x/sys/windows"
"github.com/shirou/gopsutil/v4/cpu"
"github.com/shirou/gopsutil/v4/internal/common"
"github.com/shirou/gopsutil/v4/net"
"golang.org/x/sys/windows"
)
type Signal = syscall.Signal
@ -245,7 +245,7 @@ func pidsWithContext(ctx context.Context) ([]int32, error) {
// inspired by https://gist.github.com/henkman/3083408
// and https://github.com/giampaolo/psutil/blob/1c3a15f637521ba5c0031283da39c733fda53e4c/psutil/arch/windows/process_info.c#L315-L329
var ret []int32
var read uint32 = 0
var read uint32
var psSize uint32 = 1024
const dwordSize uint32 = 4
@ -288,10 +288,10 @@ func PidExistsWithContext(ctx context.Context, pid int32) (bool, error) {
return false, err
}
h, err := windows.OpenProcess(windows.SYNCHRONIZE, false, uint32(pid))
if err == windows.ERROR_ACCESS_DENIED {
if errors.Is(err, windows.ERROR_ACCESS_DENIED) {
return true, nil
}
if err == windows.ERROR_INVALID_PARAMETER {
if errors.Is(err, windows.ERROR_INVALID_PARAMETER) {
return false, nil
}
if err != nil {
@ -330,7 +330,7 @@ func (p *Process) NameWithContext(ctx context.Context) (string, error) {
exe, err := p.ExeWithContext(ctx)
if err != nil {
return "", fmt.Errorf("could not get Name: %s", err)
return "", fmt.Errorf("could not get Name: %w", err)
}
return filepath.Base(exe), nil
@ -370,7 +370,7 @@ func (p *Process) ExeWithContext(ctx context.Context) (string, error) {
func (p *Process) CmdlineWithContext(_ context.Context) (string, error) {
cmdline, err := getProcessCommandLine(p.Pid)
if err != nil {
return "", fmt.Errorf("could not get CommandLine: %s", err)
return "", fmt.Errorf("could not get CommandLine: %w", err)
}
return cmdline, nil
}
@ -380,13 +380,33 @@ func (p *Process) CmdlineSliceWithContext(ctx context.Context) ([]string, error)
if err != nil {
return nil, err
}
return strings.Split(cmdline, " "), nil
return parseCmdline(cmdline)
}
func parseCmdline(cmdline string) ([]string, error) {
cmdlineptr, err := windows.UTF16PtrFromString(cmdline)
if err != nil {
return nil, err
}
var argc int32
argvptr, err := windows.CommandLineToArgv(cmdlineptr, &argc)
if err != nil {
return nil, err
}
defer windows.LocalFree(windows.Handle(uintptr(unsafe.Pointer(argvptr))))
argv := make([]string, argc)
for i, v := range (*argvptr)[:argc] {
argv[i] = windows.UTF16ToString((*v)[:])
}
return argv, nil
}
func (p *Process) createTimeWithContext(ctx context.Context) (int64, error) {
ru, err := getRusage(p.Pid)
if err != nil {
return 0, fmt.Errorf("could not get CreationDate: %s", err)
return 0, fmt.Errorf("could not get CreationDate: %w", err)
}
return ru.CreationTime.Nanoseconds() / 1000000, nil
@ -394,7 +414,7 @@ func (p *Process) createTimeWithContext(ctx context.Context) (int64, error) {
func (p *Process) CwdWithContext(_ context.Context) (string, error) {
h, err := windows.OpenProcess(processQueryInformation|windows.PROCESS_VM_READ, false, uint32(p.Pid))
if err == windows.ERROR_ACCESS_DENIED || err == windows.ERROR_INVALID_PARAMETER {
if errors.Is(err, windows.ERROR_ACCESS_DENIED) || errors.Is(err, windows.ERROR_INVALID_PARAMETER) {
return "", nil
}
if err != nil {
@ -831,9 +851,9 @@ func (p *Process) KillWithContext(ctx context.Context) error {
}
func (p *Process) EnvironWithContext(ctx context.Context) ([]string, error) {
envVars, err := getProcessEnvironmentVariables(p.Pid, ctx)
envVars, err := getProcessEnvironmentVariables(ctx, p.Pid)
if err != nil {
return nil, fmt.Errorf("could not get environment variables: %s", err)
return nil, fmt.Errorf("could not get environment variables: %w", err)
}
return envVars, nil
}
@ -853,7 +873,7 @@ func (p *Process) setPpid(ppid int32) {
p.parent = ppid
}
func getFromSnapProcess(pid int32) (int32, int32, string, error) {
func getFromSnapProcess(pid int32) (int32, int32, string, error) { //nolint:unparam //FIXME
snap, err := windows.CreateToolhelp32Snapshot(windows.TH32CS_SNAPPROCESS, uint32(pid))
if err != nil {
return 0, 0, "", err
@ -881,7 +901,7 @@ func ProcessesWithContext(ctx context.Context) ([]*Process, error) {
pids, err := PidsWithContext(ctx)
if err != nil {
return out, fmt.Errorf("could not get Processes %s", err)
return out, fmt.Errorf("could not get Processes %w", err)
}
for _, pid := range pids {
@ -972,13 +992,13 @@ func getUserProcessParams32(handle windows.Handle) (rtlUserProcessParameters32,
buf := readProcessMemory(syscall.Handle(handle), true, pebAddress, uint(unsafe.Sizeof(processEnvironmentBlock32{})))
if len(buf) != int(unsafe.Sizeof(processEnvironmentBlock32{})) {
return rtlUserProcessParameters32{}, fmt.Errorf("cannot read process PEB")
return rtlUserProcessParameters32{}, errors.New("cannot read process PEB")
}
peb := (*processEnvironmentBlock32)(unsafe.Pointer(&buf[0]))
userProcessAddress := uint64(peb.ProcessParameters)
buf = readProcessMemory(syscall.Handle(handle), true, userProcessAddress, uint(unsafe.Sizeof(rtlUserProcessParameters32{})))
if len(buf) != int(unsafe.Sizeof(rtlUserProcessParameters32{})) {
return rtlUserProcessParameters32{}, fmt.Errorf("cannot read user process parameters")
return rtlUserProcessParameters32{}, errors.New("cannot read user process parameters")
}
return *(*rtlUserProcessParameters32)(unsafe.Pointer(&buf[0])), nil
}
@ -991,13 +1011,13 @@ func getUserProcessParams64(handle windows.Handle) (rtlUserProcessParameters64,
buf := readProcessMemory(syscall.Handle(handle), false, pebAddress, uint(unsafe.Sizeof(processEnvironmentBlock64{})))
if len(buf) != int(unsafe.Sizeof(processEnvironmentBlock64{})) {
return rtlUserProcessParameters64{}, fmt.Errorf("cannot read process PEB")
return rtlUserProcessParameters64{}, errors.New("cannot read process PEB")
}
peb := (*processEnvironmentBlock64)(unsafe.Pointer(&buf[0]))
userProcessAddress := peb.ProcessParameters
buf = readProcessMemory(syscall.Handle(handle), false, userProcessAddress, uint(unsafe.Sizeof(rtlUserProcessParameters64{})))
if len(buf) != int(unsafe.Sizeof(rtlUserProcessParameters64{})) {
return rtlUserProcessParameters64{}, fmt.Errorf("cannot read user process parameters")
return rtlUserProcessParameters64{}, errors.New("cannot read user process parameters")
}
return *(*rtlUserProcessParameters64)(unsafe.Pointer(&buf[0])), nil
}
@ -1047,9 +1067,9 @@ func is32BitProcess(h windows.Handle) bool {
return procIs32Bits
}
func getProcessEnvironmentVariables(pid int32, ctx context.Context) ([]string, error) {
func getProcessEnvironmentVariables(ctx context.Context, pid int32) ([]string, error) {
h, err := windows.OpenProcess(processQueryInformation|windows.PROCESS_VM_READ, false, uint32(pid))
if err == windows.ERROR_ACCESS_DENIED || err == windows.ERROR_INVALID_PARAMETER {
if errors.Is(err, windows.ERROR_ACCESS_DENIED) || errors.Is(err, windows.ERROR_INVALID_PARAMETER) {
return nil, nil
}
if err != nil {
@ -1133,7 +1153,7 @@ func (p *processReader) Read(buf []byte) (int, error) {
func getProcessCommandLine(pid int32) (string, error) {
h, err := windows.OpenProcess(processQueryInformation|windows.PROCESS_VM_READ, false, uint32(pid))
if err == windows.ERROR_ACCESS_DENIED || err == windows.ERROR_INVALID_PARAMETER {
if errors.Is(err, windows.ERROR_ACCESS_DENIED) || errors.Is(err, windows.ERROR_INVALID_PARAMETER) {
return "", nil
}
if err != nil {

@ -8,8 +8,9 @@ import (
"syscall"
"unsafe"
"github.com/shirou/gopsutil/v4/internal/common"
"golang.org/x/sys/windows"
"github.com/shirou/gopsutil/v4/internal/common"
)
type PROCESS_MEMORY_COUNTERS struct {
@ -39,12 +40,14 @@ func queryPebAddress(procHandle syscall.Handle, is32BitProcess bool) (uint64, er
)
if status := windows.NTStatus(ret); status == windows.STATUS_SUCCESS {
return uint64(info.PebBaseAddress), nil
} else {
}
return 0, windows.NTStatus(ret)
}
} else {
// we are on a 32-bit process reading an external 64-bit process
if common.ProcNtWow64QueryInformationProcess64.Find() == nil { // avoid panic
if common.ProcNtWow64QueryInformationProcess64.Find() != nil {
return 0, errors.New("can't find API to query 64 bit process from 32 bit")
}
// avoid panic
var info processBasicInformation64
ret, _, _ := common.ProcNtWow64QueryInformationProcess64.Call(
@ -56,13 +59,8 @@ func queryPebAddress(procHandle syscall.Handle, is32BitProcess bool) (uint64, er
)
if status := windows.NTStatus(ret); status == windows.STATUS_SUCCESS {
return info.PebBaseAddress, nil
} else {
return 0, windows.NTStatus(ret)
}
} else {
return 0, errors.New("can't find API to query 64 bit process from 32 bit")
}
}
return 0, windows.NTStatus(ret)
}
func readProcessMemory(h syscall.Handle, is32BitProcess bool, address uint64, size uint) []byte {

@ -7,8 +7,9 @@ import (
"syscall"
"unsafe"
"github.com/shirou/gopsutil/v4/internal/common"
"golang.org/x/sys/windows"
"github.com/shirou/gopsutil/v4/internal/common"
)
type PROCESS_MEMORY_COUNTERS struct {
@ -38,10 +39,9 @@ func queryPebAddress(procHandle syscall.Handle, is32BitProcess bool) (uint64, er
)
if status := windows.NTStatus(ret); status == windows.STATUS_SUCCESS {
return uint64(wow64), nil
} else {
}
return 0, windows.NTStatus(ret)
}
} else {
// we are on a 64-bit process reading an external 64-bit process
var info processBasicInformation64
@ -54,10 +54,8 @@ func queryPebAddress(procHandle syscall.Handle, is32BitProcess bool) (uint64, er
)
if status := windows.NTStatus(ret); status == windows.STATUS_SUCCESS {
return info.PebBaseAddress, nil
} else {
return 0, windows.NTStatus(ret)
}
}
return 0, windows.NTStatus(ret)
}
func readProcessMemory(procHandle syscall.Handle, _ bool, address uint64, size uint) []byte {

@ -5,7 +5,7 @@ package sensors
import (
"context"
"fmt"
"errors"
"unsafe"
"github.com/shirou/gopsutil/v4/internal/common"
@ -129,7 +129,7 @@ func readSMC(smc *common.SMC, key string) (*smcReturn, error) {
resultSmc.kSMC = result.result
if err != nil || result.result != common.KSMCSuccess {
return resultSmc, fmt.Errorf("ERROR: IOConnectCallStructMethod failed")
return resultSmc, errors.New("ERROR: IOConnectCallStructMethod failed")
}
resultSmc.dataSize = uint32(result.keyInfo.dataSize)
@ -158,7 +158,7 @@ func callSMC(smc *common.SMC, input *smcParamStruct) (*smcParamStruct, error) {
uintptr(unsafe.Pointer(input)), inputCnt, uintptr(unsafe.Pointer(output)), &outputCnt)
if result != 0 {
return output, fmt.Errorf("ERROR: IOConnectCallStructMethod failed")
return output, errors.New("ERROR: IOConnectCallStructMethod failed")
}
return output, nil
@ -169,7 +169,7 @@ func toUint32(key string) uint32 {
return 0
}
var ans uint32 = 0
var ans uint32
var shift uint32 = 24
for i := 0; i < smcKeySize; i++ {

@ -6,6 +6,7 @@ package sensors
import (
"context"
"encoding/csv"
"errors"
"io"
"strconv"
"strings"
@ -24,7 +25,7 @@ func TemperaturesWithContext(ctx context.Context) ([]TemperatureStat, error) {
r.FieldsPerRecord = -1
for {
record, err := r.Read()
if err == io.EOF {
if errors.Is(err, io.EOF) {
break
}
if err != nil {

@ -7,8 +7,9 @@ import (
"context"
"math"
"github.com/shirou/gopsutil/v4/internal/common"
"github.com/yusufpapurcu/wmi"
"github.com/shirou/gopsutil/v4/internal/common"
)
type msAcpi_ThermalZoneTemperature struct {

@ -5,6 +5,7 @@ package winservices
import (
"context"
"errors"
"unsafe"
"golang.org/x/sys/windows"
@ -86,7 +87,7 @@ func (s *Service) QueryStatusWithContext(ctx context.Context) (ServiceStatus, er
var bytesNeeded uint32
var buf []byte
if err := windows.QueryServiceStatusEx(s.srv.Handle, windows.SC_STATUS_PROCESS_INFO, nil, 0, &bytesNeeded); err != windows.ERROR_INSUFFICIENT_BUFFER {
if err := windows.QueryServiceStatusEx(s.srv.Handle, windows.SC_STATUS_PROCESS_INFO, nil, 0, &bytesNeeded); !errors.Is(err, windows.ERROR_INSUFFICIENT_BUFFER) {
return ServiceStatus{}, err
}

Loading…
Cancel
Save