diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..a681ce3 --- /dev/null +++ b/.gitattributes @@ -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 diff --git a/.github/workflows/build_test.yml b/.github/workflows/build_test.yml index 3cc7ee4..815a47e 100644 --- a/.github/workflows/build_test.yml +++ b/.github/workflows/build_test.yml @@ -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 - 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- - - name: Build Test v3 - run: | - make build_test + - name: Checkout code + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - name: Install Go + uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5.3.0 + with: + go-version: ${{ matrix.go-version }} + - name: Build Test v3 + run: | + make build_test diff --git a/.github/workflows/labeler.yml b/.github/workflows/labeler.yml index 5626060..81fe734 100644 --- a/.github/workflows/labeler.yml +++ b/.github/workflows/labeler.yml @@ -1,6 +1,7 @@ name: "Pull Request Labeler" + on: -- pull_request_target + pull_request_target: permissions: contents: read @@ -12,6 +13,6 @@ jobs: pull-requests: write # for actions/labeler to add labels to PRs runs-on: ubuntu-latest steps: - - uses: actions/labeler@ac9175f8a1f3625fd0d4fb234536d26811351594 # v4.3.0 - with: - repo-token: "${{ secrets.GITHUB_TOKEN }}" + - uses: actions/labeler@ac9175f8a1f3625fd0d4fb234536d26811351594 # v4.3.0 + with: + repo-token: "${{ secrets.GITHUB_TOKEN }}" diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 63854e3..886b118 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -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 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 28c22d7..6df6fbe 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,8 +1,9 @@ +name: Release + on: schedule: - - cron: '0 1 1 * *' # UTC 01:00 on the first day of the Month + - cron: '0 1 1 * *' # UTC 01:00 on the first day of the Month -name: Release permissions: contents: write diff --git a/.github/workflows/sbom_generator.yml b/.github/workflows/sbom_generator.yml index f53ff1c..d411748 100644 --- a/.github/workflows/sbom_generator.yml +++ b/.github/workflows/sbom_generator.yml @@ -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" diff --git a/.github/workflows/shellcheck.yml b/.github/workflows/shellcheck.yml index f6bca03..800e71b 100644 --- a/.github/workflows/shellcheck.yml +++ b/.github/workflows/shellcheck.yml @@ -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 @@ -8,6 +18,6 @@ jobs: name: Shellcheck runs-on: ubuntu-latest steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - name: Run ShellCheck - uses: ludeeus/action-shellcheck@00cae500b08a931fb5698e11e79bfbd38e612a38 # v2.0.0 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - name: Run ShellCheck + uses: ludeeus/action-shellcheck@00cae500b08a931fb5698e11e79bfbd38e612a38 # v2.0.0 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 9285d6e..3a0241f 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -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 - 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- - - name: Test - run: | - go test -coverprofile='coverage.out' -covermode=atomic ./... + - name: Checkout code + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - name: Install Go + uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5.3.0 + with: + go-version: ${{ matrix.go-version }} + - name: Test + run: | + go test -coverprofile='coverage.out' -covermode=atomic ./... diff --git a/.golangci.yml b/.golangci.yml index 0bf3e18..9229c09 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -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 diff --git a/Makefile b/Makefile index 25e978c..5422d39 100644 --- a/Makefile +++ b/Makefile @@ -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) diff --git a/cpu/cpu_dragonfly.go b/cpu/cpu_dragonfly.go index 19b1e9d..fb9b937 100644 --- a/cpu/cpu_dragonfly.go +++ b/cpu/cpu_dragonfly.go @@ -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 { diff --git a/cpu/cpu_netbsd.go b/cpu/cpu_netbsd.go index 198be5e..7d807dc 100644 --- a/cpu/cpu_netbsd.go +++ b/cpu/cpu_netbsd.go @@ -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 diff --git a/cpu/cpu_openbsd.go b/cpu/cpu_openbsd.go index 33233d3..30d87ac 100644 --- a/cpu/cpu_openbsd.go +++ b/cpu/cpu_openbsd.go @@ -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 diff --git a/cpu/cpu_plan9.go b/cpu/cpu_plan9.go index bff2e0c..d6f63ba 100644 --- a/cpu/cpu_plan9.go +++ b/cpu/cpu_plan9.go @@ -9,6 +9,7 @@ import ( "runtime" stats "github.com/lufia/plan9stats" + "github.com/shirou/gopsutil/v4/internal/common" ) diff --git a/cpu/cpu_solaris.go b/cpu/cpu_solaris.go index d8ba1d3..91d41a9 100644 --- a/cpu/cpu_solaris.go +++ b/cpu/cpu_solaris.go @@ -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++ { diff --git a/cpu/cpu_windows.go b/cpu/cpu_windows.go index 4476b91..a71df97 100644 --- a/cpu/cpu_windows.go +++ b/cpu/cpu_windows.go @@ -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), diff --git a/disk/disk_darwin.go b/disk/disk_darwin.go index f5482ed..94f10b9 100644 --- a/disk/disk_darwin.go +++ b/disk/disk_darwin.go @@ -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 } diff --git a/disk/disk_openbsd.go b/disk/disk_openbsd.go index 713e38e..c840088 100644 --- a/disk/disk_openbsd.go +++ b/disk/disk_openbsd.go @@ -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) { diff --git a/disk/disk_solaris.go b/disk/disk_solaris.go index f849da9..7360a47 100644 --- a/disk/disk_solaris.go +++ b/disk/disk_solaris.go @@ -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) diff --git a/disk/disk_windows.go b/disk/disk_windows.go index 4f371a3..5f24389 100644 --- a/disk/disk_windows.go +++ b/disk/disk_windows.go @@ -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 diff --git a/docker/docker_linux.go b/docker/docker_linux.go index 23e7ef1..5ac1581 100644 --- a/docker/docker_linux.go +++ b/docker/docker_linux.go @@ -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" ) diff --git a/go.mod b/go.mod index 34b4f95..f69e48f 100644 --- a/go.mod +++ b/go.mod @@ -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 diff --git a/go.sum b/go.sum index e816771..a0c7f95 100644 --- a/go.sum +++ b/go.sum @@ -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= diff --git a/host/host_aix.go b/host/host_aix.go index 4358b61..9cd8153 100644 --- a/host/host_aix.go +++ b/host/host_aix.go @@ -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 diff --git a/host/host_openbsd.go b/host/host_openbsd.go index f21c5e8..d5a5cd1 100644 --- a/host/host_openbsd.go +++ b/host/host_openbsd.go @@ -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 ( diff --git a/host/host_solaris.go b/host/host_solaris.go index 371cc98..e7adba0 100644 --- a/host/host_solaris.go +++ b/host/host_solaris.go @@ -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" { - hostname, err := os.Hostname() - if err == nil { - return hostname, nil - } - } else { + if line != "global" { return strings.TrimSpace(line), nil } + hostname, err := os.Hostname() + if err == nil { + return hostname, 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 diff --git a/host/host_windows.go b/host/host_windows.go index 99a23bd..41f4b7f 100644 --- a/host/host_windows.go +++ b/host/host_windows.go @@ -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(®Buf[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 } diff --git a/internal/common/binary.go b/internal/common/binary.go index 6e75e74..11a4fd4 100644 --- a/internal/common/binary.go +++ b/internal/common/binary.go @@ -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 diff --git a/internal/common/common.go b/internal/common/common.go index 868ea4d..3981603 100644 --- a/internal/common/common.go +++ b/internal/common/common.go @@ -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() diff --git a/internal/common/common_darwin.go b/internal/common/common_darwin.go index 2de3bb1..afa780d 100644 --- a/internal/common/common_darwin.go +++ b/internal/common/common_darwin.go @@ -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 { diff --git a/internal/common/common_windows.go b/internal/common/common_windows.go index 766ed2f..09ecf59 100644 --- a/internal/common/common_windows.go +++ b/internal/common/common_windows.go @@ -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,19 +273,19 @@ 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 } + if !st.IsError() { + *buf = (*buf)[:int(*resultLength)] + } + return st } } diff --git a/load/load_windows.go b/load/load_windows.go index a55c7b4..f430d2a 100644 --- a/load/load_windows.go +++ b/load/load_windows.go @@ -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 ) diff --git a/mem/mem_bsd_test.go b/mem/mem_bsd_test.go index 8b0eb9f..ef2ae3a 100644 --- a/mem/mem_bsd_test.go +++ b/mem/mem_bsd_test.go @@ -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) { diff --git a/mem/mem_darwin_test.go b/mem/mem_darwin_test.go index c7f5668..c2a6f3f 100644 --- a/mem/mem_darwin_test.go +++ b/mem/mem_darwin_test.go @@ -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) } diff --git a/mem/mem_linux_test.go b/mem/mem_linux_test.go index b71b71c..ac02fb8 100644 --- a/mem/mem_linux_test.go +++ b/mem/mem_linux_test.go @@ -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, diff --git a/mem/mem_openbsd.go b/mem/mem_openbsd.go index 2510bb0..ade3a12 100644 --- a/mem/mem_openbsd.go +++ b/mem/mem_openbsd.go @@ -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) { diff --git a/mem/mem_plan9.go b/mem/mem_plan9.go index c17a102..4f1990c 100644 --- a/mem/mem_plan9.go +++ b/mem/mem_plan9.go @@ -8,6 +8,7 @@ import ( "os" stats "github.com/lufia/plan9stats" + "github.com/shirou/gopsutil/v4/internal/common" ) diff --git a/mem/mem_solaris.go b/mem/mem_solaris.go index 06d0d9a..ca5af48 100644 --- a/mem/mem_solaris.go +++ b/mem/mem_solaris.go @@ -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 diff --git a/mem/mem_solaris_test.go b/mem/mem_solaris_test.go index 5e0aa70..31b35e0 100644 --- a/mem/mem_solaris_test.go +++ b/mem/mem_solaris_test.go @@ -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) { diff --git a/mem/mem_windows.go b/mem/mem_windows.go index a94b61f..d7dcef4 100644 --- a/mem/mem_windows.go +++ b/mem/mem_windows.go @@ -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 ( diff --git a/net/net.go b/net/net.go index 74af54a..e114fab 100644 --- a/net/net.go +++ b/net/net.go @@ -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 diff --git a/net/net_aix_cgo.go b/net/net_aix_cgo.go index a45a5b7..c440051 100644 --- a/net/net_aix_cgo.go +++ b/net/net_aix_cgo.go @@ -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 } diff --git a/net/net_aix_nocgo.go b/net/net_aix_nocgo.go index f63a21e..2f4172a 100644 --- a/net/net_aix_nocgo.go +++ b/net/net_aix_nocgo.go @@ -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 } diff --git a/net/net_darwin.go b/net/net_darwin.go index 86c541e..08266fd 100644 --- a/net/net_darwin.go +++ b/net/net_darwin.go @@ -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 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 } diff --git a/net/net_darwin_test.go b/net/net_darwin_test.go index 86ed126..ba4131e 100644 --- a/net/net_darwin_test.go +++ b/net/net_darwin_test.go @@ -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") } diff --git a/net/net_freebsd.go b/net/net_freebsd.go index 655e133..33d0f7c 100644 --- a/net/net_freebsd.go +++ b/net/net_freebsd.go @@ -85,7 +85,7 @@ func IOCountersWithContext(ctx context.Context, pernic bool) ([]IOCountersStat, } if !pernic { - return getIOCountersAll(ret) + return getIOCountersAll(ret), nil } return ret, nil diff --git a/net/net_linux.go b/net/net_linux.go index 23113fe..6072965 100644 --- a/net/net_linux.go +++ b/net/net_linux.go @@ -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 diff --git a/net/net_linux_test.go b/net/net_linux_test.go index abd3396..f23bd03 100644 --- a/net/net_linux_test.go +++ b/net/net_linux_test.go @@ -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) } } } diff --git a/net/net_openbsd.go b/net/net_openbsd.go index a90d590..ed9c506 100644 --- a/net/net_openbsd.go +++ b/net/net_openbsd.go @@ -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) { diff --git a/net/net_solaris.go b/net/net_solaris.go index 83eb1d0..e44979d 100644 --- a/net/net_solaris.go +++ b/net/net_solaris.go @@ -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 diff --git a/net/net_test.go b/net/net_test.go index 60e8438..630b64b 100644 --- a/net/net_test.go +++ b/net/net_test.go @@ -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") } diff --git a/net/net_windows.go b/net/net_windows.go index 00ebf89..d1029cf 100644 --- a/net/net_windows.go +++ b/net/net_windows.go @@ -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) diff --git a/process/process.go b/process/process.go index c60e7b4..de8ffcd 100644 --- a/process/process.go +++ b/process/process.go @@ -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()) } diff --git a/process/process_darwin.go b/process/process_darwin.go index 33abc10..2c14f2e 100644 --- a/process/process_darwin.go +++ b/process/process_darwin.go @@ -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 } diff --git a/process/process_openbsd.go b/process/process_openbsd.go index 5e8a9e0..381b143 100644 --- a/process/process_openbsd.go +++ b/process/process_openbsd.go @@ -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") } } diff --git a/process/process_solaris.go b/process/process_solaris.go index 5c8d4d3..279d11c 100644 --- a/process/process_solaris.go +++ b/process/process_solaris.go @@ -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 diff --git a/process/process_windows.go b/process/process_windows.go index 1924273..9d94ab2 100644 --- a/process/process_windows.go +++ b/process/process_windows.go @@ -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 { diff --git a/process/process_windows_32bit.go b/process/process_windows_32bit.go index 2b231c7..d69916b 100644 --- a/process/process_windows_32bit.go +++ b/process/process_windows_32bit.go @@ -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,30 +40,27 @@ 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 - var info processBasicInformation64 + return 0, windows.NTStatus(ret) + } + // we are on a 32-bit process reading an external 64-bit process + 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( - uintptr(procHandle), - uintptr(common.ProcessBasicInformation), - uintptr(unsafe.Pointer(&info)), - uintptr(unsafe.Sizeof(info)), - uintptr(0), - ) - 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") - } + ret, _, _ := common.ProcNtWow64QueryInformationProcess64.Call( + uintptr(procHandle), + uintptr(common.ProcessBasicInformation), + uintptr(unsafe.Pointer(&info)), + uintptr(unsafe.Sizeof(info)), + uintptr(0), + ) + if status := windows.NTStatus(ret); status == windows.STATUS_SUCCESS { + return info.PebBaseAddress, nil } + return 0, windows.NTStatus(ret) } func readProcessMemory(h syscall.Handle, is32BitProcess bool, address uint64, size uint) []byte { diff --git a/process/process_windows_64bit.go b/process/process_windows_64bit.go index befe521..69018fe 100644 --- a/process/process_windows_64bit.go +++ b/process/process_windows_64bit.go @@ -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,26 +39,23 @@ 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 + return 0, windows.NTStatus(ret) + } + // we are on a 64-bit process reading an external 64-bit process + var info processBasicInformation64 - ret, _, _ := common.ProcNtQueryInformationProcess.Call( - uintptr(procHandle), - uintptr(common.ProcessBasicInformation), - uintptr(unsafe.Pointer(&info)), - uintptr(unsafe.Sizeof(info)), - uintptr(0), - ) - if status := windows.NTStatus(ret); status == windows.STATUS_SUCCESS { - return info.PebBaseAddress, nil - } else { - return 0, windows.NTStatus(ret) - } + ret, _, _ := common.ProcNtQueryInformationProcess.Call( + uintptr(procHandle), + uintptr(common.ProcessBasicInformation), + uintptr(unsafe.Pointer(&info)), + uintptr(unsafe.Sizeof(info)), + uintptr(0), + ) + if status := windows.NTStatus(ret); status == windows.STATUS_SUCCESS { + return info.PebBaseAddress, nil } + return 0, windows.NTStatus(ret) } func readProcessMemory(procHandle syscall.Handle, _ bool, address uint64, size uint) []byte { diff --git a/sensors/sensors_darwin.go b/sensors/sensors_darwin.go index b8535e7..23a3a7a 100644 --- a/sensors/sensors_darwin.go +++ b/sensors/sensors_darwin.go @@ -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++ { diff --git a/sensors/sensors_solaris.go b/sensors/sensors_solaris.go index c5d1bce..0ca1d9a 100644 --- a/sensors/sensors_solaris.go +++ b/sensors/sensors_solaris.go @@ -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 { diff --git a/sensors/sensors_windows.go b/sensors/sensors_windows.go index 32b9ee4..aa1e42b 100644 --- a/sensors/sensors_windows.go +++ b/sensors/sensors_windows.go @@ -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 { diff --git a/winservices/winservices.go b/winservices/winservices.go index 0c85a01..1c06265 100644 --- a/winservices/winservices.go +++ b/winservices/winservices.go @@ -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 }