mirror of
https://github.com/status-im/consul.git
synced 2025-01-21 02:59:48 +00:00
95c027a3ea
https://github.com/shirou/gopsutil/pull/895 is merged and fixes our problem. Time to update. Since there is no new version just yet, updating to the sha.
196 lines
6.4 KiB
Go
196 lines
6.4 KiB
Go
// +build windows
|
|
|
|
package disk
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"fmt"
|
|
"syscall"
|
|
"unsafe"
|
|
|
|
"github.com/shirou/gopsutil/internal/common"
|
|
"golang.org/x/sys/windows"
|
|
)
|
|
|
|
var (
|
|
procGetDiskFreeSpaceExW = common.Modkernel32.NewProc("GetDiskFreeSpaceExW")
|
|
procGetLogicalDriveStringsW = common.Modkernel32.NewProc("GetLogicalDriveStringsW")
|
|
procGetDriveType = common.Modkernel32.NewProc("GetDriveTypeW")
|
|
procGetVolumeInformation = common.Modkernel32.NewProc("GetVolumeInformationW")
|
|
)
|
|
|
|
var (
|
|
FileFileCompression = int64(16) // 0x00000010
|
|
FileReadOnlyVolume = int64(524288) // 0x00080000
|
|
)
|
|
|
|
// diskPerformance is an equivalent representation of DISK_PERFORMANCE in the Windows API.
|
|
// https://docs.microsoft.com/fr-fr/windows/win32/api/winioctl/ns-winioctl-disk_performance
|
|
type diskPerformance struct {
|
|
BytesRead int64
|
|
BytesWritten int64
|
|
ReadTime int64
|
|
WriteTime int64
|
|
IdleTime int64
|
|
ReadCount uint32
|
|
WriteCount uint32
|
|
QueueDepth uint32
|
|
SplitCount uint32
|
|
QueryTime int64
|
|
StorageDeviceNumber uint32
|
|
StorageManagerName [8]uint16
|
|
alignmentPadding uint32 // necessary for 32bit support, see https://github.com/elastic/beats/pull/16553
|
|
}
|
|
|
|
func Usage(path string) (*UsageStat, error) {
|
|
return UsageWithContext(context.Background(), path)
|
|
}
|
|
|
|
func UsageWithContext(ctx context.Context, path string) (*UsageStat, error) {
|
|
lpFreeBytesAvailable := int64(0)
|
|
lpTotalNumberOfBytes := int64(0)
|
|
lpTotalNumberOfFreeBytes := int64(0)
|
|
diskret, _, err := procGetDiskFreeSpaceExW.Call(
|
|
uintptr(unsafe.Pointer(windows.StringToUTF16Ptr(path))),
|
|
uintptr(unsafe.Pointer(&lpFreeBytesAvailable)),
|
|
uintptr(unsafe.Pointer(&lpTotalNumberOfBytes)),
|
|
uintptr(unsafe.Pointer(&lpTotalNumberOfFreeBytes)))
|
|
if diskret == 0 {
|
|
return nil, err
|
|
}
|
|
ret := &UsageStat{
|
|
Path: path,
|
|
Total: uint64(lpTotalNumberOfBytes),
|
|
Free: uint64(lpTotalNumberOfFreeBytes),
|
|
Used: uint64(lpTotalNumberOfBytes) - uint64(lpTotalNumberOfFreeBytes),
|
|
UsedPercent: (float64(lpTotalNumberOfBytes) - float64(lpTotalNumberOfFreeBytes)) / float64(lpTotalNumberOfBytes) * 100,
|
|
// InodesTotal: 0,
|
|
// InodesFree: 0,
|
|
// InodesUsed: 0,
|
|
// InodesUsedPercent: 0,
|
|
}
|
|
return ret, nil
|
|
}
|
|
|
|
func Partitions(all bool) ([]PartitionStat, error) {
|
|
return PartitionsWithContext(context.Background(), all)
|
|
}
|
|
|
|
func PartitionsWithContext(ctx context.Context, all bool) ([]PartitionStat, error) {
|
|
var ret []PartitionStat
|
|
lpBuffer := make([]byte, 254)
|
|
diskret, _, err := procGetLogicalDriveStringsW.Call(
|
|
uintptr(len(lpBuffer)),
|
|
uintptr(unsafe.Pointer(&lpBuffer[0])))
|
|
if diskret == 0 {
|
|
return ret, err
|
|
}
|
|
for _, v := range lpBuffer {
|
|
if v >= 65 && v <= 90 {
|
|
path := string(v) + ":"
|
|
typepath, _ := windows.UTF16PtrFromString(path)
|
|
typeret, _, _ := procGetDriveType.Call(uintptr(unsafe.Pointer(typepath)))
|
|
if typeret == 0 {
|
|
return ret, windows.GetLastError()
|
|
}
|
|
// 2: DRIVE_REMOVABLE 3: DRIVE_FIXED 4: DRIVE_REMOTE 5: DRIVE_CDROM
|
|
|
|
if typeret == 2 || typeret == 3 || typeret == 4 || typeret == 5 {
|
|
lpVolumeNameBuffer := make([]byte, 256)
|
|
lpVolumeSerialNumber := int64(0)
|
|
lpMaximumComponentLength := int64(0)
|
|
lpFileSystemFlags := int64(0)
|
|
lpFileSystemNameBuffer := make([]byte, 256)
|
|
volpath, _ := windows.UTF16PtrFromString(string(v) + ":/")
|
|
driveret, _, err := procGetVolumeInformation.Call(
|
|
uintptr(unsafe.Pointer(volpath)),
|
|
uintptr(unsafe.Pointer(&lpVolumeNameBuffer[0])),
|
|
uintptr(len(lpVolumeNameBuffer)),
|
|
uintptr(unsafe.Pointer(&lpVolumeSerialNumber)),
|
|
uintptr(unsafe.Pointer(&lpMaximumComponentLength)),
|
|
uintptr(unsafe.Pointer(&lpFileSystemFlags)),
|
|
uintptr(unsafe.Pointer(&lpFileSystemNameBuffer[0])),
|
|
uintptr(len(lpFileSystemNameBuffer)))
|
|
if driveret == 0 {
|
|
if typeret == 5 || typeret == 2 {
|
|
continue //device is not ready will happen if there is no disk in the drive
|
|
}
|
|
return ret, err
|
|
}
|
|
opts := "rw"
|
|
if lpFileSystemFlags&FileReadOnlyVolume != 0 {
|
|
opts = "ro"
|
|
}
|
|
if lpFileSystemFlags&FileFileCompression != 0 {
|
|
opts += ".compress"
|
|
}
|
|
|
|
d := PartitionStat{
|
|
Mountpoint: path,
|
|
Device: path,
|
|
Fstype: string(bytes.Replace(lpFileSystemNameBuffer, []byte("\x00"), []byte(""), -1)),
|
|
Opts: opts,
|
|
}
|
|
ret = append(ret, d)
|
|
}
|
|
}
|
|
}
|
|
return ret, nil
|
|
}
|
|
|
|
func IOCounters(names ...string) (map[string]IOCountersStat, error) {
|
|
return IOCountersWithContext(context.Background(), names...)
|
|
}
|
|
|
|
func IOCountersWithContext(ctx context.Context, names ...string) (map[string]IOCountersStat, error) {
|
|
// https://github.com/giampaolo/psutil/blob/544e9daa4f66a9f80d7bf6c7886d693ee42f0a13/psutil/arch/windows/disk.c#L83
|
|
drivemap := make(map[string]IOCountersStat, 0)
|
|
var diskPerformance diskPerformance
|
|
|
|
lpBuffer := make([]uint16, 254)
|
|
lpBufferLen, err := windows.GetLogicalDriveStrings(uint32(len(lpBuffer)), &lpBuffer[0])
|
|
if err != nil {
|
|
return drivemap, err
|
|
}
|
|
for _, v := range lpBuffer[:lpBufferLen] {
|
|
if 'A' <= v && v <= 'Z' {
|
|
path := string(v) + ":"
|
|
typepath, _ := windows.UTF16PtrFromString(path)
|
|
typeret := windows.GetDriveType(typepath)
|
|
if typeret == 0 {
|
|
return drivemap, windows.GetLastError()
|
|
}
|
|
if typeret != windows.DRIVE_FIXED {
|
|
continue
|
|
}
|
|
szDevice := fmt.Sprintf(`\\.\%s`, 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 {
|
|
continue
|
|
}
|
|
return drivemap, err
|
|
}
|
|
defer windows.CloseHandle(h)
|
|
|
|
var diskPerformanceSize uint32
|
|
err = windows.DeviceIoControl(h, IOCTL_DISK_PERFORMANCE, nil, 0, (*byte)(unsafe.Pointer(&diskPerformance)), uint32(unsafe.Sizeof(diskPerformance)), &diskPerformanceSize, nil)
|
|
if err != nil {
|
|
return drivemap, err
|
|
}
|
|
drivemap[path] = IOCountersStat{
|
|
ReadBytes: uint64(diskPerformance.BytesRead),
|
|
WriteBytes: uint64(diskPerformance.BytesWritten),
|
|
ReadCount: uint64(diskPerformance.ReadCount),
|
|
WriteCount: uint64(diskPerformance.WriteCount),
|
|
ReadTime: uint64(diskPerformance.ReadTime / 10000 / 1000), // convert to ms: https://github.com/giampaolo/psutil/issues/1012
|
|
WriteTime: uint64(diskPerformance.WriteTime / 10000 / 1000),
|
|
Name: path,
|
|
}
|
|
}
|
|
}
|
|
return drivemap, nil
|
|
}
|