github.com/gagliardetto/golang-go@v0.0.0-20201020153340-53909ea70814/cmd/go/not-internal/lockedfile/internal/filelock/filelock.go (about) 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. 8 package filelock 9 10 import ( 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. 18 type 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. 41 func 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. 54 func 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. 61 func 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). 67 func (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. 81 func IsNotSupported(err error) bool { 82 return isNotSupported(underlyingError(err)) 83 } 84 85 var ErrNotSupported = errors.New("operation not supported") 86 87 // underlyingError returns the underlying error for known os error types. 88 func 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 }