1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213
use anyhow::Error;
pub fn get_error_code(err: &Error) -> Option<&'static str> {
err
.downcast_ref::<std::io::Error>()
.map(|e| match e.raw_os_error() {
Some(code) => get_os_error_code(code),
None => get_io_error_code(e),
})
.and_then(|code| match code.is_empty() {
true => None,
false => Some(code),
})
}
fn get_io_error_code(err: &std::io::Error) -> &'static str {
// not exhaustive but simple and possibly sufficient once `io_error_more` is stabilized (https://github.com/rust-lang/rust/issues/86442)
// inversion of https://github.com/rust-lang/rust/blob/dca3f1b786efd27be3b325ed1e01e247aa589c3b/library/std/src/sys/unix/mod.rs#L138-L185
// TODO(@AaronO): revisit as `io_error_more` lands in rust stable
use std::io::ErrorKind;
match err.kind() {
// ErrorKind::ArgumentListTooLong => "E2BIG",
ErrorKind::AddrInUse => "EADDRINUSE",
ErrorKind::AddrNotAvailable => "EADDRNOTAVAIL",
// ErrorKind::ResourceBusy => "EBUSY",
ErrorKind::ConnectionAborted => "ECONNABORTED",
ErrorKind::ConnectionRefused => "ECONNREFUSED",
ErrorKind::ConnectionReset => "ECONNRESET",
// ErrorKind::Deadlock => "EDEADLK",
// ErrorKind::FilesystemQuotaExceeded => "EDQUOT",
ErrorKind::AlreadyExists => "EEXIST",
// ErrorKind::FileTooLarge => "EFBIG",
// ErrorKind::HostUnreachable => "EHOSTUNREACH",
ErrorKind::Interrupted => "EINTR",
ErrorKind::InvalidInput => "EINVAL",
// ErrorKind::IsADirectory => "EISDIR",
// ErrorKind::FilesystemLoop => "ELOOP",
ErrorKind::NotFound => "ENOENT",
ErrorKind::OutOfMemory => "ENOMEM",
// ErrorKind::StorageFull => "ENOSPC",
ErrorKind::Unsupported => "ENOSYS",
// ErrorKind::TooManyLinks => "EMLINK",
// ErrorKind::FilenameTooLong => "ENAMETOOLONG",
// ErrorKind::NetworkDown => "ENETDOWN",
// ErrorKind::NetworkUnreachable => "ENETUNREACH",
ErrorKind::NotConnected => "ENOTCONN",
// ErrorKind::NotADirectory => "ENOTDIR",
// ErrorKind::DirectoryNotEmpty => "ENOTEMPTY",
ErrorKind::BrokenPipe => "EPIPE",
// ErrorKind::ReadOnlyFilesystem => "EROFS",
// ErrorKind::NotSeekable => "ESPIPE",
// ErrorKind::StaleNetworkFileHandle => "ESTALE",
ErrorKind::TimedOut => "ETIMEDOUT",
// ErrorKind::ExecutableFileBusy => "ETXTBSY",
// ErrorKind::CrossesDevices => "EXDEV",
ErrorKind::PermissionDenied => "EACCES", // NOTE: Collides with EPERM ...
_ => "",
}
}
/// Maps OS errno codes to string names
/// derived from libuv: https://github.com/libuv/libuv/blob/26b2e5dbb6301756644d6e4cf6ca9c49c00513d3/include/uv/errno.h
/// generated with tools/codegen_error_codes.js
#[cfg(unix)]
fn get_os_error_code(errno: i32) -> &'static str {
match errno {
libc::E2BIG => "E2BIG",
libc::EACCES => "EACCES",
libc::EADDRINUSE => "EADDRINUSE",
libc::EADDRNOTAVAIL => "EADDRNOTAVAIL",
libc::EAFNOSUPPORT => "EAFNOSUPPORT",
libc::EAGAIN => "EAGAIN",
libc::EALREADY => "EALREADY",
libc::EBADF => "EBADF",
libc::EBUSY => "EBUSY",
libc::ECANCELED => "ECANCELED",
libc::ECONNABORTED => "ECONNABORTED",
libc::ECONNREFUSED => "ECONNREFUSED",
libc::ECONNRESET => "ECONNRESET",
libc::EEXIST => "EEXIST",
libc::EFAULT => "EFAULT",
libc::EHOSTUNREACH => "EHOSTUNREACH",
libc::EINVAL => "EINVAL",
libc::EIO => "EIO",
libc::EISCONN => "EISCONN",
libc::EISDIR => "EISDIR",
libc::ELOOP => "ELOOP",
libc::EMFILE => "EMFILE",
libc::EMSGSIZE => "EMSGSIZE",
libc::ENAMETOOLONG => "ENAMETOOLONG",
libc::ENETUNREACH => "ENETUNREACH",
libc::ENOBUFS => "ENOBUFS",
libc::ENOENT => "ENOENT",
libc::ENOMEM => "ENOMEM",
libc::ENOSPC => "ENOSPC",
libc::ENOTCONN => "ENOTCONN",
libc::ENOTDIR => "ENOTDIR",
libc::ENOTEMPTY => "ENOTEMPTY",
libc::ENOTSOCK => "ENOTSOCK",
libc::ENOTSUP => "ENOTSUP",
libc::EPERM => "EPERM",
libc::EPIPE => "EPIPE",
libc::EPROTONOSUPPORT => "EPROTONOSUPPORT",
libc::EROFS => "EROFS",
libc::ETIMEDOUT => "ETIMEDOUT",
libc::EXDEV => "EXDEV",
libc::ESOCKTNOSUPPORT => "ESOCKTNOSUPPORT",
_ => "",
}
}
#[cfg(windows)]
fn get_os_error_code(errno: i32) -> &'static str {
match errno {
998 => "EACCES", // ERROR_NOACCESS
10013 => "EACCES", // WSAEACCES
1920 => "EACCES", // ERROR_CANT_ACCESS_FILE
1227 => "EADDRINUSE", // ERROR_ADDRESS_ALREADY_ASSOCIATED
10048 => "EADDRINUSE", // WSAEADDRINUSE
10049 => "EADDRNOTAVAIL", // WSAEADDRNOTAVAIL
10047 => "EAFNOSUPPORT", // WSAEAFNOSUPPORT
10035 => "EAGAIN", // WSAEWOULDBLOCK
10037 => "EALREADY", // WSAEALREADY
1004 => "EBADF", // ERROR_INVALID_FLAGS
6 => "EBADF", // ERROR_INVALID_HANDLE
33 => "EBUSY", // ERROR_LOCK_VIOLATION
231 => "EBUSY", // ERROR_PIPE_BUSY
32 => "EBUSY", // ERROR_SHARING_VIOLATION
995 => "ECANCELED", // ERROR_OPERATION_ABORTED
10004 => "ECANCELED", // WSAEINTR
1236 => "ECONNABORTED", // ERROR_CONNECTION_ABORTED
10053 => "ECONNABORTED", // WSAECONNABORTED
1225 => "ECONNREFUSED", // ERROR_CONNECTION_REFUSED
10061 => "ECONNREFUSED", // WSAECONNREFUSED
64 => "ECONNRESET", // ERROR_NETNAME_DELETED
10054 => "ECONNRESET", // WSAECONNRESET
183 => "EEXIST", // ERROR_ALREADY_EXISTS
80 => "EEXIST", // ERROR_FILE_EXISTS
111 => "EFAULT", // ERROR_BUFFER_OVERFLOW
10014 => "EFAULT", // WSAEFAULT
1232 => "EHOSTUNREACH", // ERROR_HOST_UNREACHABLE
10065 => "EHOSTUNREACH", // WSAEHOSTUNREACH
122 => "EINVAL", // ERROR_INSUFFICIENT_BUFFER
13 => "EINVAL", // ERROR_INVALID_DATA
87 => "EINVAL", // ERROR_INVALID_PARAMETER
1464 => "EINVAL", // ERROR_SYMLINK_NOT_SUPPORTED
10022 => "EINVAL", // WSAEINVAL
10046 => "EINVAL", // WSAEPFNOSUPPORT
1102 => "EIO", // ERROR_BEGINNING_OF_MEDIA
1111 => "EIO", // ERROR_BUS_RESET
23 => "EIO", // ERROR_CRC
1166 => "EIO", // ERROR_DEVICE_DOOR_OPEN
1165 => "EIO", // ERROR_DEVICE_REQUIRES_CLEANING
1393 => "EIO", // ERROR_DISK_CORRUPT
1129 => "EIO", // ERROR_EOM_OVERFLOW
1101 => "EIO", // ERROR_FILEMARK_DETECTED
31 => "EIO", // ERROR_GEN_FAILURE
1106 => "EIO", // ERROR_INVALID_BLOCK_LENGTH
1117 => "EIO", // ERROR_IO_DEVICE
1104 => "EIO", // ERROR_NO_DATA_DETECTED
205 => "EIO", // ERROR_NO_SIGNAL_SENT
110 => "EIO", // ERROR_OPEN_FAILED
1103 => "EIO", // ERROR_SETMARK_DETECTED
156 => "EIO", // ERROR_SIGNAL_REFUSED
10056 => "EISCONN", // WSAEISCONN
1921 => "ELOOP", // ERROR_CANT_RESOLVE_FILENAME
4 => "EMFILE", // ERROR_TOO_MANY_OPEN_FILES
10024 => "EMFILE", // WSAEMFILE
10040 => "EMSGSIZE", // WSAEMSGSIZE
206 => "ENAMETOOLONG", // ERROR_FILENAME_EXCED_RANGE
1231 => "ENETUNREACH", // ERROR_NETWORK_UNREACHABLE
10051 => "ENETUNREACH", // WSAENETUNREACH
10055 => "ENOBUFS", // WSAENOBUFS
161 => "ENOENT", // ERROR_BAD_PATHNAME
267 => "ENOENT", // ERROR_DIRECTORY
203 => "ENOENT", // ERROR_ENVVAR_NOT_FOUND
2 => "ENOENT", // ERROR_FILE_NOT_FOUND
123 => "ENOENT", // ERROR_INVALID_NAME
15 => "ENOENT", // ERROR_INVALID_DRIVE
4392 => "ENOENT", // ERROR_INVALID_REPARSE_DATA
126 => "ENOENT", // ERROR_MOD_NOT_FOUND
3 => "ENOENT", // ERROR_PATH_NOT_FOUND
11001 => "ENOENT", // WSAHOST_NOT_FOUND
11004 => "ENOENT", // WSANO_DATA
8 => "ENOMEM", // ERROR_NOT_ENOUGH_MEMORY
14 => "ENOMEM", // ERROR_OUTOFMEMORY
82 => "ENOSPC", // ERROR_CANNOT_MAKE
112 => "ENOSPC", // ERROR_DISK_FULL
277 => "ENOSPC", // ERROR_EA_TABLE_FULL
1100 => "ENOSPC", // ERROR_END_OF_MEDIA
39 => "ENOSPC", // ERROR_HANDLE_DISK_FULL
2250 => "ENOTCONN", // ERROR_NOT_CONNECTED
10057 => "ENOTCONN", // WSAENOTCONN
145 => "ENOTEMPTY", // ERROR_DIR_NOT_EMPTY
10038 => "ENOTSOCK", // WSAENOTSOCK
50 => "ENOTSUP", // ERROR_NOT_SUPPORTED
5 => "EPERM", // ERROR_ACCESS_DENIED
1314 => "EPERM", // ERROR_PRIVILEGE_NOT_HELD
230 => "EPIPE", // ERROR_BAD_PIPE
232 => "EPIPE", // ERROR_NO_DATA
233 => "EPIPE", // ERROR_PIPE_NOT_CONNECTED
10058 => "EPIPE", // WSAESHUTDOWN
10043 => "EPROTONOSUPPORT", // WSAEPROTONOSUPPORT
19 => "EROFS", // ERROR_WRITE_PROTECT
121 => "ETIMEDOUT", // ERROR_SEM_TIMEOUT
10060 => "ETIMEDOUT", // WSAETIMEDOUT
17 => "EXDEV", // ERROR_NOT_SAME_DEVICE
1 => "EISDIR", // ERROR_INVALID_FUNCTION
208 => "E2BIG", // ERROR_META_EXPANSION_TOO_LONG
10044 => "ESOCKTNOSUPPORT", // WSAESOCKTNOSUPPORT
_ => "",
}
}