1// Copyright 2018 The Go Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style 3// license that can be found in the LICENSE file. 4 5// Package filelock provides a platform-independent API for advisory file 6// locking. Calls to functions in this package on platforms that do not support 7// advisory locks will return errors for which IsNotSupported returns true. 8package filelock 9 10import ( 11 "errors" 12 "os" 13) 14 15// A File provides the minimal set of methods required to lock an open file. 16// File implementations must be usable as map keys. 17// The usual implementation is *os.File. 18type File interface { 19 // Name returns the name of the file. 20 Name() string 21 22 // Fd returns a valid file descriptor. 23 // (If the File is an *os.File, it must not be closed.) 24 Fd() uintptr 25 26 // Stat returns the FileInfo structure describing file. 27 Stat() (os.FileInfo, error) 28} 29 30// Lock places an advisory write lock on the file, blocking until it can be 31// locked. 32// 33// If Lock returns nil, no other process will be able to place a read or write 34// lock on the file until this process exits, closes f, or calls Unlock on it. 35// 36// If f's descriptor is already read- or write-locked, the behavior of Lock is 37// unspecified. 38// 39// Closing the file may or may not release the lock promptly. Callers should 40// ensure that Unlock is always called when Lock succeeds. 41func Lock(f File) error { 42 return lock(f, writeLock) 43} 44 45// RLock places an advisory read lock on the file, blocking until it can be locked. 46// 47// If RLock returns nil, no other process will be able to place a write lock on 48// the file until this process exits, closes f, or calls Unlock on it. 49// 50// If f is already read- or write-locked, the behavior of RLock is unspecified. 51// 52// Closing the file may or may not release the lock promptly. Callers should 53// ensure that Unlock is always called if RLock succeeds. 54func RLock(f File) error { 55 return lock(f, readLock) 56} 57 58// Unlock removes an advisory lock placed on f by this process. 59// 60// The caller must not attempt to unlock a file that is not locked. 61func Unlock(f File) error { 62 return unlock(f) 63} 64 65// String returns the name of the function corresponding to lt 66// (Lock, RLock, or Unlock). 67func (lt lockType) String() string { 68 switch lt { 69 case readLock: 70 return "RLock" 71 case writeLock: 72 return "Lock" 73 default: 74 return "Unlock" 75 } 76} 77 78// IsNotSupported returns a boolean indicating whether the error is known to 79// report that a function is not supported (possibly for a specific input). 80// It is satisfied by ErrNotSupported as well as some syscall errors. 81func IsNotSupported(err error) bool { 82 return isNotSupported(underlyingError(err)) 83} 84 85var ErrNotSupported = errors.New("operation not supported") 86 87// underlyingError returns the underlying error for known os error types. 88func underlyingError(err error) error { 89 switch err := err.(type) { 90 case *os.PathError: 91 return err.Err 92 case *os.LinkError: 93 return err.Err 94 case *os.SyscallError: 95 return err.Err 96 } 97 return err 98} 99