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