chore: enable golangci-lint on Windows and MacOS

Signed-off-by: Matthieu MOREL <matthieu.morel35@gmail.com>
pull/1785/head
Matthieu MOREL 1 month ago
parent 90e59961ca
commit 9ce2ec161e

1
.gitattributes vendored

@ -0,0 +1 @@
*.go text eol=lf

@ -9,11 +9,15 @@ permissions:
jobs: jobs:
golangci: golangci:
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
permissions: permissions:
contents: read # for actions/checkout to fetch code contents: read # for actions/checkout to fetch code
pull-requests: read # for golangci/golangci-lint-action to fetch pull requests pull-requests: read # for golangci/golangci-lint-action to fetch pull requests
name: lint name: lint
runs-on: ubuntu-latest runs-on: ${{ matrix.os }}
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2

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

@ -222,7 +222,7 @@ func (i *ioCounters) getDriveStat(d uint32) (*IOCountersStat, error) {
defer i.ioObjectRelease(parent) defer i.ioObjectRelease(parent)
if !ioObjectConformsTo(parent, "IOBlockStorageDriver") { 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 return nil, nil
} }

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

@ -13,9 +13,10 @@ import (
"time" "time"
"unsafe" "unsafe"
"golang.org/x/sys/windows"
"github.com/shirou/gopsutil/v4/internal/common" "github.com/shirou/gopsutil/v4/internal/common"
"github.com/shirou/gopsutil/v4/process" "github.com/shirou/gopsutil/v4/process"
"golang.org/x/sys/windows"
) )
var ( var (
@ -79,7 +80,7 @@ func HostIDWithContext(ctx 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) return "", fmt.Errorf("HostID incorrect: %q\n", hostID) //nolint:revive //FIXME
} }
return strings.ToLower(hostID), nil return strings.ToLower(hostID), nil
@ -135,15 +136,15 @@ func BootTimeWithContext(ctx context.Context) (uint64, error) {
return t, nil return t, nil
} }
func PlatformInformationWithContext(ctx context.Context) (platform string, family string, version string, err error) { func PlatformInformationWithContext(_ context.Context) (platform string, family string, version string, err error) {
platform, family, _, displayVersion, err := platformInformation(ctx) platform, family, _, displayVersion, err := platformInformation()
if err != nil { if err != nil {
return "", "", "", err return "", "", "", err
} }
return platform, family, displayVersion, nil 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 // 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 // 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 // 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)) 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 return //nolint:nakedret //FIXME
} }
// 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 return //nolint:nakedret //FIXME
} }
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 return //nolint:nakedret //FIXME
} }
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 return //nolint:nakedret //FIXME
} }
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
@ -243,8 +244,8 @@ func VirtualizationWithContext(ctx context.Context) (string, string, error) {
return "", "", common.ErrNotImplementedError return "", "", common.ErrNotImplementedError
} }
func KernelVersionWithContext(ctx context.Context) (string, error) { func KernelVersionWithContext(_ context.Context) (string, error) {
_, _, version, _, err := platformInformation(ctx) _, _, version, _, err := platformInformation()
return version, err return version, err
} }

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

@ -273,19 +273,19 @@ type SystemExtendedHandleInformation struct {
// CallWithExpandingBuffer https://github.com/hillu/go-ntdll // CallWithExpandingBuffer https://github.com/hillu/go-ntdll
func CallWithExpandingBuffer(fn func() NtStatus, buf *[]byte, resultLength *uint32) NtStatus { func CallWithExpandingBuffer(fn func() NtStatus, buf *[]byte, resultLength *uint32) NtStatus {
for { 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) { if int(*resultLength) <= cap(*buf) {
(*reflect.SliceHeader)(unsafe.Pointer(buf)).Len = int(*resultLength) (*reflect.SliceHeader)(unsafe.Pointer(buf)).Len = int(*resultLength)
} else { } else {
*buf = make([]byte, int(*resultLength)) *buf = make([]byte, int(*resultLength))
} }
continue continue
} else {
if !st.IsError() {
*buf = (*buf)[:int(*resultLength)]
}
return st
} }
if !st.IsError() {
*buf = (*buf)[:int(*resultLength)]
}
return st
} }
} }

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

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

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

