github.com/sunvim/utils@v0.1.0/fs/os_windows.go (about) 1 //go:build windows 2 3 package fs 4 5 import ( 6 "os" 7 "syscall" 8 "unsafe" 9 ) 10 11 var ( 12 modkernel32 = syscall.NewLazyDLL("kernel32.dll") 13 procLockFileEx = modkernel32.NewProc("LockFileEx") 14 ) 15 16 const ( 17 errorLockViolation = 0x21 18 ) 19 20 func lockfile(f *os.File) error { 21 var ol syscall.Overlapped 22 23 r1, _, err := syscall.Syscall6( 24 procLockFileEx.Addr(), 25 6, 26 uintptr(f.Fd()), // handle 27 uintptr(0x0003), 28 uintptr(0), // reserved 29 uintptr(1), // locklow 30 uintptr(0), // lockhigh 31 uintptr(unsafe.Pointer(&ol)), 32 ) 33 if r1 == 0 && (err == syscall.ERROR_FILE_EXISTS || err == errorLockViolation) { 34 return os.ErrExist 35 } 36 return nil 37 } 38 39 func createLockFile(name string, perm os.FileMode) (LockFile, bool, error) { 40 acquiredExisting := false 41 if _, err := os.Stat(name); err == nil { 42 acquiredExisting = true 43 } 44 fd, err := syscall.CreateFile(&(syscall.StringToUTF16(name)[0]), 45 syscall.GENERIC_READ|syscall.GENERIC_WRITE, 46 syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE|syscall.FILE_SHARE_DELETE, 47 nil, 48 syscall.CREATE_ALWAYS, 49 syscall.FILE_ATTRIBUTE_NORMAL, 50 0) 51 if err != nil { 52 return nil, false, os.ErrExist 53 } 54 f := os.NewFile(uintptr(fd), name) 55 if err := lockfile(f); err != nil { 56 f.Close() 57 return nil, false, err 58 } 59 return &osLockFile{f, name}, acquiredExisting, nil 60 }