forked from rosa/hakurei
This is a pretty solid implementation backed by robust tests, with a much cleaner interface. Signed-off-by: Ophestra <cat@gensokyo.uk>
58 lines
1.3 KiB
Go
58 lines
1.3 KiB
Go
// Copyright 2018 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
//go:build windows
|
|
|
|
package filelock
|
|
|
|
import (
|
|
"internal/syscall/windows"
|
|
"io/fs"
|
|
"syscall"
|
|
)
|
|
|
|
type lockType uint32
|
|
|
|
const (
|
|
readLock lockType = 0
|
|
writeLock lockType = windows.LOCKFILE_EXCLUSIVE_LOCK
|
|
)
|
|
|
|
const (
|
|
reserved = 0
|
|
allBytes = ^uint32(0)
|
|
)
|
|
|
|
func lock(f File, lt lockType) error {
|
|
// Per https://golang.org/issue/19098, “Programs currently expect the Fd
|
|
// method to return a handle that uses ordinary synchronous I/O.”
|
|
// However, LockFileEx still requires an OVERLAPPED structure,
|
|
// which contains the file offset of the beginning of the lock range.
|
|
// We want to lock the entire file, so we leave the offset as zero.
|
|
ol := new(syscall.Overlapped)
|
|
|
|
err := windows.LockFileEx(syscall.Handle(f.Fd()), uint32(lt), reserved, allBytes, allBytes, ol)
|
|
if err != nil {
|
|
return &fs.PathError{
|
|
Op: lt.String(),
|
|
Path: f.Name(),
|
|
Err: err,
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func unlock(f File) error {
|
|
ol := new(syscall.Overlapped)
|
|
err := windows.UnlockFileEx(syscall.Handle(f.Fd()), reserved, allBytes, allBytes, ol)
|
|
if err != nil {
|
|
return &fs.PathError{
|
|
Op: "Unlock",
|
|
Path: f.Name(),
|
|
Err: err,
|
|
}
|
|
}
|
|
return nil
|
|
}
|