github.com/MerlinKodo/gvisor@v0.0.0-20231110090155-957f62ecf90e/pkg/errors/linuxerr/linuxerr.go (about)

     1  // Copyright 2021 The gVisor Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License"),;
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  // Package linuxerr contains syscall error codes exported as an error interface
    16  // pointers. This allows for fast comparison and return operations comperable
    17  // to unix.Errno constants.
    18  package linuxerr
    19  
    20  import (
    21  	"fmt"
    22  
    23  	"golang.org/x/sys/unix"
    24  	"github.com/MerlinKodo/gvisor/pkg/abi/linux/errno"
    25  	"github.com/MerlinKodo/gvisor/pkg/errors"
    26  )
    27  
    28  const maxErrno uint32 = errno.EHWPOISON + 1
    29  
    30  // The following errors are semantically identical to Errno of type unix.Errno
    31  // or sycall.Errno. However, since the type are distinct ( these are
    32  // *errors.Error), they are not directly comperable. However, the Errno method
    33  // returns an Errno number such that the error can be compared to unix/syscall.Errno
    34  // (e.g. unix.Errno(EPERM.Errno()) == unix.EPERM is true). Converting unix/syscall.Errno
    35  // to the errors should be done via the lookup methods provided.
    36  var (
    37  	noError *errors.Error = nil
    38  	EPERM                 = errors.New(errno.EPERM, "operation not permitted")
    39  	ENOENT                = errors.New(errno.ENOENT, "no such file or directory")
    40  	ESRCH                 = errors.New(errno.ESRCH, "no such process")
    41  	EINTR                 = errors.New(errno.EINTR, "interrupted system call")
    42  	EIO                   = errors.New(errno.EIO, "I/O error")
    43  	ENXIO                 = errors.New(errno.ENXIO, "no such device or address")
    44  	E2BIG                 = errors.New(errno.E2BIG, "argument list too long")
    45  	ENOEXEC               = errors.New(errno.ENOEXEC, "exec format error")
    46  	EBADF                 = errors.New(errno.EBADF, "bad file number")
    47  	ECHILD                = errors.New(errno.ECHILD, "no child processes")
    48  	EAGAIN                = errors.New(errno.EAGAIN, "try again")
    49  	ENOMEM                = errors.New(errno.ENOMEM, "out of memory")
    50  	EACCES                = errors.New(errno.EACCES, "permission denied")
    51  	EFAULT                = errors.New(errno.EFAULT, "bad address")
    52  	ENOTBLK               = errors.New(errno.ENOTBLK, "block device required")
    53  	EBUSY                 = errors.New(errno.EBUSY, "device or resource busy")
    54  	EEXIST                = errors.New(errno.EEXIST, "file exists")
    55  	EXDEV                 = errors.New(errno.EXDEV, "cross-device link")
    56  	ENODEV                = errors.New(errno.ENODEV, "no such device")
    57  	ENOTDIR               = errors.New(errno.ENOTDIR, "not a directory")
    58  	EISDIR                = errors.New(errno.EISDIR, "is a directory")
    59  	EINVAL                = errors.New(errno.EINVAL, "invalid argument")
    60  	ENFILE                = errors.New(errno.ENFILE, "file table overflow")
    61  	EMFILE                = errors.New(errno.EMFILE, "too many open files")
    62  	ENOTTY                = errors.New(errno.ENOTTY, "not a typewriter")
    63  	ETXTBSY               = errors.New(errno.ETXTBSY, "text file busy")
    64  	EFBIG                 = errors.New(errno.EFBIG, "file too large")
    65  	ENOSPC                = errors.New(errno.ENOSPC, "no space left on device")
    66  	ESPIPE                = errors.New(errno.ESPIPE, "illegal seek")
    67  	EROFS                 = errors.New(errno.EROFS, "read-only file system")
    68  	EMLINK                = errors.New(errno.EMLINK, "too many links")
    69  	EPIPE                 = errors.New(errno.EPIPE, "broken pipe")
    70  	EDOM                  = errors.New(errno.EDOM, "math argument out of domain of func")
    71  	ERANGE                = errors.New(errno.ERANGE, "math result not representable")
    72  
    73  	// Errno values from include/uapi/asm-generic/errno.h.
    74  	EDEADLK         = errors.New(errno.EDEADLK, "resource deadlock would occur")
    75  	ENAMETOOLONG    = errors.New(errno.ENAMETOOLONG, "file name too long")
    76  	ENOLCK          = errors.New(errno.ENOLCK, "no record locks available")
    77  	ENOSYS          = errors.New(errno.ENOSYS, "invalid system call number")
    78  	ENOTEMPTY       = errors.New(errno.ENOTEMPTY, "directory not empty")
    79  	ELOOP           = errors.New(errno.ELOOP, "too many symbolic links encountered")
    80  	ENOMSG          = errors.New(errno.ENOMSG, "no message of desired type")
    81  	EIDRM           = errors.New(errno.EIDRM, "identifier removed")
    82  	ECHRNG          = errors.New(errno.ECHRNG, "channel number out of range")
    83  	EL2NSYNC        = errors.New(errno.EL2NSYNC, "level 2 not synchronized")
    84  	EL3HLT          = errors.New(errno.EL3HLT, "level 3 halted")
    85  	EL3RST          = errors.New(errno.EL3RST, "level 3 reset")
    86  	ELNRNG          = errors.New(errno.ELNRNG, "link number out of range")
    87  	EUNATCH         = errors.New(errno.EUNATCH, "protocol driver not attached")
    88  	ENOCSI          = errors.New(errno.ENOCSI, "no CSI structure available")
    89  	EL2HLT          = errors.New(errno.EL2HLT, "level 2 halted")
    90  	EBADE           = errors.New(errno.EBADE, "invalid exchange")
    91  	EBADR           = errors.New(errno.EBADR, "invalid request descriptor")
    92  	EXFULL          = errors.New(errno.EXFULL, "exchange full")
    93  	ENOANO          = errors.New(errno.ENOANO, "no anode")
    94  	EBADRQC         = errors.New(errno.EBADRQC, "invalid request code")
    95  	EBADSLT         = errors.New(errno.EBADSLT, "invalid slot")
    96  	EBFONT          = errors.New(errno.EBFONT, "bad font file format")
    97  	ENOSTR          = errors.New(errno.ENOSTR, "device not a stream")
    98  	ENODATA         = errors.New(errno.ENODATA, "no data available")
    99  	ETIME           = errors.New(errno.ETIME, "timer expired")
   100  	ENOSR           = errors.New(errno.ENOSR, "out of streams resources")
   101  	ENOPKG          = errors.New(errno.ENOPKG, "package not installed")
   102  	EREMOTE         = errors.New(errno.EREMOTE, "object is remote")
   103  	ENOLINK         = errors.New(errno.ENOLINK, "link has been severed")
   104  	EADV            = errors.New(errno.EADV, "advertise error")
   105  	ESRMNT          = errors.New(errno.ESRMNT, "srmount error")
   106  	ECOMM           = errors.New(errno.ECOMM, "communication error on send")
   107  	EPROTO          = errors.New(errno.EPROTO, "protocol error")
   108  	EMULTIHOP       = errors.New(errno.EMULTIHOP, "multihop attempted")
   109  	EDOTDOT         = errors.New(errno.EDOTDOT, "RFS specific error")
   110  	EBADMSG         = errors.New(errno.EBADMSG, "not a data message")
   111  	EOVERFLOW       = errors.New(errno.EOVERFLOW, "value too large for defined data type")
   112  	ENOTUNIQ        = errors.New(errno.ENOTUNIQ, "name not unique on network")
   113  	EBADFD          = errors.New(errno.EBADFD, "file descriptor in bad state")
   114  	EREMCHG         = errors.New(errno.EREMCHG, "remote address changed")
   115  	ELIBACC         = errors.New(errno.ELIBACC, "can not access a needed shared library")
   116  	ELIBBAD         = errors.New(errno.ELIBBAD, "accessing a corrupted shared library")
   117  	ELIBSCN         = errors.New(errno.ELIBSCN, ".lib section in a.out corrupted")
   118  	ELIBMAX         = errors.New(errno.ELIBMAX, "attempting to link in too many shared libraries")
   119  	ELIBEXEC        = errors.New(errno.ELIBEXEC, "cannot exec a shared library directly")
   120  	EILSEQ          = errors.New(errno.EILSEQ, "illegal byte sequence")
   121  	ERESTART        = errors.New(errno.ERESTART, "interrupted system call should be restarted")
   122  	ESTRPIPE        = errors.New(errno.ESTRPIPE, "streams pipe error")
   123  	EUSERS          = errors.New(errno.EUSERS, "too many users")
   124  	ENOTSOCK        = errors.New(errno.ENOTSOCK, "socket operation on non-socket")
   125  	EDESTADDRREQ    = errors.New(errno.EDESTADDRREQ, "destination address required")
   126  	EMSGSIZE        = errors.New(errno.EMSGSIZE, "message too long")
   127  	EPROTOTYPE      = errors.New(errno.EPROTOTYPE, "protocol wrong type for socket")
   128  	ENOPROTOOPT     = errors.New(errno.ENOPROTOOPT, "protocol not available")
   129  	EPROTONOSUPPORT = errors.New(errno.EPROTONOSUPPORT, "protocol not supported")
   130  	ESOCKTNOSUPPORT = errors.New(errno.ESOCKTNOSUPPORT, "socket type not supported")
   131  	EOPNOTSUPP      = errors.New(errno.EOPNOTSUPP, "operation not supported on transport endpoint")
   132  	EPFNOSUPPORT    = errors.New(errno.EPFNOSUPPORT, "protocol family not supported")
   133  	EAFNOSUPPORT    = errors.New(errno.EAFNOSUPPORT, "address family not supported by protocol")
   134  	EADDRINUSE      = errors.New(errno.EADDRINUSE, "address already in use")
   135  	EADDRNOTAVAIL   = errors.New(errno.EADDRNOTAVAIL, "cannot assign requested address")
   136  	ENETDOWN        = errors.New(errno.ENETDOWN, "network is down")
   137  	ENETUNREACH     = errors.New(errno.ENETUNREACH, "network is unreachable")
   138  	ENETRESET       = errors.New(errno.ENETRESET, "network dropped connection because of reset")
   139  	ECONNABORTED    = errors.New(errno.ECONNABORTED, "software caused connection abort")
   140  	ECONNRESET      = errors.New(errno.ECONNRESET, "connection reset by peer")
   141  	ENOBUFS         = errors.New(errno.ENOBUFS, "no buffer space available")
   142  	EISCONN         = errors.New(errno.EISCONN, "transport endpoint is already connected")
   143  	ENOTCONN        = errors.New(errno.ENOTCONN, "transport endpoint is not connected")
   144  	ESHUTDOWN       = errors.New(errno.ESHUTDOWN, "cannot send after transport endpoint shutdown")
   145  	ETOOMANYREFS    = errors.New(errno.ETOOMANYREFS, "too many references: cannot splice")
   146  	ETIMEDOUT       = errors.New(errno.ETIMEDOUT, "connection timed out")
   147  	ECONNREFUSED    = errors.New(errno.ECONNREFUSED, "connection refused")
   148  	EHOSTDOWN       = errors.New(errno.EHOSTDOWN, "host is down")
   149  	EHOSTUNREACH    = errors.New(errno.EHOSTUNREACH, "no route to host")
   150  	EALREADY        = errors.New(errno.EALREADY, "operation already in progress")
   151  	EINPROGRESS     = errors.New(errno.EINPROGRESS, "operation now in progress")
   152  	ESTALE          = errors.New(errno.ESTALE, "stale file handle")
   153  	EUCLEAN         = errors.New(errno.EUCLEAN, "structure needs cleaning")
   154  	ENOTNAM         = errors.New(errno.ENOTNAM, "not a XENIX named type file")
   155  	ENAVAIL         = errors.New(errno.ENAVAIL, "no XENIX semaphores available")
   156  	EISNAM          = errors.New(errno.EISNAM, "is a named type file")
   157  	EREMOTEIO       = errors.New(errno.EREMOTEIO, "remote I/O error")
   158  	EDQUOT          = errors.New(errno.EDQUOT, "quota exceeded")
   159  	ENOMEDIUM       = errors.New(errno.ENOMEDIUM, "no medium found")
   160  	EMEDIUMTYPE     = errors.New(errno.EMEDIUMTYPE, "wrong medium type")
   161  	ECANCELED       = errors.New(errno.ECANCELED, "operation Canceled")
   162  	ENOKEY          = errors.New(errno.ENOKEY, "required key not available")
   163  	EKEYEXPIRED     = errors.New(errno.EKEYEXPIRED, "key has expired")
   164  	EKEYREVOKED     = errors.New(errno.EKEYREVOKED, "key has been revoked")
   165  	EKEYREJECTED    = errors.New(errno.EKEYREJECTED, "key was rejected by service")
   166  	EOWNERDEAD      = errors.New(errno.EOWNERDEAD, "owner died")
   167  	ENOTRECOVERABLE = errors.New(errno.ENOTRECOVERABLE, "state not recoverable")
   168  	ERFKILL         = errors.New(errno.ERFKILL, "operation not possible due to RF-kill")
   169  	EHWPOISON       = errors.New(errno.EHWPOISON, "memory page has hardware error")
   170  
   171  	// Errors equivalent to other errors.
   172  	EWOULDBLOCK = EAGAIN
   173  	EDEADLOCK   = EDEADLK
   174  	ENONET      = ENOENT
   175  	ENOATTR     = ENODATA
   176  	ENOTSUP     = EOPNOTSUPP
   177  )
   178  
   179  // A nil *errors.Error denotes no error and is placed at the 0 index of
   180  // errorSlice. Thus, any other empty index should not be nil or a valid error.
   181  // This marks that index as an invalid error so any comparison to nil or a
   182  // valid linuxerr fails.
   183  var errNotValidError = errors.New(errno.Errno(maxErrno), "not a valid error")
   184  
   185  // The following errorSlice holds errors by errno for fast translation between
   186  // errnos (especially uint32(sycall.Errno)) and *errors.Error.
   187  var errorSlice = []*errors.Error{
   188  	// Errno values from include/uapi/asm-generic/errno-base.h.
   189  	errno.NOERRNO: noError,
   190  	errno.EPERM:   EPERM,
   191  	errno.ENOENT:  ENOENT,
   192  	errno.ESRCH:   ESRCH,
   193  	errno.EINTR:   EINTR,
   194  	errno.EIO:     EIO,
   195  	errno.ENXIO:   ENXIO,
   196  	errno.E2BIG:   E2BIG,
   197  	errno.ENOEXEC: ENOEXEC,
   198  	errno.EBADF:   EBADF,
   199  	errno.ECHILD:  ECHILD,
   200  	errno.EAGAIN:  EAGAIN,
   201  	errno.ENOMEM:  ENOMEM,
   202  	errno.EACCES:  EACCES,
   203  	errno.EFAULT:  EFAULT,
   204  	errno.ENOTBLK: ENOTBLK,
   205  	errno.EBUSY:   EBUSY,
   206  	errno.EEXIST:  EEXIST,
   207  	errno.EXDEV:   EXDEV,
   208  	errno.ENODEV:  ENODEV,
   209  	errno.ENOTDIR: ENOTDIR,
   210  	errno.EISDIR:  EISDIR,
   211  	errno.EINVAL:  EINVAL,
   212  	errno.ENFILE:  ENFILE,
   213  	errno.EMFILE:  EMFILE,
   214  	errno.ENOTTY:  ENOTTY,
   215  	errno.ETXTBSY: ETXTBSY,
   216  	errno.EFBIG:   EFBIG,
   217  	errno.ENOSPC:  ENOSPC,
   218  	errno.ESPIPE:  ESPIPE,
   219  	errno.EROFS:   EROFS,
   220  	errno.EMLINK:  EMLINK,
   221  	errno.EPIPE:   EPIPE,
   222  	errno.EDOM:    EDOM,
   223  	errno.ERANGE:  ERANGE,
   224  
   225  	// Errno values from include/uapi/asm-generic/errno.h.
   226  	errno.EDEADLK:         EDEADLK,
   227  	errno.ENAMETOOLONG:    ENAMETOOLONG,
   228  	errno.ENOLCK:          ENOLCK,
   229  	errno.ENOSYS:          ENOSYS,
   230  	errno.ENOTEMPTY:       ENOTEMPTY,
   231  	errno.ELOOP:           ELOOP,
   232  	errno.ELOOP + 1:       errNotValidError, // No valid errno between ELOOP and ENOMSG.
   233  	errno.ENOMSG:          ENOMSG,
   234  	errno.EIDRM:           EIDRM,
   235  	errno.ECHRNG:          ECHRNG,
   236  	errno.EL2NSYNC:        EL2NSYNC,
   237  	errno.EL3HLT:          EL3HLT,
   238  	errno.EL3RST:          EL3RST,
   239  	errno.ELNRNG:          ELNRNG,
   240  	errno.EUNATCH:         EUNATCH,
   241  	errno.ENOCSI:          ENOCSI,
   242  	errno.EL2HLT:          EL2HLT,
   243  	errno.EBADE:           EBADE,
   244  	errno.EBADR:           EBADR,
   245  	errno.EXFULL:          EXFULL,
   246  	errno.ENOANO:          ENOANO,
   247  	errno.EBADRQC:         EBADRQC,
   248  	errno.EBADSLT:         EBADSLT,
   249  	errno.EBADSLT + 1:     errNotValidError, // No valid errno between EBADSLT and ENOPKG.
   250  	errno.EBFONT:          EBFONT,
   251  	errno.ENOSTR:          ENOSTR,
   252  	errno.ENODATA:         ENODATA,
   253  	errno.ETIME:           ETIME,
   254  	errno.ENOSR:           ENOSR,
   255  	errno.ENOSR + 1:       errNotValidError, // No valid errno betweeen ENOSR and ENOPKG.
   256  	errno.ENOPKG:          ENOPKG,
   257  	errno.EREMOTE:         EREMOTE,
   258  	errno.ENOLINK:         ENOLINK,
   259  	errno.EADV:            EADV,
   260  	errno.ESRMNT:          ESRMNT,
   261  	errno.ECOMM:           ECOMM,
   262  	errno.EPROTO:          EPROTO,
   263  	errno.EMULTIHOP:       EMULTIHOP,
   264  	errno.EDOTDOT:         EDOTDOT,
   265  	errno.EBADMSG:         EBADMSG,
   266  	errno.EOVERFLOW:       EOVERFLOW,
   267  	errno.ENOTUNIQ:        ENOTUNIQ,
   268  	errno.EBADFD:          EBADFD,
   269  	errno.EREMCHG:         EREMCHG,
   270  	errno.ELIBACC:         ELIBACC,
   271  	errno.ELIBBAD:         ELIBBAD,
   272  	errno.ELIBSCN:         ELIBSCN,
   273  	errno.ELIBMAX:         ELIBMAX,
   274  	errno.ELIBEXEC:        ELIBEXEC,
   275  	errno.EILSEQ:          EILSEQ,
   276  	errno.ERESTART:        ERESTART,
   277  	errno.ESTRPIPE:        ESTRPIPE,
   278  	errno.EUSERS:          EUSERS,
   279  	errno.ENOTSOCK:        ENOTSOCK,
   280  	errno.EDESTADDRREQ:    EDESTADDRREQ,
   281  	errno.EMSGSIZE:        EMSGSIZE,
   282  	errno.EPROTOTYPE:      EPROTOTYPE,
   283  	errno.ENOPROTOOPT:     ENOPROTOOPT,
   284  	errno.EPROTONOSUPPORT: EPROTONOSUPPORT,
   285  	errno.ESOCKTNOSUPPORT: ESOCKTNOSUPPORT,
   286  	errno.EOPNOTSUPP:      EOPNOTSUPP,
   287  	errno.EPFNOSUPPORT:    EPFNOSUPPORT,
   288  	errno.EAFNOSUPPORT:    EAFNOSUPPORT,
   289  	errno.EADDRINUSE:      EADDRINUSE,
   290  	errno.EADDRNOTAVAIL:   EADDRNOTAVAIL,
   291  	errno.ENETDOWN:        ENETDOWN,
   292  	errno.ENETUNREACH:     ENETUNREACH,
   293  	errno.ENETRESET:       ENETRESET,
   294  	errno.ECONNABORTED:    ECONNABORTED,
   295  	errno.ECONNRESET:      ECONNRESET,
   296  	errno.ENOBUFS:         ENOBUFS,
   297  	errno.EISCONN:         EISCONN,
   298  	errno.ENOTCONN:        ENOTCONN,
   299  	errno.ESHUTDOWN:       ESHUTDOWN,
   300  	errno.ETOOMANYREFS:    ETOOMANYREFS,
   301  	errno.ETIMEDOUT:       ETIMEDOUT,
   302  	errno.ECONNREFUSED:    ECONNREFUSED,
   303  	errno.EHOSTDOWN:       EHOSTDOWN,
   304  	errno.EHOSTUNREACH:    EHOSTUNREACH,
   305  	errno.EALREADY:        EALREADY,
   306  	errno.EINPROGRESS:     EINPROGRESS,
   307  	errno.ESTALE:          ESTALE,
   308  	errno.EUCLEAN:         EUCLEAN,
   309  	errno.ENOTNAM:         ENOTNAM,
   310  	errno.ENAVAIL:         ENAVAIL,
   311  	errno.EISNAM:          EISNAM,
   312  	errno.EREMOTEIO:       EREMOTEIO,
   313  	errno.EDQUOT:          EDQUOT,
   314  	errno.ENOMEDIUM:       ENOMEDIUM,
   315  	errno.EMEDIUMTYPE:     EMEDIUMTYPE,
   316  	errno.ECANCELED:       ECANCELED,
   317  	errno.ENOKEY:          ENOKEY,
   318  	errno.EKEYEXPIRED:     EKEYEXPIRED,
   319  	errno.EKEYREVOKED:     EKEYREVOKED,
   320  	errno.EKEYREJECTED:    EKEYREJECTED,
   321  	errno.EOWNERDEAD:      EOWNERDEAD,
   322  	errno.ENOTRECOVERABLE: ENOTRECOVERABLE,
   323  	errno.ERFKILL:         ERFKILL,
   324  	errno.EHWPOISON:       EHWPOISON,
   325  }
   326  
   327  // ErrorFromUnix returns a linuxerr from a unix.Errno.
   328  func ErrorFromUnix(err unix.Errno) error {
   329  	if err == unix.Errno(0) {
   330  		return nil
   331  	}
   332  	e := errorSlice[errno.Errno(err)]
   333  	// Done this way because a single comparison in benchmarks is 2-3 faster
   334  	// than something like ( if err == nil && err > 0 ).
   335  	if e == errNotValidError {
   336  		panic(fmt.Sprintf("invalid error requested with errno: %v", e))
   337  	}
   338  	return e
   339  }
   340  
   341  // ToError converts a linuxerr to an error type.
   342  func ToError(err *errors.Error) error {
   343  	if err == noError {
   344  		return nil
   345  	}
   346  	return err
   347  }
   348  
   349  // ToUnix converts a linuxerr to a unix.Errno.
   350  func ToUnix(e *errors.Error) unix.Errno {
   351  	var unixErr unix.Errno
   352  	if e != noError {
   353  		unixErr = unix.Errno(e.Errno())
   354  	}
   355  	return unixErr
   356  }
   357  
   358  // Equals compars a linuxerr to a given error.
   359  func Equals(e *errors.Error, err error) bool {
   360  	var unixErr unix.Errno
   361  	if e != noError {
   362  		unixErr = unix.Errno(e.Errno())
   363  	}
   364  	if err == nil {
   365  		err = noError
   366  	}
   367  	return e == err || unixErr == err
   368  }