Home | History | Annotate | Download | only in 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 	"errors"
      9 	"internal/poll"
     10 )
     11 
     12 // Portable analogs of some common system call errors.
     13 var (
     14 	ErrInvalid    = errors.New("invalid argument") // methods on File will return this error when the receiver is nil
     15 	ErrPermission = errors.New("permission denied")
     16 	ErrExist      = errors.New("file already exists")
     17 	ErrNotExist   = errors.New("file does not exist")
     18 	ErrClosed     = errors.New("file already closed")
     19 	ErrNoDeadline = poll.ErrNoDeadline
     20 )
     21 
     22 type timeout interface {
     23 	Timeout() bool
     24 }
     25 
     26 // PathError records an error and the operation and file path that caused it.
     27 type PathError struct {
     28 	Op   string
     29 	Path string
     30 	Err  error
     31 }
     32 
     33 func (e *PathError) Error() string { return e.Op + " " + e.Path + ": " + e.Err.Error() }
     34 
     35 // Timeout reports whether this error represents a timeout.
     36 func (e *PathError) Timeout() bool {
     37 	t, ok := e.Err.(timeout)
     38 	return ok && t.Timeout()
     39 }
     40 
     41 // SyscallError records an error from a specific system call.
     42 type SyscallError struct {
     43 	Syscall string
     44 	Err     error
     45 }
     46 
     47 func (e *SyscallError) Error() string { return e.Syscall + ": " + e.Err.Error() }
     48 
     49 // Timeout reports whether this error represents a timeout.
     50 func (e *SyscallError) Timeout() bool {
     51 	t, ok := e.Err.(timeout)
     52 	return ok && t.Timeout()
     53 }
     54 
     55 // NewSyscallError returns, as an error, a new SyscallError
     56 // with the given system call name and error details.
     57 // As a convenience, if err is nil, NewSyscallError returns nil.
     58 func NewSyscallError(syscall string, err error) error {
     59 	if err == nil {
     60 		return nil
     61 	}
     62 	return &SyscallError{syscall, err}
     63 }
     64 
     65 // IsExist returns a boolean indicating whether the error is known to report
     66 // that a file or directory already exists. It is satisfied by ErrExist as
     67 // well as some syscall errors.
     68 func IsExist(err error) bool {
     69 	return isExist(err)
     70 }
     71 
     72 // IsNotExist returns a boolean indicating whether the error is known to
     73 // report that a file or directory does not exist. It is satisfied by
     74 // ErrNotExist as well as some syscall errors.
     75 func IsNotExist(err error) bool {
     76 	return isNotExist(err)
     77 }
     78 
     79 // IsPermission returns a boolean indicating whether the error is known to
     80 // report that permission is denied. It is satisfied by ErrPermission as well
     81 // as some syscall errors.
     82 func IsPermission(err error) bool {
     83 	return isPermission(err)
     84 }
     85 
     86 // IsTimeout returns a boolean indicating whether the error is known
     87 // to report that a timeout occurred.
     88 func IsTimeout(err error) bool {
     89 	terr, ok := underlyingError(err).(timeout)
     90 	return ok && terr.Timeout()
     91 }
     92 
     93 // underlyingError returns the underlying error for known os error types.
     94 func underlyingError(err error) error {
     95 	switch err := err.(type) {
     96 	case *PathError:
     97 		return err.Err
     98 	case *LinkError:
     99 		return err.Err
    100 	case *SyscallError:
    101 		return err.Err
    102 	}
    103 	return err
    104 }
    105