github.com/opentofu/opentofu@v1.7.1/internal/command/clistate/local_state_lock_windows.go (about) 1 // Copyright (c) The OpenTofu Authors 2 // SPDX-License-Identifier: MPL-2.0 3 // Copyright (c) 2023 HashiCorp, Inc. 4 // SPDX-License-Identifier: MPL-2.0 5 6 //go:build windows 7 // +build windows 8 9 package clistate 10 11 import ( 12 "math" 13 "syscall" 14 "unsafe" 15 ) 16 17 var ( 18 modkernel32 = syscall.NewLazyDLL("kernel32.dll") 19 procLockFileEx = modkernel32.NewProc("LockFileEx") 20 procCreateEventW = modkernel32.NewProc("CreateEventW") 21 ) 22 23 const ( 24 // dwFlags defined for LockFileEx 25 // https://msdn.microsoft.com/en-us/library/windows/desktop/aa365203(v=vs.85).aspx 26 _LOCKFILE_FAIL_IMMEDIATELY = 1 27 _LOCKFILE_EXCLUSIVE_LOCK = 2 28 ) 29 30 func (s *LocalState) lock() error { 31 // even though we're failing immediately, an overlapped event structure is 32 // required 33 ol, err := newOverlapped() 34 if err != nil { 35 return err 36 } 37 defer syscall.CloseHandle(ol.HEvent) 38 39 return lockFileEx( 40 syscall.Handle(s.stateFileOut.Fd()), 41 _LOCKFILE_EXCLUSIVE_LOCK|_LOCKFILE_FAIL_IMMEDIATELY, 42 0, // reserved 43 0, // bytes low 44 math.MaxUint32, // bytes high 45 ol, 46 ) 47 } 48 49 func (s *LocalState) unlock() error { 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 }