Compare commits

...

33 Commits

Author SHA1 Message Date
shirou 3ef5d4cb9d
Merge pull request #1847 from mmorel-35/nakedret
fix ignore nakedret
2 days ago
Matthieu MOREL 6a79b392ac fix ignore nakedret
Signed-off-by: Matthieu MOREL <matthieu.morel35@gmail.com>
2 days ago
shirou a60205c17c
Merge pull request #1852 from shirou/feat/bump_purego_version
[darwin]: bump purego veresion to 0.8.3
2 days ago
shirou ecf970423e [darwin]: bump purego veresion to 0.8.3 2 days ago
shirou 15eaecda07
Merge pull request #1846 from mmorel-35/staticcheck/ST1005
fix(ST1005): Incorrectly formatted error string
5 days ago
Matthieu MOREL 71c74393f2 fix(ST1005): Incorrectly formatted error string
Signed-off-by: Matthieu MOREL <matthieu.morel35@gmail.com>
6 days ago
shirou ec85c0b45b
Merge pull request #1842 from mmorel-35/golangci-lint/staticcheck
chore: enable staticcheck
1 week ago
shirou d5e33f710b
Merge pull request #1839 from OrbintSoft/remove-wmi
Remove wmi for Get physical CPU core count
1 week ago
Stefano Balzarotti f2b0aa5e86
linter 2 weeks ago
Matthieu MOREL cefed48244 chore: enable staticcheck linter
Signed-off-by: Matthieu MOREL <matthieu.morel35@gmail.com>
2 weeks ago
shirou 3ba33b4651
Merge pull request #1843 from mmorel-35/golangci-lint/ineffassign
chore: enable ineffassign linter
2 weeks ago
Matthieu MOREL 6469062ba9 chore: enable ineffassign linter
Signed-off-by: Matthieu MOREL <matthieu.morel35@gmail.com>
2 weeks ago
shirou af2d6de7aa
Merge pull request #1825 from mmorel-35/golangci-lint/govet
chore: enable govet linter
2 weeks ago
Stefano Balzarotti ab48e6b803
remove context cancellation 3 weeks ago
Matthieu MOREL 10be661aa4 chore: enable govet linter
Signed-off-by: Matthieu MOREL <matthieu.morel35@gmail.com>
3 weeks ago
shirou 3c34181ac9
Merge pull request #1841 from shirou/feat/update_github_action_runners_images
fix: update github actions runner images
3 weeks ago
shirou c43a933f9c fix: update github actions runner images 3 weeks ago
shirou f9f5620e1e
Merge pull request #1840 from s0ders/refactor/host-info-error-msg
refactor: using fmt.Errorf in InfoWithContext
3 weeks ago
s0ders 0bbc484a68
refactor: using fmt.Errorf on some error returns.
The following brings:
- Refactoring of `InfoWithContext` to wrap errors with `fmt.Errorf` in
  order to add textual context, making error message more helpful for
  the end user.

ref: 1836
4 weeks ago
shirou 7d9af6fd99
Merge pull request #1829 from mmorel-35/golangci-lint@v2
[chore]: bump golangci-lint to v2.1.1
4 weeks ago
shirou 61f624bcb8
Merge pull request #1831 from niemp100/win32_cpu_values
Fix win32_SystemProcessorPerformanceInformation struct
4 weeks ago
Stefano Balzarotti d46c4a822d
use testify 4 weeks ago
Stefano Balzarotti b30f1523d8
code review 4 weeks ago
Matthieu MOREL 15a77650a1 [chore]: bump golangci-lint to v2.1.1
Signed-off-by: Matthieu MOREL <matthieu.morel35@gmail.com>
4 weeks ago
Stefano Balzarotti 00a28a710e
lint 4 weeks ago
shirou ef5056a446
Merge pull request #1835 from dvovk/fix_unsafeptr
fix nil ptr
4 weeks ago
Stefano Balzarotti b4446224fc
fix 4 weeks ago
Stefano Balzarotti 1ebcd369ab
implement get physical core api 4 weeks ago
shirou 3608872740
Merge pull request #1838 from NewbieOrange/master
[disk][linux] add bcachefs magic
4 weeks ago
NewbieOrange 212dfbbb39
[disk][linux] add bcachefs magic 1 month ago
Dmytro Vovk 244d63ddfc fix lint 1 month ago
Dmytro Vovk 1de755d2f2 possible fix 1 month ago
Niklas Empt 6f4ea788d9 Fix win32_SystemProcessorPerformanceInformation struct 1 month ago

