github.com/tinygo-org/tinygo@v0.31.3-0.20240404173401-90b0bf646c27/src/os/errors.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  	"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  }