...

Source file src/os/error.go

     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.Wrapper implementations.
   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	}
   135	

View as plain text