@ -30,14 +30,14 @@ func parseNetstatLine(line string) (stat *IOCountersStat, linkID *uint, err erro
if columns[0] == "Name" { if columns[0] == "Name" {
err = errNetstatHeader err = errNetstatHeader
return 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 return //nolint:nakedret //FIXME
} }
linkIDUint := uint(numericValue) linkIDUint := uint(numericValue)
linkID = &linkIDUint linkID = &linkIDUint
@ -51,7 +51,7 @@ func parseNetstatLine(line string) (stat *IOCountersStat, linkID *uint, err erro
} }
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) 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) 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 { if numericValue, err = strconv.ParseUint(target, 10, 64); err != nil {
return return //nolint:nakedret //FIXME
} }
parsed = append(parsed, numericValue) parsed = append(parsed, numericValue)
} }
@ -91,7 +91,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 return //nolint:nakedret //FIXME
} }
type netstatInterface struct { type netstatInterface struct {

@ -137,5 +137,5 @@ func TestParseNetstatTruncated(t *testing.T) {
mapUsage := newMapInterfaceNameUsage(nsInterfaces) mapUsage := newMapInterfaceNameUsage(nsInterfaces)
assert.True(t, mapUsage.isTruncated()) 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")
} }

@ -5,14 +5,16 @@ package net
import ( import (
"context" "context"
"errors"
"fmt" "fmt"
"net" "net"
"os" "os"
"syscall" "syscall"
"unsafe" "unsafe"
"github.com/shirou/gopsutil/v4/internal/common"
"golang.org/x/sys/windows" "golang.org/x/sys/windows"
"github.com/shirou/gopsutil/v4/internal/common"
) )
var ( var (
@ -197,7 +199,7 @@ func IOCountersWithContext(ctx context.Context, pernic bool) ([]IOCountersStat,
} }
func IOCountersByFileWithContext(ctx context.Context, pernic bool, filename string) ([]IOCountersStat, error) { 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) { 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) { func getNetStatWithKind(kindType netConnectionKindType) ([]ConnectionStat, error) {
if kindType.filename == "" { if kindType.filename == "" {
return nil, fmt.Errorf("kind filename must be required") return nil, errors.New("kind filename must be required")
} }
switch kindType.filename { switch kindType.filename {
@ -360,7 +362,7 @@ func getTCPConnections(family uint32) ([]ConnectionStat, error) {
) )
if family == 0 { if family == 0 {
return nil, fmt.Errorf("faimly must be required") return nil, errors.New("faimly must be required")
} }
for { for {
@ -390,7 +392,7 @@ func getTCPConnections(family uint32) ([]ConnectionStat, error) {
if err == nil { if err == nil {
break break
} }
if err != windows.ERROR_INSUFFICIENT_BUFFER { if !errors.Is(err, windows.ERROR_INSUFFICIENT_BUFFER) {
return nil, err return nil, err
} }
buf = make([]byte, size) buf = make([]byte, size)
@ -441,7 +443,7 @@ func getUDPConnections(family uint32) ([]ConnectionStat, error) {
) )
if family == 0 { if family == 0 {
return nil, fmt.Errorf("faimly must be required") return nil, errors.New("faimly must be required")
} }
for { for {
@ -473,7 +475,7 @@ func getUDPConnections(family uint32) ([]ConnectionStat, error) {
if err == nil { if err == nil {
break break
} }
if err != windows.ERROR_INSUFFICIENT_BUFFER { if !errors.Is(err, windows.ERROR_INSUFFICIENT_BUFFER) {
return nil, err return nil, err
} }
buf = make([]byte, size) buf = make([]byte, size)

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

@ -18,10 +18,11 @@ import (
"unicode/utf16" "unicode/utf16"
"unsafe" "unsafe"
"golang.org/x/sys/windows"
"github.com/shirou/gopsutil/v4/cpu" "github.com/shirou/gopsutil/v4/cpu"
"github.com/shirou/gopsutil/v4/internal/common" "github.com/shirou/gopsutil/v4/internal/common"
"github.com/shirou/gopsutil/v4/net" "github.com/shirou/gopsutil/v4/net"
"golang.org/x/sys/windows"
) )
type Signal = syscall.Signal type Signal = syscall.Signal
@ -245,7 +246,7 @@ func pidsWithContext(ctx context.Context) ([]int32, error) {
// inspired by https://gist.github.com/henkman/3083408 // inspired by https://gist.github.com/henkman/3083408
// and https://github.com/giampaolo/psutil/blob/1c3a15f637521ba5c0031283da39c733fda53e4c/psutil/arch/windows/process_info.c#L315-L329 // and https://github.com/giampaolo/psutil/blob/1c3a15f637521ba5c0031283da39c733fda53e4c/psutil/arch/windows/process_info.c#L315-L329
var ret []int32 var ret []int32
var read uint32 = 0 var read uint32
var psSize uint32 = 1024 var psSize uint32 = 1024
const dwordSize uint32 = 4 const dwordSize uint32 = 4
@ -288,10 +289,10 @@ func PidExistsWithContext(ctx context.Context, pid int32) (bool, error) {
return false, err return false, err
} }
h, err := windows.OpenProcess(windows.SYNCHRONIZE, false, uint32(pid)) 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 return true, nil
} }
if err == windows.ERROR_INVALID_PARAMETER { if errors.Is(err, windows.ERROR_INVALID_PARAMETER) {
return false, nil return false, nil
} }
if err != nil { if err != nil {
@ -330,7 +331,7 @@ func (p *Process) NameWithContext(ctx context.Context) (string, error) {
exe, err := p.ExeWithContext(ctx) exe, err := p.ExeWithContext(ctx)
if err != nil { 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 return filepath.Base(exe), nil
@ -370,7 +371,7 @@ func (p *Process) ExeWithContext(ctx context.Context) (string, error) {
func (p *Process) CmdlineWithContext(_ context.Context) (string, error) { func (p *Process) CmdlineWithContext(_ context.Context) (string, error) {
cmdline, err := getProcessCommandLine(p.Pid) cmdline, err := getProcessCommandLine(p.Pid)
if err != nil { if err != nil {
return "", fmt.Errorf("could not get CommandLine: %s", err) return "", fmt.Errorf("could not get CommandLine: %w", err)
} }
return cmdline, nil return cmdline, nil
} }
@ -386,7 +387,7 @@ func (p *Process) CmdlineSliceWithContext(ctx context.Context) ([]string, error)
func (p *Process) createTimeWithContext(ctx context.Context) (int64, error) { func (p *Process) createTimeWithContext(ctx context.Context) (int64, error) {
ru, err := getRusage(p.Pid) ru, err := getRusage(p.Pid)
if err != nil { 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 return ru.CreationTime.Nanoseconds() / 1000000, nil
@ -394,7 +395,7 @@ func (p *Process) createTimeWithContext(ctx context.Context) (int64, error) {
func (p *Process) CwdWithContext(_ context.Context) (string, error) { func (p *Process) CwdWithContext(_ context.Context) (string, error) {
h, err := windows.OpenProcess(processQueryInformation|windows.PROCESS_VM_READ, false, uint32(p.Pid)) 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 return "", nil
} }
if err != nil { if err != nil {
@ -822,9 +823,9 @@ func (p *Process) KillWithContext(ctx context.Context) error {
} }
func (p *Process) EnvironWithContext(ctx context.Context) ([]string, 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 { 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 return envVars, nil
} }
@ -844,7 +845,7 @@ func (p *Process) setPpid(ppid int32) {
p.parent = ppid 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)) snap, err := windows.CreateToolhelp32Snapshot(windows.TH32CS_SNAPPROCESS, uint32(pid))
if err != nil { if err != nil {
return 0, 0, "", err return 0, 0, "", err
@ -872,7 +873,7 @@ func ProcessesWithContext(ctx context.Context) ([]*Process, error) {
pids, err := PidsWithContext(ctx) pids, err := PidsWithContext(ctx)
if err != nil { 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 { for _, pid := range pids {
@ -963,13 +964,13 @@ func getUserProcessParams32(handle windows.Handle) (rtlUserProcessParameters32,
buf := readProcessMemory(syscall.Handle(handle), true, pebAddress, uint(unsafe.Sizeof(processEnvironmentBlock32{}))) buf := readProcessMemory(syscall.Handle(handle), true, pebAddress, uint(unsafe.Sizeof(processEnvironmentBlock32{})))
if len(buf) != int(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])) peb := (*processEnvironmentBlock32)(unsafe.Pointer(&buf[0]))
userProcessAddress := uint64(peb.ProcessParameters) userProcessAddress := uint64(peb.ProcessParameters)
buf = readProcessMemory(syscall.Handle(handle), true, userProcessAddress, uint(unsafe.Sizeof(rtlUserProcessParameters32{}))) buf = readProcessMemory(syscall.Handle(handle), true, userProcessAddress, uint(unsafe.Sizeof(rtlUserProcessParameters32{})))
if len(buf) != int(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 return *(*rtlUserProcessParameters32)(unsafe.Pointer(&buf[0])), nil
} }
@ -982,13 +983,13 @@ func getUserProcessParams64(handle windows.Handle) (rtlUserProcessParameters64,
buf := readProcessMemory(syscall.Handle(handle), false, pebAddress, uint(unsafe.Sizeof(processEnvironmentBlock64{}))) buf := readProcessMemory(syscall.Handle(handle), false, pebAddress, uint(unsafe.Sizeof(processEnvironmentBlock64{})))
if len(buf) != int(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])) peb := (*processEnvironmentBlock64)(unsafe.Pointer(&buf[0]))
userProcessAddress := peb.ProcessParameters userProcessAddress := peb.ProcessParameters
buf = readProcessMemory(syscall.Handle(handle), false, userProcessAddress, uint(unsafe.Sizeof(rtlUserProcessParameters64{}))) buf = readProcessMemory(syscall.Handle(handle), false, userProcessAddress, uint(unsafe.Sizeof(rtlUserProcessParameters64{})))
if len(buf) != int(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 return *(*rtlUserProcessParameters64)(unsafe.Pointer(&buf[0])), nil
} }
@ -1038,9 +1039,9 @@ func is32BitProcess(h windows.Handle) bool {
return procIs32Bits 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)) 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 return nil, nil
} }
if err != nil { if err != nil {
@ -1124,7 +1125,7 @@ func (p *processReader) Read(buf []byte) (int, error) {
func getProcessCommandLine(pid int32) (string, error) { func getProcessCommandLine(pid int32) (string, error) {
h, err := windows.OpenProcess(processQueryInformation|windows.PROCESS_VM_READ, false, uint32(pid)) 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 return "", nil
} }
if err != nil { if err != nil {

@ -7,8 +7,9 @@ import (
"syscall" "syscall"
"unsafe" "unsafe"
"github.com/shirou/gopsutil/v4/internal/common"
"golang.org/x/sys/windows" "golang.org/x/sys/windows"
"github.com/shirou/gopsutil/v4/internal/common"
) )
type PROCESS_MEMORY_COUNTERS struct { 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 { if status := windows.NTStatus(ret); status == windows.STATUS_SUCCESS {
return uint64(wow64), nil return uint64(wow64), nil
} else {
return 0, windows.NTStatus(ret)
} }
} else { return 0, windows.NTStatus(ret)
// we are on a 64-bit process reading an external 64-bit process }
var info processBasicInformation64 // we are on a 64-bit process reading an external 64-bit process
var info processBasicInformation64
ret, _, _ := common.ProcNtQueryInformationProcess.Call( ret, _, _ := common.ProcNtQueryInformationProcess.Call(
uintptr(procHandle), uintptr(procHandle),
uintptr(common.ProcessBasicInformation), uintptr(common.ProcessBasicInformation),
uintptr(unsafe.Pointer(&info)), uintptr(unsafe.Pointer(&info)),
uintptr(unsafe.Sizeof(info)), uintptr(unsafe.Sizeof(info)),
uintptr(0), uintptr(0),
) )
if status := windows.NTStatus(ret); status == windows.STATUS_SUCCESS { if status := windows.NTStatus(ret); status == windows.STATUS_SUCCESS {
return info.PebBaseAddress, nil return info.PebBaseAddress, nil
} else {
return 0, windows.NTStatus(ret)
}
} }
return 0, windows.NTStatus(ret)
} }
func readProcessMemory(procHandle syscall.Handle, _ bool, address uint64, size uint) []byte { func readProcessMemory(procHandle syscall.Handle, _ bool, address uint64, size uint) []byte {

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

@ -5,6 +5,7 @@ package winservices
import ( import (
"context" "context"
"errors"
"unsafe" "unsafe"
"golang.org/x/sys/windows" "golang.org/x/sys/windows"
@ -86,7 +87,7 @@ func (s *Service) QueryStatusWithContext(ctx context.Context) (ServiceStatus, er
var bytesNeeded uint32 var bytesNeeded uint32
var buf []byte 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 return ServiceStatus{}, err
} }

Loading…
Cancel
Save