[disk][windows]: add context handling on PartionsWithContext

pull/1407/head
shirou 2 years ago
parent 581c27c0e6
commit 8105a6d577

@ -81,72 +81,93 @@ func UsageWithContext(ctx context.Context, path string) (*UsageStat, error) {
return ret, nil return ret, nil
} }
// PartitionsWithContext returns disk partitions.
// Since GetVolumeInformation doesn't have a timeout, this method uses context to set deadline by users.
func PartitionsWithContext(ctx context.Context, all bool) ([]PartitionStat, error) { func PartitionsWithContext(ctx context.Context, all bool) ([]PartitionStat, error) {
warnings := Warnings{ warnings := Warnings{
Verbose: true, Verbose: true,
} }
var ret []PartitionStat var ret []PartitionStat
retChan := make(chan []PartitionStat)
errChan := make(chan error)
defer close(retChan)
defer close(errChan)
lpBuffer := make([]byte, 254) lpBuffer := make([]byte, 254)
diskret, _, err := procGetLogicalDriveStringsW.Call(
uintptr(len(lpBuffer)), f := func() {
uintptr(unsafe.Pointer(&lpBuffer[0]))) diskret, _, err := procGetLogicalDriveStringsW.Call(
if diskret == 0 { uintptr(len(lpBuffer)),
return ret, err uintptr(unsafe.Pointer(&lpBuffer[0])))
} if diskret == 0 {
for _, v := range lpBuffer { errChan <- err
if v >= 65 && v <= 90 { return
path := string(v) + ":" }
typepath, _ := windows.UTF16PtrFromString(path) for _, v := range lpBuffer {
typeret, _, _ := procGetDriveType.Call(uintptr(unsafe.Pointer(typepath))) if v >= 65 && v <= 90 {
if typeret == 0 { path := string(v) + ":"
err := windows.GetLastError() typepath, _ := windows.UTF16PtrFromString(path)
warnings.Add(err) typeret, _, _ := procGetDriveType.Call(uintptr(unsafe.Pointer(typepath)))
continue if typeret == 0 {
} err := 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
}
warnings.Add(err) warnings.Add(err)
continue continue
} }
opts := []string{"rw"} // 2: DRIVE_REMOVABLE 3: DRIVE_FIXED 4: DRIVE_REMOTE 5: DRIVE_CDROM
if lpFileSystemFlags&fileReadOnlyVolume != 0 {
opts = []string{"ro"} if typeret == 2 || typeret == 3 || typeret == 4 || typeret == 5 {
} lpVolumeNameBuffer := make([]byte, 256)
if lpFileSystemFlags&fileFileCompression != 0 { lpVolumeSerialNumber := int64(0)
opts = append(opts, "compress") 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
}
warnings.Add(err)
continue
}
opts := []string{"rw"}
if lpFileSystemFlags&fileReadOnlyVolume != 0 {
opts = []string{"ro"}
}
if lpFileSystemFlags&fileFileCompression != 0 {
opts = append(opts, "compress")
}
d := PartitionStat{ d := PartitionStat{
Mountpoint: path, Mountpoint: path,
Device: path, Device: path,
Fstype: string(bytes.Replace(lpFileSystemNameBuffer, []byte("\x00"), []byte(""), -1)), Fstype: string(bytes.Replace(lpFileSystemNameBuffer, []byte("\x00"), []byte(""), -1)),
Opts: opts, Opts: opts,
}
ret = append(ret, d)
} }
ret = append(ret, d)
} }
} }
retChan <- ret
}
go f()
select {
case err := <-errChan:
return ret, err
case ret := <-retChan:
return ret, warnings.Reference()
case <-ctx.Done():
return ret, ctx.Err()
} }
return ret, warnings.Reference()
} }
func IOCountersWithContext(ctx context.Context, names ...string) (map[string]IOCountersStat, error) { func IOCountersWithContext(ctx context.Context, names ...string) (map[string]IOCountersStat, error) {

Loading…
Cancel
Save