github.com/rstandt/terraform@v0.12.32-0.20230710220336-b1063613405c/states/statemgr/filesystem_lock_windows.go (about) 1 // +build windows 2 3 package statemgr 4 5 import ( 6 "log" 7 "math" 8 "syscall" 9 "unsafe" 10 ) 11 12 var ( 13 modkernel32 = syscall.NewLazyDLL("kernel32.dll") 14 procLockFileEx = modkernel32.NewProc("LockFileEx") 15 procCreateEventW = modkernel32.NewProc("CreateEventW") 16 ) 17 18 const ( 19 // dwFlags defined for LockFileEx 20 // https://msdn.microsoft.com/en-us/library/windows/desktop/aa365203(v=vs.85).aspx 21 _LOCKFILE_FAIL_IMMEDIATELY = 1 22 _LOCKFILE_EXCLUSIVE_LOCK = 2 23 ) 24 25 func (s *Filesystem) lock() error { 26 log.Printf("[TRACE] statemgr.Filesystem: locking %s using LockFileEx", s.path) 27 28 // even though we're failing immediately, an overlapped event structure is 29 // required 30 ol, err := newOverlapped() 31 if err != nil { 32 return err 33 } 34 defer syscall.CloseHandle(ol.HEvent) 35 36 return lockFileEx( 37 syscall.Handle(s.stateFileOut.Fd()), 38 _LOCKFILE_EXCLUSIVE_LOCK|_LOCKFILE_FAIL_IMMEDIATELY, 39 0, // reserved 40 0, // bytes low 41 math.MaxUint32, // bytes high 42 ol, 43 ) 44 } 45 46 func (s *Filesystem) unlock() error { 47 log.Printf("[TRACE] statemgr.Filesystem: unlocked by closing %s", s.path) 48 49 // the file is closed in Unlock 50 return nil 51 } 52 53 func lockFileEx(h syscall.Handle, flags, reserved, locklow, lockhigh uint32, ol *syscall.Overlapped) (err error) { 54 r1, _, e1 := syscall.Syscall6( 55 procLockFileEx.Addr(), 56 6, 57 uintptr(h), 58 uintptr(flags), 59 uintptr(reserved), 60 uintptr(locklow), 61 uintptr(lockhigh), 62 uintptr(unsafe.Pointer(ol)), 63 ) 64 if r1 == 0 { 65 if e1 != 0 { 66 err = error(e1) 67 } else { 68 err = syscall.EINVAL 69 } 70 } 71 return 72 } 73 74 // newOverlapped creates a structure used to track asynchronous 75 // I/O requests that have been issued. 76 func newOverlapped() (*syscall.Overlapped, error) { 77 event, err := createEvent(nil, true, false, nil) 78 if err != nil { 79 return nil, err 80 } 81 return &syscall.Overlapped{HEvent: event}, nil 82 } 83 84 func createEvent(sa *syscall.SecurityAttributes, manualReset bool, initialState bool, name *uint16) (handle syscall.Handle, err error) { 85 var _p0 uint32 86 if manualReset { 87 _p0 = 1 88 } 89 var _p1 uint32 90 if initialState { 91 _p1 = 1 92 } 93 94 r0, _, e1 := syscall.Syscall6( 95 procCreateEventW.Addr(), 96 4, 97 uintptr(unsafe.Pointer(sa)), 98 uintptr(_p0), 99 uintptr(_p1), 100 uintptr(unsafe.Pointer(name)), 101 0, 102 0, 103 ) 104 handle = syscall.Handle(r0) 105 if handle == syscall.InvalidHandle { 106 if e1 != 0 { 107 err = error(e1) 108 } else { 109 err = syscall.EINVAL 110 } 111 } 112 return 113 }