...

Source file src/os/error.go

Documentation: os

		 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  	"io/fs"
		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  	ErrNoDeadline			 = errNoDeadline()			 // "file type does not support deadline"
		28  	ErrDeadlineExceeded = errDeadlineExceeded() // "i/o timeout"
		29  )
		30  
		31  func errClosed() error		 { return oserror.ErrClosed }
		32  func errNoDeadline() error { return poll.ErrNoDeadline }
		33  
		34  // errDeadlineExceeded returns the value for os.ErrDeadlineExceeded.
		35  // This error comes from the internal/poll package, which is also
		36  // used by package net. Doing this this way ensures that the net
		37  // package will return os.ErrDeadlineExceeded for an exceeded deadline,
		38  // as documented by net.Conn.SetDeadline, without requiring any extra
		39  // work in the net package and without requiring the internal/poll
		40  // package to import os (which it can't, because that would be circular).
		41  func errDeadlineExceeded() error { return poll.ErrDeadlineExceeded }
		42  
		43  type timeout interface {
		44  	Timeout() bool
		45  }
		46  
		47  // PathError records an error and the operation and file path that caused it.
		48  type PathError = fs.PathError
		49  
		50  // SyscallError records an error from a specific system call.
		51  type SyscallError struct {
		52  	Syscall string
		53  	Err		 error
		54  }
		55  
		56  func (e *SyscallError) Error() string { return e.Syscall + ": " + e.Err.Error() }
		57  
		58  func (e *SyscallError) Unwrap() error { return e.Err }
		59  
		60  // Timeout reports whether this error represents a timeout.
		61  func (e *SyscallError) Timeout() bool {
		62  	t, ok := e.Err.(timeout)
		63  	return ok && t.Timeout()
		64  }
		65  
		66  // NewSyscallError returns, as an error, a new SyscallError
		67  // with the given system call name and error details.
		68  // As a convenience, if err is nil, NewSyscallError returns nil.
		69  func NewSyscallError(syscall string, err error) error {
		70  	if err == nil {
		71  		return nil
		72  	}
		73  	return &SyscallError{syscall, err}
		74  }
		75  
		76  // IsExist returns a boolean indicating whether the error is known to report
		77  // that a file or directory already exists. It is satisfied by ErrExist as
		78  // well as some syscall errors.
		79  //
		80  // This function predates errors.Is. It only supports errors returned by
		81  // the os package. New code should use errors.Is(err, fs.ErrExist).
		82  func IsExist(err error) bool {
		83  	return underlyingErrorIs(err, ErrExist)
		84  }
		85  
		86  // IsNotExist returns a boolean indicating whether the error is known to
		87  // report that a file or directory does not exist. It is satisfied by
		88  // ErrNotExist as well as some syscall errors.
		89  //
		90  // This function predates errors.Is. It only supports errors returned by
		91  // the os package. New code should use errors.Is(err, fs.ErrNotExist).
		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  //
	 100  // This function predates errors.Is. It only supports errors returned by
	 101  // the os package. New code should use errors.Is(err, fs.ErrPermission).
	 102  func IsPermission(err error) bool {
	 103  	return underlyingErrorIs(err, ErrPermission)
	 104  }
	 105  
	 106  // IsTimeout returns a boolean indicating whether the error is known
	 107  // to report that a timeout occurred.
	 108  //
	 109  // This function predates errors.Is, and the notion of whether an
	 110  // error indicates a timeout can be ambiguous. For example, the Unix
	 111  // error EWOULDBLOCK sometimes indicates a timeout and sometimes does not.
	 112  // New code should use errors.Is with a value appropriate to the call
	 113  // returning the error, such as os.ErrDeadlineExceeded.
	 114  func IsTimeout(err error) bool {
	 115  	terr, ok := underlyingError(err).(timeout)
	 116  	return ok && terr.Timeout()
	 117  }
	 118  
	 119  func underlyingErrorIs(err, target error) bool {
	 120  	// Note that this function is not errors.Is:
	 121  	// underlyingError only unwraps the specific error-wrapping types
	 122  	// that it historically did, not all errors implementing Unwrap().
	 123  	err = underlyingError(err)
	 124  	if err == target {
	 125  		return true
	 126  	}
	 127  	// To preserve prior behavior, only examine syscall errors.
	 128  	e, ok := err.(syscallErrorType)
	 129  	return ok && e.Is(target)
	 130  }
	 131  
	 132  // underlyingError returns the underlying error for known os error types.
	 133  func underlyingError(err error) error {
	 134  	switch err := err.(type) {
	 135  	case *PathError:
	 136  		return err.Err
	 137  	case *LinkError:
	 138  		return err.Err
	 139  	case *SyscallError:
	 140  		return err.Err
	 141  	}
	 142  	return err
	 143  }
	 144  

View as plain text