@ -69,7 +69,7 @@ jobs:
with: with:
go-version-file: go.mod go-version-file: go.mod
- name: Setup golangci-lint - name: Setup golangci-lint
uses: golangci/golangci-lint-action@55c2c1448f86e01eaae002a5a3a9624417608d84 # v6.5.2 uses: golangci/golangci-lint-action@1481404843c368bc19ca9406f87d6e0fc97bdcfd # v7.0.0
with: with:
args: --verbose args: --verbose
version: latest version: latest

@ -29,7 +29,7 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
go-version: ${{fromJson(needs.go-versions.outputs.versions)}} go-version: ${{fromJson(needs.go-versions.outputs.versions)}}
os: [ubuntu-22.04, ubuntu-20.04, ubuntu-24.04, windows-2022, windows-2019, macos-13, macos-14, macos-15] os: [ubuntu-22.04, ubuntu-24.04, windows-2019, windows-2022, windows-2025, macos-13, macos-14, macos-15]
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
steps: steps:
- name: Checkout code - name: Checkout code

@ -1,115 +1,142 @@
version: "2"
formatters:
enable:
- gci
- gofumpt
settings:
gci:
sections:
- standard
- default
- prefix(github.com/shirou)
issues: issues:
max-same-issues: 0 max-same-issues: 0
exclude-rules: []
linters: linters:
enable: enable:
- asciicheck - asciicheck
- contextcheck - contextcheck
- durationcheck - durationcheck
- errorlint - errorlint
- gci
- gocritic - gocritic
- gofmt
- gofumpt
- goimports
- gomodguard - gomodguard
- gosec - gosec
- gosimple - govet
- importas - importas
- ineffassign
- misspell - misspell
- nakedret - nakedret
- nolintlint - nolintlint
- perfsprint - perfsprint
- predeclared - predeclared
- revive - revive
- staticcheck
- testifylint - testifylint
- thelper - thelper
- typecheck
- unparam - unparam
- usetesting - usetesting
disable: disable:
- errcheck - errcheck
- govet
- ineffassign
- staticcheck
- unused - unused
linters-settings: settings:
gci: gocritic:
sections: disabled-checks:
- standard - captLocal
- default gomodguard:
- prefix(github.com/shirou) blocked:
gocritic: modules:
disabled-checks: - io/ioutil:
- captLocal recommendations:
gomodguard: - io
blocked: - os
modules: gosec:
- io/ioutil: excludes:
recommendations: - G115
- io govet:
- os disable:
gosec: - copylocks
excludes: - fieldalignment
- G115 - shadow
perfsprint: - testinggoroutine
# Optimizes even if it requires an int or uint type cast. enable-all: true
int-conversion: true perfsprint:
# Optimizes into `err.Error()` even if it is only equivalent for non-nil errors. # Optimizes even if it requires an int or uint type cast.
err-error: true int-conversion: true
# Optimizes `fmt.Errorf`. # Optimizes into `err.Error()` even if it is only equivalent for non-nil errors.
errorf: true err-error: true
# Optimizes `fmt.Sprintf` with only one argument. # Optimizes `fmt.Errorf`.
sprintf1: true errorf: true
# Optimizes into strings concatenation. # Optimizes `fmt.Sprintf` with only one argument.
strconcat: true sprintf1: true
revive: # Optimizes into strings concatenation.
rules: strconcat: true
- name: blank-imports revive:
- name: context-as-argument rules:
arguments: - name: blank-imports
- allowTypesBefore: "*testing.T" - name: context-as-argument
- name: context-keys-type arguments:
- name: dot-imports - allowTypesBefore: "*testing.T"
- name: duplicated-imports - name: context-keys-type
- name: early-return - name: dot-imports
arguments: - name: duplicated-imports
- "preserveScope" - name: early-return
- name: empty-block arguments:
disabled: true - "preserveScope"
- name: error-naming - name: empty-block
- name: error-return disabled: true
- name: error-strings - name: error-naming
- name: exported - name: error-return
disabled: true - name: error-strings
- name: errorf - name: exported
- name: increment-decrement disabled: true
- name: indent-error-flow - name: errorf
arguments: - name: increment-decrement
- "preserveScope" - name: indent-error-flow
- name: range arguments:
- name: receiver-naming - "preserveScope"
- name: redefines-builtin-id - name: range
- name: redundant-import-alias - name: receiver-naming
- name: superfluous-else - name: redefines-builtin-id
arguments: - name: redundant-import-alias
- "preserveScope" - name: superfluous-else
- name: time-naming arguments:
- name: unexported-return - "preserveScope"
- name: unnecessary-stmt - name: time-naming
- name: unreachable-code - name: unexported-return
- name: unused-parameter - name: unnecessary-stmt
- name: use-any - name: unreachable-code
- name: var-declaration - name: unused-parameter
- name: var-naming - name: use-any
arguments: - name: var-declaration
- ["ID"] # AllowList - name: var-naming
- ["VM"] # DenyList arguments:
- - upperCaseConst: true # Extra parameter (upperCaseConst|skipPackageNameChecks) - ["ID"] # AllowList
testifylint: - ["VM"] # DenyList
enable-all: true - - upperCaseConst: true # Extra parameter (upperCaseConst|skipPackageNameChecks)
usetesting: staticcheck:
checks:
- all
- -SA1019 # Using a deprecated function, variable, constant or field
- -SA2002 # Called testing.T.FailNow or SkipNow in a goroutine, which isnt allowed
- -SA4003 # Comparing unsigned values against negative values is pointless
- -SA4004 # The loop exits unconditionally after one iteration
- -SA4008 # The variable in the loop condition never changes, are you incrementing the wrong variable?
- -SA5003 # Defers in infinite loops will never execute
- -SA9003 # Empty body in an if or else branch
- -ST1003 # Poorly chosen identifier
testifylint:
enable-all: true
usetesting:
os-create-temp: false os-create-temp: false
os-mkdir-temp: false os-mkdir-temp: false
exclusions:
generated: lax
presets:
- comments
- common-false-positives
- legacy
- std-error-handling
warn-unused: true
output:
show-stats: false
run: run:
timeout: 5m timeout: 5m

