1
0
Fork 0
forked from wry/wry
wry/utils/src/oserror.rs

242 lines
8.5 KiB
Rust

use {
std::{
error::Error,
fmt::{Display, Formatter},
sync::LazyLock,
},
uapi::{
Errno,
c::{self, c_int},
},
};
static ERRORS: LazyLock<&'static [Option<&'static str>]> = LazyLock::new(|| {
static MSGS: &[(c::c_int, &str)] = &[
(c::EWOULDBLOCK, "Operation would block"),
(c::ENOTSUP, "Not supported"),
(c::EHWPOISON, "Memory page has hardware error"),
(c::ERFKILL, "Operation not possible due to RF-kill"),
(c::EKEYREJECTED, "Key was rejected by service"),
(c::EKEYREVOKED, "Key has been revoked"),
(c::EKEYEXPIRED, "Key has expired"),
(c::ENOKEY, "Required key not available"),
(c::EMEDIUMTYPE, "Wrong medium type"),
(c::ENOMEDIUM, "No medium found"),
(c::EREMOTEIO, "Remote I/O error"),
(c::EISNAM, "Is a named type file"),
(c::ENAVAIL, "No XENIX semaphores available"),
(c::ENOTNAM, "Not a XENIX named type file"),
(c::EUCLEAN, "Structure needs cleaning"),
(c::ESTRPIPE, "Streams pipe error"),
(c::ELIBEXEC, "Cannot exec a shared library directly"),
(
c::ELIBMAX,
"Attempting to link in too many shared libraries",
),
(c::ELIBSCN, ".lib section in a.out corrupted"),
(c::ELIBBAD, "Accessing a corrupted shared library"),
(c::ELIBACC, "Can not access a needed shared library"),
(c::EREMCHG, "Remote address changed"),
(c::EBADFD, "File descriptor in bad state"),
(c::ENOTUNIQ, "Name not unique on network"),
(c::EDOTDOT, "RFS specific error"),
(c::ECOMM, "Communication error on send"),
(c::ESRMNT, "Srmount error"),
(c::EADV, "Advertise error"),
(c::ENOPKG, "Package not installed"),
(c::ENONET, "Machine is not on the network"),
(c::EBFONT, "Bad font file format"),
(c::EBADSLT, "Invalid slot"),
(c::EBADRQC, "Invalid request code"),
(c::ENOANO, "No anode"),
(c::EXFULL, "Exchange full"),
(c::EBADR, "Invalid request descriptor"),
(c::EBADE, "Invalid exchange"),
(c::EL2HLT, "Level 2 halted"),
(c::ENOCSI, "No CSI structure available"),
(c::EUNATCH, "Protocol driver not attached"),
(c::ELNRNG, "Link number out of range"),
(c::EL3RST, "Level 3 reset"),
(c::EL3HLT, "Level 3 halted"),
(c::EL2NSYNC, "Level 2 not synchronized"),
(c::ECHRNG, "Channel number out of range"),
(c::ERESTART, "Interrupted system call should be restarted"),
(c::ENOTRECOVERABLE, "State not recoverable"),
(c::EOWNERDEAD, "Owner died"),
(c::ECANCELED, "Operation canceled"),
(c::ETIME, "Timer expired"),
(c::EPROTO, "Protocol error"),
(c::EOVERFLOW, "Value too large for defined data type"),
(c::ENOSTR, "Device not a stream"),
(c::ENOSR, "Out of streams resources"),
(c::ENOMSG, "No message of desired type"),
(c::ENOLINK, "Link has been severed"),
(c::ENODATA, "No data available"),
(c::EMULTIHOP, "Multihop attempted"),
(c::EIDRM, "Identifier removed"),
(c::EBADMSG, "Bad message"),
(
c::EILSEQ,
"Invalid or incomplete multibyte or wide character",
),
(c::ENOSYS, "Function not implemented"),
(c::ENOLCK, "No locks available"),
(c::EREMOTE, "Object is remote"),
(c::ESTALE, "Stale file handle"),
(c::EDQUOT, "Disk quota exceeded"),
(c::EUSERS, "Too many users"),
(c::ENOTEMPTY, "Directory not empty"),
(c::EHOSTUNREACH, "No route to host"),
(c::EHOSTDOWN, "Host is down"),
(c::ENAMETOOLONG, "File name too long"),
(c::ELOOP, "Too many levels of symbolic links"),
(c::ECONNREFUSED, "Connection refused"),
(c::ETIMEDOUT, "Connection timed out"),
(c::ETOOMANYREFS, "Too many references: cannot splice"),
(
c::ESHUTDOWN,
"Cannot send after transport endpoint shutdown",
),
(c::EDESTADDRREQ, "Destination address required"),
(c::ENOTCONN, "Transport endpoint is not connected"),
(c::EISCONN, "Transport endpoint is already connected"),
(c::ENOBUFS, "No buffer space available"),
(c::ECONNRESET, "Connection reset by peer"),
(c::ECONNABORTED, "Software caused connection abort"),
(c::ENETRESET, "Network dropped connection on reset"),
(c::ENETUNREACH, "Network is unreachable"),
(c::ENETDOWN, "Network is down"),
(c::EADDRNOTAVAIL, "Cannot assign requested address"),
(c::EADDRINUSE, "Address already in use"),
(c::EAFNOSUPPORT, "Address family not supported by protocol"),
(c::EPFNOSUPPORT, "Protocol family not supported"),
(c::EOPNOTSUPP, "Operation not supported"),
(c::ESOCKTNOSUPPORT, "Socket type not supported"),
(c::EPROTONOSUPPORT, "Protocol not supported"),
(c::ENOPROTOOPT, "Protocol not available"),
(c::EPROTOTYPE, "Protocol wrong type for socket"),
(c::EMSGSIZE, "Message too long"),
(c::ENOTSOCK, "Socket operation on non-socket"),
(c::EALREADY, "Operation already in progress"),
(c::EINPROGRESS, "Operation now in progress"),
(c::EAGAIN, "Resource temporarily unavailable"),
(c::ERANGE, "Numerical result out of range"),
(c::EDOM, "Numerical argument out of domain"),
(c::EPIPE, "Broken pipe"),
(c::EMLINK, "Too many links"),
(c::EROFS, "Read-only file system"),
(c::ESPIPE, "Illegal seek"),
(c::ENOSPC, "No space left on device"),
(c::EFBIG, "File too large"),
(c::ETXTBSY, "Text file busy"),
(c::ENOTTY, "Inappropriate ioctl for device"),
(c::ENFILE, "Too many open files in system"),
(c::EMFILE, "Too many open files"),
(c::EINVAL, "Invalid argument"),
(c::EISDIR, "Is a directory"),
(c::ENOTDIR, "Not a directory"),
(c::ENODEV, "No such device"),
(c::EXDEV, "Invalid cross-device link"),
(c::EEXIST, "File exists"),
(c::EBUSY, "Device or resource busy"),
(c::ENOTBLK, "Block device required"),
(c::EFAULT, "Bad address"),
(c::EACCES, "Permission denied"),
(c::ENOMEM, "Cannot allocate memory"),
(c::EDEADLK, "Resource deadlock avoided"),
(c::ECHILD, "No child processes"),
(c::EBADF, "Bad file descriptor"),
(c::ENOEXEC, "Exec format error"),
(c::E2BIG, "Argument list too long"),
(c::ENXIO, "No such device or address"),
(c::EIO, "Input/output error"),
(c::EINTR, "Interrupted system call"),
(c::ESRCH, "No such process"),
(c::ENOENT, "No such file or directory"),
(c::EPERM, "Operation not permitted"),
];
let mut res = vec![];
for &(idx, msg) in MSGS {
let idx = idx as usize;
while res.len() <= idx {
res.push(None);
}
res[idx] = Some(msg);
}
res.leak()
});
#[derive(Debug, Eq, PartialEq)]
pub struct OsError(pub c::c_int);
impl From<c::c_int> for OsError {
fn from(v: c_int) -> Self {
Self(v)
}
}
impl From<std::io::Error> for OsError {
fn from(v: std::io::Error) -> Self {
match v.raw_os_error() {
Some(v) => Self(v),
None => Self(c::EINVAL),
}
}
}
impl Default for OsError {
fn default() -> Self {
OsError(Errno::default().0)
}
}
impl Error for OsError {}
impl Display for OsError {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
let msg = ERRORS
.get(self.0 as usize)
.and_then(|v| *v)
.unwrap_or("unknown error");
write!(f, "{} (os error {})", msg, self.0)
}
}
pub trait OsErrorExt {
type Container;
fn to_os_error(self) -> Self::Container;
}
impl<T> OsErrorExt for Result<T, Errno> {
type Container = Result<T, OsError>;
fn to_os_error(self) -> Self::Container {
match self {
Ok(v) => Ok(v),
Err(e) => Err(OsError(e.0)),
}
}
}
pub trait OsErrorExt2 {
type T;
fn map_os_err<F, O>(self, op: O) -> Result<Self::T, F>
where
O: FnOnce(OsError) -> F;
}
impl<T> OsErrorExt2 for Result<T, Errno> {
type T = T;
fn map_os_err<F, O>(self, op: O) -> Result<T, F>
where
O: FnOnce(OsError) -> F,
{
match self {
Ok(t) => Ok(t),
Err(e) => Err(op(OsError(e.0))),
}
}
}