forked from rosa/hakurei
internal/app/state: use internal/lockedfile
This is a pretty solid implementation backed by robust tests, with a much cleaner interface. Signed-off-by: Ophestra <cat@gensokyo.uk>
This commit is contained in:
@@ -0,0 +1,57 @@
|
||||
// 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
|
||||
}
|
||||
Reference in New Issue
Block a user