errors.go 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. package netlink
  2. import (
  3. "errors"
  4. "fmt"
  5. "net"
  6. "os"
  7. )
  8. // Error messages which can be returned by Validate.
  9. var (
  10. errMismatchedSequence = errors.New("mismatched sequence in netlink reply")
  11. errMismatchedPID = errors.New("mismatched PID in netlink reply")
  12. errShortErrorMessage = errors.New("not enough data for netlink error code")
  13. )
  14. // Errors which can be returned by a Socket that does not implement
  15. // all exposed methods of Conn.
  16. var errNotSupported = errors.New("operation not supported")
  17. // notSupported provides a concise constructor for "not supported" errors.
  18. func notSupported(op string) error {
  19. return newOpError(op, errNotSupported)
  20. }
  21. // IsNotExist determines if an error is produced as the result of querying some
  22. // file, object, resource, etc. which does not exist. Users of this package
  23. // should always use netlink.IsNotExist, rather than os.IsNotExist, when
  24. // checking for specific netlink-related errors.
  25. //
  26. // Errors types created by this package, such as OpError, can be used with
  27. // IsNotExist, but this function also defers to the behavior of os.IsNotExist
  28. // for unrecognized error types.
  29. //
  30. // Deprecated: make use of errors.Unwrap and errors.Is in Go 1.13+.
  31. func IsNotExist(err error) bool {
  32. switch err := err.(type) {
  33. case *OpError:
  34. // TODO(mdlayher): more error handling logic?
  35. // Unwrap the inner error and use the stdlib's logic.
  36. return os.IsNotExist(err.Err)
  37. default:
  38. return os.IsNotExist(err)
  39. }
  40. }
  41. var (
  42. _ error = &OpError{}
  43. _ net.Error = &OpError{}
  44. // Ensure compatibility with Go 1.13+ errors package.
  45. _ interface{ Unwrap() error } = &OpError{}
  46. )
  47. // An OpError is an error produced as the result of a failed netlink operation.
  48. type OpError struct {
  49. // Op is the operation which caused this OpError, such as "send"
  50. // or "receive".
  51. Op string
  52. // Err is the underlying error which caused this OpError.
  53. //
  54. // If Err was produced by a system call error, Err will be of type
  55. // *os.SyscallError. If Err was produced by an error code in a netlink
  56. // message, Err will contain a raw error value type such as a unix.Errno.
  57. //
  58. // Most callers should inspect Err using a helper such as IsNotExist.
  59. Err error
  60. }
  61. // newOpError is a small wrapper for creating an OpError. As a convenience, it
  62. // returns nil if the input err is nil: akin to os.NewSyscallError.
  63. func newOpError(op string, err error) error {
  64. if err == nil {
  65. return nil
  66. }
  67. return &OpError{
  68. Op: op,
  69. Err: err,
  70. }
  71. }
  72. func (e *OpError) Error() string {
  73. if e == nil {
  74. return "<nil>"
  75. }
  76. return fmt.Sprintf("netlink %s: %v", e.Op, e.Err)
  77. }
  78. // Unwrap unwraps the internal Err field for use with errors.Unwrap.
  79. func (e *OpError) Unwrap() error { return e.Err }
  80. // Portions of this code taken from the Go standard library:
  81. //
  82. // Copyright 2009 The Go Authors. All rights reserved.
  83. // Use of this source code is governed by a BSD-style
  84. // license that can be found in the LICENSE file.
  85. type timeout interface {
  86. Timeout() bool
  87. }
  88. // Timeout reports whether the error was caused by an I/O timeout.
  89. func (e *OpError) Timeout() bool {
  90. if ne, ok := e.Err.(*os.SyscallError); ok {
  91. t, ok := ne.Err.(timeout)
  92. return ok && t.Timeout()
  93. }
  94. t, ok := e.Err.(timeout)
  95. return ok && t.Timeout()
  96. }
  97. type temporary interface {
  98. Temporary() bool
  99. }
  100. // Temporary reports whether an operation may succeed if retried.
  101. func (e *OpError) Temporary() bool {
  102. if ne, ok := e.Err.(*os.SyscallError); ok {
  103. t, ok := ne.Err.(temporary)
  104. return ok && t.Temporary()
  105. }
  106. t, ok := e.Err.(temporary)
  107. return ok && t.Temporary()
  108. }