errors.mx raw

   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  	"errors"
   9  	"io/fs"
  10  	"syscall"
  11  )
  12  
  13  // Portable analogs of some common system call errors.
  14  //
  15  // Errors returned from this package may be tested against these errors
  16  // with errors.Is.
  17  var (
  18  	// ErrInvalid indicates an invalid argument.
  19  	// Methods on File will return this error when the receiver is nil.
  20  	ErrInvalid = fs.ErrInvalid // "invalid argument"
  21  
  22  	ErrPermission = fs.ErrPermission // "permission denied"
  23  	ErrExist      = fs.ErrExist      // "file already exists"
  24  	ErrNotExist   = fs.ErrNotExist   // "file does not exist"
  25  	ErrClosed     = fs.ErrClosed     // "file already closed"
  26  
  27  	// Note that these are exported for use in the Filesystem interface.
  28  	ErrUnsupported    = errors.New("operation not supported")
  29  	ErrNotImplemented = errors.New("operation not implemented")
  30  )
  31  
  32  // The following code is copied from the official implementation.
  33  // src/internal/poll/fd.go
  34  
  35  // ErrNoDeadline is returned when a request is made to set a deadline
  36  // on a file type that does not use the poller.
  37  var ErrNoDeadline = errors.New("file type does not support deadline")
  38  
  39  // ErrDeadlineExceeded is returned for an expired deadline.
  40  // This is exported by the os package as os.ErrDeadlineExceeded.
  41  var ErrDeadlineExceeded error = &DeadlineExceededError{}
  42  
  43  // DeadlineExceededError is returned for an expired deadline.
  44  type DeadlineExceededError struct{}
  45  
  46  // Implement the net.Error interface.
  47  // The string is "i/o timeout" because that is what was returned
  48  // by earlier Go versions. Changing it may break programs that
  49  // match on error strings.
  50  func (e *DeadlineExceededError) Error() string   { return "i/o timeout" }
  51  func (e *DeadlineExceededError) Timeout() bool   { return true }
  52  func (e *DeadlineExceededError) Temporary() bool { return true }
  53  
  54  // The following code is copied from the official implementation.
  55  // https://github.com/golang/go/blob/4ce6a8e89668b87dce67e2f55802903d6eb9110a/src/os/error.go#L65-L104
  56  
  57  func NewSyscallError(syscall string, err error) error {
  58  	if err == nil {
  59  		return nil
  60  	}
  61  	return &SyscallError{syscall, err}
  62  }
  63  
  64  // PathError records an error and the operation and file path that caused it.
  65  type PathError = fs.PathError
  66  
  67  // SyscallError records an error from a specific system call.
  68  type SyscallError struct {
  69  	Syscall string
  70  	Err     error
  71  }
  72  
  73  func (e *SyscallError) Error() string { return e.Syscall + ": " + e.Err.Error() }
  74  
  75  func (e *SyscallError) Unwrap() error { return e.Err }
  76  
  77  type timeout interface {
  78  	Timeout() bool
  79  }
  80  
  81  // Timeout reports whether this error represents a timeout.
  82  func (e *SyscallError) Timeout() bool {
  83  	t, ok := e.Err.(timeout)
  84  	return ok && t.Timeout()
  85  }
  86  
  87  func IsExist(err error) bool {
  88  	return underlyingErrorIs(err, ErrExist)
  89  }
  90  
  91  func IsNotExist(err error) bool {
  92  	return underlyingErrorIs(err, ErrNotExist)
  93  }
  94  
  95  func IsPermission(err error) bool {
  96  	return underlyingErrorIs(err, ErrPermission)
  97  }
  98  
  99  func IsTimeout(err error) bool {
 100  	terr, ok := underlyingError(err).(timeout)
 101  	return ok && terr.Timeout()
 102  }
 103  
 104  func underlyingErrorIs(err, target error) bool {
 105  	// Note that this function is not errors.Is:
 106  	// underlyingError only unwraps the specific error-wrapping types
 107  	// that it historically did, not all errors implementing Unwrap().
 108  	err = underlyingError(err)
 109  	if err == target {
 110  		return true
 111  	}
 112  	// To preserve prior behavior, only examine syscall errors.
 113  	e, ok := err.(syscall.Errno)
 114  	return ok && e.Is(target)
 115  }
 116  
 117  // underlyingError returns the underlying error for known os error types.
 118  func underlyingError(err error) error {
 119  	switch err := err.(type) {
 120  	case *PathError:
 121  		return err.Err
 122  	case *SyscallError:
 123  		return err.Err
 124  	}
 125  	return err
 126  }
 127