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