github.com/guyezi/gofrontend@v0.0.0-20200228202240-7a62a49e62c0/libgo/go/os/error.go (about) 1 // Copyright 2009 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 os 6 7 import ( 8 "internal/oserror" 9 "internal/poll" 10 ) 11 12 // Portable analogs of some common system call errors. 13 // 14 // Errors returned from this package may be tested against these errors 15 // with errors.Is. 16 var ( 17 // ErrInvalid indicates an invalid argument. 18 // Methods on File will return this error when the receiver is nil. 19 ErrInvalid = errInvalid() // "invalid argument" 20 21 ErrPermission = errPermission() // "permission denied" 22 ErrExist = errExist() // "file already exists" 23 ErrNotExist = errNotExist() // "file does not exist" 24 ErrClosed = errClosed() // "file already closed" 25 ErrNoDeadline = errNoDeadline() // "file type does not support deadline" 26 ) 27 28 func errInvalid() error { return oserror.ErrInvalid } 29 func errPermission() error { return oserror.ErrPermission } 30 func errExist() error { return oserror.ErrExist } 31 func errNotExist() error { return oserror.ErrNotExist } 32 func errClosed() error { return oserror.ErrClosed } 33 func errNoDeadline() error { return poll.ErrNoDeadline } 34 35 type timeout interface { 36 Timeout() bool 37 } 38 39 // PathError records an error and the operation and file path that caused it. 40 type PathError struct { 41 Op string 42 Path string 43 Err error 44 } 45 46 func (e *PathError) Error() string { return e.Op + " " + e.Path + ": " + e.Err.Error() } 47 48 func (e *PathError) Unwrap() error { return e.Err } 49 50 // Timeout reports whether this error represents a timeout. 51 func (e *PathError) Timeout() bool { 52 t, ok := e.Err.(timeout) 53 return ok && t.Timeout() 54 } 55 56 // SyscallError records an error from a specific system call. 57 type SyscallError struct { 58 Syscall string 59 Err error 60 } 61 62 func (e *SyscallError) Error() string { return e.Syscall + ": " + e.Err.Error() } 63 64 func (e *SyscallError) Unwrap() error { return e.Err } 65 66 // Timeout reports whether this error represents a timeout. 67 func (e *SyscallError) Timeout() bool { 68 t, ok := e.Err.(timeout) 69 return ok && t.Timeout() 70 } 71 72 // NewSyscallError returns, as an error, a new SyscallError 73 // with the given system call name and error details. 74 // As a convenience, if err is nil, NewSyscallError returns nil. 75 func NewSyscallError(syscall string, err error) error { 76 if err == nil { 77 return nil 78 } 79 return &SyscallError{syscall, err} 80 } 81 82 // IsExist returns a boolean indicating whether the error is known to report 83 // that a file or directory already exists. It is satisfied by ErrExist as 84 // well as some syscall errors. 85 func IsExist(err error) bool { 86 return underlyingErrorIs(err, ErrExist) 87 } 88 89 // IsNotExist returns a boolean indicating whether the error is known to 90 // report that a file or directory does not exist. It is satisfied by 91 // ErrNotExist as well as some syscall errors. 92 func IsNotExist(err error) bool { 93 return underlyingErrorIs(err, ErrNotExist) 94 } 95 96 // IsPermission returns a boolean indicating whether the error is known to 97 // report that permission is denied. It is satisfied by ErrPermission as well 98 // as some syscall errors. 99 func IsPermission(err error) bool { 100 return underlyingErrorIs(err, ErrPermission) 101 } 102 103 // IsTimeout returns a boolean indicating whether the error is known 104 // to report that a timeout occurred. 105 func IsTimeout(err error) bool { 106 terr, ok := underlyingError(err).(timeout) 107 return ok && terr.Timeout() 108 } 109 110 func underlyingErrorIs(err, target error) bool { 111 // Note that this function is not errors.Is: 112 // underlyingError only unwraps the specific error-wrapping types 113 // that it historically did, not all errors implementing Unwrap(). 114 err = underlyingError(err) 115 if err == target { 116 return true 117 } 118 // To preserve prior behavior, only examine syscall errors. 119 e, ok := err.(syscallErrorType) 120 return ok && e.Is(target) 121 } 122 123 // underlyingError returns the underlying error for known os error types. 124 func underlyingError(err error) error { 125 switch err := err.(type) { 126 case *PathError: 127 return err.Err 128 case *LinkError: 129 return err.Err 130 case *SyscallError: 131 return err.Err 132 } 133 return err 134 }