//go:build windows package lockfile import ( "errors" "os" "syscall" "golang.org/x/sys/windows" ) var errDaemonLocked = errors.New("daemon lock already held by another process") // flockExclusive acquires an exclusive non-blocking lock on the file using LockFileEx func flockExclusive(f *os.File) error { // LOCKFILE_EXCLUSIVE_LOCK (2) | LOCKFILE_FAIL_IMMEDIATELY (1) = 3 const flags = windows.LOCKFILE_EXCLUSIVE_LOCK | windows.LOCKFILE_FAIL_IMMEDIATELY // Create overlapped structure for the entire file ol := &windows.Overlapped{} // Lock entire file (0xFFFFFFFF, 0xFFFFFFFF = maximum range) err := windows.LockFileEx( windows.Handle(f.Fd()), flags, 0, // reserved 0xFFFFFFFF, // number of bytes to lock (low) 0xFFFFFFFF, // number of bytes to lock (high) ol, ) if err == windows.ERROR_LOCK_VIOLATION || err == syscall.EWOULDBLOCK { return errDaemonLocked } return err } // FlockExclusiveBlocking acquires an exclusive blocking lock on the file. // This will wait until the lock is available. func FlockExclusiveBlocking(f *os.File) error { // LOCKFILE_EXCLUSIVE_LOCK only (no FAIL_IMMEDIATELY = blocking) const flags = windows.LOCKFILE_EXCLUSIVE_LOCK ol := &windows.Overlapped{} return windows.LockFileEx( windows.Handle(f.Fd()), flags, 0, 0xFFFFFFFF, 0xFFFFFFFF, ol, ) } // FlockUnlock releases a lock on the file. func FlockUnlock(f *os.File) error { ol := &windows.Overlapped{} return windows.UnlockFileEx( windows.Handle(f.Fd()), 0, 0xFFFFFFFF, 0xFFFFFFFF, ol, ) }