error.go 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  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. package os
  5. import (
  6. "internal/oserror"
  7. "internal/poll"
  8. "io/fs"
  9. )
  10. // Portable analogs of some common system call errors.
  11. //
  12. // Errors returned from this package may be tested against these errors
  13. // with errors.Is.
  14. var (
  15. // ErrInvalid indicates an invalid argument.
  16. // Methods on File will return this error when the receiver is nil.
  17. ErrInvalid = fs.ErrInvalid // "invalid argument"
  18. ErrPermission = fs.ErrPermission // "permission denied"
  19. ErrExist = fs.ErrExist // "file already exists"
  20. ErrNotExist = fs.ErrNotExist // "file does not exist"
  21. ErrClosed = fs.ErrClosed // "file already closed"
  22. ErrNoDeadline = errNoDeadline() // "file type does not support deadline"
  23. ErrDeadlineExceeded = errDeadlineExceeded() // "i/o timeout"
  24. )
  25. func errClosed() error { return oserror.ErrClosed }
  26. func errNoDeadline() error { return poll.ErrNoDeadline }
  27. // errDeadlineExceeded returns the value for os.ErrDeadlineExceeded.
  28. // This error comes from the internal/poll package, which is also
  29. // used by package net. Doing this this way ensures that the net
  30. // package will return os.ErrDeadlineExceeded for an exceeded deadline,
  31. // as documented by net.Conn.SetDeadline, without requiring any extra
  32. // work in the net package and without requiring the internal/poll
  33. // package to import os (which it can't, because that would be circular).
  34. func errDeadlineExceeded() error { return poll.ErrDeadlineExceeded }
  35. type timeout interface {
  36. Timeout() bool
  37. }
  38. // PathError records an error and the operation and file path that caused it.
  39. type PathError = fs.PathError
  40. // SyscallError records an error from a specific system call.
  41. type SyscallError struct {
  42. Syscall string
  43. Err error
  44. }
  45. func (e *SyscallError) Error() string { return e.Syscall + ": " + e.Err.Error() }
  46. func (e *SyscallError) Unwrap() error { return e.Err }
  47. // Timeout reports whether this error represents a timeout.
  48. func (e *SyscallError) Timeout() bool {
  49. t, ok := e.Err.(timeout)
  50. return ok && t.Timeout()
  51. }
  52. // NewSyscallError returns, as an error, a new SyscallError
  53. // with the given system call name and error details.
  54. // As a convenience, if err is nil, NewSyscallError returns nil.
  55. func NewSyscallError(syscall string, err error) error {
  56. if err == nil {
  57. return nil
  58. }
  59. return &SyscallError{syscall, err}
  60. }
  61. // IsExist returns a boolean indicating whether the error is known to report
  62. // that a file or directory already exists. It is satisfied by ErrExist as
  63. // well as some syscall errors.
  64. //
  65. // This function predates errors.Is. It only supports errors returned by
  66. // the os package. New code should use errors.Is(err, fs.ErrExist).
  67. func IsExist(err error) bool {
  68. return underlyingErrorIs(err, ErrExist)
  69. }
  70. // IsNotExist returns a boolean indicating whether the error is known to
  71. // report that a file or directory does not exist. It is satisfied by
  72. // ErrNotExist as well as some syscall errors.
  73. //
  74. // This function predates errors.Is. It only supports errors returned by
  75. // the os package. New code should use errors.Is(err, fs.ErrNotExist).
  76. func IsNotExist(err error) bool {
  77. return underlyingErrorIs(err, ErrNotExist)
  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. //
  83. // This function predates errors.Is. It only supports errors returned by
  84. // the os package. New code should use errors.Is(err, fs.ErrPermission).
  85. func IsPermission(err error) bool {
  86. return underlyingErrorIs(err, ErrPermission)
  87. }
  88. // IsTimeout returns a boolean indicating whether the error is known
  89. // to report that a timeout occurred.
  90. //
  91. // This function predates errors.Is, and the notion of whether an
  92. // error indicates a timeout can be ambiguous. For example, the Unix
  93. // error EWOULDBLOCK sometimes indicates a timeout and sometimes does not.
  94. // New code should use errors.Is with a value appropriate to the call
  95. // returning the error, such as os.ErrDeadlineExceeded.
  96. func IsTimeout(err error) bool {
  97. terr, ok := underlyingError(err).(timeout)
  98. return ok && terr.Timeout()
  99. }
  100. func underlyingErrorIs(err, target error) bool {
  101. // Note that this function is not errors.Is:
  102. // underlyingError only unwraps the specific error-wrapping types
  103. // that it historically did, not all errors implementing Unwrap().
  104. err = underlyingError(err)
  105. if err == target {
  106. return true
  107. }
  108. // To preserve prior behavior, only examine syscall errors.
  109. e, ok := err.(syscallErrorType)
  110. return ok && e.Is(target)
  111. }
  112. // underlyingError returns the underlying error for known os error types.
  113. func underlyingError(err error) error {
  114. switch err := err.(type) {
  115. case *PathError:
  116. return err.Err
  117. case *LinkError:
  118. return err.Err
  119. case *SyscallError:
  120. return err.Err
  121. }
  122. return err
  123. }