windows: add GetDiskFreeSpaceEx function
ref:
https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getdiskfreespaceexw
Change-Id: If57b0777106a2253e4287818d2c5aee2d6be13d3
Reviewed-on: https://go-review.googlesource.com/c/sys/+/200257
Run-TryBot: Jason A. Donenfeld <Jason@zx2c4.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Jason A. Donenfeld <Jason@zx2c4.com>
diff --git a/windows/syscall_windows.go b/windows/syscall_windows.go
index 33513e3..df0ffc6 100644
--- a/windows/syscall_windows.go
+++ b/windows/syscall_windows.go
@@ -290,6 +290,7 @@
//sys FindNextVolumeMountPoint(findVolumeMountPoint Handle, volumeMountPoint *uint16, bufferLength uint32) (err error) = FindNextVolumeMountPointW
//sys FindVolumeClose(findVolume Handle) (err error)
//sys FindVolumeMountPointClose(findVolumeMountPoint Handle) (err error)
+//sys GetDiskFreeSpaceEx(directoryName *uint16, freeBytesAvailableToCaller *uint64, totalNumberOfBytes *uint64, totalNumberOfFreeBytes *uint64) (err error) = GetDiskFreeSpaceExW
//sys GetDriveType(rootPathName *uint16) (driveType uint32) = GetDriveTypeW
//sys GetLogicalDrives() (drivesBitMask uint32, err error) [failretval==0]
//sys GetLogicalDriveStrings(bufferLength uint32, buffer *uint16) (n uint32, err error) [failretval==0] = GetLogicalDriveStringsW
diff --git a/windows/syscall_windows_test.go b/windows/syscall_windows_test.go
index a63df60..7f23216 100644
--- a/windows/syscall_windows_test.go
+++ b/windows/syscall_windows_test.go
@@ -356,3 +356,24 @@
t.Fatalf("SD = %q; want %q", got, want)
}
}
+
+func TestGetDiskFreeSpaceEx(t *testing.T) {
+ cwd, err := windows.UTF16PtrFromString(".")
+ if err != nil {
+ t.Fatalf(`failed to call UTF16PtrFromString("."): %v`, err)
+ }
+ var freeBytesAvailableToCaller, totalNumberOfBytes, totalNumberOfFreeBytes uint64
+ if err := windows.GetDiskFreeSpaceEx(cwd, &freeBytesAvailableToCaller, &totalNumberOfBytes, &totalNumberOfFreeBytes); err != nil {
+ t.Fatalf("failed to call GetDiskFreeSpaceEx: %v", err)
+ }
+
+ if freeBytesAvailableToCaller == 0 {
+ t.Errorf("freeBytesAvailableToCaller: got 0; want > 0")
+ }
+ if totalNumberOfBytes == 0 {
+ t.Errorf("totalNumberOfBytes: got 0; want > 0")
+ }
+ if totalNumberOfFreeBytes == 0 {
+ t.Errorf("totalNumberOfFreeBytes: got 0; want > 0")
+ }
+}
diff --git a/windows/zsyscall_windows.go b/windows/zsyscall_windows.go
index ace2c19..74d721e 100644
--- a/windows/zsyscall_windows.go
+++ b/windows/zsyscall_windows.go
@@ -224,6 +224,7 @@
procFindNextVolumeMountPointW = modkernel32.NewProc("FindNextVolumeMountPointW")
procFindVolumeClose = modkernel32.NewProc("FindVolumeClose")
procFindVolumeMountPointClose = modkernel32.NewProc("FindVolumeMountPointClose")
+ procGetDiskFreeSpaceExW = modkernel32.NewProc("GetDiskFreeSpaceExW")
procGetDriveTypeW = modkernel32.NewProc("GetDriveTypeW")
procGetLogicalDrives = modkernel32.NewProc("GetLogicalDrives")
procGetLogicalDriveStringsW = modkernel32.NewProc("GetLogicalDriveStringsW")
@@ -2503,6 +2504,18 @@
return
}
+func GetDiskFreeSpaceEx(directoryName *uint16, freeBytesAvailableToCaller *uint64, totalNumberOfBytes *uint64, totalNumberOfFreeBytes *uint64) (err error) {
+ r1, _, e1 := syscall.Syscall6(procGetDiskFreeSpaceExW.Addr(), 4, uintptr(unsafe.Pointer(directoryName)), uintptr(unsafe.Pointer(freeBytesAvailableToCaller)), uintptr(unsafe.Pointer(totalNumberOfBytes)), uintptr(unsafe.Pointer(totalNumberOfFreeBytes)), 0, 0)
+ if r1 == 0 {
+ if e1 != 0 {
+ err = errnoErr(e1)
+ } else {
+ err = syscall.EINVAL
+ }
+ }
+ return
+}
+
func GetDriveType(rootPathName *uint16) (driveType uint32) {
r0, _, _ := syscall.Syscall(procGetDriveTypeW.Addr(), 1, uintptr(unsafe.Pointer(rootPathName)), 0, 0)
driveType = uint32(r0)