@ -5,6 +5,7 @@ package cpu
import ( import (
"context" "context"
"errors"
"fmt" "fmt"
"strconv" "strconv"
"strings" "strings"
@ -152,6 +153,10 @@ func perCPUTimes(machLib *common.Library) ([]TimesStat, error) {
return nil, fmt.Errorf("host_processor_info error=%d", status) return nil, fmt.Errorf("host_processor_info error=%d", status)
} }
if cpuload == nil {
return nil, errors.New("host_processor_info returned nil cpuload")
}
defer vmDeallocate(machTaskSelf(), uintptr(unsafe.Pointer(cpuload)), uintptr(ncpu)) defer vmDeallocate(machTaskSelf(), uintptr(unsafe.Pointer(cpuload)), uintptr(ncpu))
ret := []TimesStat{} ret := []TimesStat{}

@ -51,7 +51,7 @@ func getFrequency() (float64, error) {
var pCoreHz uint32 var pCoreHz uint32
for { for {
service := ioIteratorNext(iterator) service := ioIteratorNext(iterator)
if !(service > 0) { if service <= 0 {
break break
} }

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

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

@ -159,10 +159,7 @@ func parseISAInfo(cmdOutput string) ([]string, error) {
return nil, errors.New("attempted to parse invalid isainfo output") return nil, errors.New("attempted to parse invalid isainfo output")
} }
flags := make([]string, len(words)-4) flags := words[4:]
for i, val := range words[4:] { //nolint:gosimple //FIXME
flags[i] = val
}
sort.Strings(flags) sort.Strings(flags)
return flags, nil return flags, nil

@ -59,16 +59,17 @@ func TestTimes(t *testing.T) {
} }
func TestCounts(t *testing.T) { func TestCounts(t *testing.T) {
v, err := Counts(true) logicalCount, err := Counts(true)
common.SkipIfNotImplementedErr(t, err) common.SkipIfNotImplementedErr(t, err)
require.NoError(t, err) require.NoError(t, err)
assert.NotZerof(t, v, "could not get logical CPU counts: %v", v) assert.NotZerof(t, logicalCount, "could not get logical CPU counts: %v", logicalCount)
t.Logf("logical cores: %d", v) t.Logf("logical cores: %d", logicalCount)
v, err = Counts(false) physicalCount, err := Counts(false)
common.SkipIfNotImplementedErr(t, err) common.SkipIfNotImplementedErr(t, err)
require.NoError(t, err) require.NoError(t, err)
assert.NotZerof(t, v, "could not get physical CPU counts: %v", v) assert.NotZerof(t, physicalCount, "could not get physical CPU counts: %v", physicalCount)
t.Logf("physical cores: %d", v) t.Logf("physical cores: %d", physicalCount)
assert.GreaterOrEqualf(t, logicalCount, physicalCount, "logical CPU count should be greater than or equal to physical CPU count: %v >= %v", logicalCount, physicalCount)
} }
func TestTimeStat_String(t *testing.T) { func TestTimeStat_String(t *testing.T) {

@ -5,6 +5,7 @@ package cpu
import ( import (
"context" "context"
"errors"
"fmt" "fmt"
"strconv" "strconv"
"unsafe" "unsafe"
@ -15,7 +16,10 @@ import (
"github.com/shirou/gopsutil/v4/internal/common" "github.com/shirou/gopsutil/v4/internal/common"
) )
var procGetNativeSystemInfo = common.Modkernel32.NewProc("GetNativeSystemInfo") var (
procGetNativeSystemInfo = common.Modkernel32.NewProc("GetNativeSystemInfo")
procGetLogicalProcessorInformationEx = common.Modkernel32.NewProc("GetLogicalProcessorInformationEx")
)
type win32_Processor struct { //nolint:revive //FIXME type win32_Processor struct { //nolint:revive //FIXME
Family uint16 Family uint16
@ -34,12 +38,12 @@ type win32_Processor struct { //nolint:revive //FIXME
// additional fields documented here // additional fields documented here
// https://www.geoffchappell.com/studies/windows/km/ntoskrnl/api/ex/sysinfo/processor_performance.htm // https://www.geoffchappell.com/studies/windows/km/ntoskrnl/api/ex/sysinfo/processor_performance.htm
type win32_SystemProcessorPerformanceInformation struct { //nolint:revive //FIXME type win32_SystemProcessorPerformanceInformation struct { //nolint:revive //FIXME
IdleTime int64 // idle time in 100ns (this is not a filetime). IdleTime int64 // idle time in 100ns (this is not a filetime).
KernelTime int64 // kernel time in 100ns. kernel time includes idle time. (this is not a filetime). KernelTime int64 // kernel time in 100ns. kernel time includes idle time. (this is not a filetime).
UserTime int64 // usertime in 100ns (this is not a filetime). UserTime int64 // usertime in 100ns (this is not a filetime).
DpcTime int64 // dpc time in 100ns (this is not a filetime). DpcTime int64 // dpc time in 100ns (this is not a filetime).
InterruptTime int64 // interrupt time in 100ns InterruptTime int64 // interrupt time in 100ns
InterruptCount uint32 InterruptCount uint64 // ULONG needs to be uint64
} }
const ( const (
@ -200,13 +204,70 @@ type systemInfo struct {
wProcessorRevision uint16 wProcessorRevision uint16
} }
func CountsWithContext(ctx context.Context, logical bool) (int, error) { type groupAffinity struct {
mask uintptr // https://learn.microsoft.com/it-it/windows-hardware/drivers/kernel/interrupt-affinity-and-priority#about-kaffinity
group uint16
reserved [3]uint16
}
// https://learn.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-processor_relationship
type processorRelationship struct {
flags byte
efficientClass byte
reserved [20]byte
groupCount uint16
groupMask [1]groupAffinity
}
// https://learn.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-system_logical_processor_information_ex
type systemLogicalProcessorInformationEx struct {
Relationship uint32
Size uint32
Processor processorRelationship
}
func getPhysicalCoreCount() (int, error) {
var length uint32
const relationAll = 0xffff
const relationProcessorCore = 0x0
// First call to determine the required buffer size
_, _, err := procGetLogicalProcessorInformationEx.Call(uintptr(relationAll), 0, uintptr(unsafe.Pointer(&length)))
if err != nil && !errors.Is(err, windows.ERROR_INSUFFICIENT_BUFFER) {
return 0, fmt.Errorf("failed to get buffer size: %w", err)
}
// Allocate the buffer
buffer := make([]byte, length)
// Second call to retrieve the processor information
_, _, err = procGetLogicalProcessorInformationEx.Call(uintptr(relationAll), uintptr(unsafe.Pointer(&buffer[0])), uintptr(unsafe.Pointer(&length)))
if err != nil && !errors.Is(err, windows.NTE_OP_OK) {
return 0, fmt.Errorf("failed to get logical processor information: %w", err)
}
// Iterate through the buffer to count physical cores
offset := uintptr(0)
ncpus := 0
for offset < uintptr(length) {
info := (*systemLogicalProcessorInformationEx)(unsafe.Pointer(uintptr(unsafe.Pointer(&buffer[0])) + offset))
if info.Relationship == relationProcessorCore {
ncpus++
}
offset += uintptr(info.Size)
}
return ncpus, nil
}
func CountsWithContext(_ context.Context, logical bool) (int, error) {
if logical { if logical {
// https://github.com/giampaolo/psutil/blob/d01a9eaa35a8aadf6c519839e987a49d8be2d891/psutil/_psutil_windows.c#L97 // Get logical processor count https://github.com/giampaolo/psutil/blob/d01a9eaa35a8aadf6c519839e987a49d8be2d891/psutil/_psutil_windows.c#L97
ret := windows.GetActiveProcessorCount(windows.ALL_PROCESSOR_GROUPS) ret := windows.GetActiveProcessorCount(windows.ALL_PROCESSOR_GROUPS)
if ret != 0 { if ret != 0 {
return int(ret), nil return int(ret), nil
} }
var systemInfo systemInfo var systemInfo systemInfo
_, _, err := procGetNativeSystemInfo.Call(uintptr(unsafe.Pointer(&systemInfo))) _, _, err := procGetNativeSystemInfo.Call(uintptr(unsafe.Pointer(&systemInfo)))
if systemInfo.dwNumberOfProcessors == 0 { if systemInfo.dwNumberOfProcessors == 0 {
@ -214,16 +275,7 @@ func CountsWithContext(ctx context.Context, logical bool) (int, error) {
} }
return int(systemInfo.dwNumberOfProcessors), nil return int(systemInfo.dwNumberOfProcessors), nil
} }
// physical cores https://github.com/giampaolo/psutil/blob/d01a9eaa35a8aadf6c519839e987a49d8be2d891/psutil/_psutil_windows.c#L499
// for the time being, try with unreliable and slow WMI call… // Get physical core count https://github.com/giampaolo/psutil/blob/d01a9eaa35a8aadf6c519839e987a49d8be2d891/psutil/_psutil_windows.c#L499
var dst []win32_Processor return getPhysicalCoreCount()
q := wmi.CreateQuery(&dst, "")
if err := common.WMIQueryWithContext(ctx, q, &dst); err != nil {
return 0, err
}
var count uint32
for _, d := range dst {
count += d.NumberOfCores
}
return int(count), nil
} }

@ -63,7 +63,7 @@ func PartitionsWithContext(ctx context.Context, _ bool) ([]PartitionStat, error)
if startBlank.MatchString(line) { if startBlank.MatchString(line) {
line = "localhost" + line line = "localhost" + line
} }
p := strings.Fields(lines[idx]) p := strings.Fields(line)
if len(p) < 5 || ignoreFSType[p[colidx["vfs"]]] { if len(p) < 5 || ignoreFSType[p[colidx["vfs"]]] {
continue continue
} }

@ -201,7 +201,7 @@ func IOCountersWithContext(_ context.Context, names ...string) (map[string]IOCou
stats := make([]IOCountersStat, 0, 16) stats := make([]IOCountersStat, 0, 16)
for { for {
d := ioIteratorNext(drives) d := ioIteratorNext(drives)
if !(d > 0) { if d <= 0 {
break break
} }

@ -100,6 +100,7 @@ const (
AFS_SUPER_MAGIC = 0x5346414F AFS_SUPER_MAGIC = 0x5346414F
AUFS_SUPER_MAGIC = 0x61756673 AUFS_SUPER_MAGIC = 0x61756673
ANON_INODE_FS_SUPER_MAGIC = 0x09041934 ANON_INODE_FS_SUPER_MAGIC = 0x09041934
BCACHEFS_SUPER_MAGIC = 0xCA451A4E
BPF_FS_MAGIC = 0xCAFE4A11 BPF_FS_MAGIC = 0xCAFE4A11
CEPH_SUPER_MAGIC = 0x00C36400 CEPH_SUPER_MAGIC = 0x00C36400
CGROUP2_SUPER_MAGIC = 0x63677270 CGROUP2_SUPER_MAGIC = 0x63677270
@ -139,6 +140,7 @@ var fsTypeMap = map[int64]string{
ANON_INODE_FS_SUPER_MAGIC: "anon-inode FS", /* 0x09041934 local */ ANON_INODE_FS_SUPER_MAGIC: "anon-inode FS", /* 0x09041934 local */
AUFS_SUPER_MAGIC: "aufs", /* 0x61756673 remote */ AUFS_SUPER_MAGIC: "aufs", /* 0x61756673 remote */
// AUTOFS_SUPER_MAGIC: "autofs", /* 0x0187 local */ // AUTOFS_SUPER_MAGIC: "autofs", /* 0x0187 local */
BCACHEFS_SUPER_MAGIC: "bcachefs", /* 0xCA451A4E local */
BEFS_SUPER_MAGIC: "befs", /* 0x42465331 local */ BEFS_SUPER_MAGIC: "befs", /* 0x42465331 local */
BDEVFS_MAGIC: "bdevfs", /* 0x62646576 local */ BDEVFS_MAGIC: "bdevfs", /* 0x62646576 local */
BFS_MAGIC: "bfs", /* 0x1BADFACE local */ BFS_MAGIC: "bfs", /* 0x1BADFACE local */

@ -3,7 +3,7 @@ module github.com/shirou/gopsutil/v4
go 1.23 go 1.23
require ( require (
github.com/ebitengine/purego v0.8.2 github.com/ebitengine/purego v0.8.3
github.com/google/go-cmp v0.7.0 github.com/google/go-cmp v0.7.0
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c

@ -1,7 +1,7 @@
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 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/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/ebitengine/purego v0.8.2 h1:jPPGWs2sZ1UgOSgD2bClL0MJIqu58nOmIcBuXr62z1I= github.com/ebitengine/purego v0.8.3 h1:K+0AjQp63JEZTEMZiwsI9g0+hAMNohwUOtY0RPGexmc=
github.com/ebitengine/purego v0.8.2/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= github.com/ebitengine/purego v0.8.3/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 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=

@ -5,6 +5,7 @@ import (
"context" "context"
"encoding/json" "encoding/json"
"errors" "errors"
"fmt"
"os" "os"
"runtime" "runtime"
"time" "time"
@ -70,47 +71,47 @@ func InfoWithContext(ctx context.Context) (*InfoStat, error) {
ret.Hostname, err = os.Hostname() ret.Hostname, err = os.Hostname()
if err != nil && !errors.Is(err, common.ErrNotImplementedError) { if err != nil && !errors.Is(err, common.ErrNotImplementedError) {
return nil, err return nil, fmt.Errorf("getting hostname: %w", err)
} }
ret.Platform, ret.PlatformFamily, ret.PlatformVersion, err = PlatformInformationWithContext(ctx) ret.Platform, ret.PlatformFamily, ret.PlatformVersion, err = PlatformInformationWithContext(ctx)
if err != nil && !errors.Is(err, common.ErrNotImplementedError) { if err != nil && !errors.Is(err, common.ErrNotImplementedError) {
return nil, err return nil, fmt.Errorf("getting platform information: %w", err)
} }
ret.KernelVersion, err = KernelVersionWithContext(ctx) ret.KernelVersion, err = KernelVersionWithContext(ctx)
if err != nil && !errors.Is(err, common.ErrNotImplementedError) { if err != nil && !errors.Is(err, common.ErrNotImplementedError) {
return nil, err return nil, fmt.Errorf("getting kernel version: %w", err)
} }
ret.KernelArch, err = KernelArch() ret.KernelArch, err = KernelArch()
if err != nil && !errors.Is(err, common.ErrNotImplementedError) { if err != nil && !errors.Is(err, common.ErrNotImplementedError) {
return nil, err return nil, fmt.Errorf("getting kernel archictecture: %w", err)
} }
ret.VirtualizationSystem, ret.VirtualizationRole, err = VirtualizationWithContext(ctx) ret.VirtualizationSystem, ret.VirtualizationRole, err = VirtualizationWithContext(ctx)
if err != nil && !errors.Is(err, common.ErrNotImplementedError) { if err != nil && !errors.Is(err, common.ErrNotImplementedError) {
return nil, err return nil, fmt.Errorf("getting virtualization information: %w", err)
} }
ret.BootTime, err = BootTimeWithContext(ctx) ret.BootTime, err = BootTimeWithContext(ctx)
if err != nil && !errors.Is(err, common.ErrNotImplementedError) { if err != nil && !errors.Is(err, common.ErrNotImplementedError) {
return nil, err return nil, fmt.Errorf("getting boot time: %w", err)
} }
ret.Uptime, err = UptimeWithContext(ctx) ret.Uptime, err = UptimeWithContext(ctx)
if err != nil && !errors.Is(err, common.ErrNotImplementedError) { if err != nil && !errors.Is(err, common.ErrNotImplementedError) {
return nil, err return nil, fmt.Errorf("getting uptime: %w", err)
} }
ret.Procs, err = numProcs(ctx) ret.Procs, err = numProcs(ctx)
if err != nil && !errors.Is(err, common.ErrNotImplementedError) { if err != nil && !errors.Is(err, common.ErrNotImplementedError) {
return nil, err return nil, fmt.Errorf("getting number of procs: %w", err)
} }
ret.HostID, err = HostIDWithContext(ctx) ret.HostID, err = HostIDWithContext(ctx)
if err != nil && !errors.Is(err, common.ErrNotImplementedError) { if err != nil && !errors.Is(err, common.ErrNotImplementedError) {
return nil, err return nil, fmt.Errorf("getting host ID: %w", err)
} }
return ret, nil return ret, nil

@ -67,8 +67,8 @@ func parseUptime(uptime string) uint64 {
var days, hours, mins uint64 var days, hours, mins uint64
var err error var err error
switch { switch ut[3] {
case ut[3] == "day," || ut[3] == "days,": case "day,", "days,":
days, err = strconv.ParseUint(ut[2], 10, 64) days, err = strconv.ParseUint(ut[2], 10, 64)
if err != nil { if err != nil {
return 0 return 0
@ -105,12 +105,12 @@ func parseUptime(uptime string) uint64 {
return 0 return 0
} }
} }
case ut[3] == "hr," || ut[3] == "hrs,": case "hr,", "hrs,":
hours, err = strconv.ParseUint(ut[2], 10, 64) hours, err = strconv.ParseUint(ut[2], 10, 64)
if err != nil { if err != nil {
return 0 return 0
} }
case ut[3] == "min," || ut[3] == "mins,": case "min,", "mins,":
mins, err = strconv.ParseUint(ut[2], 10, 64) mins, err = strconv.ParseUint(ut[2], 10, 64)
if err != nil { if err != nil {
return 0 return 0

@ -67,8 +67,7 @@ func UsersWithContext(_ context.Context) ([]UserStat, error) {
// Skip macOS utmpx header part // Skip macOS utmpx header part
buf = buf[604:] buf = buf[604:]
u := Utmpx{} entrySize := int(unsafe.Sizeof(Utmpx{}))
entrySize := int(unsafe.Sizeof(u))
count := len(buf) / entrySize count := len(buf) / entrySize
for i := 0; i < count; i++ { for i := 0; i < count; i++ {

@ -117,8 +117,7 @@ func getUsersFromUtmp(utmpfile string) ([]UserStat, error) {
return ret, err return ret, err
} }
u := Utmp{} entrySize := int(unsafe.Sizeof(Utmp{}))
entrySize := int(unsafe.Sizeof(u))
count := len(buf) / entrySize count := len(buf) / entrySize
for i := 0; i < count; i++ { for i := 0; i < count; i++ {

@ -71,8 +71,7 @@ func UsersWithContext(_ context.Context) ([]UserStat, error) {
return ret, err return ret, err
} }
u := Utmp{} entrySize := int(unsafe.Sizeof(Utmp{}))
entrySize := int(unsafe.Sizeof(u))
count := len(buf) / entrySize count := len(buf) / entrySize
for i := 0; i < count; i++ { for i := 0; i < count; i++ {

@ -80,7 +80,7 @@ func HostIDWithContext(_ context.Context) (string, error) {
hostID := windows.UTF16ToString(regBuf[:]) hostID := windows.UTF16ToString(regBuf[:])
hostIDLen := len(hostID) hostIDLen := len(hostID)
if hostIDLen != uuidLen { if hostIDLen != uuidLen {
return "", fmt.Errorf("HostID incorrect: %q\n", hostID) //nolint:revive //FIXME return "", fmt.Errorf("HostID incorrect: %q", hostID)
} }
return strings.ToLower(hostID), nil return strings.ToLower(hostID), nil
@ -153,26 +153,26 @@ func platformInformation() (platform, family, version, displayVersion string, er
osInfo.dwOSVersionInfoSize = uint32(unsafe.Sizeof(osInfo)) osInfo.dwOSVersionInfoSize = uint32(unsafe.Sizeof(osInfo))
ret, _, err := procRtlGetVersion.Call(uintptr(unsafe.Pointer(&osInfo))) ret, _, err := procRtlGetVersion.Call(uintptr(unsafe.Pointer(&osInfo)))
if ret != 0 { if ret != 0 {
return //nolint:nakedret //FIXME return platform, family, version, displayVersion, err
} }
// Platform // Platform
var h windows.Handle // like HostIDWithContext(), we query the registry using the raw windows.RegOpenKeyEx/RegQueryValueEx 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) 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 { if err != nil {
return //nolint:nakedret //FIXME return platform, family, version, displayVersion, err
} }
defer windows.RegCloseKey(h) defer windows.RegCloseKey(h)
var bufLen uint32 var bufLen uint32
var valType uint32 var valType uint32
err = windows.RegQueryValueEx(h, windows.StringToUTF16Ptr(`ProductName`), nil, &valType, nil, &bufLen) err = windows.RegQueryValueEx(h, windows.StringToUTF16Ptr(`ProductName`), nil, &valType, nil, &bufLen)
if err != nil { if err != nil {
return //nolint:nakedret //FIXME return platform, family, version, displayVersion, err
} }
regBuf := make([]uint16, bufLen/2+1) regBuf := make([]uint16, bufLen/2+1)
err = windows.RegQueryValueEx(h, windows.StringToUTF16Ptr(`ProductName`), nil, &valType, (*byte)(unsafe.Pointer(&regBuf[0])), &bufLen) err = windows.RegQueryValueEx(h, windows.StringToUTF16Ptr(`ProductName`), nil, &valType, (*byte)(unsafe.Pointer(&regBuf[0])), &bufLen)
if err != nil { if err != nil {
return //nolint:nakedret //FIXME return platform, family, version, displayVersion, err
} }
platform = windows.UTF16ToString(regBuf) platform = windows.UTF16ToString(regBuf)
if strings.Contains(platform, "Windows 10") { // check build number to determine whether it's actually Windows 11 if strings.Contains(platform, "Windows 10") { // check build number to determine whether it's actually Windows 11

@ -393,10 +393,7 @@ func GoString(cStr *byte) string {
return "" return ""
} }
var length int var length int
for { for *(*byte)(unsafe.Add(unsafe.Pointer(cStr), uintptr(length))) != '\x00' {
if *(*byte)(unsafe.Add(unsafe.Pointer(cStr), uintptr(length))) == '\x00' {
break
}
length++ length++
} }
return string(unsafe.Slice(cStr, length)) return string(unsafe.Slice(cStr, length))

@ -16,7 +16,7 @@ import (
) )
var ( var (
errNetstatHeader = errors.New("Can't parse header of netstat output") errNetstatHeader = errors.New("can't parse header of netstat output")
netstatLinkRegexp = regexp.MustCompile(`^<Link#(\d+)>$`) netstatLinkRegexp = regexp.MustCompile(`^<Link#(\d+)>$`)
) )
@ -29,15 +29,14 @@ func parseNetstatLine(line string) (stat *IOCountersStat, linkID *uint, err erro
) )
if columns[0] == "Name" { if columns[0] == "Name" {
err = errNetstatHeader return nil, nil, errNetstatHeader
return //nolint:nakedret //FIXME
} }
// try to extract the numeric value from <Link#123> // try to extract the numeric value from <Link#123>
if subMatch := netstatLinkRegexp.FindStringSubmatch(columns[2]); len(subMatch) == 2 { if subMatch := netstatLinkRegexp.FindStringSubmatch(columns[2]); len(subMatch) == 2 {
numericValue, err = strconv.ParseUint(subMatch[1], 10, 64) numericValue, err = strconv.ParseUint(subMatch[1], 10, 64)
if err != nil { if err != nil {
return //nolint:nakedret //FIXME return nil, nil, err
} }
linkIDUint := uint(numericValue) linkIDUint := uint(numericValue)
linkID = &linkIDUint linkID = &linkIDUint
@ -50,8 +49,7 @@ func parseNetstatLine(line string) (stat *IOCountersStat, linkID *uint, err erro
base = 0 base = 0
} }
if numberColumns < 11 || numberColumns > 13 { if numberColumns < 11 || numberColumns > 13 {
err = fmt.Errorf("Line %q do have an invalid number of columns %d", line, numberColumns) return nil, nil, fmt.Errorf("line %q do have an invalid number of columns %d", line, numberColumns)
return //nolint:nakedret //FIXME
} }
parsed := make([]uint64, 0, 7) parsed := make([]uint64, 0, 7)
@ -74,7 +72,7 @@ func parseNetstatLine(line string) (stat *IOCountersStat, linkID *uint, err erro
} }
if numericValue, err = strconv.ParseUint(target, 10, 64); err != nil { if numericValue, err = strconv.ParseUint(target, 10, 64); err != nil {
return //nolint:nakedret //FIXME return nil, nil, err
} }
parsed = append(parsed, numericValue) parsed = append(parsed, numericValue)
} }
@ -91,7 +89,7 @@ func parseNetstatLine(line string) (stat *IOCountersStat, linkID *uint, err erro
if len(parsed) == 7 { if len(parsed) == 7 {
stat.Dropout = parsed[6] stat.Dropout = parsed[6]
} }
return //nolint:nakedret //FIXME return stat, linkID, nil
} }
type netstatInterface struct { type netstatInterface struct {

@ -296,7 +296,7 @@ func ConnectionsWithContext(ctx context.Context, kind string) ([]ConnectionStat,
} }
lines := strings.Split(string(out), "\n") lines := strings.Split(string(out), "\n")
for _, line := range lines { for _, line := range lines {
if !(strings.HasPrefix(line, "tcp") || strings.HasPrefix(line, "udp")) { if !strings.HasPrefix(line, "tcp") && !strings.HasPrefix(line, "udp") {
continue continue
} }
n, err := parseNetstatLine(line) n, err := parseNetstatLine(line)

@ -554,7 +554,7 @@ func TestOpenFiles(t *testing.T) {
assert.NotEmpty(t, v) // test always open files. assert.NotEmpty(t, v) // test always open files.
for _, vv := range v { for _, vv := range v {
assert.NotEqual(t, "", vv.Path) assert.NotEmpty(t, vv.Path)
} }
} }

@ -594,7 +594,7 @@ func (p *Process) NumThreadsWithContext(_ context.Context) (int32, error) {
// if no errors and not cached already, cache ppid // if no errors and not cached already, cache ppid
p.parent = ppid p.parent = ppid
if 0 == p.getPpid() { if p.getPpid() == 0 {
p.setPpid(ppid) p.setPpid(ppid)
} }

Loading…
Cancel
Save