Path: blob/main/crates/wasi-common/src/snapshots/preview_1/error.rs
3120 views
use wasmtime_environ::error::format_err;12pub use super::types::{Errno, Error};34pub trait ErrorExt {5fn not_found() -> Self;6fn too_big() -> Self;7fn badf() -> Self;8fn exist() -> Self;9fn illegal_byte_sequence() -> Self;10fn invalid_argument() -> Self;11fn io() -> Self;12fn name_too_long() -> Self;13fn not_dir() -> Self;14fn not_supported() -> Self;15fn overflow() -> Self;16fn range() -> Self;17fn seek_pipe() -> Self;18fn perm() -> Self;19}2021impl ErrorExt for Error {22fn not_found() -> Self {23Errno::Noent.into()24}25fn too_big() -> Self {26Errno::TooBig.into()27}28fn badf() -> Self {29Errno::Badf.into()30}31fn exist() -> Self {32Errno::Exist.into()33}34fn illegal_byte_sequence() -> Self {35Errno::Ilseq.into()36}37fn invalid_argument() -> Self {38Errno::Inval.into()39}40fn io() -> Self {41Errno::Io.into()42}43fn name_too_long() -> Self {44Errno::Nametoolong.into()45}46fn not_dir() -> Self {47Errno::Notdir.into()48}49fn not_supported() -> Self {50Errno::Notsup.into()51}52fn overflow() -> Self {53Errno::Overflow.into()54}55fn range() -> Self {56Errno::Range.into()57}58fn seek_pipe() -> Self {59Errno::Spipe.into()60}61fn perm() -> Self {62Errno::Perm.into()63}64}6566#[cfg(unix)]67fn from_raw_os_error(err: Option<i32>) -> Option<Error> {68use rustix::io::Errno as RustixErrno;69if err.is_none() {70return None;71}72Some(match RustixErrno::from_raw_os_error(err.unwrap()) {73RustixErrno::AGAIN => Errno::Again.into(),74RustixErrno::PIPE => Errno::Pipe.into(),75RustixErrno::PERM => Errno::Perm.into(),76RustixErrno::NOENT => Errno::Noent.into(),77RustixErrno::NOMEM => Errno::Nomem.into(),78RustixErrno::TOOBIG => Errno::TooBig.into(),79RustixErrno::IO => Errno::Io.into(),80RustixErrno::BADF => Errno::Badf.into(),81RustixErrno::BUSY => Errno::Busy.into(),82RustixErrno::ACCESS => Errno::Acces.into(),83RustixErrno::FAULT => Errno::Fault.into(),84RustixErrno::NOTDIR => Errno::Notdir.into(),85RustixErrno::ISDIR => Errno::Isdir.into(),86RustixErrno::INVAL => Errno::Inval.into(),87RustixErrno::EXIST => Errno::Exist.into(),88RustixErrno::FBIG => Errno::Fbig.into(),89RustixErrno::NOSPC => Errno::Nospc.into(),90RustixErrno::SPIPE => Errno::Spipe.into(),91RustixErrno::MFILE => Errno::Mfile.into(),92RustixErrno::MLINK => Errno::Mlink.into(),93RustixErrno::NAMETOOLONG => Errno::Nametoolong.into(),94RustixErrno::NFILE => Errno::Nfile.into(),95RustixErrno::NOTEMPTY => Errno::Notempty.into(),96RustixErrno::LOOP => Errno::Loop.into(),97RustixErrno::OVERFLOW => Errno::Overflow.into(),98RustixErrno::ILSEQ => Errno::Ilseq.into(),99RustixErrno::NOTSUP => Errno::Notsup.into(),100RustixErrno::ADDRINUSE => Errno::Addrinuse.into(),101RustixErrno::CANCELED => Errno::Canceled.into(),102RustixErrno::ADDRNOTAVAIL => Errno::Addrnotavail.into(),103RustixErrno::AFNOSUPPORT => Errno::Afnosupport.into(),104RustixErrno::ALREADY => Errno::Already.into(),105RustixErrno::CONNABORTED => Errno::Connaborted.into(),106RustixErrno::CONNREFUSED => Errno::Connrefused.into(),107RustixErrno::CONNRESET => Errno::Connreset.into(),108RustixErrno::DESTADDRREQ => Errno::Destaddrreq.into(),109RustixErrno::DQUOT => Errno::Dquot.into(),110RustixErrno::HOSTUNREACH => Errno::Hostunreach.into(),111RustixErrno::INPROGRESS => Errno::Inprogress.into(),112RustixErrno::INTR => Errno::Intr.into(),113RustixErrno::ISCONN => Errno::Isconn.into(),114RustixErrno::MSGSIZE => Errno::Msgsize.into(),115RustixErrno::NETDOWN => Errno::Netdown.into(),116RustixErrno::NETRESET => Errno::Netreset.into(),117RustixErrno::NETUNREACH => Errno::Netunreach.into(),118RustixErrno::NOBUFS => Errno::Nobufs.into(),119RustixErrno::NOPROTOOPT => Errno::Noprotoopt.into(),120RustixErrno::NOTCONN => Errno::Notconn.into(),121RustixErrno::NOTSOCK => Errno::Notsock.into(),122RustixErrno::PROTONOSUPPORT => Errno::Protonosupport.into(),123RustixErrno::PROTOTYPE => Errno::Prototype.into(),124RustixErrno::STALE => Errno::Stale.into(),125RustixErrno::TIMEDOUT => Errno::Timedout.into(),126127// On some platforms.into(), these have the same value as other errno values.128#[allow(unreachable_patterns, reason = "see comment")]129RustixErrno::WOULDBLOCK => Errno::Again.into(),130#[allow(unreachable_patterns, reason = "see comment")]131RustixErrno::OPNOTSUPP => Errno::Notsup.into(),132133_ => return None,134})135}136#[cfg(windows)]137fn from_raw_os_error(raw_os_error: Option<i32>) -> Option<Error> {138use windows_sys::Win32::Foundation;139use windows_sys::Win32::Networking::WinSock;140141match raw_os_error.map(|code| code as u32) {142Some(Foundation::ERROR_BAD_ENVIRONMENT) => return Some(Errno::TooBig.into()),143Some(Foundation::ERROR_FILE_NOT_FOUND) => return Some(Errno::Noent.into()),144Some(Foundation::ERROR_PATH_NOT_FOUND) => return Some(Errno::Noent.into()),145Some(Foundation::ERROR_TOO_MANY_OPEN_FILES) => return Some(Errno::Nfile.into()),146Some(Foundation::ERROR_ACCESS_DENIED) => return Some(Errno::Acces.into()),147Some(Foundation::ERROR_SHARING_VIOLATION) => return Some(Errno::Acces.into()),148Some(Foundation::ERROR_PRIVILEGE_NOT_HELD) => return Some(Errno::Perm.into()),149Some(Foundation::ERROR_INVALID_HANDLE) => return Some(Errno::Badf.into()),150Some(Foundation::ERROR_INVALID_NAME) => return Some(Errno::Noent.into()),151Some(Foundation::ERROR_NOT_ENOUGH_MEMORY) => return Some(Errno::Nomem.into()),152Some(Foundation::ERROR_OUTOFMEMORY) => return Some(Errno::Nomem.into()),153Some(Foundation::ERROR_DIR_NOT_EMPTY) => return Some(Errno::Notempty.into()),154Some(Foundation::ERROR_NOT_READY) => return Some(Errno::Busy.into()),155Some(Foundation::ERROR_BUSY) => return Some(Errno::Busy.into()),156Some(Foundation::ERROR_NOT_SUPPORTED) => return Some(Errno::Notsup.into()),157Some(Foundation::ERROR_FILE_EXISTS) => return Some(Errno::Exist.into()),158Some(Foundation::ERROR_BROKEN_PIPE) => return Some(Errno::Pipe.into()),159Some(Foundation::ERROR_BUFFER_OVERFLOW) => return Some(Errno::Nametoolong.into()),160Some(Foundation::ERROR_NOT_A_REPARSE_POINT) => return Some(Errno::Inval.into()),161Some(Foundation::ERROR_NEGATIVE_SEEK) => return Some(Errno::Inval.into()),162Some(Foundation::ERROR_DIRECTORY) => return Some(Errno::Notdir.into()),163Some(Foundation::ERROR_ALREADY_EXISTS) => return Some(Errno::Exist.into()),164Some(Foundation::ERROR_STOPPED_ON_SYMLINK) => return Some(Errno::Loop.into()),165Some(Foundation::ERROR_DIRECTORY_NOT_SUPPORTED) => return Some(Errno::Isdir.into()),166_ => {}167}168169match raw_os_error {170Some(WinSock::WSAEWOULDBLOCK) => Some(Errno::Again.into()),171Some(WinSock::WSAECANCELLED) => Some(Errno::Canceled.into()),172Some(WinSock::WSA_E_CANCELLED) => Some(Errno::Canceled.into()),173Some(WinSock::WSAEBADF) => Some(Errno::Badf.into()),174Some(WinSock::WSAEFAULT) => Some(Errno::Fault.into()),175Some(WinSock::WSAEINVAL) => Some(Errno::Inval.into()),176Some(WinSock::WSAEMFILE) => Some(Errno::Mfile.into()),177Some(WinSock::WSAENAMETOOLONG) => Some(Errno::Nametoolong.into()),178Some(WinSock::WSAENOTEMPTY) => Some(Errno::Notempty.into()),179Some(WinSock::WSAELOOP) => Some(Errno::Loop.into()),180Some(WinSock::WSAEOPNOTSUPP) => Some(Errno::Notsup.into()),181Some(WinSock::WSAEADDRINUSE) => Some(Errno::Addrinuse.into()),182Some(WinSock::WSAEACCES) => Some(Errno::Acces.into()),183Some(WinSock::WSAEADDRNOTAVAIL) => Some(Errno::Addrnotavail.into()),184Some(WinSock::WSAEAFNOSUPPORT) => Some(Errno::Afnosupport.into()),185Some(WinSock::WSAEALREADY) => Some(Errno::Already.into()),186Some(WinSock::WSAECONNABORTED) => Some(Errno::Connaborted.into()),187Some(WinSock::WSAECONNREFUSED) => Some(Errno::Connrefused.into()),188Some(WinSock::WSAECONNRESET) => Some(Errno::Connreset.into()),189Some(WinSock::WSAEDESTADDRREQ) => Some(Errno::Destaddrreq.into()),190Some(WinSock::WSAEDQUOT) => Some(Errno::Dquot.into()),191Some(WinSock::WSAEHOSTUNREACH) => Some(Errno::Hostunreach.into()),192Some(WinSock::WSAEINPROGRESS) => Some(Errno::Inprogress.into()),193Some(WinSock::WSAEINTR) => Some(Errno::Intr.into()),194Some(WinSock::WSAEISCONN) => Some(Errno::Isconn.into()),195Some(WinSock::WSAEMSGSIZE) => Some(Errno::Msgsize.into()),196Some(WinSock::WSAENETDOWN) => Some(Errno::Netdown.into()),197Some(WinSock::WSAENETRESET) => Some(Errno::Netreset.into()),198Some(WinSock::WSAENETUNREACH) => Some(Errno::Netunreach.into()),199Some(WinSock::WSAENOBUFS) => Some(Errno::Nobufs.into()),200Some(WinSock::WSAENOPROTOOPT) => Some(Errno::Noprotoopt.into()),201Some(WinSock::WSAENOTCONN) => Some(Errno::Notconn.into()),202Some(WinSock::WSAENOTSOCK) => Some(Errno::Notsock.into()),203Some(WinSock::WSAEPROTONOSUPPORT) => Some(Errno::Protonosupport.into()),204Some(WinSock::WSAEPROTOTYPE) => Some(Errno::Prototype.into()),205Some(WinSock::WSAESTALE) => Some(Errno::Stale.into()),206Some(WinSock::WSAETIMEDOUT) => Some(Errno::Timedout.into()),207_ => None,208}209}210211impl From<std::io::Error> for Error {212fn from(err: std::io::Error) -> Error {213match from_raw_os_error(err.raw_os_error()) {214Some(errno) => errno,215None => match err.kind() {216std::io::ErrorKind::NotFound => Errno::Noent.into(),217std::io::ErrorKind::PermissionDenied => Errno::Perm.into(),218std::io::ErrorKind::AlreadyExists => Errno::Exist.into(),219std::io::ErrorKind::InvalidInput => Errno::Inval.into(),220std::io::ErrorKind::WouldBlock => Errno::Again.into(),221_ => Error::trap(format_err!(err).context("Unknown OS error")),222},223}224}225}226227impl From<cap_rand::Error> for Error {228fn from(err: cap_rand::Error) -> Error {229// I picked Error::Io as a 'reasonable default', FIXME dan is this ok?230from_raw_os_error(err.raw_os_error()).unwrap_or_else(|| Error::from(Errno::Io))231}232}233234impl From<wiggle::GuestError> for Error {235fn from(err: wiggle::GuestError) -> Error {236use wiggle::GuestError::*;237match err {238InvalidFlagValue { .. } => Errno::Inval.into(),239InvalidEnumValue { .. } => Errno::Inval.into(),240// As per241// https://github.com/WebAssembly/wasi/blob/main/legacy/tools/witx-docs.md#pointers242//243// > If a misaligned pointer is passed to a function, the function244// > shall trap.245// >246// > If an out-of-bounds pointer is passed to a function and the247// > function needs to dereference it, the function shall trap.248//249// so this turns OOB and misalignment errors into traps.250PtrOverflow { .. } | PtrOutOfBounds { .. } | PtrNotAligned { .. } => {251Error::trap(err.into())252}253InvalidUtf8 { .. } => Errno::Ilseq.into(),254TryFromIntError { .. } => Errno::Overflow.into(),255SliceLengthsDiffer { .. } => Errno::Fault.into(),256InFunc { err, .. } => Error::from(*err),257}258}259}260261impl From<std::num::TryFromIntError> for Error {262fn from(_err: std::num::TryFromIntError) -> Error {263Errno::Overflow.into()264}265}266267268