// flock acquires an advisory lock on a file descriptor. func flock(f *os.File, exclusive bool, timeout time.Duration) error { var t time.Time for { // If we're beyond our timeout then return an error. // This can only occur after we've attempted a flock once. if t.IsZero() { t = time.Now() } else if timeout > 0 && time.Since(t) > timeout { return ErrTimeout } var lock syscall.Flock_t lock.Start = 0 lock.Len = 0 lock.Pid = 0 lock.Whence = 0 lock.Pid = 0 if exclusive { lock.Type = syscall.F_WRLCK } else { lock.Type = syscall.F_RDLCK } err := syscall.FcntlFlock(f.Fd(), syscall.F_SETLK, &lock) if err == nil { return nil } else if err != syscall.EAGAIN { return err } // Wait for a bit and try again. time.Sleep(50 * time.Millisecond) } }
func setFileLock(f *os.File, readOnly, lock bool) error { flock := syscall.Flock_t{ Type: syscall.F_UNLCK, Start: 0, Len: 0, Whence: 1, } if lock { if readOnly { flock.Type = syscall.F_RDLCK } else { flock.Type = syscall.F_WRLCK } } return syscall.FcntlFlock(f.Fd(), syscall.F_SETLK, &flock) }
// funlock releases an advisory lock on a file descriptor. func funlock(f *os.File) error { var lock syscall.Flock_t lock.Start = 0 lock.Len = 0 lock.Type = syscall.F_UNLCK lock.Whence = 0 return syscall.FcntlFlock(uintptr(f.Fd()), syscall.F_SETLK, &lock) }
// Unlock an open file. Unlocking errors are ignored. func Unlock(file *os.File, lk *syscall.Flock_t) error { if lk == nil || file == nil { return fmt.Errorf("file or lock are nil file: %s lk: %v", file.Name(), lk) } lk.Type = syscall.F_UNLCK return syscall.FcntlFlock(file.Fd(), syscall.F_SETLK, lk) }
// Lock acquires exclusivity on the lock without blocking func (l *lock) Lock() error { var lock syscall.Flock_t lock.Start = 0 lock.Len = 0 lock.Type = syscall.F_WRLCK lock.Whence = 0 lock.Pid = 0 return syscall.FcntlFlock(uintptr(l.fd), syscall.F_SETLK, &lock) }
func (l *unixLock) set(lock bool) error { flock := syscall.Flock_t{ Type: syscall.F_UNLCK, Start: 0, Len: 0, Whence: 1, } if lock { flock.Type = syscall.F_WRLCK } return syscall.FcntlFlock(l.f.Fd(), syscall.F_SETLK, &flock) }
// Unlock unlocks the lock func (l *lock) Unlock() error { var lock syscall.Flock_t lock.Start = 0 lock.Len = 0 lock.Type = syscall.F_UNLCK lock.Whence = 0 err := syscall.FcntlFlock(uintptr(l.fd), syscall.F_SETLK, &lock) if err != nil && err == syscall.EAGAIN { return ErrLocked } return err }
func LockFile(path string, flag int, perm os.FileMode) (*LockedFile, error) { var lock syscall.Flock_t lock.Start = 0 lock.Len = 0 lock.Pid = 0 lock.Type = syscall.F_WRLCK lock.Whence = 0 f, err := os.OpenFile(path, flag, perm) if err != nil { return nil, err } if err = syscall.FcntlFlock(f.Fd(), syscall.F_SETLKW, &lock); err != nil { f.Close() return nil, err } return &LockedFile{f}, nil }