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