shirou_gopsutil/disk/disk_windows.go

156 lines
4.4 KiB
Go
Raw Normal View History

2014-04-18 20:28:00 +08:00
// +build windows
2014-12-30 21:09:05 +08:00
package disk
2014-04-18 20:28:00 +08:00
2014-04-19 23:03:47 +08:00
import (
2014-04-20 00:53:34 +08:00
"bytes"
2014-04-19 23:03:47 +08:00
"syscall"
"unsafe"
"github.com/StackExchange/wmi"
2015-10-19 23:04:57 +08:00
"github.com/shirou/gopsutil/internal/common"
2014-04-19 23:03:47 +08:00
)
var (
2014-11-27 21:28:05 +08:00
procGetDiskFreeSpaceExW = common.Modkernel32.NewProc("GetDiskFreeSpaceExW")
procGetLogicalDriveStringsW = common.Modkernel32.NewProc("GetLogicalDriveStringsW")
procGetDriveType = common.Modkernel32.NewProc("GetDriveTypeW")
provGetVolumeInformation = common.Modkernel32.NewProc("GetVolumeInformationW")
2014-04-20 00:53:34 +08:00
)
var (
2014-08-16 02:05:26 +08:00
FileFileCompression = int64(16) // 0x00000010
FileReadOnlyVolume = int64(524288) // 0x00080000
2014-04-19 23:03:47 +08:00
)
2014-04-18 20:28:00 +08:00
type Win32_PerfFormattedData struct {
Name string
AvgDiskBytesPerRead uint64
AvgDiskBytesPerWrite uint64
AvgDiskReadQueueLength uint64
AvgDiskWriteQueueLength uint64
AvgDisksecPerRead uint64
AvgDisksecPerWrite uint64
}
const WaitMSec = 500
func Usage(path string) (*UsageStat, error) {
ret := &UsageStat{}
2014-04-18 20:28:00 +08:00
2014-04-19 23:03:47 +08:00
lpFreeBytesAvailable := int64(0)
lpTotalNumberOfBytes := int64(0)
lpTotalNumberOfFreeBytes := int64(0)
2014-04-20 00:53:34 +08:00
diskret, _, err := procGetDiskFreeSpaceExW.Call(
2014-04-19 23:03:47 +08:00
uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(path))),
uintptr(unsafe.Pointer(&lpFreeBytesAvailable)),
uintptr(unsafe.Pointer(&lpTotalNumberOfBytes)),
uintptr(unsafe.Pointer(&lpTotalNumberOfFreeBytes)))
if diskret == 0 {
2015-08-27 23:51:03 +08:00
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,
2015-08-27 23:51:03 +08:00
// InodesTotal: 0,
// InodesFree: 0,
// InodesUsed: 0,
// InodesUsedPercent: 0,
2014-04-19 23:03:47 +08:00
}
2014-04-18 20:28:00 +08:00
return ret, nil
}
2014-04-20 00:53:34 +08:00
func Partitions(all bool) ([]PartitionStat, error) {
var ret []PartitionStat
2014-04-20 00:53:34 +08:00
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) + ":"
if path == "A:" || path == "B:" { // skip floppy drives
continue
}
typepath, _ := syscall.UTF16PtrFromString(path)
typeret, _, _ := procGetDriveType.Call(uintptr(unsafe.Pointer(typepath)))
if typeret == 0 {
return ret, syscall.GetLastError()
}
// 2: DRIVE_REMOVABLE 3: DRIVE_FIXED 5: DRIVE_CDROM
if typeret == 2 || typeret == 3 || typeret == 5 {
lpVolumeNameBuffer := make([]byte, 256)
lpVolumeSerialNumber := int64(0)
lpMaximumComponentLength := int64(0)
lpFileSystemFlags := int64(0)
lpFileSystemNameBuffer := make([]byte, 256)
volpath, _ := syscall.UTF16PtrFromString(string(v) + ":/")
driveret, _, err := provGetVolumeInformation.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 {
continue //device is not ready will happen if there is no disk in the drive
}
2014-04-20 00:53:34 +08:00
return ret, err
}
opts := "rw"
2014-08-16 02:05:26 +08:00
if lpFileSystemFlags&FileReadOnlyVolume != 0 {
2014-04-20 00:53:34 +08:00
opts = "ro"
}
2014-08-16 02:05:26 +08:00
if lpFileSystemFlags&FileFileCompression != 0 {
2014-04-20 00:53:34 +08:00
opts += ".compress"
}
d := PartitionStat{
2014-04-20 00:53:34 +08:00
Mountpoint: path,
Device: path,
Fstype: string(bytes.Replace(lpFileSystemNameBuffer, []byte("\x00"), []byte(""), -1)),
Opts: opts,
}
ret = append(ret, d)
}
}
}
return ret, nil
}
2014-04-29 13:59:22 +08:00
func IOCounters() (map[string]IOCountersStat, error) {
ret := make(map[string]IOCountersStat, 0)
var dst []Win32_PerfFormattedData
err := wmi.Query("SELECT * FROM Win32_PerfFormattedData_PerfDisk_LogicalDisk ", &dst)
if err != nil {
return ret, err
}
for _, d := range dst {
if len(d.Name) > 3 { // not get _Total or Harddrive
continue
}
ret[d.Name] = IOCountersStat{
Name: d.Name,
ReadCount: uint64(d.AvgDiskReadQueueLength),
WriteCount: d.AvgDiskWriteQueueLength,
ReadBytes: uint64(d.AvgDiskBytesPerRead),
WriteBytes: uint64(d.AvgDiskBytesPerWrite),
ReadTime: d.AvgDisksecPerRead,
WriteTime: d.AvgDisksecPerWrite,
}
}
return ret, nil
2014-04-29 13:59:22 +08:00
}