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