github.com/searKing/golang/go@v1.2.74/os/disk_windows.go (about) 1 // Copyright 2022 The searKing Author. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 //go:build windows 6 // +build windows 7 8 package os 9 10 import ( 11 "fmt" 12 "os" 13 "syscall" 14 "unsafe" 15 16 "golang.org/x/sys/windows" 17 ) 18 19 var ( 20 kernel32 = windows.NewLazySystemDLL("kernel32.dll") 21 22 // GetDiskFreeSpaceEx - https://msdn.microsoft.com/en-us/library/windows/desktop/aa364937(v=vs.85).aspx 23 // Retrieves information about the amount of space that is available on a disk volume, 24 // which is the total amount of space, the total amount of free space, and the total 25 // amount of free space available to the user that is associated with the calling thread. 26 GetDiskFreeSpaceEx = kernel32.NewProc("GetDiskFreeSpaceExW") 27 28 // GetDiskFreeSpace - https://msdn.microsoft.com/en-us/library/windows/desktop/aa364935(v=vs.85).aspx 29 // Retrieves information about the specified disk, including the amount of free space on the disk. 30 GetDiskFreeSpace = kernel32.NewProc("GetDiskFreeSpaceW") 31 ) 32 33 // DiskUsage returns total and free bytes available in a directory, e.g. `C:\`. 34 // It returns free space available to the user (including quota limitations) 35 // 36 // https://msdn.microsoft.com/en-us/library/windows/desktop/aa364937(v=vs.85).aspx 37 func DiskUsage(path string) (total uint64, free uint64, avail uint64, inodes uint64, inodesFree uint64, err error) { 38 // Stat to know if the path exists. 39 if _, err = os.Stat(path); err != nil { 40 return 0, 0, 0, 0, 0, err 41 } 42 43 lpFreeBytesAvailable := int64(0) 44 lpTotalNumberOfBytes := int64(0) 45 lpTotalNumberOfFreeBytes := int64(0) 46 47 // Extract values safely 48 // BOOL WINAPI GetDiskFreeSpaceEx( 49 // _In_opt_ LPCTSTR lpDirectoryName, 50 // _Out_opt_ PULARGE_INTEGER lpFreeBytesAvailable, 51 // _Out_opt_ PULARGE_INTEGER lpTotalNumberOfBytes, 52 // _Out_opt_ PULARGE_INTEGER lpTotalNumberOfFreeBytes 53 // ); 54 _, _, _ = GetDiskFreeSpaceEx.Call(uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(path))), 55 uintptr(unsafe.Pointer(&lpFreeBytesAvailable)), 56 uintptr(unsafe.Pointer(&lpTotalNumberOfBytes)), 57 uintptr(unsafe.Pointer(&lpTotalNumberOfFreeBytes))) 58 59 if uint64(lpTotalNumberOfFreeBytes) > uint64(lpTotalNumberOfBytes) { 60 return 0, 0, 0, 0, 0, fmt.Errorf("detected free space (%d) > total disk space (%d), fs corruption at (%s). please run 'fsck'", 61 uint64(lpTotalNumberOfFreeBytes), uint64(lpTotalNumberOfBytes), path) 62 } 63 64 // Return values of GetDiskFreeSpace() 65 lpSectorsPerCluster := uint32(0) 66 lpBytesPerSector := uint32(0) 67 lpNumberOfFreeClusters := uint32(0) 68 lpTotalNumberOfClusters := uint32(0) 69 70 // Extract values safely 71 // BOOL WINAPI GetDiskFreeSpace( 72 // _In_ LPCTSTR lpRootPathName, 73 // _Out_ LPDWORD lpSectorsPerCluster, 74 // _Out_ LPDWORD lpBytesPerSector, 75 // _Out_ LPDWORD lpNumberOfFreeClusters, 76 // _Out_ LPDWORD lpTotalNumberOfClusters 77 // ); 78 _, _, _ = GetDiskFreeSpace.Call(uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(path))), 79 uintptr(unsafe.Pointer(&lpSectorsPerCluster)), 80 uintptr(unsafe.Pointer(&lpBytesPerSector)), 81 uintptr(unsafe.Pointer(&lpNumberOfFreeClusters)), 82 uintptr(unsafe.Pointer(&lpTotalNumberOfClusters))) 83 84 return uint64(lpTotalNumberOfBytes), uint64(lpTotalNumberOfFreeBytes), lpFreeBytesAvailable, uint64(lpTotalNumberOfClusters), uint64(lpNumberOfFreeClusters), err 85 }