11package repo
22
33import (
4+ "errors"
45 "syscall"
6+ "unsafe"
57
68 "github.com/itchio/ox/syscallex"
79 "github.com/itchio/ox/winox"
10+ "golang.org/x/sys/windows"
811)
912
1013var (
1114 advapi32DLL = syscall .NewLazyDLL ("advapi32.dll" )
1215 impersonateSelfProc = advapi32DLL .NewProc ("ImpersonateSelf" )
16+
17+ kernel32DLL = syscall .NewLazyDLL ("kernel32.dll" )
18+ getDiskFreeSpaceExWProc = kernel32DLL .NewProc ("GetDiskFreeSpaceExW" )
1319)
1420
1521func ImpersonateSelf (impersonationLevel uint64 ) (bool , error ) {
@@ -22,6 +28,21 @@ func ImpersonateSelf(impersonationLevel uint64) (bool, error) {
2228 return syscall .Handle (r1 ) == 1 , nil
2329}
2430
31+ func GetDiskFreeSpaceExW (path string ) (int64 , error ) {
32+ var freeBytes int64
33+
34+ _ , _ , err := getDiskFreeSpaceExWProc .Call (
35+ uintptr (unsafe .Pointer (windows .StringToUTF16Ptr (path ))),
36+ uintptr (unsafe .Pointer (& freeBytes )),
37+ 0 ,
38+ 0 ,
39+ )
40+ if err != syscall .Errno (0 ) {
41+ return 0 , err
42+ }
43+ return freeBytes , nil
44+ }
45+
2546func isWritable (path string ) (bool , error ) {
2647 if _ , err := ImpersonateSelf (syscallex .SecurityImpersonation ); err != nil {
2748 return false , err
@@ -45,3 +66,11 @@ func isWritable(path string) (bool, error) {
4566
4667 return winox .UserHasPermission (impersonationToken , winox .RightsRead | winox .RightsWrite , path )
4768}
69+
70+ func getFreeSpace (path string ) (uint64 , error ) {
71+ freeBytes , err := GetDiskFreeSpaceExW (path )
72+ if err == nil && freeBytes < 0 {
73+ return 0 , errors .New ("free space can't be negative" )
74+ }
75+ return uint64 (freeBytes ), err
76+ }
0 commit comments