mirror of
https://github.com/linuxkit/linuxkit.git
synced 2025-07-19 09:16:29 +00:00
create filelock utility
Signed-off-by: Avi Deitcher <avi@deitcher.net>
This commit is contained in:
parent
0e3147e387
commit
e6a1de1330
9
src/cmd/linuxkit/util/filelock.go
Normal file
9
src/cmd/linuxkit/util/filelock.go
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
package util
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
type FileLock struct {
|
||||||
|
file *os.File
|
||||||
|
}
|
19
src/cmd/linuxkit/util/filelock_other.go
Normal file
19
src/cmd/linuxkit/util/filelock_other.go
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
//go:build !unix
|
||||||
|
|
||||||
|
package util
|
||||||
|
|
||||||
|
// Lock opens the file (creating it if needed) and sets an exclusive lock.
|
||||||
|
// Returns a FileLock that can later be unlocked.
|
||||||
|
func Lock(path string) (*FileLock, error) {
|
||||||
|
return &FileLock{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unlock releases the lock and closes the file.
|
||||||
|
func (l *FileLock) Unlock() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CheckLock attempts to detect if the file is locked by another process.
|
||||||
|
func CheckLock(path string) (locked bool, holderPID int, err error) {
|
||||||
|
return false, 0, nil
|
||||||
|
}
|
101
src/cmd/linuxkit/util/filelock_unix.go
Normal file
101
src/cmd/linuxkit/util/filelock_unix.go
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
//go:build unix
|
||||||
|
|
||||||
|
package util
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Lock opens the file (creating it if needed) and sets an exclusive lock.
|
||||||
|
// Returns a FileLock that can later be unlocked.
|
||||||
|
func Lock(path string) (*FileLock, error) {
|
||||||
|
f, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE, 0644)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("open file: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
flock := unix.Flock_t{
|
||||||
|
Type: unix.F_WRLCK,
|
||||||
|
Whence: int16(io.SeekStart),
|
||||||
|
Start: 0,
|
||||||
|
Len: 0,
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := unix.FcntlFlock(f.Fd(), unix.F_SETLKW, &flock); err != nil {
|
||||||
|
_ = f.Close()
|
||||||
|
return nil, fmt.Errorf("set lock: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &FileLock{file: f}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unlock releases the lock and closes the file.
|
||||||
|
func (l *FileLock) Unlock() error {
|
||||||
|
flock := unix.Flock_t{
|
||||||
|
Type: unix.F_UNLCK,
|
||||||
|
Whence: int16(io.SeekStart),
|
||||||
|
Start: 0,
|
||||||
|
Len: 0,
|
||||||
|
}
|
||||||
|
if err := unix.FcntlFlock(l.file.Fd(), unix.F_SETLKW, &flock); err != nil {
|
||||||
|
return fmt.Errorf("unlock: %w", err)
|
||||||
|
}
|
||||||
|
return l.file.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
// CheckLock attempts to detect if the file is locked by another process.
|
||||||
|
func CheckLock(path string) (locked bool, holderPID int, err error) {
|
||||||
|
f, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE, 0644)
|
||||||
|
if err != nil {
|
||||||
|
return false, 0, fmt.Errorf("open file: %w", err)
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
_ = f.Close()
|
||||||
|
}()
|
||||||
|
|
||||||
|
check := unix.Flock_t{
|
||||||
|
Type: unix.F_WRLCK,
|
||||||
|
Whence: int16(io.SeekStart),
|
||||||
|
Start: 0,
|
||||||
|
Len: 0,
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := unix.FcntlFlock(f.Fd(), unix.F_GETLK, &check); err != nil {
|
||||||
|
return false, 0, fmt.Errorf("get lock: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if check.Type == unix.F_UNLCK {
|
||||||
|
return false, 0, nil
|
||||||
|
}
|
||||||
|
return true, int(check.Pid), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// WaitUnlocked waits until the file is unlocked by another process, and uses it for reading but not writing.
|
||||||
|
func WaitUnlocked(path string) error {
|
||||||
|
f, err := os.OpenFile(path, os.O_RDONLY, 0644)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("open file: %w", err)
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
_ = f.Close()
|
||||||
|
}()
|
||||||
|
|
||||||
|
flock := unix.Flock_t{
|
||||||
|
Type: unix.F_RDLCK,
|
||||||
|
Whence: int16(io.SeekStart),
|
||||||
|
Start: 0,
|
||||||
|
Len: 0,
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := unix.FcntlFlock(f.Fd(), unix.F_SETLKW, &flock); err != nil {
|
||||||
|
_ = f.Close()
|
||||||
|
return fmt.Errorf("set lock: %w", err)
|
||||||
|
}
|
||||||
|
fileRef := &FileLock{file: f}
|
||||||
|
_ = fileRef.Unlock()
|
||||||
|
return nil
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user