[wasi-common]: clean up error handling (#1253)

* Introduce WasiCtxBuilderError error type

`WasiCtxBuilderError` is the `wasi-common` client-facing error type
which is exclusively thrown when building a new `WasiCtx` instance.
As such, building such an instance should not require the client to
understand different WASI errno values as was assumed until now.

This commit is a first step at streamlining error handling in
`wasi-common` and makes way for the `wiggle` crate.

When adding the `WasiCtxBuilderError`, I've had to do two things of
notable importance:
1. I've removed a couple of `ok_or` calls in `WasiCtxBuilder::build`
   and replaced them with `unwrap`s, following the same pattern in
   different builder methods above. This is fine since we _always_
   operate on non-empty `Option`s in `WasiCtxBuilder` thus `unwrap`ing
   will never fail. On the other hand, this might be a good opportunity
   to rethink the structure of our builder, and how we good remove
   the said `Option`s especially since we always populate them with
   empty containers to begin with. I understand this is to make
   chaining of builder methods easier which take and return `&mut self`
   and the same applies to `WasiCtxBuilder::build(&mut self)` method,
   but perhaps it would more cleanly signal the intentions if we simply
   moved `WasiCtxBuilder` instance around. Food for thought!
2. Methods specific to determining rights of passed around `std::fs::File`
   objects when populating `WasiCtx` `FdEntry` entities now return
   `io::Error` directly so that we can reuse them in `WasiCtxBuilder` methods
   (returning `WasiCtxBuilderError` error type), and in syscalls
   (returning WASI errno).

* Return WasiError directly in syscalls

Also, removes `error::Error` type altogether. Now, `io::Error` and
related are automatically converted to their corresponding WASI
errno value encapsulated as `WasiError`.

While here, it made sense to me to move `WasiError` to `wasi` module
which will align itself well with the upcoming changes introduced
by `wiggle`. To different standard `Result` from WASI specific, I've
created a helper alias `WasiResult` also residing in `wasi` module.

* Update wig

* Add from ffi::NulError and pass context to NotADirectory

* Add dummy commit to test CI
This commit is contained in:
Jakub Konka
2020-03-09 22:58:55 +01:00
committed by GitHub
parent 963bf0e255
commit 773915b4bf
59 changed files with 1465 additions and 1552 deletions

View File

@@ -1,16 +1,44 @@
use crate::fdentry::{Descriptor, FdEntry};
use crate::sys::fdentry_impl::OsHandle;
use crate::virtfs::{VirtualDir, VirtualDirEntry};
use crate::{wasi, Error, Result};
use crate::wasi::{self, WasiError, WasiResult};
use std::borrow::Borrow;
use std::collections::HashMap;
use std::env;
use std::ffi::{CString, OsString};
use std::ffi::{self, CString, OsString};
use std::fs::File;
use std::path::{Path, PathBuf};
use std::{env, io, string};
/// Possible errors when `WasiCtxBuilder` fails building
/// `WasiCtx`.
#[derive(Debug, thiserror::Error)]
pub enum WasiCtxBuilderError {
/// General I/O error was encountered.
#[error("general I/O error encountered: {0}")]
Io(#[from] io::Error),
/// Provided sequence of bytes was not a valid UTF-8.
#[error("provided sequence is not valid UTF-8: {0}")]
InvalidUtf8(#[from] string::FromUtf8Error),
/// Provided sequence of bytes was not a valid UTF-16.
///
/// This error is expected to only occur on Windows hosts.
#[error("provided sequence is not valid UTF-16: {0}")]
InvalidUtf16(#[from] string::FromUtf16Error),
/// Provided sequence of bytes contained an unexpected NUL byte.
#[error("provided sequence contained an unexpected NUL byte")]
UnexpectedNul(#[from] ffi::NulError),
/// Provided `File` is not a directory.
#[error("preopened directory path {} is not a directory", .0.display())]
NotADirectory(PathBuf),
/// `WasiCtx` has too many opened files.
#[error("context object has too many opened files")]
TooManyFilesOpen,
}
type WasiCtxBuilderResult<T> = std::result::Result<T, WasiCtxBuilderError>;
enum PendingFdEntry {
Thunk(fn() -> Result<FdEntry>),
Thunk(fn() -> io::Result<FdEntry>),
File(File),
}
@@ -20,7 +48,7 @@ impl std::fmt::Debug for PendingFdEntry {
Self::Thunk(f) => write!(
fmt,
"PendingFdEntry::Thunk({:p})",
f as *const fn() -> Result<FdEntry>
f as *const fn() -> io::Result<FdEntry>
),
Self::File(f) => write!(fmt, "PendingFdEntry::File({:?})", f),
}
@@ -46,17 +74,29 @@ impl From<OsString> for PendingCString {
}
impl PendingCString {
fn into_string(self) -> Result<String> {
match self {
Self::Bytes(v) => String::from_utf8(v).map_err(|_| Error::EILSEQ),
Self::OsString(s) => s.into_string().map_err(|_| Error::EILSEQ),
fn into_string(self) -> WasiCtxBuilderResult<String> {
let res = match self {
Self::Bytes(v) => String::from_utf8(v)?,
#[cfg(unix)]
Self::OsString(s) => {
use std::os::unix::ffi::OsStringExt;
String::from_utf8(s.into_vec())?
}
#[cfg(windows)]
Self::OsString(s) => {
use std::os::windows::ffi::OsStrExt;
let bytes: Vec<u16> = s.encode_wide().collect();
String::from_utf16(&bytes)?
}
};
Ok(res)
}
/// Create a `CString` containing valid UTF-8, or fail with `Error::EILSEQ`.
fn into_utf8_cstring(self) -> Result<CString> {
self.into_string()
.and_then(|s| CString::new(s).map_err(|_| Error::EILSEQ))
/// Create a `CString` containing valid UTF-8.
fn into_utf8_cstring(self) -> WasiCtxBuilderResult<CString> {
let s = self.into_string()?;
let s = CString::new(s)?;
Ok(s)
}
}
@@ -87,8 +127,7 @@ impl WasiCtxBuilder {
/// Add arguments to the command-line arguments list.
///
/// Arguments must be valid UTF-8 with no NUL bytes, or else `WasiCtxBuilder::build()` will fail
/// with `Error::EILSEQ`.
/// Arguments must be valid UTF-8 with no NUL bytes, or else `WasiCtxBuilder::build()` will fail.
pub fn args<S: AsRef<[u8]>>(&mut self, args: impl IntoIterator<Item = S>) -> &mut Self {
self.args
.as_mut()
@@ -99,8 +138,7 @@ impl WasiCtxBuilder {
/// Add an argument to the command-line arguments list.
///
/// Arguments must be valid UTF-8 with no NUL bytes, or else `WasiCtxBuilder::build()` will fail
/// with `Error::EILSEQ`.
/// Arguments must be valid UTF-8 with no NUL bytes, or else `WasiCtxBuilder::build()` will fail.
pub fn arg<S: AsRef<[u8]>>(&mut self, arg: S) -> &mut Self {
self.args
.as_mut()
@@ -112,7 +150,7 @@ impl WasiCtxBuilder {
/// Inherit the command-line arguments from the host process.
///
/// If any arguments from the host process contain invalid UTF-8, `WasiCtxBuilder::build()` will
/// fail with `Error::EILSEQ`.
/// fail.
pub fn inherit_args(&mut self) -> &mut Self {
let args = self.args.as_mut().unwrap();
args.clear();
@@ -159,8 +197,7 @@ impl WasiCtxBuilder {
/// Inherit the environment variables from the host process.
///
/// If any environment variables from the host process contain invalid Unicode (UTF-16 for
/// Windows, UTF-8 for other platforms), `WasiCtxBuilder::build()` will fail with
/// `Error::EILSEQ`.
/// Windows, UTF-8 for other platforms), `WasiCtxBuilder::build()` will fail.
pub fn inherit_env(&mut self) -> &mut Self {
let env = self.env.as_mut().unwrap();
env.clear();
@@ -171,7 +208,7 @@ impl WasiCtxBuilder {
/// Add an entry to the environment.
///
/// Environment variable keys and values must be valid UTF-8 with no NUL bytes, or else
/// `WasiCtxBuilder::build()` will fail with `Error::EILSEQ`.
/// `WasiCtxBuilder::build()` will fail.
pub fn env<S: AsRef<[u8]>>(&mut self, k: S, v: S) -> &mut Self {
self.env
.as_mut()
@@ -183,7 +220,7 @@ impl WasiCtxBuilder {
/// Add entries to the environment.
///
/// Environment variable keys and values must be valid UTF-8 with no NUL bytes, or else
/// `WasiCtxBuilder::build()` will fail with `Error::EILSEQ`.
/// `WasiCtxBuilder::build()` will fail.
pub fn envs<S: AsRef<[u8]>, T: Borrow<(S, S)>>(
&mut self,
envs: impl IntoIterator<Item = T>,
@@ -270,22 +307,22 @@ impl WasiCtxBuilder {
/// Build a `WasiCtx`, consuming this `WasiCtxBuilder`.
///
/// If any of the arguments or environment variables in this builder cannot be converted into
/// `CString`s, either due to NUL bytes or Unicode conversions, this returns `Error::EILSEQ`.
pub fn build(&mut self) -> Result<WasiCtx> {
/// `CString`s, either due to NUL bytes or Unicode conversions, this will fail.
pub fn build(&mut self) -> WasiCtxBuilderResult<WasiCtx> {
// Process arguments and environment variables into `CString`s, failing quickly if they
// contain any NUL bytes, or if conversion from `OsString` fails.
let args = self
.args
.take()
.ok_or(Error::EINVAL)?
.unwrap()
.into_iter()
.map(|arg| arg.into_utf8_cstring())
.collect::<Result<Vec<CString>>>()?;
.collect::<WasiCtxBuilderResult<Vec<CString>>>()?;
let env = self
.env
.take()
.ok_or(Error::EINVAL)?
.unwrap()
.into_iter()
.map(|(k, v)| {
k.into_string().and_then(|mut pair| {
@@ -294,15 +331,16 @@ impl WasiCtxBuilder {
pair.push_str(v.as_str());
// We have valid UTF-8, but the keys and values have not yet been checked
// for NULs, so we do a final check here.
CString::new(pair).map_err(|_| Error::EILSEQ)
let s = CString::new(pair)?;
Ok(s)
})
})
})
.collect::<Result<Vec<CString>>>()?;
.collect::<WasiCtxBuilderResult<Vec<CString>>>()?;
let mut fds: HashMap<wasi::__wasi_fd_t, FdEntry> = HashMap::new();
// Populate the non-preopen fds.
for (fd, pending) in self.fds.take().ok_or(Error::EINVAL)? {
for (fd, pending) in self.fds.take().unwrap() {
log::debug!("WasiCtx inserting ({:?}, {:?})", fd, pending);
match pending {
PendingFdEntry::Thunk(f) => {
@@ -317,20 +355,22 @@ impl WasiCtxBuilder {
// so we start from there. This variable is initially 2, though, because the loop
// immediately does the increment and check for overflow.
let mut preopen_fd: wasi::__wasi_fd_t = 2;
for (guest_path, dir) in self.preopens.take().ok_or(Error::EINVAL)? {
for (guest_path, dir) in self.preopens.take().unwrap() {
// We do the increment at the beginning of the loop body, so that we don't overflow
// unnecessarily if we have exactly the maximum number of file descriptors.
preopen_fd = preopen_fd.checked_add(1).ok_or(Error::ENFILE)?;
preopen_fd = preopen_fd
.checked_add(1)
.ok_or(WasiCtxBuilderError::TooManyFilesOpen)?;
match &dir {
Descriptor::OsHandle(handle) => {
if !handle.metadata()?.is_dir() {
return Err(Error::EBADF);
return Err(WasiCtxBuilderError::NotADirectory(guest_path));
}
}
Descriptor::VirtualFile(virt) => {
if virt.get_file_type() != wasi::__WASI_FILETYPE_DIRECTORY {
return Err(Error::EBADF);
return Err(WasiCtxBuilderError::NotADirectory(guest_path));
}
}
Descriptor::Stdin | Descriptor::Stdout | Descriptor::Stderr => {
@@ -341,7 +381,9 @@ impl WasiCtxBuilder {
// We don't currently allow setting file descriptors other than 0-2, but this will avoid
// collisions if we restore that functionality in the future.
while fds.contains_key(&preopen_fd) {
preopen_fd = preopen_fd.checked_add(1).ok_or(Error::ENFILE)?;
preopen_fd = preopen_fd
.checked_add(1)
.ok_or(WasiCtxBuilderError::TooManyFilesOpen)?;
}
let mut fe = FdEntry::from(dir)?;
fe.preopen_path = Some(guest_path);
@@ -369,7 +411,7 @@ impl WasiCtx {
/// - Environment variables are inherited from the host process.
///
/// To override these behaviors, use `WasiCtxBuilder`.
pub fn new<S: AsRef<[u8]>>(args: impl IntoIterator<Item = S>) -> Result<Self> {
pub fn new<S: AsRef<[u8]>>(args: impl IntoIterator<Item = S>) -> WasiCtxBuilderResult<Self> {
WasiCtxBuilder::new()
.args(args)
.inherit_stdio()
@@ -383,30 +425,30 @@ impl WasiCtx {
}
/// Get an immutable `FdEntry` corresponding to the specified raw WASI `fd`.
pub(crate) unsafe fn get_fd_entry(&self, fd: wasi::__wasi_fd_t) -> Result<&FdEntry> {
self.fds.get(&fd).ok_or(Error::EBADF)
pub(crate) unsafe fn get_fd_entry(&self, fd: wasi::__wasi_fd_t) -> WasiResult<&FdEntry> {
self.fds.get(&fd).ok_or(WasiError::EBADF)
}
/// Get a mutable `FdEntry` corresponding to the specified raw WASI `fd`.
pub(crate) unsafe fn get_fd_entry_mut(
&mut self,
fd: wasi::__wasi_fd_t,
) -> Result<&mut FdEntry> {
self.fds.get_mut(&fd).ok_or(Error::EBADF)
) -> WasiResult<&mut FdEntry> {
self.fds.get_mut(&fd).ok_or(WasiError::EBADF)
}
/// Insert the specified `FdEntry` into the `WasiCtx` object.
///
/// The `FdEntry` will automatically get another free raw WASI `fd` assigned. Note that
/// the two subsequent free raw WASI `fd`s do not have to be stored contiguously.
pub(crate) fn insert_fd_entry(&mut self, fe: FdEntry) -> Result<wasi::__wasi_fd_t> {
pub(crate) fn insert_fd_entry(&mut self, fe: FdEntry) -> WasiResult<wasi::__wasi_fd_t> {
// Never insert where stdio handles are expected to be.
let mut fd = 3;
while self.fds.contains_key(&fd) {
if let Some(next_fd) = fd.checked_add(1) {
fd = next_fd;
} else {
return Err(Error::EMFILE);
return Err(WasiError::EMFILE);
}
}
self.fds.insert(fd, fe);
@@ -424,7 +466,7 @@ impl WasiCtx {
}
/// Remove `FdEntry` corresponding to the specified raw WASI `fd` from the `WasiCtx` object.
pub(crate) fn remove_fd_entry(&mut self, fd: wasi::__wasi_fd_t) -> Result<FdEntry> {
self.fds.remove(&fd).ok_or(Error::EBADF)
pub(crate) fn remove_fd_entry(&mut self, fd: wasi::__wasi_fd_t) -> WasiResult<FdEntry> {
self.fds.remove(&fd).ok_or(WasiError::EBADF)
}
}

View File

@@ -1,249 +0,0 @@
// Due to https://github.com/rust-lang/rust/issues/64247
#![allow(clippy::use_self)]
use crate::wasi;
use std::convert::Infallible;
use std::num::TryFromIntError;
use std::{ffi, str};
use thiserror::Error;
#[derive(Clone, Copy, Debug, Error, Eq, PartialEq)]
#[repr(u16)]
#[error("{:?} ({})", self, wasi::strerror(*self as wasi::__wasi_errno_t))]
pub enum WasiError {
ESUCCESS = wasi::__WASI_ERRNO_SUCCESS,
E2BIG = wasi::__WASI_ERRNO_2BIG,
EACCES = wasi::__WASI_ERRNO_ACCES,
EADDRINUSE = wasi::__WASI_ERRNO_ADDRINUSE,
EADDRNOTAVAIL = wasi::__WASI_ERRNO_ADDRNOTAVAIL,
EAFNOSUPPORT = wasi::__WASI_ERRNO_AFNOSUPPORT,
EAGAIN = wasi::__WASI_ERRNO_AGAIN,
EALREADY = wasi::__WASI_ERRNO_ALREADY,
EBADF = wasi::__WASI_ERRNO_BADF,
EBADMSG = wasi::__WASI_ERRNO_BADMSG,
EBUSY = wasi::__WASI_ERRNO_BUSY,
ECANCELED = wasi::__WASI_ERRNO_CANCELED,
ECHILD = wasi::__WASI_ERRNO_CHILD,
ECONNABORTED = wasi::__WASI_ERRNO_CONNABORTED,
ECONNREFUSED = wasi::__WASI_ERRNO_CONNREFUSED,
ECONNRESET = wasi::__WASI_ERRNO_CONNRESET,
EDEADLK = wasi::__WASI_ERRNO_DEADLK,
EDESTADDRREQ = wasi::__WASI_ERRNO_DESTADDRREQ,
EDOM = wasi::__WASI_ERRNO_DOM,
EDQUOT = wasi::__WASI_ERRNO_DQUOT,
EEXIST = wasi::__WASI_ERRNO_EXIST,
EFAULT = wasi::__WASI_ERRNO_FAULT,
EFBIG = wasi::__WASI_ERRNO_FBIG,
EHOSTUNREACH = wasi::__WASI_ERRNO_HOSTUNREACH,
EIDRM = wasi::__WASI_ERRNO_IDRM,
EILSEQ = wasi::__WASI_ERRNO_ILSEQ,
EINPROGRESS = wasi::__WASI_ERRNO_INPROGRESS,
EINTR = wasi::__WASI_ERRNO_INTR,
EINVAL = wasi::__WASI_ERRNO_INVAL,
EIO = wasi::__WASI_ERRNO_IO,
EISCONN = wasi::__WASI_ERRNO_ISCONN,
EISDIR = wasi::__WASI_ERRNO_ISDIR,
ELOOP = wasi::__WASI_ERRNO_LOOP,
EMFILE = wasi::__WASI_ERRNO_MFILE,
EMLINK = wasi::__WASI_ERRNO_MLINK,
EMSGSIZE = wasi::__WASI_ERRNO_MSGSIZE,
EMULTIHOP = wasi::__WASI_ERRNO_MULTIHOP,
ENAMETOOLONG = wasi::__WASI_ERRNO_NAMETOOLONG,
ENETDOWN = wasi::__WASI_ERRNO_NETDOWN,
ENETRESET = wasi::__WASI_ERRNO_NETRESET,
ENETUNREACH = wasi::__WASI_ERRNO_NETUNREACH,
ENFILE = wasi::__WASI_ERRNO_NFILE,
ENOBUFS = wasi::__WASI_ERRNO_NOBUFS,
ENODEV = wasi::__WASI_ERRNO_NODEV,
ENOENT = wasi::__WASI_ERRNO_NOENT,
ENOEXEC = wasi::__WASI_ERRNO_NOEXEC,
ENOLCK = wasi::__WASI_ERRNO_NOLCK,
ENOLINK = wasi::__WASI_ERRNO_NOLINK,
ENOMEM = wasi::__WASI_ERRNO_NOMEM,
ENOMSG = wasi::__WASI_ERRNO_NOMSG,
ENOPROTOOPT = wasi::__WASI_ERRNO_NOPROTOOPT,
ENOSPC = wasi::__WASI_ERRNO_NOSPC,
ENOSYS = wasi::__WASI_ERRNO_NOSYS,
ENOTCONN = wasi::__WASI_ERRNO_NOTCONN,
ENOTDIR = wasi::__WASI_ERRNO_NOTDIR,
ENOTEMPTY = wasi::__WASI_ERRNO_NOTEMPTY,
ENOTRECOVERABLE = wasi::__WASI_ERRNO_NOTRECOVERABLE,
ENOTSOCK = wasi::__WASI_ERRNO_NOTSOCK,
ENOTSUP = wasi::__WASI_ERRNO_NOTSUP,
ENOTTY = wasi::__WASI_ERRNO_NOTTY,
ENXIO = wasi::__WASI_ERRNO_NXIO,
EOVERFLOW = wasi::__WASI_ERRNO_OVERFLOW,
EOWNERDEAD = wasi::__WASI_ERRNO_OWNERDEAD,
EPERM = wasi::__WASI_ERRNO_PERM,
EPIPE = wasi::__WASI_ERRNO_PIPE,
EPROTO = wasi::__WASI_ERRNO_PROTO,
EPROTONOSUPPORT = wasi::__WASI_ERRNO_PROTONOSUPPORT,
EPROTOTYPE = wasi::__WASI_ERRNO_PROTOTYPE,
ERANGE = wasi::__WASI_ERRNO_RANGE,
EROFS = wasi::__WASI_ERRNO_ROFS,
ESPIPE = wasi::__WASI_ERRNO_SPIPE,
ESRCH = wasi::__WASI_ERRNO_SRCH,
ESTALE = wasi::__WASI_ERRNO_STALE,
ETIMEDOUT = wasi::__WASI_ERRNO_TIMEDOUT,
ETXTBSY = wasi::__WASI_ERRNO_TXTBSY,
EXDEV = wasi::__WASI_ERRNO_XDEV,
ENOTCAPABLE = wasi::__WASI_ERRNO_NOTCAPABLE,
}
impl WasiError {
pub fn as_raw_errno(self) -> wasi::__wasi_errno_t {
self as wasi::__wasi_errno_t
}
}
#[derive(Debug, Error)]
pub enum Error {
#[error("WASI error code: {0}")]
Wasi(#[from] WasiError),
#[error("IO error: {0}")]
Io(#[from] std::io::Error),
}
impl From<TryFromIntError> for Error {
fn from(_: TryFromIntError) -> Self {
Self::EOVERFLOW
}
}
impl From<Infallible> for Error {
fn from(_: Infallible) -> Self {
unreachable!()
}
}
impl From<str::Utf8Error> for Error {
fn from(_: str::Utf8Error) -> Self {
Self::EILSEQ
}
}
impl From<ffi::NulError> for Error {
fn from(_: ffi::NulError) -> Self {
Self::EILSEQ
}
}
impl From<&ffi::NulError> for Error {
fn from(_: &ffi::NulError) -> Self {
Self::EILSEQ
}
}
impl Error {
pub(crate) fn as_wasi_error(&self) -> WasiError {
match self {
Self::Wasi(err) => *err,
Self::Io(err) => {
let err = match err.raw_os_error() {
Some(code) => Self::from_raw_os_error(code),
None => {
log::debug!("Inconvertible OS error: {}", err);
Self::EIO
}
};
err.as_wasi_error()
}
}
}
pub const ESUCCESS: Self = Error::Wasi(WasiError::ESUCCESS);
pub const E2BIG: Self = Error::Wasi(WasiError::E2BIG);
pub const EACCES: Self = Error::Wasi(WasiError::EACCES);
pub const EADDRINUSE: Self = Error::Wasi(WasiError::EADDRINUSE);
pub const EADDRNOTAVAIL: Self = Error::Wasi(WasiError::EADDRNOTAVAIL);
pub const EAFNOSUPPORT: Self = Error::Wasi(WasiError::EAFNOSUPPORT);
pub const EAGAIN: Self = Error::Wasi(WasiError::EAGAIN);
pub const EALREADY: Self = Error::Wasi(WasiError::EALREADY);
pub const EBADF: Self = Error::Wasi(WasiError::EBADF);
pub const EBADMSG: Self = Error::Wasi(WasiError::EBADMSG);
pub const EBUSY: Self = Error::Wasi(WasiError::EBUSY);
pub const ECANCELED: Self = Error::Wasi(WasiError::ECANCELED);
pub const ECHILD: Self = Error::Wasi(WasiError::ECHILD);
pub const ECONNABORTED: Self = Error::Wasi(WasiError::ECONNABORTED);
pub const ECONNREFUSED: Self = Error::Wasi(WasiError::ECONNREFUSED);
pub const ECONNRESET: Self = Error::Wasi(WasiError::ECONNRESET);
pub const EDEADLK: Self = Error::Wasi(WasiError::EDEADLK);
pub const EDESTADDRREQ: Self = Error::Wasi(WasiError::EDESTADDRREQ);
pub const EDOM: Self = Error::Wasi(WasiError::EDOM);
pub const EDQUOT: Self = Error::Wasi(WasiError::EDQUOT);
pub const EEXIST: Self = Error::Wasi(WasiError::EEXIST);
pub const EFAULT: Self = Error::Wasi(WasiError::EFAULT);
pub const EFBIG: Self = Error::Wasi(WasiError::EFBIG);
pub const EHOSTUNREACH: Self = Error::Wasi(WasiError::EHOSTUNREACH);
pub const EIDRM: Self = Error::Wasi(WasiError::EIDRM);
pub const EILSEQ: Self = Error::Wasi(WasiError::EILSEQ);
pub const EINPROGRESS: Self = Error::Wasi(WasiError::EINPROGRESS);
pub const EINTR: Self = Error::Wasi(WasiError::EINTR);
pub const EINVAL: Self = Error::Wasi(WasiError::EINVAL);
pub const EIO: Self = Error::Wasi(WasiError::EIO);
pub const EISCONN: Self = Error::Wasi(WasiError::EISCONN);
pub const EISDIR: Self = Error::Wasi(WasiError::EISDIR);
pub const ELOOP: Self = Error::Wasi(WasiError::ELOOP);
pub const EMFILE: Self = Error::Wasi(WasiError::EMFILE);
pub const EMLINK: Self = Error::Wasi(WasiError::EMLINK);
pub const EMSGSIZE: Self = Error::Wasi(WasiError::EMSGSIZE);
pub const EMULTIHOP: Self = Error::Wasi(WasiError::EMULTIHOP);
pub const ENAMETOOLONG: Self = Error::Wasi(WasiError::ENAMETOOLONG);
pub const ENETDOWN: Self = Error::Wasi(WasiError::ENETDOWN);
pub const ENETRESET: Self = Error::Wasi(WasiError::ENETRESET);
pub const ENETUNREACH: Self = Error::Wasi(WasiError::ENETUNREACH);
pub const ENFILE: Self = Error::Wasi(WasiError::ENFILE);
pub const ENOBUFS: Self = Error::Wasi(WasiError::ENOBUFS);
pub const ENODEV: Self = Error::Wasi(WasiError::ENODEV);
pub const ENOENT: Self = Error::Wasi(WasiError::ENOENT);
pub const ENOEXEC: Self = Error::Wasi(WasiError::ENOEXEC);
pub const ENOLCK: Self = Error::Wasi(WasiError::ENOLCK);
pub const ENOLINK: Self = Error::Wasi(WasiError::ENOLINK);
pub const ENOMEM: Self = Error::Wasi(WasiError::ENOMEM);
pub const ENOMSG: Self = Error::Wasi(WasiError::ENOMSG);
pub const ENOPROTOOPT: Self = Error::Wasi(WasiError::ENOPROTOOPT);
pub const ENOSPC: Self = Error::Wasi(WasiError::ENOSPC);
pub const ENOSYS: Self = Error::Wasi(WasiError::ENOSYS);
pub const ENOTCONN: Self = Error::Wasi(WasiError::ENOTCONN);
pub const ENOTDIR: Self = Error::Wasi(WasiError::ENOTDIR);
pub const ENOTEMPTY: Self = Error::Wasi(WasiError::ENOTEMPTY);
pub const ENOTRECOVERABLE: Self = Error::Wasi(WasiError::ENOTRECOVERABLE);
pub const ENOTSOCK: Self = Error::Wasi(WasiError::ENOTSOCK);
pub const ENOTSUP: Self = Error::Wasi(WasiError::ENOTSUP);
pub const ENOTTY: Self = Error::Wasi(WasiError::ENOTTY);
pub const ENXIO: Self = Error::Wasi(WasiError::ENXIO);
pub const EOVERFLOW: Self = Error::Wasi(WasiError::EOVERFLOW);
pub const EOWNERDEAD: Self = Error::Wasi(WasiError::EOWNERDEAD);
pub const EPERM: Self = Error::Wasi(WasiError::EPERM);
pub const EPIPE: Self = Error::Wasi(WasiError::EPIPE);
pub const EPROTO: Self = Error::Wasi(WasiError::EPROTO);
pub const EPROTONOSUPPORT: Self = Error::Wasi(WasiError::EPROTONOSUPPORT);
pub const EPROTOTYPE: Self = Error::Wasi(WasiError::EPROTOTYPE);
pub const ERANGE: Self = Error::Wasi(WasiError::ERANGE);
pub const EROFS: Self = Error::Wasi(WasiError::EROFS);
pub const ESPIPE: Self = Error::Wasi(WasiError::ESPIPE);
pub const ESRCH: Self = Error::Wasi(WasiError::ESRCH);
pub const ESTALE: Self = Error::Wasi(WasiError::ESTALE);
pub const ETIMEDOUT: Self = Error::Wasi(WasiError::ETIMEDOUT);
pub const ETXTBSY: Self = Error::Wasi(WasiError::ETXTBSY);
pub const EXDEV: Self = Error::Wasi(WasiError::EXDEV);
pub const ENOTCAPABLE: Self = Error::Wasi(WasiError::ENOTCAPABLE);
}
pub(crate) trait FromRawOsError {
fn from_raw_os_error(code: i32) -> Self;
}
pub(crate) type Result<T> = std::result::Result<T, Error>;
pub(crate) trait AsWasiError {
fn as_wasi_error(&self) -> WasiError;
}
impl<T> AsWasiError for Result<T> {
fn as_wasi_error(&self) -> WasiError {
self.as_ref()
.err()
.unwrap_or(&Error::ESUCCESS)
.as_wasi_error()
}
}

View File

@@ -3,7 +3,7 @@ use crate::sys::fdentry_impl::{
descriptor_as_oshandle, determine_type_and_access_rights, OsHandle,
};
use crate::virtfs::VirtualFile;
use crate::{wasi, Error, Result};
use crate::wasi::{self, WasiError, WasiResult};
use std::marker::PhantomData;
use std::mem::ManuallyDrop;
use std::ops::{Deref, DerefMut};
@@ -56,22 +56,22 @@ impl Descriptor {
/// Return a reference to the `OsHandle` or `VirtualFile` treating it as an
/// actual file/dir, and allowing operations which require an actual file and
/// not just a stream or socket file descriptor.
pub(crate) fn as_file<'descriptor>(&'descriptor self) -> Result<&'descriptor Descriptor> {
pub(crate) fn as_file<'descriptor>(&'descriptor self) -> WasiResult<&'descriptor Descriptor> {
match self {
Self::OsHandle(_) => Ok(self),
Self::VirtualFile(_) => Ok(self),
_ => Err(Error::EBADF),
_ => Err(WasiError::EBADF),
}
}
/// Like `as_file`, but return a mutable reference.
pub(crate) fn as_file_mut<'descriptor>(
&'descriptor mut self,
) -> Result<&'descriptor mut Descriptor> {
) -> WasiResult<&'descriptor mut Descriptor> {
match self {
Self::OsHandle(_) => Ok(self),
Self::VirtualFile(_) => Ok(self),
_ => Err(Error::EBADF),
_ => Err(WasiError::EBADF),
}
}
@@ -100,7 +100,7 @@ pub(crate) struct FdEntry {
}
impl FdEntry {
pub(crate) fn from(file: Descriptor) -> Result<Self> {
pub(crate) fn from(file: Descriptor) -> io::Result<Self> {
match file {
Descriptor::OsHandle(handle) => unsafe { determine_type_and_access_rights(&handle) }
.map(|(file_type, rights_base, rights_inheriting)| Self {
@@ -129,7 +129,7 @@ impl FdEntry {
}
}
pub(crate) fn duplicate_stdin() -> Result<Self> {
pub(crate) fn duplicate_stdin() -> io::Result<Self> {
unsafe { determine_type_and_access_rights(&io::stdin()) }.map(
|(file_type, rights_base, rights_inheriting)| Self {
file_type,
@@ -141,7 +141,7 @@ impl FdEntry {
)
}
pub(crate) fn duplicate_stdout() -> Result<Self> {
pub(crate) fn duplicate_stdout() -> io::Result<Self> {
unsafe { determine_type_and_access_rights(&io::stdout()) }.map(
|(file_type, rights_base, rights_inheriting)| Self {
file_type,
@@ -153,7 +153,7 @@ impl FdEntry {
)
}
pub(crate) fn duplicate_stderr() -> Result<Self> {
pub(crate) fn duplicate_stderr() -> io::Result<Self> {
unsafe { determine_type_and_access_rights(&io::stderr()) }.map(
|(file_type, rights_base, rights_inheriting)| Self {
file_type,
@@ -165,7 +165,7 @@ impl FdEntry {
)
}
pub(crate) fn null() -> Result<Self> {
pub(crate) fn null() -> io::Result<Self> {
Self::from(OsHandle::from(dev_null()?).into())
}
@@ -175,12 +175,12 @@ impl FdEntry {
/// The `FdEntry` can only be converted into a valid `Descriptor` object if
/// the specified set of base rights `rights_base`, and inheriting rights `rights_inheriting`
/// is a subset of rights attached to this `FdEntry`. The check is performed using
/// `FdEntry::validate_rights` method. If the check fails, `Error::ENOTCAPABLE` is returned.
/// `FdEntry::validate_rights` method. If the check fails, `WasiError::ENOTCAPABLE` is returned.
pub(crate) fn as_descriptor(
&self,
rights_base: wasi::__wasi_rights_t,
rights_inheriting: wasi::__wasi_rights_t,
) -> Result<&Descriptor> {
) -> WasiResult<&Descriptor> {
self.validate_rights(rights_base, rights_inheriting)?;
Ok(&self.descriptor)
}
@@ -191,12 +191,12 @@ impl FdEntry {
/// The `FdEntry` can only be converted into a valid `Descriptor` object if
/// the specified set of base rights `rights_base`, and inheriting rights `rights_inheriting`
/// is a subset of rights attached to this `FdEntry`. The check is performed using
/// `FdEntry::validate_rights` method. If the check fails, `Error::ENOTCAPABLE` is returned.
/// `FdEntry::validate_rights` method. If the check fails, `WasiError::ENOTCAPABLE` is returned.
pub(crate) fn as_descriptor_mut(
&mut self,
rights_base: wasi::__wasi_rights_t,
rights_inheriting: wasi::__wasi_rights_t,
) -> Result<&mut Descriptor> {
) -> WasiResult<&mut Descriptor> {
self.validate_rights(rights_base, rights_inheriting)?;
Ok(&mut self.descriptor)
}
@@ -205,12 +205,12 @@ impl FdEntry {
/// inheriting rights `rights_inheriting`; i.e., if rights attached to this `FdEntry` object
/// are a superset.
///
/// Upon unsuccessful check, `Error::ENOTCAPABLE` is returned.
/// Upon unsuccessful check, `WasiError::ENOTCAPABLE` is returned.
fn validate_rights(
&self,
rights_base: wasi::__wasi_rights_t,
rights_inheriting: wasi::__wasi_rights_t,
) -> Result<()> {
) -> WasiResult<()> {
let missing_base = !self.rights_base & rights_base;
let missing_inheriting = !self.rights_inheriting & rights_inheriting;
if missing_base != 0 || missing_inheriting != 0 {
@@ -226,7 +226,7 @@ impl FdEntry {
missing_base,
missing_inheriting
);
Err(Error::ENOTCAPABLE)
Err(WasiError::ENOTCAPABLE)
} else {
Ok(())
}

View File

@@ -1,5 +1,6 @@
use crate::fs::Metadata;
use crate::{host, hostcalls, hostcalls_impl, wasi, Result, WasiCtx};
use crate::wasi::{self, WasiResult};
use crate::{host, hostcalls, hostcalls_impl, WasiCtx};
use std::io;
/// A reference to an open file on the filesystem.
@@ -34,7 +35,7 @@ impl<'ctx> File<'ctx> {
/// This corresponds to [`std::fs::File::sync_all`].
///
/// [`std::fs::File::sync_all`]: https://doc.rust-lang.org/std/fs/struct.File.html#method.sync_all
pub fn sync_all(&self) -> Result<()> {
pub fn sync_all(&self) -> WasiResult<()> {
unsafe {
hostcalls_impl::fd_sync(self.ctx, &mut [], self.fd)?;
}
@@ -47,7 +48,7 @@ impl<'ctx> File<'ctx> {
/// This corresponds to [`std::fs::File::sync_data`].
///
/// [`std::fs::File::sync_data`]: https://doc.rust-lang.org/std/fs/struct.File.html#method.sync_data
pub fn sync_data(&self) -> Result<()> {
pub fn sync_data(&self) -> WasiResult<()> {
unsafe {
hostcalls_impl::fd_datasync(self.ctx, &mut [], self.fd)?;
}
@@ -60,7 +61,7 @@ impl<'ctx> File<'ctx> {
/// This corresponds to [`std::fs::File::set_len`].
///
/// [`std::fs::File::set_len`]: https://doc.rust-lang.org/std/fs/struct.File.html#method.set_len
pub fn set_len(&self, size: u64) -> Result<()> {
pub fn set_len(&self, size: u64) -> WasiResult<()> {
unsafe {
hostcalls_impl::fd_filestat_set_size(self.ctx, &mut [], self.fd, size)?;
}
@@ -72,7 +73,7 @@ impl<'ctx> File<'ctx> {
/// This corresponds to [`std::fs::File::metadata`].
///
/// [`std::fs::File::metadata`]: https://doc.rust-lang.org/std/fs/struct.File.html#method.metadata
pub fn metadata(&self) -> Result<Metadata> {
pub fn metadata(&self) -> WasiResult<Metadata> {
Ok(Metadata {})
}
}

View File

@@ -1,10 +1,11 @@
use crate::{Error, Result};
use crate::wasi::WasiResult;
use std::str;
/// Creates not-owned WASI path from byte slice.
///
/// NB WASI spec requires bytes to be valid UTF-8. Otherwise,
/// `__WASI_ERRNO_ILSEQ` error is returned.
pub(crate) fn path_from_slice<'a>(s: &'a [u8]) -> Result<&'a str> {
str::from_utf8(s).map_err(|_| Error::EILSEQ)
pub(crate) fn path_from_slice<'a>(s: &'a [u8]) -> WasiResult<&'a str> {
let s = str::from_utf8(s)?;
Ok(s)
}

View File

@@ -5,7 +5,6 @@
#![allow(non_snake_case)]
use crate::wasi::*;
use crate::{Error, Result};
use std::{convert::TryInto, io, mem, slice};
use wig::witx_host_types;
@@ -67,11 +66,13 @@ pub struct Dirent {
impl Dirent {
/// Serialize the directory entry to the format define by `__wasi_fd_readdir`,
/// so that the serialized entries can be concatenated by the implementation.
pub fn to_wasi_raw(&self) -> Result<Vec<u8>> {
pub fn to_wasi_raw(&self) -> WasiResult<Vec<u8>> {
let name = self.name.as_bytes();
let namlen = name.len();
let dirent_size = mem::size_of::<__wasi_dirent_t>();
let offset = dirent_size.checked_add(namlen).ok_or(Error::EOVERFLOW)?;
let offset = dirent_size
.checked_add(namlen)
.ok_or(WasiError::EOVERFLOW)?;
let mut raw = Vec::<u8>::with_capacity(offset);
raw.resize(offset, 0);

View File

@@ -8,7 +8,8 @@ use crate::memory::*;
use crate::sandboxed_tty_writer::SandboxedTTYWriter;
use crate::sys::hostcalls_impl::fs_helpers::path_open_rights;
use crate::sys::{host_impl, hostcalls_impl};
use crate::{helpers, host, wasi, wasi32, Error, Result};
use crate::wasi::{self, WasiError, WasiResult};
use crate::{helpers, host, wasi32};
use filetime::{set_file_handle_times, FileTime};
use log::trace;
use std::convert::TryInto;
@@ -20,13 +21,13 @@ pub(crate) unsafe fn fd_close(
wasi_ctx: &mut WasiCtx,
_memory: &mut [u8],
fd: wasi::__wasi_fd_t,
) -> Result<()> {
) -> WasiResult<()> {
trace!("fd_close(fd={:?})", fd);
if let Ok(fe) = wasi_ctx.get_fd_entry(fd) {
// can't close preopened files
if fe.preopen_path.is_some() {
return Err(Error::ENOTSUP);
return Err(WasiError::ENOTSUP);
}
}
@@ -38,7 +39,7 @@ pub(crate) unsafe fn fd_datasync(
wasi_ctx: &WasiCtx,
_memory: &mut [u8],
fd: wasi::__wasi_fd_t,
) -> Result<()> {
) -> WasiResult<()> {
trace!("fd_datasync(fd={:?})", fd);
let file = wasi_ctx
@@ -60,7 +61,7 @@ pub(crate) unsafe fn fd_pread(
iovs_len: wasi32::size_t,
offset: wasi::__wasi_filesize_t,
nread: wasi32::uintptr_t,
) -> Result<()> {
) -> WasiResult<()> {
trace!(
"fd_pread(fd={:?}, iovs_ptr={:#x?}, iovs_len={:?}, offset={}, nread={:#x?})",
fd,
@@ -78,7 +79,7 @@ pub(crate) unsafe fn fd_pread(
let iovs = dec_iovec_slice(memory, iovs_ptr, iovs_len)?;
if offset > i64::max_value() as u64 {
return Err(Error::EIO);
return Err(WasiError::EIO);
}
let buf_size = iovs
.iter()
@@ -90,7 +91,7 @@ pub(crate) unsafe fn fd_pread(
cast_iovlen
})
.fold(Some(0u32), |len, iov| len.and_then(|x| x.checked_add(iov)))
.ok_or(Error::EINVAL)?;
.ok_or(WasiError::EINVAL)?;
let mut buf = vec![0; buf_size as usize];
let host_nread = match file {
Descriptor::OsHandle(fd) => hostcalls_impl::fd_pread(&fd, &mut buf, offset)?,
@@ -128,7 +129,7 @@ pub(crate) unsafe fn fd_pwrite(
iovs_len: wasi32::size_t,
offset: wasi::__wasi_filesize_t,
nwritten: wasi32::uintptr_t,
) -> Result<()> {
) -> WasiResult<()> {
trace!(
"fd_pwrite(fd={:?}, iovs_ptr={:#x?}, iovs_len={:?}, offset={}, nwritten={:#x?})",
fd,
@@ -148,7 +149,7 @@ pub(crate) unsafe fn fd_pwrite(
let iovs = dec_ciovec_slice(memory, iovs_ptr, iovs_len)?;
if offset > i64::max_value() as u64 {
return Err(Error::EIO);
return Err(WasiError::EIO);
}
let buf_size = iovs
.iter()
@@ -160,7 +161,7 @@ pub(crate) unsafe fn fd_pwrite(
cast_iovlen
})
.fold(Some(0u32), |len, iov| len.and_then(|x| x.checked_add(iov)))
.ok_or(Error::EINVAL)?;
.ok_or(WasiError::EINVAL)?;
let mut buf = Vec::with_capacity(buf_size as usize);
for iov in &iovs {
buf.extend_from_slice(std::slice::from_raw_parts(
@@ -190,7 +191,7 @@ pub(crate) unsafe fn fd_read(
iovs_ptr: wasi32::uintptr_t,
iovs_len: wasi32::size_t,
nread: wasi32::uintptr_t,
) -> Result<()> {
) -> WasiResult<()> {
trace!(
"fd_read(fd={:?}, iovs_ptr={:#x?}, iovs_len={:?}, nread={:#x?})",
fd,
@@ -212,7 +213,7 @@ pub(crate) unsafe fn fd_read(
Descriptor::OsHandle(file) => file.read_vectored(&mut iovs).map_err(Into::into),
Descriptor::VirtualFile(virt) => virt.read_vectored(&mut iovs),
Descriptor::Stdin => io::stdin().read_vectored(&mut iovs).map_err(Into::into),
_ => return Err(Error::EBADF),
_ => return Err(WasiError::EBADF),
};
let host_nread = maybe_host_nread?;
@@ -227,11 +228,11 @@ pub(crate) unsafe fn fd_renumber(
_memory: &mut [u8],
from: wasi::__wasi_fd_t,
to: wasi::__wasi_fd_t,
) -> Result<()> {
) -> WasiResult<()> {
trace!("fd_renumber(from={:?}, to={:?})", from, to);
if !wasi_ctx.contains_fd_entry(from) {
return Err(Error::EBADF);
return Err(WasiError::EBADF);
}
// Don't allow renumbering over a pre-opened resource.
@@ -239,11 +240,11 @@ pub(crate) unsafe fn fd_renumber(
// userspace is capable of removing entries from its tables as well.
let from_fe = wasi_ctx.get_fd_entry(from)?;
if from_fe.preopen_path.is_some() {
return Err(Error::ENOTSUP);
return Err(WasiError::ENOTSUP);
}
if let Ok(to_fe) = wasi_ctx.get_fd_entry(to) {
if to_fe.preopen_path.is_some() {
return Err(Error::ENOTSUP);
return Err(WasiError::ENOTSUP);
}
}
@@ -260,7 +261,7 @@ pub(crate) unsafe fn fd_seek(
offset: wasi::__wasi_filedelta_t,
whence: wasi::__wasi_whence_t,
newoffset: wasi32::uintptr_t,
) -> Result<()> {
) -> WasiResult<()> {
trace!(
"fd_seek(fd={:?}, offset={:?}, whence={}, newoffset={:#x?})",
fd,
@@ -283,7 +284,7 @@ pub(crate) unsafe fn fd_seek(
wasi::__WASI_WHENCE_CUR => SeekFrom::Current(offset),
wasi::__WASI_WHENCE_END => SeekFrom::End(offset),
wasi::__WASI_WHENCE_SET => SeekFrom::Start(offset as u64),
_ => return Err(Error::EINVAL),
_ => return Err(WasiError::EINVAL),
};
let host_newoffset = match file {
Descriptor::OsHandle(fd) => fd.seek(pos)?,
@@ -305,7 +306,7 @@ pub(crate) unsafe fn fd_tell(
memory: &mut [u8],
fd: wasi::__wasi_fd_t,
newoffset: wasi32::uintptr_t,
) -> Result<()> {
) -> WasiResult<()> {
trace!("fd_tell(fd={:?}, newoffset={:#x?})", fd, newoffset);
let file = wasi_ctx
@@ -333,7 +334,7 @@ pub(crate) unsafe fn fd_fdstat_get(
memory: &mut [u8],
fd: wasi::__wasi_fd_t,
fdstat_ptr: wasi32::uintptr_t, // *mut wasi::__wasi_fdstat_t
) -> Result<()> {
) -> WasiResult<()> {
trace!("fd_fdstat_get(fd={:?}, fdstat_ptr={:#x?})", fd, fdstat_ptr);
let mut fdstat = dec_fdstat_byref(memory, fdstat_ptr)?;
@@ -361,7 +362,7 @@ pub(crate) unsafe fn fd_fdstat_set_flags(
_memory: &mut [u8],
fd: wasi::__wasi_fd_t,
fdflags: wasi::__wasi_fdflags_t,
) -> Result<()> {
) -> WasiResult<()> {
trace!("fd_fdstat_set_flags(fd={:?}, fdflags={:#x?})", fd, fdflags);
let descriptor = wasi_ctx
@@ -400,7 +401,7 @@ pub(crate) unsafe fn fd_fdstat_set_rights(
fd: wasi::__wasi_fd_t,
fs_rights_base: wasi::__wasi_rights_t,
fs_rights_inheriting: wasi::__wasi_rights_t,
) -> Result<()> {
) -> WasiResult<()> {
trace!(
"fd_fdstat_set_rights(fd={:?}, fs_rights_base={:#x?}, fs_rights_inheriting={:#x?})",
fd,
@@ -412,7 +413,7 @@ pub(crate) unsafe fn fd_fdstat_set_rights(
if fe.rights_base & fs_rights_base != fs_rights_base
|| fe.rights_inheriting & fs_rights_inheriting != fs_rights_inheriting
{
return Err(Error::ENOTCAPABLE);
return Err(WasiError::ENOTCAPABLE);
}
fe.rights_base = fs_rights_base;
fe.rights_inheriting = fs_rights_inheriting;
@@ -424,7 +425,7 @@ pub(crate) unsafe fn fd_sync(
wasi_ctx: &WasiCtx,
_memory: &mut [u8],
fd: wasi::__wasi_fd_t,
) -> Result<()> {
) -> WasiResult<()> {
trace!("fd_sync(fd={:?})", fd);
let file = wasi_ctx
@@ -449,7 +450,7 @@ pub(crate) unsafe fn fd_write(
iovs_ptr: wasi32::uintptr_t,
iovs_len: wasi32::size_t,
nwritten: wasi32::uintptr_t,
) -> Result<()> {
) -> WasiResult<()> {
trace!(
"fd_write(fd={:?}, iovs_ptr={:#x?}, iovs_len={:?}, nwritten={:#x?})",
fd,
@@ -480,7 +481,7 @@ pub(crate) unsafe fn fd_write(
virt.write_vectored(&iovs)?
}
}
Descriptor::Stdin => return Err(Error::EBADF),
Descriptor::Stdin => return Err(WasiError::EBADF),
Descriptor::Stdout => {
// lock for the duration of the scope
let stdout = io::stdout();
@@ -512,7 +513,7 @@ pub(crate) unsafe fn fd_advise(
offset: wasi::__wasi_filesize_t,
len: wasi::__wasi_filesize_t,
advice: wasi::__wasi_advice_t,
) -> Result<()> {
) -> WasiResult<()> {
trace!(
"fd_advise(fd={:?}, offset={}, len={}, advice={:?})",
fd,
@@ -543,7 +544,7 @@ pub(crate) unsafe fn fd_allocate(
fd: wasi::__wasi_fd_t,
offset: wasi::__wasi_filesize_t,
len: wasi::__wasi_filesize_t,
) -> Result<()> {
) -> WasiResult<()> {
trace!("fd_allocate(fd={:?}, offset={}, len={})", fd, offset, len);
let file = wasi_ctx
@@ -556,10 +557,10 @@ pub(crate) unsafe fn fd_allocate(
let metadata = fd.metadata()?;
let current_size = metadata.len();
let wanted_size = offset.checked_add(len).ok_or(Error::E2BIG)?;
let wanted_size = offset.checked_add(len).ok_or(WasiError::E2BIG)?;
// This check will be unnecessary when rust-lang/rust#63326 is fixed
if wanted_size > i64::max_value() as u64 {
return Err(Error::E2BIG);
return Err(WasiError::E2BIG);
}
if wanted_size > current_size {
@@ -583,7 +584,7 @@ pub(crate) unsafe fn path_create_directory(
dirfd: wasi::__wasi_fd_t,
path_ptr: wasi32::uintptr_t,
path_len: wasi32::size_t,
) -> Result<()> {
) -> WasiResult<()> {
trace!(
"path_create_directory(dirfd={:?}, path_ptr={:#x?}, path_len={})",
dirfd,
@@ -612,7 +613,7 @@ pub(crate) unsafe fn path_link(
new_dirfd: wasi::__wasi_fd_t,
new_path_ptr: wasi32::uintptr_t,
new_path_len: wasi32::size_t,
) -> Result<()> {
) -> WasiResult<()> {
trace!(
"path_link(old_dirfd={:?}, old_flags={:?}, old_path_ptr={:#x?}, old_path_len={}, new_dirfd={:?}, new_path_ptr={:#x?}, new_path_len={})",
old_dirfd,
@@ -664,7 +665,7 @@ pub(crate) unsafe fn path_open(
fs_rights_inheriting: wasi::__wasi_rights_t,
fs_flags: wasi::__wasi_fdflags_t,
fd_out_ptr: wasi32::uintptr_t,
) -> Result<()> {
) -> WasiResult<()> {
trace!(
"path_open(dirfd={:?}, dirflags={:?}, path_ptr={:#x?}, path_len={:?}, oflags={:#x?}, fs_rights_base={:#x?}, fs_rights_inheriting={:#x?}, fs_flags={:#x?}, fd_out_ptr={:#x?})",
dirfd,
@@ -739,7 +740,7 @@ pub(crate) unsafe fn path_readlink(
buf_ptr: wasi32::uintptr_t,
buf_len: wasi32::size_t,
buf_used: wasi32::uintptr_t,
) -> Result<()> {
) -> WasiResult<()> {
trace!(
"path_readlink(dirfd={:?}, path_ptr={:#x?}, path_len={:?}, buf_ptr={:#x?}, buf_len={}, buf_used={:#x?})",
dirfd,
@@ -783,7 +784,7 @@ pub(crate) unsafe fn path_rename(
new_dirfd: wasi::__wasi_fd_t,
new_path_ptr: wasi32::uintptr_t,
new_path_len: wasi32::size_t,
) -> Result<()> {
) -> WasiResult<()> {
trace!(
"path_rename(old_dirfd={:?}, old_path_ptr={:#x?}, old_path_len={:?}, new_dirfd={:?}, new_path_ptr={:#x?}, new_path_len={:?})",
old_dirfd,
@@ -838,7 +839,7 @@ pub(crate) unsafe fn fd_filestat_get(
memory: &mut [u8],
fd: wasi::__wasi_fd_t,
filestat_ptr: wasi32::uintptr_t,
) -> Result<()> {
) -> WasiResult<()> {
trace!(
"fd_filestat_get(fd={:?}, filestat_ptr={:#x?})",
fd,
@@ -871,7 +872,7 @@ pub(crate) unsafe fn fd_filestat_set_times(
st_atim: wasi::__wasi_timestamp_t,
st_mtim: wasi::__wasi_timestamp_t,
fst_flags: wasi::__wasi_fstflags_t,
) -> Result<()> {
) -> WasiResult<()> {
trace!(
"fd_filestat_set_times(fd={:?}, st_atim={}, st_mtim={}, fst_flags={:#x?})",
fd,
@@ -893,14 +894,14 @@ pub(crate) fn fd_filestat_set_times_impl(
st_atim: wasi::__wasi_timestamp_t,
st_mtim: wasi::__wasi_timestamp_t,
fst_flags: wasi::__wasi_fstflags_t,
) -> Result<()> {
) -> WasiResult<()> {
let set_atim = fst_flags & wasi::__WASI_FSTFLAGS_ATIM != 0;
let set_atim_now = fst_flags & wasi::__WASI_FSTFLAGS_ATIM_NOW != 0;
let set_mtim = fst_flags & wasi::__WASI_FSTFLAGS_MTIM != 0;
let set_mtim_now = fst_flags & wasi::__WASI_FSTFLAGS_MTIM_NOW != 0;
if (set_atim && set_atim_now) || (set_mtim && set_mtim_now) {
return Err(Error::EINVAL);
return Err(WasiError::EINVAL);
}
let atim = if set_atim {
let time = UNIX_EPOCH + Duration::from_nanos(st_atim);
@@ -937,7 +938,7 @@ pub(crate) unsafe fn fd_filestat_set_size(
_memory: &mut [u8],
fd: wasi::__wasi_fd_t,
st_size: wasi::__wasi_filesize_t,
) -> Result<()> {
) -> WasiResult<()> {
trace!("fd_filestat_set_size(fd={:?}, st_size={})", fd, st_size);
let file = wasi_ctx
@@ -947,7 +948,7 @@ pub(crate) unsafe fn fd_filestat_set_size(
// This check will be unnecessary when rust-lang/rust#63326 is fixed
if st_size > i64::max_value() as u64 {
return Err(Error::E2BIG);
return Err(WasiError::E2BIG);
}
match file {
Descriptor::OsHandle(fd) => fd.set_len(st_size).map_err(Into::into),
@@ -968,7 +969,7 @@ pub(crate) unsafe fn path_filestat_get(
path_ptr: wasi32::uintptr_t,
path_len: wasi32::size_t,
filestat_ptr: wasi32::uintptr_t,
) -> Result<()> {
) -> WasiResult<()> {
trace!(
"path_filestat_get(dirfd={:?}, dirflags={:?}, path_ptr={:#x?}, path_len={}, filestat_ptr={:#x?})",
dirfd,
@@ -1013,7 +1014,7 @@ pub(crate) unsafe fn path_filestat_set_times(
st_atim: wasi::__wasi_timestamp_t,
st_mtim: wasi::__wasi_timestamp_t,
fst_flags: wasi::__wasi_fstflags_t,
) -> Result<()> {
) -> WasiResult<()> {
trace!(
"path_filestat_set_times(dirfd={:?}, dirflags={:?}, path_ptr={:#x?}, path_len={}, st_atim={}, st_mtim={}, fst_flags={:#x?})",
dirfd,
@@ -1056,7 +1057,7 @@ pub(crate) unsafe fn path_symlink(
dirfd: wasi::__wasi_fd_t,
new_path_ptr: wasi32::uintptr_t,
new_path_len: wasi32::size_t,
) -> Result<()> {
) -> WasiResult<()> {
trace!(
"path_symlink(old_path_ptr={:#x?}, old_path_len={}, dirfd={:?}, new_path_ptr={:#x?}, new_path_len={})",
old_path_ptr,
@@ -1089,7 +1090,7 @@ pub(crate) unsafe fn path_unlink_file(
dirfd: wasi::__wasi_fd_t,
path_ptr: wasi32::uintptr_t,
path_len: wasi32::size_t,
) -> Result<()> {
) -> WasiResult<()> {
trace!(
"path_unlink_file(dirfd={:?}, path_ptr={:#x?}, path_len={})",
dirfd,
@@ -1116,7 +1117,7 @@ pub(crate) unsafe fn path_remove_directory(
dirfd: wasi::__wasi_fd_t,
path_ptr: wasi32::uintptr_t,
path_len: wasi32::size_t,
) -> Result<()> {
) -> WasiResult<()> {
trace!(
"path_remove_directory(dirfd={:?}, path_ptr={:#x?}, path_len={})",
dirfd,
@@ -1151,7 +1152,7 @@ pub(crate) unsafe fn fd_prestat_get(
memory: &mut [u8],
fd: wasi::__wasi_fd_t,
prestat_ptr: wasi32::uintptr_t,
) -> Result<()> {
) -> WasiResult<()> {
trace!(
"fd_prestat_get(fd={:?}, prestat_ptr={:#x?})",
fd,
@@ -1160,9 +1161,9 @@ pub(crate) unsafe fn fd_prestat_get(
// TODO: should we validate any rights here?
let fe = wasi_ctx.get_fd_entry(fd)?;
let po_path = fe.preopen_path.as_ref().ok_or(Error::ENOTSUP)?;
let po_path = fe.preopen_path.as_ref().ok_or(WasiError::ENOTSUP)?;
if fe.file_type != wasi::__WASI_FILETYPE_DIRECTORY {
return Err(Error::ENOTDIR);
return Err(WasiError::ENOTDIR);
}
let path = host_impl::path_from_host(po_path.as_os_str())?;
@@ -1187,7 +1188,7 @@ pub(crate) unsafe fn fd_prestat_dir_name(
fd: wasi::__wasi_fd_t,
path_ptr: wasi32::uintptr_t,
path_len: wasi32::size_t,
) -> Result<()> {
) -> WasiResult<()> {
trace!(
"fd_prestat_dir_name(fd={:?}, path_ptr={:#x?}, path_len={})",
fd,
@@ -1197,15 +1198,15 @@ pub(crate) unsafe fn fd_prestat_dir_name(
// TODO: should we validate any rights here?
let fe = wasi_ctx.get_fd_entry(fd)?;
let po_path = fe.preopen_path.as_ref().ok_or(Error::ENOTSUP)?;
let po_path = fe.preopen_path.as_ref().ok_or(WasiError::ENOTSUP)?;
if fe.file_type != wasi::__WASI_FILETYPE_DIRECTORY {
return Err(Error::ENOTDIR);
return Err(WasiError::ENOTDIR);
}
let path = host_impl::path_from_host(po_path.as_os_str())?;
if path.len() > dec_usize(path_len) {
return Err(Error::ENAMETOOLONG);
return Err(WasiError::ENAMETOOLONG);
}
trace!(" | (path_ptr,path_len)='{}'", path);
@@ -1221,7 +1222,7 @@ pub(crate) unsafe fn fd_readdir(
buf_len: wasi32::size_t,
cookie: wasi::__wasi_dircookie_t,
buf_used: wasi32::uintptr_t,
) -> Result<()> {
) -> WasiResult<()> {
trace!(
"fd_readdir(fd={:?}, buf={:#x?}, buf_len={}, cookie={:#x?}, buf_used={:#x?})",
fd,
@@ -1241,10 +1242,10 @@ pub(crate) unsafe fn fd_readdir(
trace!(" | (buf,buf_len)={:?}", host_buf);
fn copy_entities<T: Iterator<Item = Result<Dirent>>>(
fn copy_entities<T: Iterator<Item = WasiResult<Dirent>>>(
iter: T,
mut host_buf: &mut [u8],
) -> Result<usize> {
) -> WasiResult<usize> {
let mut host_bufused = 0;
for dirent in iter {
let dirent_raw = dirent?.to_wasi_raw()?;

View File

@@ -2,7 +2,8 @@
use crate::sys::fdentry_impl::OsHandle;
use crate::sys::host_impl;
use crate::sys::hostcalls_impl::fs_helpers::*;
use crate::{error::WasiError, fdentry::Descriptor, fdentry::FdEntry, wasi, Error, Result};
use crate::wasi::{self, WasiError, WasiResult};
use crate::{fdentry::Descriptor, fdentry::FdEntry};
use std::path::{Component, Path};
#[derive(Debug)]
@@ -20,7 +21,7 @@ impl PathGet {
&self.path
}
pub(crate) fn path_create_directory(self) -> Result<()> {
pub(crate) fn path_create_directory(self) -> WasiResult<()> {
match &self.dirfd {
Descriptor::OsHandle(file) => {
crate::sys::hostcalls_impl::path_create_directory(&file, &self.path)
@@ -38,7 +39,7 @@ impl PathGet {
write: bool,
oflags: u16,
fs_flags: u16,
) -> Result<Descriptor> {
) -> WasiResult<Descriptor> {
match &self.dirfd {
Descriptor::OsHandle(_) => {
crate::sys::hostcalls_impl::path_open(self, read, write, oflags, fs_flags)
@@ -64,7 +65,7 @@ impl<'a, 'b> PathRef<'a, 'b> {
PathRef { dirfd, path }
}
fn open(&self) -> Result<Descriptor> {
fn open(&self) -> WasiResult<Descriptor> {
match self.dirfd {
Descriptor::OsHandle(file) => Ok(Descriptor::OsHandle(OsHandle::from(openat(
&file, &self.path,
@@ -84,7 +85,7 @@ impl<'a, 'b> PathRef<'a, 'b> {
}
}
fn readlink(&self) -> Result<String> {
fn readlink(&self) -> WasiResult<String> {
match self.dirfd {
Descriptor::OsHandle(file) => readlinkat(file, self.path),
Descriptor::VirtualFile(virt) => {
@@ -107,17 +108,17 @@ pub(crate) fn path_get(
dirflags: wasi::__wasi_lookupflags_t,
path: &str,
needs_final_component: bool,
) -> Result<PathGet> {
) -> WasiResult<PathGet> {
const MAX_SYMLINK_EXPANSIONS: usize = 128;
if path.contains('\0') {
// if contains NUL, return EILSEQ
return Err(Error::EILSEQ);
return Err(WasiError::EILSEQ);
}
if fe.file_type != wasi::__WASI_FILETYPE_DIRECTORY {
// if `dirfd` doesn't refer to a directory, return `ENOTDIR`.
return Err(Error::ENOTDIR);
return Err(WasiError::ENOTDIR);
}
let dirfd = fe
@@ -148,7 +149,7 @@ pub(crate) fn path_get(
let ends_with_slash = cur_path.ends_with('/');
let mut components = Path::new(&cur_path).components();
let head = match components.next() {
None => return Err(Error::ENOENT),
None => return Err(WasiError::ENOENT),
Some(p) => p,
};
let tail = components.as_path();
@@ -166,18 +167,18 @@ pub(crate) fn path_get(
match head {
Component::Prefix(_) | Component::RootDir => {
// path is absolute!
return Err(Error::ENOTCAPABLE);
return Err(WasiError::ENOTCAPABLE);
}
Component::CurDir => {
// "." so skip
}
Component::ParentDir => {
// ".." so pop a dir
let _ = dir_stack.pop().ok_or(Error::ENOTCAPABLE)?;
let _ = dir_stack.pop().ok_or(WasiError::ENOTCAPABLE)?;
// we're not allowed to pop past the original directory
if dir_stack.is_empty() {
return Err(Error::ENOTCAPABLE);
return Err(WasiError::ENOTCAPABLE);
}
}
Component::Normal(head) => {
@@ -188,14 +189,17 @@ pub(crate) fn path_get(
}
if !path_stack.is_empty() || (ends_with_slash && !needs_final_component) {
match PathRef::new(dir_stack.last().ok_or(Error::ENOTCAPABLE)?, &head)
match PathRef::new(
dir_stack.last().ok_or(WasiError::ENOTCAPABLE)?,
&head,
)
.open()
{
Ok(new_dir) => {
dir_stack.push(new_dir);
}
Err(e) => {
match e.as_wasi_error() {
match e {
WasiError::ELOOP
| WasiError::EMLINK
| WasiError::ENOTDIR =>
@@ -204,14 +208,14 @@ pub(crate) fn path_get(
{
// attempt symlink expansion
let mut link_path = PathRef::new(
dir_stack.last().ok_or(Error::ENOTCAPABLE)?,
dir_stack.last().ok_or(WasiError::ENOTCAPABLE)?,
&head,
)
.readlink()?;
symlink_expansions += 1;
if symlink_expansions > MAX_SYMLINK_EXPANSIONS {
return Err(Error::ELOOP);
return Err(WasiError::ELOOP);
}
if head.ends_with('/') {
@@ -238,13 +242,16 @@ pub(crate) fn path_get(
{
// if there's a trailing slash, or if `LOOKUP_SYMLINK_FOLLOW` is set, attempt
// symlink expansion
match PathRef::new(dir_stack.last().ok_or(Error::ENOTCAPABLE)?, &head)
match PathRef::new(
dir_stack.last().ok_or(WasiError::ENOTCAPABLE)?,
&head,
)
.readlink()
{
Ok(mut link_path) => {
symlink_expansions += 1;
if symlink_expansions > MAX_SYMLINK_EXPANSIONS {
return Err(Error::ELOOP);
return Err(WasiError::ELOOP);
}
if head.ends_with('/') {
@@ -260,12 +267,12 @@ pub(crate) fn path_get(
continue;
}
Err(e) => {
if e.as_wasi_error() != WasiError::EINVAL
&& e.as_wasi_error() != WasiError::ENOENT
if e != WasiError::EINVAL
&& e != WasiError::ENOENT
// this handles the cases when trying to link to
// a destination that already exists, and the target
// path contains a slash
&& e.as_wasi_error() != WasiError::ENOTDIR
&& e != WasiError::ENOTDIR
{
return Err(e);
}
@@ -275,7 +282,7 @@ pub(crate) fn path_get(
// not a symlink, so we're done;
return Ok(PathGet {
dirfd: dir_stack.pop().ok_or(Error::ENOTCAPABLE)?,
dirfd: dir_stack.pop().ok_or(WasiError::ENOTCAPABLE)?,
path: head,
});
}
@@ -285,7 +292,7 @@ pub(crate) fn path_get(
// no further components to process. means we've hit a case like "." or "a/..", or if the
// input path has trailing slashes and `needs_final_component` is not set
return Ok(PathGet {
dirfd: dir_stack.pop().ok_or(Error::ENOTCAPABLE)?,
dirfd: dir_stack.pop().ok_or(WasiError::ENOTCAPABLE)?,
path: String::from("."),
});
}

View File

@@ -3,7 +3,8 @@ use crate::ctx::WasiCtx;
use crate::fdentry::Descriptor;
use crate::memory::*;
use crate::sys::hostcalls_impl;
use crate::{wasi, wasi32, Error, Result};
use crate::wasi::{self, WasiError, WasiResult};
use crate::wasi32;
use log::{error, trace};
use std::convert::TryFrom;
@@ -12,7 +13,7 @@ pub(crate) fn args_get(
memory: &mut [u8],
argv_ptr: wasi32::uintptr_t,
argv_buf: wasi32::uintptr_t,
) -> Result<()> {
) -> WasiResult<()> {
trace!(
"args_get(argv_ptr={:#x?}, argv_buf={:#x?})",
argv_ptr,
@@ -31,7 +32,9 @@ pub(crate) fn args_get(
argv.push(arg_ptr);
let len = wasi32::uintptr_t::try_from(arg_bytes.len())?;
argv_buf_offset = argv_buf_offset.checked_add(len).ok_or(Error::EOVERFLOW)?;
argv_buf_offset = argv_buf_offset
.checked_add(len)
.ok_or(WasiError::EOVERFLOW)?;
}
enc_slice_of_wasi32_uintptr(memory, argv.as_slice(), argv_ptr)
@@ -42,7 +45,7 @@ pub(crate) fn args_sizes_get(
memory: &mut [u8],
argc_ptr: wasi32::uintptr_t,
argv_buf_size_ptr: wasi32::uintptr_t,
) -> Result<()> {
) -> WasiResult<()> {
trace!(
"args_sizes_get(argc_ptr={:#x?}, argv_buf_size_ptr={:#x?})",
argc_ptr,
@@ -70,7 +73,7 @@ pub(crate) fn environ_get(
memory: &mut [u8],
environ_ptr: wasi32::uintptr_t,
environ_buf: wasi32::uintptr_t,
) -> Result<()> {
) -> WasiResult<()> {
trace!(
"environ_get(environ_ptr={:#x?}, environ_buf={:#x?})",
environ_ptr,
@@ -91,7 +94,7 @@ pub(crate) fn environ_get(
let len = wasi32::uintptr_t::try_from(env_bytes.len())?;
environ_buf_offset = environ_buf_offset
.checked_add(len)
.ok_or(Error::EOVERFLOW)?;
.ok_or(WasiError::EOVERFLOW)?;
}
enc_slice_of_wasi32_uintptr(memory, environ.as_slice(), environ_ptr)
@@ -102,7 +105,7 @@ pub(crate) fn environ_sizes_get(
memory: &mut [u8],
environ_count_ptr: wasi32::uintptr_t,
environ_size_ptr: wasi32::uintptr_t,
) -> Result<()> {
) -> WasiResult<()> {
trace!(
"environ_sizes_get(environ_count_ptr={:#x?}, environ_size_ptr={:#x?})",
environ_count_ptr,
@@ -116,7 +119,7 @@ pub(crate) fn environ_sizes_get(
.try_fold(0, |acc: u32, pair| {
acc.checked_add(pair.as_bytes_with_nul().len() as u32)
})
.ok_or(Error::EOVERFLOW)?;
.ok_or(WasiError::EOVERFLOW)?;
trace!(" | *environ_count_ptr={:?}", environ_count);
@@ -132,14 +135,14 @@ pub(crate) fn random_get(
memory: &mut [u8],
buf_ptr: wasi32::uintptr_t,
buf_len: wasi32::size_t,
) -> Result<()> {
) -> WasiResult<()> {
trace!("random_get(buf_ptr={:#x?}, buf_len={:?})", buf_ptr, buf_len);
let buf = dec_slice_of_mut_u8(memory, buf_ptr, buf_len)?;
getrandom::getrandom(buf).map_err(|err| {
error!("getrandom failure: {:?}", err);
Error::EIO
WasiError::EIO
})
}
@@ -148,7 +151,7 @@ pub(crate) fn clock_res_get(
memory: &mut [u8],
clock_id: wasi::__wasi_clockid_t,
resolution_ptr: wasi32::uintptr_t,
) -> Result<()> {
) -> WasiResult<()> {
trace!(
"clock_res_get(clock_id={:?}, resolution_ptr={:#x?})",
clock_id,
@@ -168,7 +171,7 @@ pub(crate) fn clock_time_get(
clock_id: wasi::__wasi_clockid_t,
precision: wasi::__wasi_timestamp_t,
time_ptr: wasi32::uintptr_t,
) -> Result<()> {
) -> WasiResult<()> {
trace!(
"clock_time_get(clock_id={:?}, precision={:?}, time_ptr={:#x?})",
clock_id,
@@ -183,7 +186,7 @@ pub(crate) fn clock_time_get(
enc_timestamp_byref(memory, time_ptr, time)
}
pub(crate) fn sched_yield(_wasi_ctx: &WasiCtx, _memory: &mut [u8]) -> Result<()> {
pub(crate) fn sched_yield(_wasi_ctx: &WasiCtx, _memory: &mut [u8]) -> WasiResult<()> {
trace!("sched_yield()");
std::thread::yield_now();
@@ -198,7 +201,7 @@ pub(crate) fn poll_oneoff(
output: wasi32::uintptr_t,
nsubscriptions: wasi32::size_t,
nevents: wasi32::uintptr_t,
) -> Result<()> {
) -> WasiResult<()> {
trace!(
"poll_oneoff(input={:#x?}, output={:#x?}, nsubscriptions={}, nevents={:#x?})",
input,
@@ -208,7 +211,7 @@ pub(crate) fn poll_oneoff(
);
if u64::from(nsubscriptions) > wasi::__wasi_filesize_t::max_value() {
return Err(Error::EINVAL);
return Err(WasiError::EINVAL);
}
enc_int_byref(memory, nevents, 0)?;
@@ -222,7 +225,7 @@ pub(crate) fn poll_oneoff(
// As mandated by the WASI spec:
// > If `nsubscriptions` is 0, returns `errno::inval`.
if subscriptions.is_empty() {
return Err(Error::EINVAL);
return Err(WasiError::EINVAL);
}
for subscription in subscriptions {
match subscription.u.tag {
@@ -258,7 +261,7 @@ pub(crate) fn poll_oneoff(
Err(err) => {
let event = wasi::__wasi_event_t {
userdata: subscription.userdata,
error: err.as_wasi_error().as_raw_errno(),
error: err.as_raw_errno(),
r#type: wasi::__WASI_EVENTTYPE_FD_READ,
fd_readwrite: wasi::__wasi_event_fd_readwrite_t {
nbytes: 0,
@@ -286,7 +289,7 @@ pub(crate) fn poll_oneoff(
Err(err) => {
let event = wasi::__wasi_event_t {
userdata: subscription.userdata,
error: err.as_wasi_error().as_raw_errno(),
error: err.as_raw_errno(),
r#type: wasi::__WASI_EVENTTYPE_FD_WRITE,
fd_readwrite: wasi::__wasi_event_fd_readwrite_t {
nbytes: 0,
@@ -310,7 +313,7 @@ pub(crate) fn poll_oneoff(
// events have been filtered out as errors in the code above.
hostcalls_impl::poll_oneoff(timeout, fd_events, &mut events)?;
let events_count = u32::try_from(events.len()).map_err(|_| Error::EOVERFLOW)?;
let events_count = u32::try_from(events.len()).map_err(|_| WasiError::EOVERFLOW)?;
enc_events(memory, output, nsubscriptions, events)?;
@@ -319,7 +322,9 @@ pub(crate) fn poll_oneoff(
enc_int_byref(memory, nevents, events_count)
}
fn wasi_clock_to_relative_ns_delay(wasi_clock: wasi::__wasi_subscription_clock_t) -> Result<u128> {
fn wasi_clock_to_relative_ns_delay(
wasi_clock: wasi::__wasi_subscription_clock_t,
) -> WasiResult<u128> {
use std::time::SystemTime;
if wasi_clock.flags != wasi::__WASI_SUBCLOCKFLAGS_SUBSCRIPTION_CLOCK_ABSTIME {
@@ -327,7 +332,7 @@ fn wasi_clock_to_relative_ns_delay(wasi_clock: wasi::__wasi_subscription_clock_t
}
let now: u128 = SystemTime::now()
.duration_since(SystemTime::UNIX_EPOCH)
.map_err(|_| Error::ENOTCAPABLE)?
.map_err(|_| WasiError::ENOTCAPABLE)?
.as_nanos();
let deadline = u128::from(wasi_clock.timeout);
Ok(deadline.saturating_sub(now))
@@ -357,6 +362,6 @@ pub(crate) fn proc_raise(
_wasi_ctx: &WasiCtx,
_memory: &mut [u8],
_sig: wasi::__wasi_signal_t,
) -> Result<()> {
) -> WasiResult<()> {
unimplemented!("proc_raise")
}

View File

@@ -1,5 +1,6 @@
use crate::ctx::WasiCtx;
use crate::{wasi, wasi32, Result};
use crate::wasi::{self, WasiResult};
use crate::wasi32;
pub fn sock_recv(
_wasi_ctx: &WasiCtx,
@@ -10,7 +11,7 @@ pub fn sock_recv(
_ri_flags: wasi::__wasi_riflags_t,
_ro_datalen: wasi32::uintptr_t,
_ro_flags: wasi32::uintptr_t,
) -> Result<()> {
) -> WasiResult<()> {
unimplemented!("sock_recv")
}
@@ -22,7 +23,7 @@ pub fn sock_send(
_si_data_len: wasi32::size_t,
_si_flags: wasi::__wasi_siflags_t,
_so_datalen: wasi32::uintptr_t,
) -> Result<()> {
) -> WasiResult<()> {
unimplemented!("sock_send")
}
@@ -31,6 +32,6 @@ pub fn sock_shutdown(
_memory: &mut [u8],
_sock: wasi::__wasi_fd_t,
_how: wasi::__wasi_sdflags_t,
) -> Result<()> {
) -> WasiResult<()> {
unimplemented!("sock_shutdown")
}

View File

@@ -22,7 +22,6 @@
)]
mod ctx;
mod error;
mod fdentry;
pub mod fs;
mod helpers;
@@ -43,6 +42,3 @@ pub mod hostcalls {
pub use ctx::{WasiCtx, WasiCtxBuilder};
pub use sys::preopen_dir;
pub use error::Error;
pub(crate) use error::Result;

View File

@@ -8,38 +8,39 @@
//! are not held for long durations.
#![allow(unused)]
use crate::{host, wasi, wasi32, Error, Result};
use crate::wasi::{self, WasiError, WasiResult};
use crate::{host, wasi32};
use num::PrimInt;
use std::convert::TryFrom;
use std::mem::{align_of, size_of};
use std::{ptr, slice};
fn dec_ptr(memory: &[u8], ptr: wasi32::uintptr_t, len: usize) -> Result<*const u8> {
fn dec_ptr(memory: &[u8], ptr: wasi32::uintptr_t, len: usize) -> WasiResult<*const u8> {
// check for overflow
let checked_len = (ptr as usize).checked_add(len).ok_or(Error::EFAULT)?;
let checked_len = (ptr as usize).checked_add(len).ok_or(WasiError::EFAULT)?;
// translate the pointer
memory
.get(ptr as usize..checked_len)
.ok_or(Error::EFAULT)
.ok_or(WasiError::EFAULT)
.map(|mem| mem.as_ptr())
}
fn dec_ptr_mut(memory: &mut [u8], ptr: wasi32::uintptr_t, len: usize) -> Result<*mut u8> {
fn dec_ptr_mut(memory: &mut [u8], ptr: wasi32::uintptr_t, len: usize) -> WasiResult<*mut u8> {
// check for overflow
let checked_len = (ptr as usize).checked_add(len).ok_or(Error::EFAULT)?;
let checked_len = (ptr as usize).checked_add(len).ok_or(WasiError::EFAULT)?;
// translate the pointer
memory
.get_mut(ptr as usize..checked_len)
.ok_or(Error::EFAULT)
.ok_or(WasiError::EFAULT)
.map(|mem| mem.as_mut_ptr())
}
fn dec_ptr_to<'memory, T>(memory: &'memory [u8], ptr: wasi32::uintptr_t) -> Result<&'memory T> {
fn dec_ptr_to<'memory, T>(memory: &'memory [u8], ptr: wasi32::uintptr_t) -> WasiResult<&'memory T> {
// check that the ptr is aligned
if ptr as usize % align_of::<T>() != 0 {
return Err(Error::EINVAL);
return Err(WasiError::EINVAL);
}
dec_ptr(memory, ptr, size_of::<T>()).map(|p| unsafe { &*(p as *const T) })
@@ -48,49 +49,49 @@ fn dec_ptr_to<'memory, T>(memory: &'memory [u8], ptr: wasi32::uintptr_t) -> Resu
fn dec_ptr_to_mut<'memory, T>(
memory: &'memory mut [u8],
ptr: wasi32::uintptr_t,
) -> Result<&'memory mut T> {
) -> WasiResult<&'memory mut T> {
// check that the ptr is aligned
if ptr as usize % align_of::<T>() != 0 {
return Err(Error::EINVAL);
return Err(WasiError::EINVAL);
}
dec_ptr_mut(memory, ptr, size_of::<T>()).map(|p| unsafe { &mut *(p as *mut T) })
}
/// This function does not perform endianness conversions!
fn dec_raw_byref<T>(memory: &[u8], ptr: wasi32::uintptr_t) -> Result<T> {
fn dec_raw_byref<T>(memory: &[u8], ptr: wasi32::uintptr_t) -> WasiResult<T> {
dec_ptr_to::<T>(memory, ptr).map(|p| unsafe { ptr::read(p) })
}
/// This function does not perform endianness conversions!
fn enc_raw_byref<T>(memory: &mut [u8], ptr: wasi32::uintptr_t, t: T) -> Result<()> {
fn enc_raw_byref<T>(memory: &mut [u8], ptr: wasi32::uintptr_t, t: T) -> WasiResult<()> {
dec_ptr_to_mut::<T>(memory, ptr).map(|p| unsafe { ptr::write(p, t) })
}
pub(crate) fn dec_int_byref<T>(memory: &[u8], ptr: wasi32::uintptr_t) -> Result<T>
pub(crate) fn dec_int_byref<T>(memory: &[u8], ptr: wasi32::uintptr_t) -> WasiResult<T>
where
T: PrimInt,
{
dec_raw_byref::<T>(memory, ptr).map(|i| PrimInt::from_le(i))
}
pub(crate) fn enc_int_byref<T>(memory: &mut [u8], ptr: wasi32::uintptr_t, t: T) -> Result<()>
pub(crate) fn enc_int_byref<T>(memory: &mut [u8], ptr: wasi32::uintptr_t, t: T) -> WasiResult<()>
where
T: PrimInt,
{
enc_raw_byref::<T>(memory, ptr, PrimInt::to_le(t))
}
fn check_slice_of<T>(ptr: wasi32::uintptr_t, len: wasi32::size_t) -> Result<(usize, usize)> {
fn check_slice_of<T>(ptr: wasi32::uintptr_t, len: wasi32::size_t) -> WasiResult<(usize, usize)> {
// check alignment, and that length doesn't overflow
if ptr as usize % align_of::<T>() != 0 {
return Err(Error::EINVAL);
return Err(WasiError::EINVAL);
}
let len = dec_usize(len);
let len_bytes = if let Some(len) = size_of::<T>().checked_mul(len) {
len
} else {
return Err(Error::EOVERFLOW);
return Err(WasiError::EOVERFLOW);
};
Ok((len, len_bytes))
@@ -100,7 +101,7 @@ fn dec_raw_slice_of<'memory, T>(
memory: &'memory [u8],
ptr: wasi32::uintptr_t,
len: wasi32::size_t,
) -> Result<&'memory [T]> {
) -> WasiResult<&'memory [T]> {
let (len, len_bytes) = check_slice_of::<T>(ptr, len)?;
let ptr = dec_ptr(memory, ptr, len_bytes)? as *const T;
Ok(unsafe { slice::from_raw_parts(ptr, len) })
@@ -110,7 +111,7 @@ fn dec_raw_slice_of_mut<'memory, T>(
memory: &'memory mut [u8],
ptr: wasi32::uintptr_t,
len: wasi32::size_t,
) -> Result<&'memory mut [T]> {
) -> WasiResult<&'memory mut [T]> {
let (len, len_bytes) = check_slice_of::<T>(ptr, len)?;
let ptr = dec_ptr_mut(memory, ptr, len_bytes)? as *mut T;
Ok(unsafe { slice::from_raw_parts_mut(ptr, len) })
@@ -120,16 +121,16 @@ fn raw_slice_for_enc<'memory, T>(
memory: &'memory mut [u8],
slice: &[T],
ptr: wasi32::uintptr_t,
) -> Result<&'memory mut [T]> {
) -> WasiResult<&'memory mut [T]> {
// check alignment
if ptr as usize % align_of::<T>() != 0 {
return Err(Error::EINVAL);
return Err(WasiError::EINVAL);
}
// check that length doesn't overflow
let len_bytes = if let Some(len) = size_of::<T>().checked_mul(slice.len()) {
len
} else {
return Err(Error::EOVERFLOW);
return Err(WasiError::EOVERFLOW);
};
// get the pointer into guest memory
@@ -142,7 +143,7 @@ pub(crate) fn dec_slice_of_u8<'memory>(
memory: &'memory [u8],
ptr: wasi32::uintptr_t,
len: wasi32::size_t,
) -> Result<&'memory [u8]> {
) -> WasiResult<&'memory [u8]> {
dec_raw_slice_of::<u8>(memory, ptr, len)
}
@@ -150,7 +151,7 @@ pub(crate) fn dec_slice_of_mut_u8<'memory>(
memory: &'memory mut [u8],
ptr: wasi32::uintptr_t,
len: wasi32::size_t,
) -> Result<&'memory mut [u8]> {
) -> WasiResult<&'memory mut [u8]> {
dec_raw_slice_of_mut::<u8>(memory, ptr, len)
}
@@ -158,7 +159,7 @@ pub(crate) fn enc_slice_of_u8(
memory: &mut [u8],
slice: &[u8],
ptr: wasi32::uintptr_t,
) -> Result<()> {
) -> WasiResult<()> {
let output = raw_slice_for_enc::<u8>(memory, slice, ptr)?;
output.copy_from_slice(slice);
@@ -170,7 +171,7 @@ pub(crate) fn enc_slice_of_wasi32_uintptr(
memory: &mut [u8],
slice: &[wasi32::uintptr_t],
ptr: wasi32::uintptr_t,
) -> Result<()> {
) -> WasiResult<()> {
let mut output_iter = raw_slice_for_enc::<wasi32::uintptr_t>(memory, slice, ptr)?.into_iter();
for p in slice {
@@ -182,7 +183,10 @@ pub(crate) fn enc_slice_of_wasi32_uintptr(
macro_rules! dec_enc_scalar {
($ty:ident, $dec_byref:ident, $enc_byref:ident) => {
pub(crate) fn $dec_byref(memory: &mut [u8], ptr: wasi32::uintptr_t) -> Result<wasi::$ty> {
pub(crate) fn $dec_byref(
memory: &mut [u8],
ptr: wasi32::uintptr_t,
) -> WasiResult<wasi::$ty> {
dec_int_byref::<wasi::$ty>(memory, ptr)
}
@@ -190,7 +194,7 @@ macro_rules! dec_enc_scalar {
memory: &mut [u8],
ptr: wasi32::uintptr_t,
x: wasi::$ty,
) -> Result<()> {
) -> WasiResult<()> {
enc_int_byref::<wasi::$ty>(memory, ptr, x)
}
};
@@ -200,7 +204,7 @@ pub(crate) fn dec_ciovec_slice(
memory: &[u8],
ptr: wasi32::uintptr_t,
len: wasi32::size_t,
) -> Result<Vec<host::__wasi_ciovec_t>> {
) -> WasiResult<Vec<host::__wasi_ciovec_t>> {
let raw_slice = dec_raw_slice_of::<wasi32::__wasi_ciovec_t>(memory, ptr, len)?;
raw_slice
@@ -220,7 +224,7 @@ pub(crate) fn dec_iovec_slice(
memory: &[u8],
ptr: wasi32::uintptr_t,
len: wasi32::size_t,
) -> Result<Vec<host::__wasi_iovec_t>> {
) -> WasiResult<Vec<host::__wasi_iovec_t>> {
let raw_slice = dec_raw_slice_of::<wasi32::__wasi_iovec_t>(memory, ptr, len)?;
raw_slice
@@ -248,7 +252,7 @@ dec_enc_scalar!(__wasi_linkcount_t, dev_linkcount_byref, enc_linkcount_byref);
pub(crate) fn dec_filestat_byref(
memory: &mut [u8],
filestat_ptr: wasi32::uintptr_t,
) -> Result<wasi::__wasi_filestat_t> {
) -> WasiResult<wasi::__wasi_filestat_t> {
let raw = dec_raw_byref::<wasi::__wasi_filestat_t>(memory, filestat_ptr)?;
Ok(wasi::__wasi_filestat_t {
@@ -267,7 +271,7 @@ pub(crate) fn enc_filestat_byref(
memory: &mut [u8],
filestat_ptr: wasi32::uintptr_t,
filestat: wasi::__wasi_filestat_t,
) -> Result<()> {
) -> WasiResult<()> {
let raw = wasi::__wasi_filestat_t {
dev: PrimInt::to_le(filestat.dev),
ino: PrimInt::to_le(filestat.ino),
@@ -285,7 +289,7 @@ pub(crate) fn enc_filestat_byref(
pub(crate) fn dec_fdstat_byref(
memory: &mut [u8],
fdstat_ptr: wasi32::uintptr_t,
) -> Result<wasi::__wasi_fdstat_t> {
) -> WasiResult<wasi::__wasi_fdstat_t> {
let raw = dec_raw_byref::<wasi::__wasi_fdstat_t>(memory, fdstat_ptr)?;
Ok(wasi::__wasi_fdstat_t {
@@ -300,7 +304,7 @@ pub(crate) fn enc_fdstat_byref(
memory: &mut [u8],
fdstat_ptr: wasi32::uintptr_t,
fdstat: wasi::__wasi_fdstat_t,
) -> Result<()> {
) -> WasiResult<()> {
let raw = wasi::__wasi_fdstat_t {
fs_filetype: PrimInt::to_le(fdstat.fs_filetype),
fs_flags: PrimInt::to_le(fdstat.fs_flags),
@@ -326,7 +330,7 @@ dec_enc_scalar!(__wasi_oflags_t, dec_oflags_byref, enc_oflags_byref);
pub(crate) fn dec_prestat_byref(
memory: &mut [u8],
prestat_ptr: wasi32::uintptr_t,
) -> Result<host::__wasi_prestat_t> {
) -> WasiResult<host::__wasi_prestat_t> {
let raw = dec_raw_byref::<wasi32::__wasi_prestat_t>(memory, prestat_ptr)?;
match PrimInt::from_le(raw.tag) {
@@ -338,7 +342,7 @@ pub(crate) fn dec_prestat_byref(
},
},
}),
_ => Err(Error::EINVAL),
_ => Err(WasiError::EINVAL),
}
}
@@ -346,7 +350,7 @@ pub(crate) fn enc_prestat_byref(
memory: &mut [u8],
prestat_ptr: wasi32::uintptr_t,
prestat: host::__wasi_prestat_t,
) -> Result<()> {
) -> WasiResult<()> {
let raw = match prestat.tag {
wasi::__WASI_PREOPENTYPE_DIR => Ok(wasi32::__wasi_prestat_t {
tag: PrimInt::to_le(wasi::__WASI_PREOPENTYPE_DIR),
@@ -356,7 +360,7 @@ pub(crate) fn enc_prestat_byref(
},
},
}),
_ => Err(Error::EINVAL),
_ => Err(WasiError::EINVAL),
}?;
enc_raw_byref::<wasi32::__wasi_prestat_t>(memory, prestat_ptr, raw)
@@ -377,7 +381,7 @@ pub(crate) fn enc_usize_byref(
memory: &mut [u8],
usize_ptr: wasi32::uintptr_t,
host_usize: usize,
) -> Result<()> {
) -> WasiResult<()> {
enc_int_byref::<wasi32::size_t>(memory, usize_ptr, enc_usize(host_usize))
}
@@ -402,7 +406,7 @@ pub(crate) fn dec_subscriptions(
memory: &mut [u8],
input: wasi32::uintptr_t,
nsubscriptions: wasi32::size_t,
) -> Result<Vec<wasi::__wasi_subscription_t>> {
) -> WasiResult<Vec<wasi::__wasi_subscription_t>> {
let raw_input_slice =
dec_raw_slice_of::<wasi::__wasi_subscription_t>(memory, input, nsubscriptions)?;
@@ -435,14 +439,14 @@ pub(crate) fn dec_subscriptions(
}),
},
},
_ => return Err(Error::EINVAL),
_ => return Err(WasiError::EINVAL),
};
Ok(wasi::__wasi_subscription_t {
userdata,
u: wasi::__wasi_subscription_u_t { tag, u },
})
})
.collect::<Result<Vec<_>>>()
.collect::<WasiResult<Vec<_>>>()
}
pub(crate) fn enc_events(
@@ -450,7 +454,7 @@ pub(crate) fn enc_events(
output: wasi32::uintptr_t,
nsubscriptions: wasi32::size_t,
events: Vec<wasi::__wasi_event_t>,
) -> Result<()> {
) -> WasiResult<()> {
let mut raw_output_iter =
dec_raw_slice_of_mut::<wasi::__wasi_event_t>(memory, output, nsubscriptions)?.into_iter();

View File

@@ -1,14 +1,42 @@
use crate::old::snapshot_0::fdentry::FdEntry;
use crate::old::snapshot_0::{wasi, Error, Result};
use crate::old::snapshot_0::wasi::{self, WasiError, WasiResult};
use std::borrow::Borrow;
use std::collections::HashMap;
use std::env;
use std::ffi::{CString, OsString};
use std::ffi::{self, CString, OsString};
use std::fs::File;
use std::path::{Path, PathBuf};
use std::{env, io, string};
/// Possible errors when `WasiCtxBuilder` fails building
/// `WasiCtx`.
#[derive(Debug, thiserror::Error)]
pub enum WasiCtxBuilderError {
/// General I/O error was encountered.
#[error("general I/O error encountered: {0}")]
Io(#[from] io::Error),
/// Provided sequence of bytes was not a valid UTF-8.
#[error("provided sequence is not valid UTF-8: {0}")]
InvalidUtf8(#[from] string::FromUtf8Error),
/// Provided sequence of bytes was not a valid UTF-16.
///
/// This error is expected to only occur on Windows hosts.
#[error("provided sequence is not valid UTF-16: {0}")]
InvalidUtf16(#[from] string::FromUtf16Error),
/// Provided sequence of bytes contained an unexpected NUL byte.
#[error("provided sequence contained an unexpected NUL byte")]
UnexpectedNul(#[from] ffi::NulError),
/// Provided `File` is not a directory.
#[error("preopened directory path {} is not a directory", .0.display())]
NotADirectory(PathBuf),
/// `WasiCtx` has too many opened files.
#[error("context object has too many opened files")]
TooManyFilesOpen,
}
type WasiCtxBuilderResult<T> = std::result::Result<T, WasiCtxBuilderError>;
enum PendingFdEntry {
Thunk(fn() -> Result<FdEntry>),
Thunk(fn() -> io::Result<FdEntry>),
File(File),
}
@@ -18,7 +46,7 @@ impl std::fmt::Debug for PendingFdEntry {
Self::Thunk(f) => write!(
fmt,
"PendingFdEntry::Thunk({:p})",
f as *const fn() -> Result<FdEntry>
f as *const fn() -> io::Result<FdEntry>
),
Self::File(f) => write!(fmt, "PendingFdEntry::File({:?})", f),
}
@@ -44,17 +72,29 @@ impl From<OsString> for PendingCString {
}
impl PendingCString {
fn into_string(self) -> Result<String> {
match self {
Self::Bytes(v) => String::from_utf8(v).map_err(|_| Error::EILSEQ),
Self::OsString(s) => s.into_string().map_err(|_| Error::EILSEQ),
fn into_string(self) -> WasiCtxBuilderResult<String> {
let res = match self {
Self::Bytes(v) => String::from_utf8(v)?,
#[cfg(unix)]
Self::OsString(s) => {
use std::os::unix::ffi::OsStringExt;
String::from_utf8(s.into_vec())?
}
#[cfg(windows)]
Self::OsString(s) => {
use std::os::windows::ffi::OsStrExt;
let bytes: Vec<u16> = s.encode_wide().collect();
String::from_utf16(&bytes)?
}
};
Ok(res)
}
/// Create a `CString` containing valid UTF-8, or fail with `Error::EILSEQ`.
fn into_utf8_cstring(self) -> Result<CString> {
self.into_string()
.and_then(|s| CString::new(s).map_err(|_| Error::EILSEQ))
/// Create a `CString` containing valid UTF-8, or fail.
fn into_utf8_cstring(self) -> WasiCtxBuilderResult<CString> {
let s = self.into_string()?;
let s = CString::new(s)?;
Ok(s)
}
}
@@ -85,8 +125,7 @@ impl WasiCtxBuilder {
/// Add arguments to the command-line arguments list.
///
/// Arguments must be valid UTF-8 with no NUL bytes, or else `WasiCtxBuilder::build()` will fail
/// with `Error::EILSEQ`.
/// Arguments must be valid UTF-8 with no NUL bytes, or else `WasiCtxBuilder::build()` will fail.
pub fn args<S: AsRef<[u8]>>(mut self, args: impl IntoIterator<Item = S>) -> Self {
self.args = args
.into_iter()
@@ -97,8 +136,7 @@ impl WasiCtxBuilder {
/// Add an argument to the command-line arguments list.
///
/// Arguments must be valid UTF-8 with no NUL bytes, or else `WasiCtxBuilder::build()` will fail
/// with `Error::EILSEQ`.
/// Arguments must be valid UTF-8 with no NUL bytes, or else `WasiCtxBuilder::build()` will fail.
pub fn arg<S: AsRef<[u8]>>(mut self, arg: S) -> Self {
self.args.push(arg.as_ref().to_vec().into());
self
@@ -107,7 +145,7 @@ impl WasiCtxBuilder {
/// Inherit the command-line arguments from the host process.
///
/// If any arguments from the host process contain invalid UTF-8, `WasiCtxBuilder::build()` will
/// fail with `Error::EILSEQ`.
/// fail.
pub fn inherit_args(mut self) -> Self {
self.args = env::args_os().map(PendingCString::OsString).collect();
self
@@ -127,8 +165,7 @@ impl WasiCtxBuilder {
/// Inherit the environment variables from the host process.
///
/// If any environment variables from the host process contain invalid Unicode (UTF-16 for
/// Windows, UTF-8 for other platforms), `WasiCtxBuilder::build()` will fail with
/// `Error::EILSEQ`.
/// Windows, UTF-8 for other platforms), `WasiCtxBuilder::build()` will fail.
pub fn inherit_env(mut self) -> Self {
self.env = std::env::vars_os()
.map(|(k, v)| (k.into(), v.into()))
@@ -139,7 +176,7 @@ impl WasiCtxBuilder {
/// Add an entry to the environment.
///
/// Environment variable keys and values must be valid UTF-8 with no NUL bytes, or else
/// `WasiCtxBuilder::build()` will fail with `Error::EILSEQ`.
/// `WasiCtxBuilder::build()` will fail.
pub fn env<S: AsRef<[u8]>>(mut self, k: S, v: S) -> Self {
self.env
.insert(k.as_ref().to_vec().into(), v.as_ref().to_vec().into());
@@ -149,7 +186,7 @@ impl WasiCtxBuilder {
/// Add entries to the environment.
///
/// Environment variable keys and values must be valid UTF-8 with no NUL bytes, or else
/// `WasiCtxBuilder::build()` will fail with `Error::EILSEQ`.
/// `WasiCtxBuilder::build()` will fail.
pub fn envs<S: AsRef<[u8]>, T: Borrow<(S, S)>>(
mut self,
envs: impl IntoIterator<Item = T>,
@@ -191,15 +228,15 @@ impl WasiCtxBuilder {
/// Build a `WasiCtx`, consuming this `WasiCtxBuilder`.
///
/// If any of the arguments or environment variables in this builder cannot be converted into
/// `CString`s, either due to NUL bytes or Unicode conversions, this returns `Error::EILSEQ`.
pub fn build(self) -> Result<WasiCtx> {
/// `CString`s, either due to NUL bytes or Unicode conversions, this returns an error.
pub fn build(self) -> WasiCtxBuilderResult<WasiCtx> {
// Process arguments and environment variables into `CString`s, failing quickly if they
// contain any NUL bytes, or if conversion from `OsString` fails.
let args = self
.args
.into_iter()
.map(|arg| arg.into_utf8_cstring())
.collect::<Result<Vec<CString>>>()?;
.collect::<WasiCtxBuilderResult<Vec<CString>>>()?;
let env = self
.env
@@ -211,11 +248,12 @@ impl WasiCtxBuilder {
pair.push_str(v.as_str());
// We have valid UTF-8, but the keys and values have not yet been checked
// for NULs, so we do a final check here.
CString::new(pair).map_err(|_| Error::EILSEQ)
let s = CString::new(pair)?;
Ok(s)
})
})
})
.collect::<Result<Vec<CString>>>()?;
.collect::<WasiCtxBuilderResult<Vec<CString>>>()?;
let mut fds: HashMap<wasi::__wasi_fd_t, FdEntry> = HashMap::new();
// Populate the non-preopen fds.
@@ -237,16 +275,20 @@ impl WasiCtxBuilder {
for (guest_path, dir) in self.preopens {
// We do the increment at the beginning of the loop body, so that we don't overflow
// unnecessarily if we have exactly the maximum number of file descriptors.
preopen_fd = preopen_fd.checked_add(1).ok_or(Error::ENFILE)?;
preopen_fd = preopen_fd
.checked_add(1)
.ok_or(WasiCtxBuilderError::TooManyFilesOpen)?;
if !dir.metadata()?.is_dir() {
return Err(Error::EBADF);
return Err(WasiCtxBuilderError::NotADirectory(guest_path));
}
// We don't currently allow setting file descriptors other than 0-2, but this will avoid
// collisions if we restore that functionality in the future.
while fds.contains_key(&preopen_fd) {
preopen_fd = preopen_fd.checked_add(1).ok_or(Error::ENFILE)?;
preopen_fd = preopen_fd
.checked_add(1)
.ok_or(WasiCtxBuilderError::TooManyFilesOpen)?;
}
let mut fe = FdEntry::from(dir)?;
fe.preopen_path = Some(guest_path);
@@ -274,7 +316,7 @@ impl WasiCtx {
/// - Environment variables are inherited from the host process.
///
/// To override these behaviors, use `WasiCtxBuilder`.
pub fn new<S: AsRef<[u8]>>(args: impl IntoIterator<Item = S>) -> Result<Self> {
pub fn new<S: AsRef<[u8]>>(args: impl IntoIterator<Item = S>) -> WasiCtxBuilderResult<Self> {
WasiCtxBuilder::new()
.args(args)
.inherit_stdio()
@@ -288,30 +330,30 @@ impl WasiCtx {
}
/// Get an immutable `FdEntry` corresponding to the specified raw WASI `fd`.
pub(crate) unsafe fn get_fd_entry(&self, fd: wasi::__wasi_fd_t) -> Result<&FdEntry> {
self.fds.get(&fd).ok_or(Error::EBADF)
pub(crate) unsafe fn get_fd_entry(&self, fd: wasi::__wasi_fd_t) -> WasiResult<&FdEntry> {
self.fds.get(&fd).ok_or(WasiError::EBADF)
}
/// Get a mutable `FdEntry` corresponding to the specified raw WASI `fd`.
pub(crate) unsafe fn get_fd_entry_mut(
&mut self,
fd: wasi::__wasi_fd_t,
) -> Result<&mut FdEntry> {
self.fds.get_mut(&fd).ok_or(Error::EBADF)
) -> WasiResult<&mut FdEntry> {
self.fds.get_mut(&fd).ok_or(WasiError::EBADF)
}
/// Insert the specified `FdEntry` into the `WasiCtx` object.
///
/// The `FdEntry` will automatically get another free raw WASI `fd` assigned. Note that
/// the two subsequent free raw WASI `fd`s do not have to be stored contiguously.
pub(crate) fn insert_fd_entry(&mut self, fe: FdEntry) -> Result<wasi::__wasi_fd_t> {
pub(crate) fn insert_fd_entry(&mut self, fe: FdEntry) -> WasiResult<wasi::__wasi_fd_t> {
// Never insert where stdio handles are expected to be.
let mut fd = 3;
while self.fds.contains_key(&fd) {
if let Some(next_fd) = fd.checked_add(1) {
fd = next_fd;
} else {
return Err(Error::EMFILE);
return Err(WasiError::EMFILE);
}
}
self.fds.insert(fd, fe);
@@ -329,7 +371,7 @@ impl WasiCtx {
}
/// Remove `FdEntry` corresponding to the specified raw WASI `fd` from the `WasiCtx` object.
pub(crate) fn remove_fd_entry(&mut self, fd: wasi::__wasi_fd_t) -> Result<FdEntry> {
self.fds.remove(&fd).ok_or(Error::EBADF)
pub(crate) fn remove_fd_entry(&mut self, fd: wasi::__wasi_fd_t) -> WasiResult<FdEntry> {
self.fds.remove(&fd).ok_or(WasiError::EBADF)
}
}

View File

@@ -1,234 +0,0 @@
// Due to https://github.com/rust-lang/rust/issues/64247
#![allow(clippy::use_self)]
use crate::old::snapshot_0::wasi;
use std::convert::Infallible;
use std::num::TryFromIntError;
use std::{ffi, str};
use thiserror::Error;
#[derive(Clone, Copy, Debug, Error, Eq, PartialEq)]
#[repr(u16)]
#[error("{:?} ({})", self, wasi::strerror(*self as wasi::__wasi_errno_t))]
pub enum WasiError {
ESUCCESS = wasi::__WASI_ERRNO_SUCCESS,
E2BIG = wasi::__WASI_ERRNO_2BIG,
EACCES = wasi::__WASI_ERRNO_ACCES,
EADDRINUSE = wasi::__WASI_ERRNO_ADDRINUSE,
EADDRNOTAVAIL = wasi::__WASI_ERRNO_ADDRNOTAVAIL,
EAFNOSUPPORT = wasi::__WASI_ERRNO_AFNOSUPPORT,
EAGAIN = wasi::__WASI_ERRNO_AGAIN,
EALREADY = wasi::__WASI_ERRNO_ALREADY,
EBADF = wasi::__WASI_ERRNO_BADF,
EBADMSG = wasi::__WASI_ERRNO_BADMSG,
EBUSY = wasi::__WASI_ERRNO_BUSY,
ECANCELED = wasi::__WASI_ERRNO_CANCELED,
ECHILD = wasi::__WASI_ERRNO_CHILD,
ECONNABORTED = wasi::__WASI_ERRNO_CONNABORTED,
ECONNREFUSED = wasi::__WASI_ERRNO_CONNREFUSED,
ECONNRESET = wasi::__WASI_ERRNO_CONNRESET,
EDEADLK = wasi::__WASI_ERRNO_DEADLK,
EDESTADDRREQ = wasi::__WASI_ERRNO_DESTADDRREQ,
EDOM = wasi::__WASI_ERRNO_DOM,
EDQUOT = wasi::__WASI_ERRNO_DQUOT,
EEXIST = wasi::__WASI_ERRNO_EXIST,
EFAULT = wasi::__WASI_ERRNO_FAULT,
EFBIG = wasi::__WASI_ERRNO_FBIG,
EHOSTUNREACH = wasi::__WASI_ERRNO_HOSTUNREACH,
EIDRM = wasi::__WASI_ERRNO_IDRM,
EILSEQ = wasi::__WASI_ERRNO_ILSEQ,
EINPROGRESS = wasi::__WASI_ERRNO_INPROGRESS,
EINTR = wasi::__WASI_ERRNO_INTR,
EINVAL = wasi::__WASI_ERRNO_INVAL,
EIO = wasi::__WASI_ERRNO_IO,
EISCONN = wasi::__WASI_ERRNO_ISCONN,
EISDIR = wasi::__WASI_ERRNO_ISDIR,
ELOOP = wasi::__WASI_ERRNO_LOOP,
EMFILE = wasi::__WASI_ERRNO_MFILE,
EMLINK = wasi::__WASI_ERRNO_MLINK,
EMSGSIZE = wasi::__WASI_ERRNO_MSGSIZE,
EMULTIHOP = wasi::__WASI_ERRNO_MULTIHOP,
ENAMETOOLONG = wasi::__WASI_ERRNO_NAMETOOLONG,
ENETDOWN = wasi::__WASI_ERRNO_NETDOWN,
ENETRESET = wasi::__WASI_ERRNO_NETRESET,
ENETUNREACH = wasi::__WASI_ERRNO_NETUNREACH,
ENFILE = wasi::__WASI_ERRNO_NFILE,
ENOBUFS = wasi::__WASI_ERRNO_NOBUFS,
ENODEV = wasi::__WASI_ERRNO_NODEV,
ENOENT = wasi::__WASI_ERRNO_NOENT,
ENOEXEC = wasi::__WASI_ERRNO_NOEXEC,
ENOLCK = wasi::__WASI_ERRNO_NOLCK,
ENOLINK = wasi::__WASI_ERRNO_NOLINK,
ENOMEM = wasi::__WASI_ERRNO_NOMEM,
ENOMSG = wasi::__WASI_ERRNO_NOMSG,
ENOPROTOOPT = wasi::__WASI_ERRNO_NOPROTOOPT,
ENOSPC = wasi::__WASI_ERRNO_NOSPC,
ENOSYS = wasi::__WASI_ERRNO_NOSYS,
ENOTCONN = wasi::__WASI_ERRNO_NOTCONN,
ENOTDIR = wasi::__WASI_ERRNO_NOTDIR,
ENOTEMPTY = wasi::__WASI_ERRNO_NOTEMPTY,
ENOTRECOVERABLE = wasi::__WASI_ERRNO_NOTRECOVERABLE,
ENOTSOCK = wasi::__WASI_ERRNO_NOTSOCK,
ENOTSUP = wasi::__WASI_ERRNO_NOTSUP,
ENOTTY = wasi::__WASI_ERRNO_NOTTY,
ENXIO = wasi::__WASI_ERRNO_NXIO,
EOVERFLOW = wasi::__WASI_ERRNO_OVERFLOW,
EOWNERDEAD = wasi::__WASI_ERRNO_OWNERDEAD,
EPERM = wasi::__WASI_ERRNO_PERM,
EPIPE = wasi::__WASI_ERRNO_PIPE,
EPROTO = wasi::__WASI_ERRNO_PROTO,
EPROTONOSUPPORT = wasi::__WASI_ERRNO_PROTONOSUPPORT,
EPROTOTYPE = wasi::__WASI_ERRNO_PROTOTYPE,
ERANGE = wasi::__WASI_ERRNO_RANGE,
EROFS = wasi::__WASI_ERRNO_ROFS,
ESPIPE = wasi::__WASI_ERRNO_SPIPE,
ESRCH = wasi::__WASI_ERRNO_SRCH,
ESTALE = wasi::__WASI_ERRNO_STALE,
ETIMEDOUT = wasi::__WASI_ERRNO_TIMEDOUT,
ETXTBSY = wasi::__WASI_ERRNO_TXTBSY,
EXDEV = wasi::__WASI_ERRNO_XDEV,
ENOTCAPABLE = wasi::__WASI_ERRNO_NOTCAPABLE,
}
impl WasiError {
pub fn as_raw_errno(self) -> wasi::__wasi_errno_t {
self as wasi::__wasi_errno_t
}
}
#[derive(Debug, Error)]
pub enum Error {
#[error("WASI error code: {0}")]
Wasi(#[from] WasiError),
#[error("IO error: {0}")]
Io(#[from] std::io::Error),
}
impl From<TryFromIntError> for Error {
fn from(_: TryFromIntError) -> Self {
Self::EOVERFLOW
}
}
impl From<Infallible> for Error {
fn from(_: Infallible) -> Self {
unreachable!()
}
}
impl From<str::Utf8Error> for Error {
fn from(_: str::Utf8Error) -> Self {
Self::EILSEQ
}
}
impl From<ffi::NulError> for Error {
fn from(_: ffi::NulError) -> Self {
Self::EILSEQ
}
}
impl From<&ffi::NulError> for Error {
fn from(_: &ffi::NulError) -> Self {
Self::EILSEQ
}
}
impl Error {
pub(crate) fn as_wasi_error(&self) -> WasiError {
match self {
Self::Wasi(err) => *err,
Self::Io(err) => {
let err = match err.raw_os_error() {
Some(code) => Self::from_raw_os_error(code),
None => {
log::debug!("Inconvertible OS error: {}", err);
Self::EIO
}
};
err.as_wasi_error()
}
}
}
pub const ESUCCESS: Self = Error::Wasi(WasiError::ESUCCESS);
pub const E2BIG: Self = Error::Wasi(WasiError::E2BIG);
pub const EACCES: Self = Error::Wasi(WasiError::EACCES);
pub const EADDRINUSE: Self = Error::Wasi(WasiError::EADDRINUSE);
pub const EADDRNOTAVAIL: Self = Error::Wasi(WasiError::EADDRNOTAVAIL);
pub const EAFNOSUPPORT: Self = Error::Wasi(WasiError::EAFNOSUPPORT);
pub const EAGAIN: Self = Error::Wasi(WasiError::EAGAIN);
pub const EALREADY: Self = Error::Wasi(WasiError::EALREADY);
pub const EBADF: Self = Error::Wasi(WasiError::EBADF);
pub const EBADMSG: Self = Error::Wasi(WasiError::EBADMSG);
pub const EBUSY: Self = Error::Wasi(WasiError::EBUSY);
pub const ECANCELED: Self = Error::Wasi(WasiError::ECANCELED);
pub const ECHILD: Self = Error::Wasi(WasiError::ECHILD);
pub const ECONNABORTED: Self = Error::Wasi(WasiError::ECONNABORTED);
pub const ECONNREFUSED: Self = Error::Wasi(WasiError::ECONNREFUSED);
pub const ECONNRESET: Self = Error::Wasi(WasiError::ECONNRESET);
pub const EDEADLK: Self = Error::Wasi(WasiError::EDEADLK);
pub const EDESTADDRREQ: Self = Error::Wasi(WasiError::EDESTADDRREQ);
pub const EDOM: Self = Error::Wasi(WasiError::EDOM);
pub const EDQUOT: Self = Error::Wasi(WasiError::EDQUOT);
pub const EEXIST: Self = Error::Wasi(WasiError::EEXIST);
pub const EFAULT: Self = Error::Wasi(WasiError::EFAULT);
pub const EFBIG: Self = Error::Wasi(WasiError::EFBIG);
pub const EHOSTUNREACH: Self = Error::Wasi(WasiError::EHOSTUNREACH);
pub const EIDRM: Self = Error::Wasi(WasiError::EIDRM);
pub const EILSEQ: Self = Error::Wasi(WasiError::EILSEQ);
pub const EINPROGRESS: Self = Error::Wasi(WasiError::EINPROGRESS);
pub const EINTR: Self = Error::Wasi(WasiError::EINTR);
pub const EINVAL: Self = Error::Wasi(WasiError::EINVAL);
pub const EIO: Self = Error::Wasi(WasiError::EIO);
pub const EISCONN: Self = Error::Wasi(WasiError::EISCONN);
pub const EISDIR: Self = Error::Wasi(WasiError::EISDIR);
pub const ELOOP: Self = Error::Wasi(WasiError::ELOOP);
pub const EMFILE: Self = Error::Wasi(WasiError::EMFILE);
pub const EMLINK: Self = Error::Wasi(WasiError::EMLINK);
pub const EMSGSIZE: Self = Error::Wasi(WasiError::EMSGSIZE);
pub const EMULTIHOP: Self = Error::Wasi(WasiError::EMULTIHOP);
pub const ENAMETOOLONG: Self = Error::Wasi(WasiError::ENAMETOOLONG);
pub const ENETDOWN: Self = Error::Wasi(WasiError::ENETDOWN);
pub const ENETRESET: Self = Error::Wasi(WasiError::ENETRESET);
pub const ENETUNREACH: Self = Error::Wasi(WasiError::ENETUNREACH);
pub const ENFILE: Self = Error::Wasi(WasiError::ENFILE);
pub const ENOBUFS: Self = Error::Wasi(WasiError::ENOBUFS);
pub const ENODEV: Self = Error::Wasi(WasiError::ENODEV);
pub const ENOENT: Self = Error::Wasi(WasiError::ENOENT);
pub const ENOEXEC: Self = Error::Wasi(WasiError::ENOEXEC);
pub const ENOLCK: Self = Error::Wasi(WasiError::ENOLCK);
pub const ENOLINK: Self = Error::Wasi(WasiError::ENOLINK);
pub const ENOMEM: Self = Error::Wasi(WasiError::ENOMEM);
pub const ENOMSG: Self = Error::Wasi(WasiError::ENOMSG);
pub const ENOPROTOOPT: Self = Error::Wasi(WasiError::ENOPROTOOPT);
pub const ENOSPC: Self = Error::Wasi(WasiError::ENOSPC);
pub const ENOSYS: Self = Error::Wasi(WasiError::ENOSYS);
pub const ENOTCONN: Self = Error::Wasi(WasiError::ENOTCONN);
pub const ENOTDIR: Self = Error::Wasi(WasiError::ENOTDIR);
pub const ENOTEMPTY: Self = Error::Wasi(WasiError::ENOTEMPTY);
pub const ENOTRECOVERABLE: Self = Error::Wasi(WasiError::ENOTRECOVERABLE);
pub const ENOTSOCK: Self = Error::Wasi(WasiError::ENOTSOCK);
pub const ENOTSUP: Self = Error::Wasi(WasiError::ENOTSUP);
pub const ENOTTY: Self = Error::Wasi(WasiError::ENOTTY);
pub const ENXIO: Self = Error::Wasi(WasiError::ENXIO);
pub const EOVERFLOW: Self = Error::Wasi(WasiError::EOVERFLOW);
pub const EOWNERDEAD: Self = Error::Wasi(WasiError::EOWNERDEAD);
pub const EPERM: Self = Error::Wasi(WasiError::EPERM);
pub const EPIPE: Self = Error::Wasi(WasiError::EPIPE);
pub const EPROTO: Self = Error::Wasi(WasiError::EPROTO);
pub const EPROTONOSUPPORT: Self = Error::Wasi(WasiError::EPROTONOSUPPORT);
pub const EPROTOTYPE: Self = Error::Wasi(WasiError::EPROTOTYPE);
pub const ERANGE: Self = Error::Wasi(WasiError::ERANGE);
pub const EROFS: Self = Error::Wasi(WasiError::EROFS);
pub const ESPIPE: Self = Error::Wasi(WasiError::ESPIPE);
pub const ESRCH: Self = Error::Wasi(WasiError::ESRCH);
pub const ESTALE: Self = Error::Wasi(WasiError::ESTALE);
pub const ETIMEDOUT: Self = Error::Wasi(WasiError::ETIMEDOUT);
pub const ETXTBSY: Self = Error::Wasi(WasiError::ETXTBSY);
pub const EXDEV: Self = Error::Wasi(WasiError::EXDEV);
pub const ENOTCAPABLE: Self = Error::Wasi(WasiError::ENOTCAPABLE);
}
pub(crate) trait FromRawOsError {
fn from_raw_os_error(code: i32) -> Self;
}

View File

@@ -2,7 +2,7 @@ use crate::old::snapshot_0::sys::dev_null;
use crate::old::snapshot_0::sys::fdentry_impl::{
descriptor_as_oshandle, determine_type_and_access_rights, OsHandle,
};
use crate::old::snapshot_0::{wasi, Error, Result};
use crate::old::snapshot_0::wasi::{self, WasiError, WasiResult};
use std::marker::PhantomData;
use std::mem::ManuallyDrop;
use std::ops::{Deref, DerefMut};
@@ -21,18 +21,18 @@ impl Descriptor {
/// Return a reference to the `OsHandle` treating it as an actual file/dir, and
/// allowing operations which require an actual file and not just a stream or
/// socket file descriptor.
pub(crate) fn as_file(&self) -> Result<&OsHandle> {
pub(crate) fn as_file(&self) -> WasiResult<&OsHandle> {
match self {
Self::OsHandle(file) => Ok(file),
_ => Err(Error::EBADF),
_ => Err(WasiError::EBADF),
}
}
/// Like `as_file`, but return a mutable reference.
pub(crate) fn as_file_mut(&mut self) -> Result<&mut OsHandle> {
pub(crate) fn as_file_mut(&mut self) -> WasiResult<&mut OsHandle> {
match self {
Self::OsHandle(file) => Ok(file),
_ => Err(Error::EBADF),
_ => Err(WasiError::EBADF),
}
}
@@ -64,7 +64,7 @@ impl FdEntry {
/// Create an FdEntry with *maximal* possible rights from a given `File`.
/// If this is not desired, the rights of the resulting `FdEntry` should
/// be manually restricted.
pub(crate) fn from(file: fs::File) -> Result<Self> {
pub(crate) fn from(file: fs::File) -> io::Result<Self> {
unsafe { determine_type_and_access_rights(&file) }.map(
|(file_type, rights_base, rights_inheriting)| Self {
file_type,
@@ -76,7 +76,7 @@ impl FdEntry {
)
}
pub(crate) fn duplicate_stdin() -> Result<Self> {
pub(crate) fn duplicate_stdin() -> io::Result<Self> {
unsafe { determine_type_and_access_rights(&io::stdin()) }.map(
|(file_type, rights_base, rights_inheriting)| Self {
file_type,
@@ -88,7 +88,7 @@ impl FdEntry {
)
}
pub(crate) fn duplicate_stdout() -> Result<Self> {
pub(crate) fn duplicate_stdout() -> io::Result<Self> {
unsafe { determine_type_and_access_rights(&io::stdout()) }.map(
|(file_type, rights_base, rights_inheriting)| Self {
file_type,
@@ -100,7 +100,7 @@ impl FdEntry {
)
}
pub(crate) fn duplicate_stderr() -> Result<Self> {
pub(crate) fn duplicate_stderr() -> io::Result<Self> {
unsafe { determine_type_and_access_rights(&io::stderr()) }.map(
|(file_type, rights_base, rights_inheriting)| Self {
file_type,
@@ -112,7 +112,7 @@ impl FdEntry {
)
}
pub(crate) fn null() -> Result<Self> {
pub(crate) fn null() -> io::Result<Self> {
Self::from(dev_null()?)
}
@@ -127,7 +127,7 @@ impl FdEntry {
&self,
rights_base: wasi::__wasi_rights_t,
rights_inheriting: wasi::__wasi_rights_t,
) -> Result<&Descriptor> {
) -> WasiResult<&Descriptor> {
self.validate_rights(rights_base, rights_inheriting)?;
Ok(&self.descriptor)
}
@@ -143,7 +143,7 @@ impl FdEntry {
&mut self,
rights_base: wasi::__wasi_rights_t,
rights_inheriting: wasi::__wasi_rights_t,
) -> Result<&mut Descriptor> {
) -> WasiResult<&mut Descriptor> {
self.validate_rights(rights_base, rights_inheriting)?;
Ok(&mut self.descriptor)
}
@@ -157,10 +157,10 @@ impl FdEntry {
&self,
rights_base: wasi::__wasi_rights_t,
rights_inheriting: wasi::__wasi_rights_t,
) -> Result<()> {
) -> WasiResult<()> {
if !self.rights_base & rights_base != 0 || !self.rights_inheriting & rights_inheriting != 0
{
Err(Error::ENOTCAPABLE)
Err(WasiError::ENOTCAPABLE)
} else {
Ok(())
}

View File

@@ -1,10 +1,11 @@
use crate::old::snapshot_0::{Error, Result};
use crate::old::snapshot_0::wasi::WasiResult;
use std::str;
/// Creates not-owned WASI path from byte slice.
///
/// NB WASI spec requires bytes to be valid UTF-8. Otherwise,
/// `__WASI_ERRNO_ILSEQ` error is returned.
pub(crate) fn path_from_slice<'a>(s: &'a [u8]) -> Result<&'a str> {
str::from_utf8(s).map_err(|_| Error::EILSEQ)
pub(crate) fn path_from_slice<'a>(s: &'a [u8]) -> WasiResult<&'a str> {
let s = str::from_utf8(s)?;
Ok(s)
}

View File

@@ -5,7 +5,6 @@
#![allow(non_snake_case)]
use crate::old::snapshot_0::wasi::*;
use crate::old::snapshot_0::{Error, Result};
use std::{convert::TryInto, io, mem, slice};
use wig::witx_host_types;
@@ -52,11 +51,13 @@ pub(crate) struct Dirent {
impl Dirent {
/// Serialize the directory entry to the format define by `__wasi_fd_readdir`,
/// so that the serialized entries can be concatenated by the implementation.
pub fn to_wasi_raw(&self) -> Result<Vec<u8>> {
pub fn to_wasi_raw(&self) -> WasiResult<Vec<u8>> {
let name = self.name.as_bytes();
let namlen = name.len();
let dirent_size = mem::size_of::<__wasi_dirent_t>();
let offset = dirent_size.checked_add(namlen).ok_or(Error::EOVERFLOW)?;
let offset = dirent_size
.checked_add(namlen)
.ok_or(WasiError::EOVERFLOW)?;
let mut raw = Vec::<u8>::with_capacity(offset);
raw.resize(offset, 0);

View File

@@ -7,7 +7,8 @@ use crate::old::snapshot_0::memory::*;
use crate::old::snapshot_0::sys::fdentry_impl::determine_type_rights;
use crate::old::snapshot_0::sys::hostcalls_impl::fs_helpers::path_open_rights;
use crate::old::snapshot_0::sys::{host_impl, hostcalls_impl};
use crate::old::snapshot_0::{helpers, host, wasi, wasi32, Error, Result};
use crate::old::snapshot_0::wasi::{self, WasiError, WasiResult};
use crate::old::snapshot_0::{helpers, host, wasi32};
use crate::sandboxed_tty_writer::SandboxedTTYWriter;
use filetime::{set_file_handle_times, FileTime};
use log::trace;
@@ -20,13 +21,13 @@ pub(crate) unsafe fn fd_close(
wasi_ctx: &mut WasiCtx,
_mem: &mut [u8],
fd: wasi::__wasi_fd_t,
) -> Result<()> {
) -> WasiResult<()> {
trace!("fd_close(fd={:?})", fd);
if let Ok(fe) = wasi_ctx.get_fd_entry(fd) {
// can't close preopened files
if fe.preopen_path.is_some() {
return Err(Error::ENOTSUP);
return Err(WasiError::ENOTSUP);
}
}
@@ -38,7 +39,7 @@ pub(crate) unsafe fn fd_datasync(
wasi_ctx: &WasiCtx,
_mem: &mut [u8],
fd: wasi::__wasi_fd_t,
) -> Result<()> {
) -> WasiResult<()> {
trace!("fd_datasync(fd={:?})", fd);
let fd = wasi_ctx
@@ -57,7 +58,7 @@ pub(crate) unsafe fn fd_pread(
iovs_len: wasi32::size_t,
offset: wasi::__wasi_filesize_t,
nread: wasi32::uintptr_t,
) -> Result<()> {
) -> WasiResult<()> {
trace!(
"fd_pread(fd={:?}, iovs_ptr={:#x?}, iovs_len={:?}, offset={}, nread={:#x?})",
fd,
@@ -75,7 +76,7 @@ pub(crate) unsafe fn fd_pread(
let iovs = dec_iovec_slice(memory, iovs_ptr, iovs_len)?;
if offset > i64::max_value() as u64 {
return Err(Error::EIO);
return Err(WasiError::EIO);
}
let buf_size = iovs.iter().map(|v| v.buf_len).sum();
let mut buf = vec![0; buf_size];
@@ -106,7 +107,7 @@ pub(crate) unsafe fn fd_pwrite(
iovs_len: wasi32::size_t,
offset: wasi::__wasi_filesize_t,
nwritten: wasi32::uintptr_t,
) -> Result<()> {
) -> WasiResult<()> {
trace!(
"fd_pwrite(fd={:?}, iovs_ptr={:#x?}, iovs_len={:?}, offset={}, nwritten={:#x?})",
fd,
@@ -126,7 +127,7 @@ pub(crate) unsafe fn fd_pwrite(
let iovs = dec_ciovec_slice(memory, iovs_ptr, iovs_len)?;
if offset > i64::max_value() as u64 {
return Err(Error::EIO);
return Err(WasiError::EIO);
}
let buf_size = iovs.iter().map(|v| v.buf_len).sum();
let mut buf = Vec::with_capacity(buf_size);
@@ -150,7 +151,7 @@ pub(crate) unsafe fn fd_read(
iovs_ptr: wasi32::uintptr_t,
iovs_len: wasi32::size_t,
nread: wasi32::uintptr_t,
) -> Result<()> {
) -> WasiResult<()> {
trace!(
"fd_read(fd={:?}, iovs_ptr={:#x?}, iovs_len={:?}, nread={:#x?})",
fd,
@@ -171,7 +172,7 @@ pub(crate) unsafe fn fd_read(
{
Descriptor::OsHandle(file) => file.read_vectored(&mut iovs),
Descriptor::Stdin => io::stdin().read_vectored(&mut iovs),
_ => return Err(Error::EBADF),
_ => return Err(WasiError::EBADF),
};
let host_nread = maybe_host_nread?;
@@ -186,11 +187,11 @@ pub(crate) unsafe fn fd_renumber(
_mem: &mut [u8],
from: wasi::__wasi_fd_t,
to: wasi::__wasi_fd_t,
) -> Result<()> {
) -> WasiResult<()> {
trace!("fd_renumber(from={:?}, to={:?})", from, to);
if !wasi_ctx.contains_fd_entry(from) {
return Err(Error::EBADF);
return Err(WasiError::EBADF);
}
// Don't allow renumbering over a pre-opened resource.
@@ -198,11 +199,11 @@ pub(crate) unsafe fn fd_renumber(
// userspace is capable of removing entries from its tables as well.
let from_fe = wasi_ctx.get_fd_entry(from)?;
if from_fe.preopen_path.is_some() {
return Err(Error::ENOTSUP);
return Err(WasiError::ENOTSUP);
}
if let Ok(to_fe) = wasi_ctx.get_fd_entry(to) {
if to_fe.preopen_path.is_some() {
return Err(Error::ENOTSUP);
return Err(WasiError::ENOTSUP);
}
}
@@ -219,7 +220,7 @@ pub(crate) unsafe fn fd_seek(
offset: wasi::__wasi_filedelta_t,
whence: wasi::__wasi_whence_t,
newoffset: wasi32::uintptr_t,
) -> Result<()> {
) -> WasiResult<()> {
trace!(
"fd_seek(fd={:?}, offset={:?}, whence={}, newoffset={:#x?})",
fd,
@@ -242,7 +243,7 @@ pub(crate) unsafe fn fd_seek(
wasi::__WASI_WHENCE_CUR => SeekFrom::Current(offset),
wasi::__WASI_WHENCE_END => SeekFrom::End(offset),
wasi::__WASI_WHENCE_SET => SeekFrom::Start(offset as u64),
_ => return Err(Error::EINVAL),
_ => return Err(WasiError::EINVAL),
};
let host_newoffset = fd.seek(pos)?;
@@ -256,7 +257,7 @@ pub(crate) unsafe fn fd_tell(
memory: &mut [u8],
fd: wasi::__wasi_fd_t,
newoffset: wasi32::uintptr_t,
) -> Result<()> {
) -> WasiResult<()> {
trace!("fd_tell(fd={:?}, newoffset={:#x?})", fd, newoffset);
let fd = wasi_ctx
@@ -276,7 +277,7 @@ pub(crate) unsafe fn fd_fdstat_get(
memory: &mut [u8],
fd: wasi::__wasi_fd_t,
fdstat_ptr: wasi32::uintptr_t, // *mut wasi::__wasi_fdstat_t
) -> Result<()> {
) -> WasiResult<()> {
trace!("fd_fdstat_get(fd={:?}, fdstat_ptr={:#x?})", fd, fdstat_ptr);
let mut fdstat = dec_fdstat_byref(memory, fdstat_ptr)?;
@@ -303,7 +304,7 @@ pub(crate) unsafe fn fd_fdstat_set_flags(
_mem: &mut [u8],
fd: wasi::__wasi_fd_t,
fdflags: wasi::__wasi_fdflags_t,
) -> Result<()> {
) -> WasiResult<()> {
trace!("fd_fdstat_set_flags(fd={:?}, fdflags={:#x?})", fd, fdflags);
let fd = wasi_ctx
@@ -320,7 +321,7 @@ pub(crate) unsafe fn fd_fdstat_set_rights(
fd: wasi::__wasi_fd_t,
fs_rights_base: wasi::__wasi_rights_t,
fs_rights_inheriting: wasi::__wasi_rights_t,
) -> Result<()> {
) -> WasiResult<()> {
trace!(
"fd_fdstat_set_rights(fd={:?}, fs_rights_base={:#x?}, fs_rights_inheriting={:#x?})",
fd,
@@ -332,7 +333,7 @@ pub(crate) unsafe fn fd_fdstat_set_rights(
if fe.rights_base & fs_rights_base != fs_rights_base
|| fe.rights_inheriting & fs_rights_inheriting != fs_rights_inheriting
{
return Err(Error::ENOTCAPABLE);
return Err(WasiError::ENOTCAPABLE);
}
fe.rights_base = fs_rights_base;
fe.rights_inheriting = fs_rights_inheriting;
@@ -344,7 +345,7 @@ pub(crate) unsafe fn fd_sync(
wasi_ctx: &WasiCtx,
_mem: &mut [u8],
fd: wasi::__wasi_fd_t,
) -> Result<()> {
) -> WasiResult<()> {
trace!("fd_sync(fd={:?})", fd);
let fd = wasi_ctx
@@ -361,7 +362,7 @@ pub(crate) unsafe fn fd_write(
iovs_ptr: wasi32::uintptr_t,
iovs_len: wasi32::size_t,
nwritten: wasi32::uintptr_t,
) -> Result<()> {
) -> WasiResult<()> {
trace!(
"fd_write(fd={:?}, iovs_ptr={:#x?}, iovs_len={:?}, nwritten={:#x?})",
fd,
@@ -385,7 +386,7 @@ pub(crate) unsafe fn fd_write(
file.write_vectored(&iovs)?
}
}
Descriptor::Stdin => return Err(Error::EBADF),
Descriptor::Stdin => return Err(WasiError::EBADF),
Descriptor::Stdout => {
// lock for the duration of the scope
let stdout = io::stdout();
@@ -417,7 +418,7 @@ pub(crate) unsafe fn fd_advise(
offset: wasi::__wasi_filesize_t,
len: wasi::__wasi_filesize_t,
advice: wasi::__wasi_advice_t,
) -> Result<()> {
) -> WasiResult<()> {
trace!(
"fd_advise(fd={:?}, offset={}, len={}, advice={:?})",
fd,
@@ -440,7 +441,7 @@ pub(crate) unsafe fn fd_allocate(
fd: wasi::__wasi_fd_t,
offset: wasi::__wasi_filesize_t,
len: wasi::__wasi_filesize_t,
) -> Result<()> {
) -> WasiResult<()> {
trace!("fd_allocate(fd={:?}, offset={}, len={})", fd, offset, len);
let fd = wasi_ctx
@@ -451,10 +452,10 @@ pub(crate) unsafe fn fd_allocate(
let metadata = fd.metadata()?;
let current_size = metadata.len();
let wanted_size = offset.checked_add(len).ok_or(Error::E2BIG)?;
let wanted_size = offset.checked_add(len).ok_or(WasiError::E2BIG)?;
// This check will be unnecessary when rust-lang/rust#63326 is fixed
if wanted_size > i64::max_value() as u64 {
return Err(Error::E2BIG);
return Err(WasiError::E2BIG);
}
if wanted_size > current_size {
@@ -470,7 +471,7 @@ pub(crate) unsafe fn path_create_directory(
dirfd: wasi::__wasi_fd_t,
path_ptr: wasi32::uintptr_t,
path_len: wasi32::size_t,
) -> Result<()> {
) -> WasiResult<()> {
trace!(
"path_create_directory(dirfd={:?}, path_ptr={:#x?}, path_len={})",
dirfd,
@@ -499,7 +500,7 @@ pub(crate) unsafe fn path_link(
new_dirfd: wasi::__wasi_fd_t,
new_path_ptr: wasi32::uintptr_t,
new_path_len: wasi32::size_t,
) -> Result<()> {
) -> WasiResult<()> {
trace!(
"path_link(old_dirfd={:?}, old_flags={:?}, old_path_ptr={:#x?}, old_path_len={}, new_dirfd={:?}, new_path_ptr={:#x?}, new_path_len={})",
old_dirfd,
@@ -551,7 +552,7 @@ pub(crate) unsafe fn path_open(
fs_rights_inheriting: wasi::__wasi_rights_t,
fs_flags: wasi::__wasi_fdflags_t,
fd_out_ptr: wasi32::uintptr_t,
) -> Result<()> {
) -> WasiResult<()> {
trace!(
"path_open(dirfd={:?}, dirflags={:?}, path_ptr={:#x?}, path_len={:?}, oflags={:#x?}, fs_rights_base={:#x?}, fs_rights_inheriting={:#x?}, fs_flags={:#x?}, fd_out_ptr={:#x?})",
dirfd,
@@ -616,7 +617,7 @@ pub(crate) unsafe fn path_readlink(
buf_ptr: wasi32::uintptr_t,
buf_len: wasi32::size_t,
buf_used: wasi32::uintptr_t,
) -> Result<()> {
) -> WasiResult<()> {
trace!(
"path_readlink(dirfd={:?}, path_ptr={:#x?}, path_len={:?}, buf_ptr={:#x?}, buf_len={}, buf_used={:#x?})",
dirfd,
@@ -655,7 +656,7 @@ pub(crate) unsafe fn path_rename(
new_dirfd: wasi::__wasi_fd_t,
new_path_ptr: wasi32::uintptr_t,
new_path_len: wasi32::size_t,
) -> Result<()> {
) -> WasiResult<()> {
trace!(
"path_rename(old_dirfd={:?}, old_path_ptr={:#x?}, old_path_len={:?}, new_dirfd={:?}, new_path_ptr={:#x?}, new_path_len={:?})",
old_dirfd,
@@ -702,7 +703,7 @@ pub(crate) unsafe fn fd_filestat_get(
memory: &mut [u8],
fd: wasi::__wasi_fd_t,
filestat_ptr: wasi32::uintptr_t,
) -> Result<()> {
) -> WasiResult<()> {
trace!(
"fd_filestat_get(fd={:?}, filestat_ptr={:#x?})",
fd,
@@ -724,7 +725,7 @@ pub(crate) unsafe fn fd_filestat_set_times(
st_atim: wasi::__wasi_timestamp_t,
st_mtim: wasi::__wasi_timestamp_t,
fst_flags: wasi::__wasi_fstflags_t,
) -> Result<()> {
) -> WasiResult<()> {
trace!(
"fd_filestat_set_times(fd={:?}, st_atim={}, st_mtim={}, fst_flags={:#x?})",
fd,
@@ -746,14 +747,14 @@ pub(crate) fn fd_filestat_set_times_impl(
st_atim: wasi::__wasi_timestamp_t,
st_mtim: wasi::__wasi_timestamp_t,
fst_flags: wasi::__wasi_fstflags_t,
) -> Result<()> {
) -> WasiResult<()> {
let set_atim = fst_flags & wasi::__WASI_FSTFLAGS_ATIM != 0;
let set_atim_now = fst_flags & wasi::__WASI_FSTFLAGS_ATIM_NOW != 0;
let set_mtim = fst_flags & wasi::__WASI_FSTFLAGS_MTIM != 0;
let set_mtim_now = fst_flags & wasi::__WASI_FSTFLAGS_MTIM_NOW != 0;
if (set_atim && set_atim_now) || (set_mtim && set_mtim_now) {
return Err(Error::EINVAL);
return Err(WasiError::EINVAL);
}
let atim = if set_atim {
let time = UNIX_EPOCH + Duration::from_nanos(st_atim);
@@ -782,7 +783,7 @@ pub(crate) unsafe fn fd_filestat_set_size(
_mem: &mut [u8],
fd: wasi::__wasi_fd_t,
st_size: wasi::__wasi_filesize_t,
) -> Result<()> {
) -> WasiResult<()> {
trace!("fd_filestat_set_size(fd={:?}, st_size={})", fd, st_size);
let fd = wasi_ctx
@@ -792,7 +793,7 @@ pub(crate) unsafe fn fd_filestat_set_size(
// This check will be unnecessary when rust-lang/rust#63326 is fixed
if st_size > i64::max_value() as u64 {
return Err(Error::E2BIG);
return Err(WasiError::E2BIG);
}
fd.set_len(st_size).map_err(Into::into)
}
@@ -805,7 +806,7 @@ pub(crate) unsafe fn path_filestat_get(
path_ptr: wasi32::uintptr_t,
path_len: wasi32::size_t,
filestat_ptr: wasi32::uintptr_t,
) -> Result<()> {
) -> WasiResult<()> {
trace!(
"path_filestat_get(dirfd={:?}, dirflags={:?}, path_ptr={:#x?}, path_len={}, filestat_ptr={:#x?})",
dirfd,
@@ -845,7 +846,7 @@ pub(crate) unsafe fn path_filestat_set_times(
st_atim: wasi::__wasi_timestamp_t,
st_mtim: wasi::__wasi_timestamp_t,
fst_flags: wasi::__wasi_fstflags_t,
) -> Result<()> {
) -> WasiResult<()> {
trace!(
"path_filestat_set_times(dirfd={:?}, dirflags={:?}, path_ptr={:#x?}, path_len={}, st_atim={}, st_mtim={}, fst_flags={:#x?})",
dirfd,
@@ -881,7 +882,7 @@ pub(crate) unsafe fn path_symlink(
dirfd: wasi::__wasi_fd_t,
new_path_ptr: wasi32::uintptr_t,
new_path_len: wasi32::size_t,
) -> Result<()> {
) -> WasiResult<()> {
trace!(
"path_symlink(old_path_ptr={:#x?}, old_path_len={}, dirfd={:?}, new_path_ptr={:#x?}, new_path_len={})",
old_path_ptr,
@@ -909,7 +910,7 @@ pub(crate) unsafe fn path_unlink_file(
dirfd: wasi::__wasi_fd_t,
path_ptr: wasi32::uintptr_t,
path_len: wasi32::size_t,
) -> Result<()> {
) -> WasiResult<()> {
trace!(
"path_unlink_file(dirfd={:?}, path_ptr={:#x?}, path_len={})",
dirfd,
@@ -933,7 +934,7 @@ pub(crate) unsafe fn path_remove_directory(
dirfd: wasi::__wasi_fd_t,
path_ptr: wasi32::uintptr_t,
path_len: wasi32::size_t,
) -> Result<()> {
) -> WasiResult<()> {
trace!(
"path_remove_directory(dirfd={:?}, path_ptr={:#x?}, path_len={})",
dirfd,
@@ -965,7 +966,7 @@ pub(crate) unsafe fn fd_prestat_get(
memory: &mut [u8],
fd: wasi::__wasi_fd_t,
prestat_ptr: wasi32::uintptr_t,
) -> Result<()> {
) -> WasiResult<()> {
trace!(
"fd_prestat_get(fd={:?}, prestat_ptr={:#x?})",
fd,
@@ -974,9 +975,9 @@ pub(crate) unsafe fn fd_prestat_get(
// TODO: should we validate any rights here?
let fe = wasi_ctx.get_fd_entry(fd)?;
let po_path = fe.preopen_path.as_ref().ok_or(Error::ENOTSUP)?;
let po_path = fe.preopen_path.as_ref().ok_or(WasiError::ENOTSUP)?;
if fe.file_type != wasi::__WASI_FILETYPE_DIRECTORY {
return Err(Error::ENOTDIR);
return Err(WasiError::ENOTDIR);
}
let path = host_impl::path_from_host(po_path.as_os_str())?;
@@ -1001,7 +1002,7 @@ pub(crate) unsafe fn fd_prestat_dir_name(
fd: wasi::__wasi_fd_t,
path_ptr: wasi32::uintptr_t,
path_len: wasi32::size_t,
) -> Result<()> {
) -> WasiResult<()> {
trace!(
"fd_prestat_dir_name(fd={:?}, path_ptr={:#x?}, path_len={})",
fd,
@@ -1011,15 +1012,15 @@ pub(crate) unsafe fn fd_prestat_dir_name(
// TODO: should we validate any rights here?
let fe = wasi_ctx.get_fd_entry(fd)?;
let po_path = fe.preopen_path.as_ref().ok_or(Error::ENOTSUP)?;
let po_path = fe.preopen_path.as_ref().ok_or(WasiError::ENOTSUP)?;
if fe.file_type != wasi::__WASI_FILETYPE_DIRECTORY {
return Err(Error::ENOTDIR);
return Err(WasiError::ENOTDIR);
}
let path = host_impl::path_from_host(po_path.as_os_str())?;
if path.len() > dec_usize(path_len) {
return Err(Error::ENAMETOOLONG);
return Err(WasiError::ENAMETOOLONG);
}
trace!(" | (path_ptr,path_len)='{}'", path);
@@ -1035,7 +1036,7 @@ pub(crate) unsafe fn fd_readdir(
buf_len: wasi32::size_t,
cookie: wasi::__wasi_dircookie_t,
buf_used: wasi32::uintptr_t,
) -> Result<()> {
) -> WasiResult<()> {
trace!(
"fd_readdir(fd={:?}, buf={:#x?}, buf_len={}, cookie={:#x?}, buf_used={:#x?})",
fd,

View File

@@ -1,7 +1,8 @@
#![allow(non_camel_case_types)]
use crate::old::snapshot_0::fdentry::FdEntry;
use crate::old::snapshot_0::sys::host_impl;
use crate::old::snapshot_0::sys::hostcalls_impl::fs_helpers::*;
use crate::old::snapshot_0::{error::WasiError, fdentry::FdEntry, wasi, Error, Result};
use crate::old::snapshot_0::wasi::{self, WasiError, WasiResult};
use std::fs::File;
use std::path::{Component, Path};
@@ -31,17 +32,17 @@ pub(crate) fn path_get(
dirflags: wasi::__wasi_lookupflags_t,
path: &str,
needs_final_component: bool,
) -> Result<PathGet> {
) -> WasiResult<PathGet> {
const MAX_SYMLINK_EXPANSIONS: usize = 128;
if path.contains('\0') {
// if contains NUL, return EILSEQ
return Err(Error::EILSEQ);
return Err(WasiError::EILSEQ);
}
if fe.file_type != wasi::__WASI_FILETYPE_DIRECTORY {
// if `dirfd` doesn't refer to a directory, return `ENOTDIR`.
return Err(Error::ENOTDIR);
return Err(WasiError::ENOTDIR);
}
let dirfd = fe
@@ -72,7 +73,7 @@ pub(crate) fn path_get(
let ends_with_slash = cur_path.ends_with('/');
let mut components = Path::new(&cur_path).components();
let head = match components.next() {
None => return Err(Error::ENOENT),
None => return Err(WasiError::ENOENT),
Some(p) => p,
};
let tail = components.as_path();
@@ -90,18 +91,18 @@ pub(crate) fn path_get(
match head {
Component::Prefix(_) | Component::RootDir => {
// path is absolute!
return Err(Error::ENOTCAPABLE);
return Err(WasiError::ENOTCAPABLE);
}
Component::CurDir => {
// "." so skip
}
Component::ParentDir => {
// ".." so pop a dir
let _ = dir_stack.pop().ok_or(Error::ENOTCAPABLE)?;
let _ = dir_stack.pop().ok_or(WasiError::ENOTCAPABLE)?;
// we're not allowed to pop past the original directory
if dir_stack.is_empty() {
return Err(Error::ENOTCAPABLE);
return Err(WasiError::ENOTCAPABLE);
}
}
Component::Normal(head) => {
@@ -112,12 +113,12 @@ pub(crate) fn path_get(
}
if !path_stack.is_empty() || (ends_with_slash && !needs_final_component) {
match openat(dir_stack.last().ok_or(Error::ENOTCAPABLE)?, &head) {
match openat(dir_stack.last().ok_or(WasiError::ENOTCAPABLE)?, &head) {
Ok(new_dir) => {
dir_stack.push(new_dir);
}
Err(e) => {
match e.as_wasi_error() {
match e {
WasiError::ELOOP
| WasiError::EMLINK
| WasiError::ENOTDIR =>
@@ -126,13 +127,13 @@ pub(crate) fn path_get(
{
// attempt symlink expansion
let mut link_path = readlinkat(
dir_stack.last().ok_or(Error::ENOTCAPABLE)?,
dir_stack.last().ok_or(WasiError::ENOTCAPABLE)?,
&head,
)?;
symlink_expansions += 1;
if symlink_expansions > MAX_SYMLINK_EXPANSIONS {
return Err(Error::ELOOP);
return Err(WasiError::ELOOP);
}
if head.ends_with('/') {
@@ -159,11 +160,12 @@ pub(crate) fn path_get(
{
// if there's a trailing slash, or if `LOOKUP_SYMLINK_FOLLOW` is set, attempt
// symlink expansion
match readlinkat(dir_stack.last().ok_or(Error::ENOTCAPABLE)?, &head) {
match readlinkat(dir_stack.last().ok_or(WasiError::ENOTCAPABLE)?, &head)
{
Ok(mut link_path) => {
symlink_expansions += 1;
if symlink_expansions > MAX_SYMLINK_EXPANSIONS {
return Err(Error::ELOOP);
return Err(WasiError::ELOOP);
}
if head.ends_with('/') {
@@ -179,12 +181,12 @@ pub(crate) fn path_get(
continue;
}
Err(e) => {
if e.as_wasi_error() != WasiError::EINVAL
&& e.as_wasi_error() != WasiError::ENOENT
if e != WasiError::EINVAL
&& e != WasiError::ENOENT
// this handles the cases when trying to link to
// a destination that already exists, and the target
// path contains a slash
&& e.as_wasi_error() != WasiError::ENOTDIR
&& e != WasiError::ENOTDIR
{
return Err(e);
}
@@ -194,7 +196,7 @@ pub(crate) fn path_get(
// not a symlink, so we're done;
return Ok(PathGet {
dirfd: dir_stack.pop().ok_or(Error::ENOTCAPABLE)?,
dirfd: dir_stack.pop().ok_or(WasiError::ENOTCAPABLE)?,
path: head,
});
}
@@ -204,7 +206,7 @@ pub(crate) fn path_get(
// no further components to process. means we've hit a case like "." or "a/..", or if the
// input path has trailing slashes and `needs_final_component` is not set
return Ok(PathGet {
dirfd: dir_stack.pop().ok_or(Error::ENOTCAPABLE)?,
dirfd: dir_stack.pop().ok_or(WasiError::ENOTCAPABLE)?,
path: String::from("."),
});
}

View File

@@ -3,7 +3,8 @@ use crate::old::snapshot_0::ctx::WasiCtx;
use crate::old::snapshot_0::fdentry::Descriptor;
use crate::old::snapshot_0::memory::*;
use crate::old::snapshot_0::sys::hostcalls_impl;
use crate::old::snapshot_0::{wasi, wasi32, Error, Result};
use crate::old::snapshot_0::wasi::{self, WasiError, WasiResult};
use crate::old::snapshot_0::wasi32;
use log::{error, trace};
use std::convert::TryFrom;
@@ -12,7 +13,7 @@ pub(crate) fn args_get(
memory: &mut [u8],
argv_ptr: wasi32::uintptr_t,
argv_buf: wasi32::uintptr_t,
) -> Result<()> {
) -> WasiResult<()> {
trace!(
"args_get(argv_ptr={:#x?}, argv_buf={:#x?})",
argv_ptr,
@@ -31,7 +32,9 @@ pub(crate) fn args_get(
argv.push(arg_ptr);
let len = wasi32::uintptr_t::try_from(arg_bytes.len())?;
argv_buf_offset = argv_buf_offset.checked_add(len).ok_or(Error::EOVERFLOW)?;
argv_buf_offset = argv_buf_offset
.checked_add(len)
.ok_or(WasiError::EOVERFLOW)?;
}
enc_slice_of_wasi32_uintptr(memory, argv.as_slice(), argv_ptr)
@@ -42,7 +45,7 @@ pub(crate) fn args_sizes_get(
memory: &mut [u8],
argc_ptr: wasi32::uintptr_t,
argv_buf_size_ptr: wasi32::uintptr_t,
) -> Result<()> {
) -> WasiResult<()> {
trace!(
"args_sizes_get(argc_ptr={:#x?}, argv_buf_size_ptr={:#x?})",
argc_ptr,
@@ -70,7 +73,7 @@ pub(crate) fn environ_get(
memory: &mut [u8],
environ_ptr: wasi32::uintptr_t,
environ_buf: wasi32::uintptr_t,
) -> Result<()> {
) -> WasiResult<()> {
trace!(
"environ_get(environ_ptr={:#x?}, environ_buf={:#x?})",
environ_ptr,
@@ -91,7 +94,7 @@ pub(crate) fn environ_get(
let len = wasi32::uintptr_t::try_from(env_bytes.len())?;
environ_buf_offset = environ_buf_offset
.checked_add(len)
.ok_or(Error::EOVERFLOW)?;
.ok_or(WasiError::EOVERFLOW)?;
}
enc_slice_of_wasi32_uintptr(memory, environ.as_slice(), environ_ptr)
@@ -102,7 +105,7 @@ pub(crate) fn environ_sizes_get(
memory: &mut [u8],
environ_count_ptr: wasi32::uintptr_t,
environ_size_ptr: wasi32::uintptr_t,
) -> Result<()> {
) -> WasiResult<()> {
trace!(
"environ_sizes_get(environ_count_ptr={:#x?}, environ_size_ptr={:#x?})",
environ_count_ptr,
@@ -116,7 +119,7 @@ pub(crate) fn environ_sizes_get(
.try_fold(0, |acc: u32, pair| {
acc.checked_add(pair.as_bytes_with_nul().len() as u32)
})
.ok_or(Error::EOVERFLOW)?;
.ok_or(WasiError::EOVERFLOW)?;
trace!(" | *environ_count_ptr={:?}", environ_count);
@@ -132,14 +135,14 @@ pub(crate) fn random_get(
memory: &mut [u8],
buf_ptr: wasi32::uintptr_t,
buf_len: wasi32::size_t,
) -> Result<()> {
) -> WasiResult<()> {
trace!("random_get(buf_ptr={:#x?}, buf_len={:?})", buf_ptr, buf_len);
let buf = dec_slice_of_mut_u8(memory, buf_ptr, buf_len)?;
getrandom::getrandom(buf).map_err(|err| {
error!("getrandom failure: {:?}", err);
Error::EIO
WasiError::EIO
})
}
@@ -148,7 +151,7 @@ pub(crate) fn clock_res_get(
memory: &mut [u8],
clock_id: wasi::__wasi_clockid_t,
resolution_ptr: wasi32::uintptr_t,
) -> Result<()> {
) -> WasiResult<()> {
trace!(
"clock_res_get(clock_id={:?}, resolution_ptr={:#x?})",
clock_id,
@@ -168,7 +171,7 @@ pub(crate) fn clock_time_get(
clock_id: wasi::__wasi_clockid_t,
precision: wasi::__wasi_timestamp_t,
time_ptr: wasi32::uintptr_t,
) -> Result<()> {
) -> WasiResult<()> {
trace!(
"clock_time_get(clock_id={:?}, precision={:?}, time_ptr={:#x?})",
clock_id,
@@ -183,7 +186,7 @@ pub(crate) fn clock_time_get(
enc_timestamp_byref(memory, time_ptr, time)
}
pub(crate) fn sched_yield(_wasi_ctx: &WasiCtx, _memory: &mut [u8]) -> Result<()> {
pub(crate) fn sched_yield(_wasi_ctx: &WasiCtx, _memory: &mut [u8]) -> WasiResult<()> {
trace!("sched_yield()");
std::thread::yield_now();
@@ -198,7 +201,7 @@ pub(crate) fn poll_oneoff(
output: wasi32::uintptr_t,
nsubscriptions: wasi32::size_t,
nevents: wasi32::uintptr_t,
) -> Result<()> {
) -> WasiResult<()> {
trace!(
"poll_oneoff(input={:#x?}, output={:#x?}, nsubscriptions={}, nevents={:#x?})",
input,
@@ -208,7 +211,7 @@ pub(crate) fn poll_oneoff(
);
if u64::from(nsubscriptions) > wasi::__wasi_filesize_t::max_value() {
return Err(Error::EINVAL);
return Err(WasiError::EINVAL);
}
enc_int_byref(memory, nevents, 0)?;
@@ -253,7 +256,7 @@ pub(crate) fn poll_oneoff(
Err(err) => {
let event = wasi::__wasi_event_t {
userdata: subscription.userdata,
error: err.as_wasi_error().as_raw_errno(),
error: err.as_raw_errno(),
r#type: wasi::__WASI_EVENTTYPE_FD_READ,
fd_readwrite: wasi::__wasi_event_fd_readwrite_t {
nbytes: 0,
@@ -281,7 +284,7 @@ pub(crate) fn poll_oneoff(
Err(err) => {
let event = wasi::__wasi_event_t {
userdata: subscription.userdata,
error: err.as_wasi_error().as_raw_errno(),
error: err.as_raw_errno(),
r#type: wasi::__WASI_EVENTTYPE_FD_WRITE,
fd_readwrite: wasi::__wasi_event_fd_readwrite_t {
nbytes: 0,
@@ -301,7 +304,7 @@ pub(crate) fn poll_oneoff(
hostcalls_impl::poll_oneoff(timeout, fd_events, &mut events)?;
let events_count = u32::try_from(events.len()).map_err(|_| Error::EOVERFLOW)?;
let events_count = u32::try_from(events.len()).map_err(|_| WasiError::EOVERFLOW)?;
enc_events(memory, output, nsubscriptions, events)?;
@@ -310,7 +313,9 @@ pub(crate) fn poll_oneoff(
enc_int_byref(memory, nevents, events_count)
}
fn wasi_clock_to_relative_ns_delay(wasi_clock: wasi::__wasi_subscription_clock_t) -> Result<u128> {
fn wasi_clock_to_relative_ns_delay(
wasi_clock: wasi::__wasi_subscription_clock_t,
) -> WasiResult<u128> {
use std::time::SystemTime;
if wasi_clock.flags != wasi::__WASI_SUBCLOCKFLAGS_SUBSCRIPTION_CLOCK_ABSTIME {
@@ -318,7 +323,7 @@ fn wasi_clock_to_relative_ns_delay(wasi_clock: wasi::__wasi_subscription_clock_t
}
let now: u128 = SystemTime::now()
.duration_since(SystemTime::UNIX_EPOCH)
.map_err(|_| Error::ENOTCAPABLE)?
.map_err(|_| WasiError::ENOTCAPABLE)?
.as_nanos();
let deadline = u128::from(wasi_clock.timeout);
Ok(deadline.saturating_sub(now))
@@ -348,6 +353,6 @@ pub(crate) fn proc_raise(
_wasi_ctx: &WasiCtx,
_memory: &mut [u8],
_sig: wasi::__wasi_signal_t,
) -> Result<()> {
) -> WasiResult<()> {
unimplemented!("proc_raise")
}

View File

@@ -1,4 +1,5 @@
use crate::old::snapshot_0::{wasi, wasi32, Result, WasiCtx};
use crate::old::snapshot_0::wasi::{self, WasiResult};
use crate::old::snapshot_0::{wasi32, WasiCtx};
pub fn sock_recv(
_wasi_ctx: &WasiCtx,
@@ -9,7 +10,7 @@ pub fn sock_recv(
_ri_flags: wasi::__wasi_riflags_t,
_ro_datalen: wasi32::uintptr_t,
_ro_flags: wasi32::uintptr_t,
) -> Result<()> {
) -> WasiResult<()> {
unimplemented!("sock_recv")
}
@@ -21,7 +22,7 @@ pub fn sock_send(
_si_data_len: wasi32::size_t,
_si_flags: wasi::__wasi_siflags_t,
_so_datalen: wasi32::uintptr_t,
) -> Result<()> {
) -> WasiResult<()> {
unimplemented!("sock_send")
}
@@ -30,6 +31,6 @@ pub fn sock_shutdown(
_memory: &mut [u8],
_sock: wasi::__wasi_fd_t,
_how: wasi::__wasi_sdflags_t,
) -> Result<()> {
) -> WasiResult<()> {
unimplemented!("sock_shutdown")
}

View File

@@ -8,38 +8,39 @@
//! are not held for long durations.
#![allow(unused)]
use crate::old::snapshot_0::{host, wasi, wasi32, Error, Result};
use crate::old::snapshot_0::wasi::{self, WasiError, WasiResult};
use crate::old::snapshot_0::{host, wasi32};
use num::PrimInt;
use std::convert::TryFrom;
use std::mem::{align_of, size_of};
use std::{ptr, slice};
fn dec_ptr(memory: &[u8], ptr: wasi32::uintptr_t, len: usize) -> Result<*const u8> {
fn dec_ptr(memory: &[u8], ptr: wasi32::uintptr_t, len: usize) -> WasiResult<*const u8> {
// check for overflow
let checked_len = (ptr as usize).checked_add(len).ok_or(Error::EFAULT)?;
let checked_len = (ptr as usize).checked_add(len).ok_or(WasiError::EFAULT)?;
// translate the pointer
memory
.get(ptr as usize..checked_len)
.ok_or(Error::EFAULT)
.ok_or(WasiError::EFAULT)
.map(|mem| mem.as_ptr())
}
fn dec_ptr_mut(memory: &mut [u8], ptr: wasi32::uintptr_t, len: usize) -> Result<*mut u8> {
fn dec_ptr_mut(memory: &mut [u8], ptr: wasi32::uintptr_t, len: usize) -> WasiResult<*mut u8> {
// check for overflow
let checked_len = (ptr as usize).checked_add(len).ok_or(Error::EFAULT)?;
let checked_len = (ptr as usize).checked_add(len).ok_or(WasiError::EFAULT)?;
// translate the pointer
memory
.get_mut(ptr as usize..checked_len)
.ok_or(Error::EFAULT)
.ok_or(WasiError::EFAULT)
.map(|mem| mem.as_mut_ptr())
}
fn dec_ptr_to<'memory, T>(memory: &'memory [u8], ptr: wasi32::uintptr_t) -> Result<&'memory T> {
fn dec_ptr_to<'memory, T>(memory: &'memory [u8], ptr: wasi32::uintptr_t) -> WasiResult<&'memory T> {
// check that the ptr is aligned
if ptr as usize % align_of::<T>() != 0 {
return Err(Error::EINVAL);
return Err(WasiError::EINVAL);
}
dec_ptr(memory, ptr, size_of::<T>()).map(|p| unsafe { &*(p as *const T) })
@@ -48,49 +49,49 @@ fn dec_ptr_to<'memory, T>(memory: &'memory [u8], ptr: wasi32::uintptr_t) -> Resu
fn dec_ptr_to_mut<'memory, T>(
memory: &'memory mut [u8],
ptr: wasi32::uintptr_t,
) -> Result<&'memory mut T> {
) -> WasiResult<&'memory mut T> {
// check that the ptr is aligned
if ptr as usize % align_of::<T>() != 0 {
return Err(Error::EINVAL);
return Err(WasiError::EINVAL);
}
dec_ptr_mut(memory, ptr, size_of::<T>()).map(|p| unsafe { &mut *(p as *mut T) })
}
/// This function does not perform endianness conversions!
fn dec_raw_byref<T>(memory: &[u8], ptr: wasi32::uintptr_t) -> Result<T> {
fn dec_raw_byref<T>(memory: &[u8], ptr: wasi32::uintptr_t) -> WasiResult<T> {
dec_ptr_to::<T>(memory, ptr).map(|p| unsafe { ptr::read(p) })
}
/// This function does not perform endianness conversions!
fn enc_raw_byref<T>(memory: &mut [u8], ptr: wasi32::uintptr_t, t: T) -> Result<()> {
fn enc_raw_byref<T>(memory: &mut [u8], ptr: wasi32::uintptr_t, t: T) -> WasiResult<()> {
dec_ptr_to_mut::<T>(memory, ptr).map(|p| unsafe { ptr::write(p, t) })
}
pub(crate) fn dec_int_byref<T>(memory: &[u8], ptr: wasi32::uintptr_t) -> Result<T>
pub(crate) fn dec_int_byref<T>(memory: &[u8], ptr: wasi32::uintptr_t) -> WasiResult<T>
where
T: PrimInt,
{
dec_raw_byref::<T>(memory, ptr).map(|i| PrimInt::from_le(i))
}
pub(crate) fn enc_int_byref<T>(memory: &mut [u8], ptr: wasi32::uintptr_t, t: T) -> Result<()>
pub(crate) fn enc_int_byref<T>(memory: &mut [u8], ptr: wasi32::uintptr_t, t: T) -> WasiResult<()>
where
T: PrimInt,
{
enc_raw_byref::<T>(memory, ptr, PrimInt::to_le(t))
}
fn check_slice_of<T>(ptr: wasi32::uintptr_t, len: wasi32::size_t) -> Result<(usize, usize)> {
fn check_slice_of<T>(ptr: wasi32::uintptr_t, len: wasi32::size_t) -> WasiResult<(usize, usize)> {
// check alignment, and that length doesn't overflow
if ptr as usize % align_of::<T>() != 0 {
return Err(Error::EINVAL);
return Err(WasiError::EINVAL);
}
let len = dec_usize(len);
let len_bytes = if let Some(len) = size_of::<T>().checked_mul(len) {
len
} else {
return Err(Error::EOVERFLOW);
return Err(WasiError::EOVERFLOW);
};
Ok((len, len_bytes))
@@ -100,7 +101,7 @@ fn dec_raw_slice_of<'memory, T>(
memory: &'memory [u8],
ptr: wasi32::uintptr_t,
len: wasi32::size_t,
) -> Result<&'memory [T]> {
) -> WasiResult<&'memory [T]> {
let (len, len_bytes) = check_slice_of::<T>(ptr, len)?;
let ptr = dec_ptr(memory, ptr, len_bytes)? as *const T;
Ok(unsafe { slice::from_raw_parts(ptr, len) })
@@ -110,7 +111,7 @@ fn dec_raw_slice_of_mut<'memory, T>(
memory: &'memory mut [u8],
ptr: wasi32::uintptr_t,
len: wasi32::size_t,
) -> Result<&'memory mut [T]> {
) -> WasiResult<&'memory mut [T]> {
let (len, len_bytes) = check_slice_of::<T>(ptr, len)?;
let ptr = dec_ptr_mut(memory, ptr, len_bytes)? as *mut T;
Ok(unsafe { slice::from_raw_parts_mut(ptr, len) })
@@ -120,16 +121,16 @@ fn raw_slice_for_enc<'memory, T>(
memory: &'memory mut [u8],
slice: &[T],
ptr: wasi32::uintptr_t,
) -> Result<&'memory mut [T]> {
) -> WasiResult<&'memory mut [T]> {
// check alignment
if ptr as usize % align_of::<T>() != 0 {
return Err(Error::EINVAL);
return Err(WasiError::EINVAL);
}
// check that length doesn't overflow
let len_bytes = if let Some(len) = size_of::<T>().checked_mul(slice.len()) {
len
} else {
return Err(Error::EOVERFLOW);
return Err(WasiError::EOVERFLOW);
};
// get the pointer into guest memory
@@ -142,7 +143,7 @@ pub(crate) fn dec_slice_of_u8<'memory>(
memory: &'memory [u8],
ptr: wasi32::uintptr_t,
len: wasi32::size_t,
) -> Result<&'memory [u8]> {
) -> WasiResult<&'memory [u8]> {
dec_raw_slice_of::<u8>(memory, ptr, len)
}
@@ -150,7 +151,7 @@ pub(crate) fn dec_slice_of_mut_u8<'memory>(
memory: &'memory mut [u8],
ptr: wasi32::uintptr_t,
len: wasi32::size_t,
) -> Result<&'memory mut [u8]> {
) -> WasiResult<&'memory mut [u8]> {
dec_raw_slice_of_mut::<u8>(memory, ptr, len)
}
@@ -158,7 +159,7 @@ pub(crate) fn enc_slice_of_u8(
memory: &mut [u8],
slice: &[u8],
ptr: wasi32::uintptr_t,
) -> Result<()> {
) -> WasiResult<()> {
let output = raw_slice_for_enc::<u8>(memory, slice, ptr)?;
output.copy_from_slice(slice);
@@ -170,7 +171,7 @@ pub(crate) fn enc_slice_of_wasi32_uintptr(
memory: &mut [u8],
slice: &[wasi32::uintptr_t],
ptr: wasi32::uintptr_t,
) -> Result<()> {
) -> WasiResult<()> {
let mut output_iter = raw_slice_for_enc::<wasi32::uintptr_t>(memory, slice, ptr)?.into_iter();
for p in slice {
@@ -182,7 +183,10 @@ pub(crate) fn enc_slice_of_wasi32_uintptr(
macro_rules! dec_enc_scalar {
($ty:ident, $dec_byref:ident, $enc_byref:ident) => {
pub(crate) fn $dec_byref(memory: &mut [u8], ptr: wasi32::uintptr_t) -> Result<wasi::$ty> {
pub(crate) fn $dec_byref(
memory: &mut [u8],
ptr: wasi32::uintptr_t,
) -> WasiResult<wasi::$ty> {
dec_int_byref::<wasi::$ty>(memory, ptr)
}
@@ -190,7 +194,7 @@ macro_rules! dec_enc_scalar {
memory: &mut [u8],
ptr: wasi32::uintptr_t,
x: wasi::$ty,
) -> Result<()> {
) -> WasiResult<()> {
enc_int_byref::<wasi::$ty>(memory, ptr, x)
}
};
@@ -200,7 +204,7 @@ pub(crate) fn dec_ciovec_slice(
memory: &[u8],
ptr: wasi32::uintptr_t,
len: wasi32::size_t,
) -> Result<Vec<host::__wasi_ciovec_t>> {
) -> WasiResult<Vec<host::__wasi_ciovec_t>> {
let raw_slice = dec_raw_slice_of::<wasi32::__wasi_ciovec_t>(memory, ptr, len)?;
raw_slice
@@ -220,7 +224,7 @@ pub(crate) fn dec_iovec_slice(
memory: &[u8],
ptr: wasi32::uintptr_t,
len: wasi32::size_t,
) -> Result<Vec<host::__wasi_iovec_t>> {
) -> WasiResult<Vec<host::__wasi_iovec_t>> {
let raw_slice = dec_raw_slice_of::<wasi32::__wasi_iovec_t>(memory, ptr, len)?;
raw_slice
@@ -248,7 +252,7 @@ dec_enc_scalar!(__wasi_linkcount_t, dev_linkcount_byref, enc_linkcount_byref);
pub(crate) fn dec_filestat_byref(
memory: &mut [u8],
filestat_ptr: wasi32::uintptr_t,
) -> Result<wasi::__wasi_filestat_t> {
) -> WasiResult<wasi::__wasi_filestat_t> {
let raw = dec_raw_byref::<wasi::__wasi_filestat_t>(memory, filestat_ptr)?;
Ok(wasi::__wasi_filestat_t {
@@ -267,7 +271,7 @@ pub(crate) fn enc_filestat_byref(
memory: &mut [u8],
filestat_ptr: wasi32::uintptr_t,
filestat: wasi::__wasi_filestat_t,
) -> Result<()> {
) -> WasiResult<()> {
let raw = wasi::__wasi_filestat_t {
dev: PrimInt::to_le(filestat.dev),
ino: PrimInt::to_le(filestat.ino),
@@ -285,7 +289,7 @@ pub(crate) fn enc_filestat_byref(
pub(crate) fn dec_fdstat_byref(
memory: &mut [u8],
fdstat_ptr: wasi32::uintptr_t,
) -> Result<wasi::__wasi_fdstat_t> {
) -> WasiResult<wasi::__wasi_fdstat_t> {
let raw = dec_raw_byref::<wasi::__wasi_fdstat_t>(memory, fdstat_ptr)?;
Ok(wasi::__wasi_fdstat_t {
@@ -300,7 +304,7 @@ pub(crate) fn enc_fdstat_byref(
memory: &mut [u8],
fdstat_ptr: wasi32::uintptr_t,
fdstat: wasi::__wasi_fdstat_t,
) -> Result<()> {
) -> WasiResult<()> {
let raw = wasi::__wasi_fdstat_t {
fs_filetype: PrimInt::to_le(fdstat.fs_filetype),
fs_flags: PrimInt::to_le(fdstat.fs_flags),
@@ -326,7 +330,7 @@ dec_enc_scalar!(__wasi_oflags_t, dec_oflags_byref, enc_oflags_byref);
pub(crate) fn dec_prestat_byref(
memory: &mut [u8],
prestat_ptr: wasi32::uintptr_t,
) -> Result<host::__wasi_prestat_t> {
) -> WasiResult<host::__wasi_prestat_t> {
let raw = dec_raw_byref::<wasi32::__wasi_prestat_t>(memory, prestat_ptr)?;
match PrimInt::from_le(raw.tag) {
@@ -338,7 +342,7 @@ pub(crate) fn dec_prestat_byref(
},
},
}),
_ => Err(Error::EINVAL),
_ => Err(WasiError::EINVAL),
}
}
@@ -346,7 +350,7 @@ pub(crate) fn enc_prestat_byref(
memory: &mut [u8],
prestat_ptr: wasi32::uintptr_t,
prestat: host::__wasi_prestat_t,
) -> Result<()> {
) -> WasiResult<()> {
let raw = match prestat.tag {
wasi::__WASI_PREOPENTYPE_DIR => Ok(wasi32::__wasi_prestat_t {
tag: PrimInt::to_le(wasi::__WASI_PREOPENTYPE_DIR),
@@ -356,7 +360,7 @@ pub(crate) fn enc_prestat_byref(
},
},
}),
_ => Err(Error::EINVAL),
_ => Err(WasiError::EINVAL),
}?;
enc_raw_byref::<wasi32::__wasi_prestat_t>(memory, prestat_ptr, raw)
@@ -377,7 +381,7 @@ pub(crate) fn enc_usize_byref(
memory: &mut [u8],
usize_ptr: wasi32::uintptr_t,
host_usize: usize,
) -> Result<()> {
) -> WasiResult<()> {
enc_int_byref::<wasi32::size_t>(memory, usize_ptr, enc_usize(host_usize))
}
@@ -402,7 +406,7 @@ pub(crate) fn dec_subscriptions(
memory: &mut [u8],
input: wasi32::uintptr_t,
nsubscriptions: wasi32::size_t,
) -> Result<Vec<wasi::__wasi_subscription_t>> {
) -> WasiResult<Vec<wasi::__wasi_subscription_t>> {
let raw_input_slice =
dec_raw_slice_of::<wasi::__wasi_subscription_t>(memory, input, nsubscriptions)?;
@@ -436,14 +440,14 @@ pub(crate) fn dec_subscriptions(
}),
},
},
_ => return Err(Error::EINVAL),
_ => return Err(WasiError::EINVAL),
};
Ok(wasi::__wasi_subscription_t {
userdata,
u: wasi::__wasi_subscription_u_t { tag, u },
})
})
.collect::<Result<Vec<_>>>()
.collect::<WasiResult<Vec<_>>>()
}
pub(crate) fn enc_events(
@@ -451,7 +455,7 @@ pub(crate) fn enc_events(
output: wasi32::uintptr_t,
nsubscriptions: wasi32::size_t,
events: Vec<wasi::__wasi_event_t>,
) -> Result<()> {
) -> WasiResult<()> {
let mut raw_output_iter =
dec_raw_slice_of_mut::<wasi::__wasi_event_t>(memory, output, nsubscriptions)?.into_iter();

View File

@@ -1,5 +1,4 @@
mod ctx;
mod error;
mod fdentry;
mod helpers;
mod host;
@@ -14,6 +13,3 @@ pub mod hostcalls {
}
pub use ctx::{WasiCtx, WasiCtxBuilder};
pub type Error = error::Error;
pub type Result<T> = std::result::Result<T, Error>;

View File

@@ -1,16 +1,16 @@
use crate::old::snapshot_0::{wasi, Result};
use crate::old::snapshot_0::wasi::{self, WasiResult};
use std::convert::TryFrom;
pub(crate) const O_RSYNC: yanix::file::OFlag = yanix::file::OFlag::SYNC;
pub(crate) fn stdev_from_nix(dev: libc::dev_t) -> Result<wasi::__wasi_device_t> {
pub(crate) fn stdev_from_nix(dev: libc::dev_t) -> WasiResult<wasi::__wasi_device_t> {
wasi::__wasi_device_t::try_from(dev).map_err(Into::into)
}
pub(crate) fn stino_from_nix(ino: libc::ino_t) -> Result<wasi::__wasi_inode_t> {
pub(crate) fn stino_from_nix(ino: libc::ino_t) -> WasiResult<wasi::__wasi_inode_t> {
wasi::__wasi_device_t::try_from(ino).map_err(Into::into)
}
pub(crate) fn stnlink_from_nix(nlink: libc::nlink_t) -> Result<wasi::__wasi_linkcount_t> {
pub(crate) fn stnlink_from_nix(nlink: libc::nlink_t) -> WasiResult<wasi::__wasi_linkcount_t> {
Ok(nlink.into())
}

View File

@@ -1,8 +1,8 @@
use crate::old::snapshot_0::hostcalls_impl::PathGet;
use crate::old::snapshot_0::{Error, Result};
use crate::old::snapshot_0::wasi::{WasiError, WasiResult};
use std::os::unix::prelude::AsRawFd;
pub(crate) fn path_unlink_file(resolved: PathGet) -> Result<()> {
pub(crate) fn path_unlink_file(resolved: PathGet) -> WasiResult<()> {
use yanix::file::{unlinkat, AtFlag};
match unsafe {
unlinkat(
@@ -32,7 +32,7 @@ pub(crate) fn path_unlink_file(resolved: PathGet) -> Result<()> {
} {
Ok(stat) => {
if FileType::from_stat_st_mode(stat.st_mode) == FileType::Directory {
return Err(Error::EISDIR);
return Err(WasiError::EISDIR);
}
}
Err(err) => {
@@ -47,7 +47,7 @@ pub(crate) fn path_unlink_file(resolved: PathGet) -> Result<()> {
}
}
pub(crate) fn path_symlink(old_path: &str, resolved: PathGet) -> Result<()> {
pub(crate) fn path_symlink(old_path: &str, resolved: PathGet) -> WasiResult<()> {
use yanix::file::{fstatat, symlinkat, AtFlag};
log::debug!("path_symlink old_path = {:?}", old_path);
@@ -69,7 +69,7 @@ pub(crate) fn path_symlink(old_path: &str, resolved: PathGet) -> Result<()> {
AtFlag::SYMLINK_NOFOLLOW,
)
} {
Ok(_) => return Err(Error::EEXIST),
Ok(_) => return Err(WasiError::EEXIST),
Err(err) => {
log::debug!("path_symlink fstatat error: {:?}", err);
}
@@ -81,7 +81,7 @@ pub(crate) fn path_symlink(old_path: &str, resolved: PathGet) -> Result<()> {
}
}
pub(crate) fn path_rename(resolved_old: PathGet, resolved_new: PathGet) -> Result<()> {
pub(crate) fn path_rename(resolved_old: PathGet, resolved_new: PathGet) -> WasiResult<()> {
use yanix::file::{fstatat, renameat, AtFlag};
match unsafe {
renameat(
@@ -113,9 +113,9 @@ pub(crate) fn path_rename(resolved_old: PathGet, resolved_new: PathGet) -> Resul
Ok(_) => {
// check if destination contains a trailing slash
if resolved_new.path().contains('/') {
return Err(Error::ENOTDIR);
return Err(WasiError::ENOTDIR);
} else {
return Err(Error::ENOENT);
return Err(WasiError::ENOENT);
}
}
Err(err) => {
@@ -132,13 +132,13 @@ pub(crate) fn path_rename(resolved_old: PathGet, resolved_new: PathGet) -> Resul
pub(crate) mod fd_readdir_impl {
use crate::old::snapshot_0::sys::fdentry_impl::OsHandle;
use crate::old::snapshot_0::Result;
use crate::old::snapshot_0::wasi::WasiResult;
use std::sync::{Mutex, MutexGuard};
use yanix::dir::Dir;
pub(crate) fn get_dir_from_os_handle<'a>(
os_handle: &'a mut OsHandle,
) -> Result<MutexGuard<'a, Dir>> {
) -> WasiResult<MutexGuard<'a, Dir>> {
let dir = match os_handle.dir {
Some(ref mut dir) => dir,
None => {

View File

@@ -1,5 +1,5 @@
use crate::old::snapshot_0::fdentry::{Descriptor, OsHandleRef};
use crate::old::snapshot_0::{sys::unix::sys_impl, wasi, Error, Result};
use crate::old::snapshot_0::{sys::unix::sys_impl, wasi};
use std::fs::File;
use std::io;
use std::mem::ManuallyDrop;
@@ -29,7 +29,7 @@ pub(crate) fn descriptor_as_oshandle<'lifetime>(
/// This function is unsafe because it operates on a raw file descriptor.
pub(crate) unsafe fn determine_type_and_access_rights<Fd: AsRawFd>(
fd: &Fd,
) -> Result<(
) -> io::Result<(
wasi::__wasi_filetype_t,
wasi::__wasi_rights_t,
wasi::__wasi_rights_t,
@@ -51,7 +51,7 @@ pub(crate) unsafe fn determine_type_and_access_rights<Fd: AsRawFd>(
/// This function is unsafe because it operates on a raw file descriptor.
pub(crate) unsafe fn determine_type_rights<Fd: AsRawFd>(
fd: &Fd,
) -> Result<(
) -> io::Result<(
wasi::__wasi_filetype_t,
wasi::__wasi_rights_t,
wasi::__wasi_rights_t,
@@ -111,7 +111,7 @@ pub(crate) unsafe fn determine_type_rights<Fd: AsRawFd>(
wasi::RIGHTS_SOCKET_BASE,
wasi::RIGHTS_SOCKET_INHERITING,
),
_ => return Err(Error::EINVAL),
_ => return Err(io::Error::from_raw_os_error(libc::EINVAL)),
}
} else if ft.is_fifo() {
log::debug!("Host fd {:?} is a fifo", fd.as_raw_fd());
@@ -122,7 +122,7 @@ pub(crate) unsafe fn determine_type_rights<Fd: AsRawFd>(
)
} else {
log::debug!("Host fd {:?} is unknown", fd.as_raw_fd());
return Err(Error::EINVAL);
return Err(io::Error::from_raw_os_error(libc::EINVAL));
}
};

View File

@@ -3,18 +3,19 @@
#![allow(non_snake_case)]
#![allow(dead_code)]
use crate::old::snapshot_0::host::FileType;
use crate::old::snapshot_0::{
error::FromRawOsError, helpers, sys::unix::sys_impl, wasi, Error, Result,
};
use crate::old::snapshot_0::wasi::{self, WasiError, WasiResult};
use crate::old::snapshot_0::{helpers, sys::unix::sys_impl};
use std::ffi::OsStr;
use std::io;
use std::os::unix::prelude::OsStrExt;
use yanix::file::OFlag;
pub(crate) use sys_impl::host_impl::*;
impl FromRawOsError for Error {
fn from_raw_os_error(code: i32) -> Self {
match code {
impl From<io::Error> for WasiError {
fn from(err: io::Error) -> Self {
match err.raw_os_error() {
Some(code) => match code {
libc::EPERM => Self::EPERM,
libc::ENOENT => Self::ENOENT,
libc::ESRCH => Self::ESRCH,
@@ -89,10 +90,16 @@ impl FromRawOsError for Error {
libc::ECANCELED => Self::ECANCELED,
libc::EOWNERDEAD => Self::EOWNERDEAD,
libc::ENOTRECOVERABLE => Self::ENOTRECOVERABLE,
libc::ENOTSUP => Self::ENOTSUP,
x => {
log::debug!("Unknown errno value: {}", x);
Self::EIO
}
},
None => {
log::debug!("Other I/O error: {}", err);
Self::EIO
}
}
}
}
@@ -154,13 +161,13 @@ pub(crate) fn nix_from_oflags(oflags: wasi::__wasi_oflags_t) -> OFlag {
nix_flags
}
pub(crate) fn filestat_from_nix(filestat: libc::stat) -> Result<wasi::__wasi_filestat_t> {
pub(crate) fn filestat_from_nix(filestat: libc::stat) -> WasiResult<wasi::__wasi_filestat_t> {
use std::convert::TryInto;
fn filestat_to_timestamp(secs: u64, nsecs: u64) -> Result<wasi::__wasi_timestamp_t> {
fn filestat_to_timestamp(secs: u64, nsecs: u64) -> WasiResult<wasi::__wasi_timestamp_t> {
secs.checked_mul(1_000_000_000)
.and_then(|sec_nsec| sec_nsec.checked_add(nsecs))
.ok_or(Error::EOVERFLOW)
.ok_or(WasiError::EOVERFLOW)
}
let filetype = yanix::file::FileType::from_stat_st_mode(filestat.st_mode);
@@ -195,7 +202,7 @@ pub(crate) fn filestat_from_nix(filestat: libc::stat) -> Result<wasi::__wasi_fil
///
/// NB WASI spec requires OS string to be valid UTF-8. Otherwise,
/// `__WASI_ERRNO_ILSEQ` error is returned.
pub(crate) fn path_from_host<S: AsRef<OsStr>>(s: S) -> Result<String> {
pub(crate) fn path_from_host<S: AsRef<OsStr>>(s: S) -> WasiResult<String> {
helpers::path_from_slice(s.as_ref().as_bytes()).map(String::from)
}

View File

@@ -3,7 +3,7 @@
use crate::old::snapshot_0::host::Dirent;
use crate::old::snapshot_0::hostcalls_impl::PathGet;
use crate::old::snapshot_0::sys::{fdentry_impl::OsHandle, host_impl, unix::sys_impl};
use crate::old::snapshot_0::{wasi, Error, Result};
use crate::old::snapshot_0::wasi::{self, WasiError, WasiResult};
use std::convert::TryInto;
use std::fs::File;
use std::os::unix::fs::FileExt;
@@ -15,21 +15,25 @@ pub(crate) fn fd_pread(
file: &File,
buf: &mut [u8],
offset: wasi::__wasi_filesize_t,
) -> Result<usize> {
) -> WasiResult<usize> {
file.read_at(buf, offset).map_err(Into::into)
}
pub(crate) fn fd_pwrite(file: &File, buf: &[u8], offset: wasi::__wasi_filesize_t) -> Result<usize> {
pub(crate) fn fd_pwrite(
file: &File,
buf: &[u8],
offset: wasi::__wasi_filesize_t,
) -> WasiResult<usize> {
file.write_at(buf, offset).map_err(Into::into)
}
pub(crate) fn fd_fdstat_get(fd: &File) -> Result<wasi::__wasi_fdflags_t> {
pub(crate) fn fd_fdstat_get(fd: &File) -> WasiResult<wasi::__wasi_fdflags_t> {
unsafe { yanix::fcntl::get_status_flags(fd.as_raw_fd()) }
.map(host_impl::fdflags_from_nix)
.map_err(Into::into)
}
pub(crate) fn fd_fdstat_set_flags(fd: &File, fdflags: wasi::__wasi_fdflags_t) -> Result<()> {
pub(crate) fn fd_fdstat_set_flags(fd: &File, fdflags: wasi::__wasi_fdflags_t) -> WasiResult<()> {
let nix_flags = host_impl::nix_from_fdflags(fdflags);
unsafe { yanix::fcntl::set_status_flags(fd.as_raw_fd(), nix_flags) }.map_err(Into::into)
}
@@ -39,7 +43,7 @@ pub(crate) fn fd_advise(
advice: wasi::__wasi_advice_t,
offset: wasi::__wasi_filesize_t,
len: wasi::__wasi_filesize_t,
) -> Result<()> {
) -> WasiResult<()> {
use yanix::fadvise::{posix_fadvise, PosixFadviseAdvice};
let offset = offset.try_into()?;
let len = len.try_into()?;
@@ -50,12 +54,12 @@ pub(crate) fn fd_advise(
wasi::__WASI_ADVICE_NOREUSE => PosixFadviseAdvice::NoReuse,
wasi::__WASI_ADVICE_RANDOM => PosixFadviseAdvice::Random,
wasi::__WASI_ADVICE_NORMAL => PosixFadviseAdvice::Normal,
_ => return Err(Error::EINVAL),
_ => return Err(WasiError::EINVAL),
};
unsafe { posix_fadvise(file.as_raw_fd(), offset, len, host_advice) }.map_err(Into::into)
}
pub(crate) fn path_create_directory(resolved: PathGet) -> Result<()> {
pub(crate) fn path_create_directory(resolved: PathGet) -> WasiResult<()> {
use yanix::file::{mkdirat, Mode};
unsafe {
mkdirat(
@@ -67,7 +71,7 @@ pub(crate) fn path_create_directory(resolved: PathGet) -> Result<()> {
.map_err(Into::into)
}
pub(crate) fn path_link(resolved_old: PathGet, resolved_new: PathGet) -> Result<()> {
pub(crate) fn path_link(resolved_old: PathGet, resolved_new: PathGet) -> WasiResult<()> {
use yanix::file::{linkat, AtFlag};
unsafe {
linkat(
@@ -87,7 +91,7 @@ pub(crate) fn path_open(
write: bool,
oflags: wasi::__wasi_oflags_t,
fs_flags: wasi::__wasi_fdflags_t,
) -> Result<File> {
) -> WasiResult<File> {
use yanix::file::{fstatat, openat, AtFlag, FileType, Mode, OFlag};
let mut nix_all_oflags = if read && write {
@@ -136,7 +140,7 @@ pub(crate) fn path_open(
} {
Ok(stat) => {
if FileType::from_stat_st_mode(stat.st_mode) == FileType::Socket {
return Err(Error::ENOTSUP);
return Err(WasiError::ENOTSUP);
}
}
Err(err) => {
@@ -158,7 +162,7 @@ pub(crate) fn path_open(
} {
Ok(stat) => {
if FileType::from_stat_st_mode(stat.st_mode) == FileType::Symlink {
return Err(Error::ELOOP);
return Err(WasiError::ELOOP);
}
}
Err(err) => {
@@ -169,7 +173,7 @@ pub(crate) fn path_open(
// FreeBSD returns EMLINK instead of ELOOP when using O_NOFOLLOW on
// a symlink.
libc::EMLINK if !(nix_all_oflags & OFlag::NOFOLLOW).is_empty() => {
return Err(Error::ELOOP);
return Err(WasiError::ELOOP);
}
_ => {}
}
@@ -184,7 +188,7 @@ pub(crate) fn path_open(
Ok(unsafe { File::from_raw_fd(new_fd) })
}
pub(crate) fn path_readlink(resolved: PathGet, buf: &mut [u8]) -> Result<usize> {
pub(crate) fn path_readlink(resolved: PathGet, buf: &mut [u8]) -> WasiResult<usize> {
use std::cmp::min;
use yanix::file::readlinkat;
let read_link = unsafe { readlinkat(resolved.dirfd().as_raw_fd(), resolved.path()) }
@@ -197,7 +201,7 @@ pub(crate) fn path_readlink(resolved: PathGet, buf: &mut [u8]) -> Result<usize>
Ok(copy_len)
}
pub(crate) fn fd_filestat_get(file: &std::fs::File) -> Result<wasi::__wasi_filestat_t> {
pub(crate) fn fd_filestat_get(file: &std::fs::File) -> WasiResult<wasi::__wasi_filestat_t> {
use yanix::file::fstat;
unsafe { fstat(file.as_raw_fd()) }
.map_err(Into::into)
@@ -207,7 +211,7 @@ pub(crate) fn fd_filestat_get(file: &std::fs::File) -> Result<wasi::__wasi_files
pub(crate) fn path_filestat_get(
resolved: PathGet,
dirflags: wasi::__wasi_lookupflags_t,
) -> Result<wasi::__wasi_filestat_t> {
) -> WasiResult<wasi::__wasi_filestat_t> {
use yanix::file::{fstatat, AtFlag};
let atflags = match dirflags {
0 => AtFlag::empty(),
@@ -224,7 +228,7 @@ pub(crate) fn path_filestat_set_times(
st_atim: wasi::__wasi_timestamp_t,
st_mtim: wasi::__wasi_timestamp_t,
fst_flags: wasi::__wasi_fstflags_t,
) -> Result<()> {
) -> WasiResult<()> {
use std::time::{Duration, UNIX_EPOCH};
use yanix::filetime::*;
@@ -234,7 +238,7 @@ pub(crate) fn path_filestat_set_times(
let set_mtim_now = fst_flags & wasi::__WASI_FSTFLAGS_MTIM_NOW != 0;
if (set_atim && set_atim_now) || (set_mtim && set_mtim_now) {
return Err(Error::EINVAL);
return Err(WasiError::EINVAL);
}
let symlink_nofollow = wasi::__WASI_LOOKUPFLAGS_SYMLINK_FOLLOW != dirflags;
@@ -265,7 +269,7 @@ pub(crate) fn path_filestat_set_times(
.map_err(Into::into)
}
pub(crate) fn path_remove_directory(resolved: PathGet) -> Result<()> {
pub(crate) fn path_remove_directory(resolved: PathGet) -> WasiResult<()> {
use yanix::file::{unlinkat, AtFlag};
unsafe {
unlinkat(
@@ -280,7 +284,7 @@ pub(crate) fn path_remove_directory(resolved: PathGet) -> Result<()> {
pub(crate) fn fd_readdir<'a>(
os_handle: &'a mut OsHandle,
cookie: wasi::__wasi_dircookie_t,
) -> Result<impl Iterator<Item = Result<Dirent>> + 'a> {
) -> WasiResult<impl Iterator<Item = WasiResult<Dirent>> + 'a> {
use yanix::dir::{DirIter, Entry, EntryExt, SeekLoc};
// Get an instance of `Dir`; this is host-specific due to intricasies

View File

@@ -1,7 +1,7 @@
#![allow(non_camel_case_types)]
#![allow(unused_unsafe)]
use crate::old::snapshot_0::sys::host_impl;
use crate::old::snapshot_0::{wasi, Result};
use crate::old::snapshot_0::wasi::{self, WasiResult};
use std::fs::File;
use yanix::file::OFlag;
@@ -36,7 +36,7 @@ pub(crate) fn path_open_rights(
(needed_base, needed_inheriting)
}
pub(crate) fn openat(dirfd: &File, path: &str) -> Result<File> {
pub(crate) fn openat(dirfd: &File, path: &str) -> WasiResult<File> {
use std::os::unix::prelude::{AsRawFd, FromRawFd};
use yanix::file::{openat, Mode};
@@ -54,7 +54,7 @@ pub(crate) fn openat(dirfd: &File, path: &str) -> Result<File> {
.map_err(Into::into)
}
pub(crate) fn readlinkat(dirfd: &File, path: &str) -> Result<String> {
pub(crate) fn readlinkat(dirfd: &File, path: &str) -> WasiResult<String> {
use std::os::unix::prelude::AsRawFd;
use yanix::file::readlinkat;

View File

@@ -1,22 +1,24 @@
#![allow(non_camel_case_types)]
#![allow(unused_unsafe)]
use crate::old::snapshot_0::hostcalls_impl::{ClockEventData, FdEventData};
use crate::old::snapshot_0::{wasi, Error, Result};
use crate::old::snapshot_0::wasi::{self, WasiError, WasiResult};
use std::io;
use yanix::clock::{clock_getres, clock_gettime, ClockId};
fn wasi_clock_id_to_unix(clock_id: wasi::__wasi_clockid_t) -> Result<ClockId> {
fn wasi_clock_id_to_unix(clock_id: wasi::__wasi_clockid_t) -> WasiResult<ClockId> {
// convert the supported clocks to libc types, or return EINVAL
match clock_id {
wasi::__WASI_CLOCKID_REALTIME => Ok(ClockId::Realtime),
wasi::__WASI_CLOCKID_MONOTONIC => Ok(ClockId::Monotonic),
wasi::__WASI_CLOCKID_PROCESS_CPUTIME_ID => Ok(ClockId::ProcessCPUTime),
wasi::__WASI_CLOCKID_THREAD_CPUTIME_ID => Ok(ClockId::ThreadCPUTime),
_ => Err(Error::EINVAL),
_ => Err(WasiError::EINVAL),
}
}
pub(crate) fn clock_res_get(clock_id: wasi::__wasi_clockid_t) -> Result<wasi::__wasi_timestamp_t> {
pub(crate) fn clock_res_get(
clock_id: wasi::__wasi_clockid_t,
) -> WasiResult<wasi::__wasi_timestamp_t> {
let clock_id = wasi_clock_id_to_unix(clock_id)?;
let timespec = clock_getres(clock_id)?;
@@ -26,18 +28,20 @@ pub(crate) fn clock_res_get(clock_id: wasi::__wasi_clockid_t) -> Result<wasi::__
(timespec.tv_sec as wasi::__wasi_timestamp_t)
.checked_mul(1_000_000_000)
.and_then(|sec_ns| sec_ns.checked_add(timespec.tv_nsec as wasi::__wasi_timestamp_t))
.map_or(Err(Error::EOVERFLOW), |resolution| {
.map_or(Err(WasiError::EOVERFLOW), |resolution| {
// a supported clock can never return zero; this case will probably never get hit, but
// make sure we follow the spec
if resolution == 0 {
Err(Error::EINVAL)
Err(WasiError::EINVAL)
} else {
Ok(resolution)
}
})
}
pub(crate) fn clock_time_get(clock_id: wasi::__wasi_clockid_t) -> Result<wasi::__wasi_timestamp_t> {
pub(crate) fn clock_time_get(
clock_id: wasi::__wasi_clockid_t,
) -> WasiResult<wasi::__wasi_timestamp_t> {
let clock_id = wasi_clock_id_to_unix(clock_id)?;
let timespec = clock_gettime(clock_id)?;
@@ -46,14 +50,14 @@ pub(crate) fn clock_time_get(clock_id: wasi::__wasi_clockid_t) -> Result<wasi::_
(timespec.tv_sec as wasi::__wasi_timestamp_t)
.checked_mul(1_000_000_000)
.and_then(|sec_ns| sec_ns.checked_add(timespec.tv_nsec as wasi::__wasi_timestamp_t))
.map_or(Err(Error::EOVERFLOW), Ok)
.map_or(Err(WasiError::EOVERFLOW), Ok)
}
pub(crate) fn poll_oneoff(
timeout: Option<ClockEventData>,
fd_events: Vec<FdEventData>,
events: &mut Vec<wasi::__wasi_event_t>,
) -> Result<()> {
) -> WasiResult<()> {
use std::{convert::TryInto, os::unix::prelude::AsRawFd};
use yanix::poll::{poll, PollFd, PollFlags};
@@ -122,7 +126,7 @@ fn poll_oneoff_handle_timeout_event(
fn poll_oneoff_handle_fd_event<'a>(
ready_events: impl Iterator<Item = (FdEventData<'a>, yanix::poll::PollFd)>,
events: &mut Vec<wasi::__wasi_event_t>,
) -> Result<()> {
) -> WasiResult<()> {
use std::{convert::TryInto, os::unix::prelude::AsRawFd};
use yanix::{file::fionread, poll::PollFlags};

View File

@@ -1,16 +1,16 @@
use crate::old::snapshot_0::{wasi, Result};
use crate::old::snapshot_0::wasi::{self, WasiResult};
use std::convert::TryInto;
pub(crate) const O_RSYNC: yanix::file::OFlag = yanix::file::OFlag::RSYNC;
pub(crate) fn stdev_from_nix(dev: libc::dev_t) -> Result<wasi::__wasi_device_t> {
pub(crate) fn stdev_from_nix(dev: libc::dev_t) -> WasiResult<wasi::__wasi_device_t> {
Ok(wasi::__wasi_device_t::from(dev))
}
pub(crate) fn stino_from_nix(ino: libc::ino_t) -> Result<wasi::__wasi_inode_t> {
pub(crate) fn stino_from_nix(ino: libc::ino_t) -> WasiResult<wasi::__wasi_inode_t> {
Ok(wasi::__wasi_device_t::from(ino))
}
pub(crate) fn stnlink_from_nix(nlink: libc::nlink_t) -> Result<wasi::__wasi_linkcount_t> {
pub(crate) fn stnlink_from_nix(nlink: libc::nlink_t) -> WasiResult<wasi::__wasi_linkcount_t> {
nlink.try_into().map_err(Into::into)
}

View File

@@ -1,8 +1,8 @@
use crate::old::snapshot_0::hostcalls_impl::PathGet;
use crate::old::snapshot_0::Result;
use crate::old::snapshot_0::wasi::WasiResult;
use std::os::unix::prelude::AsRawFd;
pub(crate) fn path_unlink_file(resolved: PathGet) -> Result<()> {
pub(crate) fn path_unlink_file(resolved: PathGet) -> WasiResult<()> {
use yanix::file::{unlinkat, AtFlag};
unsafe {
unlinkat(
@@ -14,7 +14,7 @@ pub(crate) fn path_unlink_file(resolved: PathGet) -> Result<()> {
.map_err(Into::into)
}
pub(crate) fn path_symlink(old_path: &str, resolved: PathGet) -> Result<()> {
pub(crate) fn path_symlink(old_path: &str, resolved: PathGet) -> WasiResult<()> {
use yanix::file::symlinkat;
log::debug!("path_symlink old_path = {:?}", old_path);
@@ -24,7 +24,7 @@ pub(crate) fn path_symlink(old_path: &str, resolved: PathGet) -> Result<()> {
.map_err(Into::into)
}
pub(crate) fn path_rename(resolved_old: PathGet, resolved_new: PathGet) -> Result<()> {
pub(crate) fn path_rename(resolved_old: PathGet, resolved_new: PathGet) -> WasiResult<()> {
use yanix::file::renameat;
unsafe {
renameat(
@@ -39,10 +39,10 @@ pub(crate) fn path_rename(resolved_old: PathGet, resolved_new: PathGet) -> Resul
pub(crate) mod fd_readdir_impl {
use crate::old::snapshot_0::sys::fdentry_impl::OsHandle;
use crate::old::snapshot_0::Result;
use crate::old::snapshot_0::wasi::WasiResult;
use yanix::dir::Dir;
pub(crate) fn get_dir_from_os_handle(os_handle: &mut OsHandle) -> Result<Box<Dir>> {
pub(crate) fn get_dir_from_os_handle(os_handle: &mut OsHandle) -> WasiResult<Box<Dir>> {
// We need to duplicate the fd, because `opendir(3)`:
// After a successful call to fdopendir(), fd is used internally by the implementation,
// and should not otherwise be used by the application.

View File

@@ -20,13 +20,9 @@ cfg_if::cfg_if! {
}
}
use crate::old::snapshot_0::Result;
use std::fs::{File, OpenOptions};
use std::io::Result;
pub(crate) fn dev_null() -> Result<File> {
OpenOptions::new()
.read(true)
.write(true)
.open("/dev/null")
.map_err(Into::into)
OpenOptions::new().read(true).write(true).open("/dev/null")
}

View File

@@ -1,5 +1,5 @@
use crate::old::snapshot_0::fdentry::{Descriptor, OsHandleRef};
use crate::old::snapshot_0::{wasi, Error, Result};
use crate::old::snapshot_0::wasi;
use std::fs::File;
use std::io;
use std::mem::ManuallyDrop;
@@ -57,7 +57,7 @@ pub(crate) fn descriptor_as_oshandle<'lifetime>(
/// This function is unsafe because it operates on a raw file handle.
pub(crate) unsafe fn determine_type_and_access_rights<Handle: AsRawHandle>(
handle: &Handle,
) -> Result<(
) -> io::Result<(
wasi::__wasi_filetype_t,
wasi::__wasi_rights_t,
wasi::__wasi_rights_t,
@@ -88,7 +88,7 @@ pub(crate) unsafe fn determine_type_and_access_rights<Handle: AsRawHandle>(
/// This function is unsafe because it operates on a raw file handle.
pub(crate) unsafe fn determine_type_rights<Handle: AsRawHandle>(
handle: &Handle,
) -> Result<(
) -> io::Result<(
wasi::__wasi_filetype_t,
wasi::__wasi_rights_t,
wasi::__wasi_rights_t,
@@ -106,7 +106,7 @@ pub(crate) unsafe fn determine_type_rights<Handle: AsRawHandle>(
} else if file_type.is_disk() {
// disk file: file, dir or disk device
let file = std::mem::ManuallyDrop::new(File::from_raw_handle(handle.as_raw_handle()));
let meta = file.metadata().map_err(|_| Error::EINVAL)?;
let meta = file.metadata()?;
if meta.is_dir() {
(
wasi::__WASI_FILETYPE_DIRECTORY,
@@ -120,7 +120,7 @@ pub(crate) unsafe fn determine_type_rights<Handle: AsRawHandle>(
wasi::RIGHTS_REGULAR_FILE_INHERITING,
)
} else {
return Err(Error::EINVAL);
return Err(io::Error::from_raw_os_error(libc::EINVAL));
}
} else if file_type.is_pipe() {
// pipe object: socket, named pipe or anonymous pipe
@@ -131,7 +131,7 @@ pub(crate) unsafe fn determine_type_rights<Handle: AsRawHandle>(
wasi::RIGHTS_SOCKET_INHERITING,
)
} else {
return Err(Error::EINVAL);
return Err(io::Error::from_raw_os_error(libc::EINVAL));
}
};
Ok((file_type, rights_base, rights_inheriting))

View File

@@ -3,7 +3,7 @@
#![allow(non_snake_case)]
#![allow(unused)]
use crate::old::snapshot_0::host::FileType;
use crate::old::snapshot_0::{error::FromRawOsError, wasi, Error, Result};
use crate::old::snapshot_0::wasi::{self, WasiError, WasiResult};
use std::convert::TryInto;
use std::ffi::OsStr;
use std::fs::OpenOptions;
@@ -15,10 +15,10 @@ use std::time::{SystemTime, UNIX_EPOCH};
use winapi::shared::winerror;
use winx::file::{AccessMode, Attributes, CreationDisposition, Flags};
impl FromRawOsError for Error {
fn from_raw_os_error(code: i32) -> Self {
// TODO: implement error mapping between Windows and WASI
match code as u32 {
impl From<io::Error> for WasiError {
fn from(err: io::Error) -> Self {
match err.raw_os_error() {
Some(code) => match code as u32 {
winerror::ERROR_SUCCESS => Self::ESUCCESS,
winerror::ERROR_BAD_ENVIRONMENT => Self::E2BIG,
winerror::ERROR_FILE_NOT_FOUND => Self::ENOENT,
@@ -26,7 +26,7 @@ impl FromRawOsError for Error {
winerror::ERROR_TOO_MANY_OPEN_FILES => Self::ENFILE,
winerror::ERROR_ACCESS_DENIED => Self::EACCES,
winerror::ERROR_SHARING_VIOLATION => Self::EACCES,
winerror::ERROR_PRIVILEGE_NOT_HELD => Self::ENOTCAPABLE, // TODO is this the correct mapping?
winerror::ERROR_PRIVILEGE_NOT_HELD => Self::ENOTCAPABLE,
winerror::ERROR_INVALID_HANDLE => Self::EBADF,
winerror::ERROR_INVALID_NAME => Self::ENOENT,
winerror::ERROR_NOT_ENOUGH_MEMORY => Self::ENOMEM,
@@ -42,7 +42,15 @@ impl FromRawOsError for Error {
winerror::ERROR_NEGATIVE_SEEK => Self::EINVAL,
winerror::ERROR_DIRECTORY => Self::ENOTDIR,
winerror::ERROR_ALREADY_EXISTS => Self::EEXIST,
_ => Self::ENOTSUP,
x => {
log::debug!("unknown error value: {}", x);
Self::EIO
}
},
None => {
log::debug!("Other I/O error: {}", err);
Self::EIO
}
}
}
}
@@ -137,15 +145,15 @@ fn change_time(file: &File) -> io::Result<i64> {
winx::file::change_time(file)
}
fn systemtime_to_timestamp(st: SystemTime) -> Result<u64> {
fn systemtime_to_timestamp(st: SystemTime) -> WasiResult<u64> {
st.duration_since(UNIX_EPOCH)
.map_err(|_| Error::EINVAL)? // date earlier than UNIX_EPOCH
.map_err(|_| WasiError::EINVAL)? // date earlier than UNIX_EPOCH
.as_nanos()
.try_into()
.map_err(Into::into) // u128 doesn't fit into u64
}
pub(crate) fn filestat_from_win(file: &File) -> Result<wasi::__wasi_filestat_t> {
pub(crate) fn filestat_from_win(file: &File) -> WasiResult<wasi::__wasi_filestat_t> {
let metadata = file.metadata()?;
Ok(wasi::__wasi_filestat_t {
dev: device_id(file)?,
@@ -163,7 +171,7 @@ pub(crate) fn filestat_from_win(file: &File) -> Result<wasi::__wasi_filestat_t>
///
/// NB WASI spec requires OS string to be valid UTF-8. Otherwise,
/// `__WASI_ERRNO_ILSEQ` error is returned.
pub(crate) fn path_from_host<S: AsRef<OsStr>>(s: S) -> Result<String> {
pub(crate) fn path_from_host<S: AsRef<OsStr>>(s: S) -> WasiResult<String> {
let vec: Vec<u16> = s.as_ref().encode_wide().collect();
String::from_utf16(&vec).map_err(|_| Error::EILSEQ)
String::from_utf16(&vec).map_err(|_| WasiError::EILSEQ)
}

View File

@@ -8,7 +8,7 @@ use crate::old::snapshot_0::hostcalls_impl::{fd_filestat_set_times_impl, PathGet
use crate::old::snapshot_0::sys::fdentry_impl::determine_type_rights;
use crate::old::snapshot_0::sys::host_impl::{self, path_from_host};
use crate::old::snapshot_0::sys::hostcalls_impl::fs_helpers::PathGetExt;
use crate::old::snapshot_0::{wasi, Error, Result};
use crate::old::snapshot_0::wasi::{self, WasiError, WasiResult};
use log::{debug, trace};
use std::convert::TryInto;
use std::fs::{File, Metadata, OpenOptions};
@@ -44,16 +44,20 @@ pub(crate) fn fd_pread(
file: &File,
buf: &mut [u8],
offset: wasi::__wasi_filesize_t,
) -> Result<usize> {
) -> WasiResult<usize> {
read_at(file, buf, offset).map_err(Into::into)
}
// TODO refactor common code with unix
pub(crate) fn fd_pwrite(file: &File, buf: &[u8], offset: wasi::__wasi_filesize_t) -> Result<usize> {
pub(crate) fn fd_pwrite(
file: &File,
buf: &[u8],
offset: wasi::__wasi_filesize_t,
) -> WasiResult<usize> {
write_at(file, buf, offset).map_err(Into::into)
}
pub(crate) fn fd_fdstat_get(fd: &File) -> Result<wasi::__wasi_fdflags_t> {
pub(crate) fn fd_fdstat_get(fd: &File) -> WasiResult<wasi::__wasi_fdflags_t> {
let mut fdflags = 0;
let handle = unsafe { fd.as_raw_handle() };
@@ -79,7 +83,7 @@ pub(crate) fn fd_fdstat_get(fd: &File) -> Result<wasi::__wasi_fdflags_t> {
Ok(fdflags)
}
pub(crate) fn fd_fdstat_set_flags(fd: &File, fdflags: wasi::__wasi_fdflags_t) -> Result<()> {
pub(crate) fn fd_fdstat_set_flags(fd: &File, fdflags: wasi::__wasi_fdflags_t) -> WasiResult<()> {
unimplemented!("fd_fdstat_set_flags")
}
@@ -88,7 +92,7 @@ pub(crate) fn fd_advise(
advice: wasi::__wasi_advice_t,
_offset: wasi::__wasi_filesize_t,
_len: wasi::__wasi_filesize_t,
) -> Result<()> {
) -> WasiResult<()> {
match advice {
wasi::__WASI_ADVICE_DONTNEED
| wasi::__WASI_ADVICE_SEQUENTIAL
@@ -96,18 +100,18 @@ pub(crate) fn fd_advise(
| wasi::__WASI_ADVICE_NOREUSE
| wasi::__WASI_ADVICE_RANDOM
| wasi::__WASI_ADVICE_NORMAL => {}
_ => return Err(Error::EINVAL),
_ => return Err(WasiError::EINVAL),
}
Ok(())
}
pub(crate) fn path_create_directory(resolved: PathGet) -> Result<()> {
pub(crate) fn path_create_directory(resolved: PathGet) -> WasiResult<()> {
let path = resolved.concatenate()?;
std::fs::create_dir(&path).map_err(Into::into)
}
pub(crate) fn path_link(resolved_old: PathGet, resolved_new: PathGet) -> Result<()> {
pub(crate) fn path_link(resolved_old: PathGet, resolved_new: PathGet) -> WasiResult<()> {
unimplemented!("path_link")
}
@@ -117,7 +121,7 @@ pub(crate) fn path_open(
write: bool,
oflags: wasi::__wasi_oflags_t,
fdflags: wasi::__wasi_fdflags_t,
) -> Result<File> {
) -> WasiResult<File> {
use winx::file::{AccessMode, CreationDisposition, Flags};
// convert open flags
@@ -143,11 +147,11 @@ pub(crate) fn path_open(
Ok(file_type) => {
// check if we are trying to open a symlink
if file_type.is_symlink() {
return Err(Error::ELOOP);
return Err(WasiError::ELOOP);
}
// check if we are trying to open a file as a dir
if file_type.is_file() && oflags & wasi::__WASI_OFLAGS_DIRECTORY != 0 {
return Err(Error::ENOTDIR);
return Err(WasiError::ENOTDIR);
}
}
Err(err) => match err.raw_os_error() {
@@ -162,7 +166,7 @@ pub(crate) fn path_open(
}
None => {
log::debug!("Inconvertible OS error: {}", err);
return Err(Error::EIO);
return Err(WasiError::EIO);
}
},
}
@@ -236,7 +240,7 @@ fn dirent_from_path<P: AsRef<Path>>(
path: P,
name: &str,
cookie: wasi::__wasi_dircookie_t,
) -> Result<Dirent> {
) -> WasiResult<Dirent> {
let path = path.as_ref();
trace!("dirent_from_path: opening {}", path.to_string_lossy());
@@ -285,7 +289,7 @@ fn dirent_from_path<P: AsRef<Path>>(
pub(crate) fn fd_readdir(
fd: &File,
cookie: wasi::__wasi_dircookie_t,
) -> Result<impl Iterator<Item = Result<Dirent>>> {
) -> WasiResult<impl Iterator<Item = WasiResult<Dirent>>> {
use winx::file::get_file_path;
let cookie = cookie.try_into()?;
@@ -321,7 +325,7 @@ pub(crate) fn fd_readdir(
Ok(iter.skip(cookie))
}
pub(crate) fn path_readlink(resolved: PathGet, buf: &mut [u8]) -> Result<usize> {
pub(crate) fn path_readlink(resolved: PathGet, buf: &mut [u8]) -> WasiResult<usize> {
use winx::file::get_file_path;
let path = resolved.concatenate()?;
@@ -335,8 +339,8 @@ pub(crate) fn path_readlink(resolved: PathGet, buf: &mut [u8]) -> Result<usize>
let dir_path = PathBuf::from(strip_extended_prefix(dir_path));
let target_path = target_path
.strip_prefix(dir_path)
.map_err(|_| Error::ENOTCAPABLE)
.and_then(|path| path.to_str().map(String::from).ok_or(Error::EILSEQ))?;
.map_err(|_| WasiError::ENOTCAPABLE)
.and_then(|path| path.to_str().map(String::from).ok_or(WasiError::EILSEQ))?;
if buf.len() > 0 {
let mut chars = target_path.chars();
@@ -358,7 +362,7 @@ pub(crate) fn path_readlink(resolved: PathGet, buf: &mut [u8]) -> Result<usize>
}
}
fn strip_trailing_slashes_and_concatenate(resolved: &PathGet) -> Result<Option<PathBuf>> {
fn strip_trailing_slashes_and_concatenate(resolved: &PathGet) -> WasiResult<Option<PathBuf>> {
if resolved.path().ends_with('/') {
let suffix = resolved.path().trim_end_matches('/');
concatenate(resolved.dirfd(), Path::new(suffix)).map(Some)
@@ -367,7 +371,7 @@ fn strip_trailing_slashes_and_concatenate(resolved: &PathGet) -> Result<Option<P
}
}
pub(crate) fn path_rename(resolved_old: PathGet, resolved_new: PathGet) -> Result<()> {
pub(crate) fn path_rename(resolved_old: PathGet, resolved_new: PathGet) -> WasiResult<()> {
use std::fs;
let old_path = resolved_old.concatenate()?;
@@ -378,12 +382,12 @@ pub(crate) fn path_rename(resolved_old: PathGet, resolved_new: PathGet) -> Resul
//
// [std::fs::rename]: https://doc.rust-lang.org/std/fs/fn.rename.html
if old_path.is_dir() && new_path.is_file() {
return Err(Error::ENOTDIR);
return Err(WasiError::ENOTDIR);
}
// Second sanity check: check we're not trying to rename a file into a path
// ending in a trailing slash.
if old_path.is_file() && resolved_new.path().ends_with('/') {
return Err(Error::ENOTDIR);
return Err(WasiError::ENOTDIR);
}
// TODO handle symlinks
@@ -399,7 +403,7 @@ pub(crate) fn path_rename(resolved_old: PathGet, resolved_new: PathGet) -> Resul
// So most likely dealing with new_path == dir.
// Eliminate case old_path == file first.
if old_path.is_file() {
return Err(Error::EISDIR);
return Err(WasiError::EISDIR);
} else {
// Ok, let's try removing an empty dir at new_path if it exists
// and is a nonempty dir.
@@ -413,7 +417,7 @@ pub(crate) fn path_rename(resolved_old: PathGet, resolved_new: PathGet) -> Resul
// a file instead of a dir, and if so, throw ENOTDIR.
if let Some(path) = strip_trailing_slashes_and_concatenate(&resolved_old)? {
if path.is_file() {
return Err(Error::ENOTDIR);
return Err(WasiError::ENOTDIR);
}
}
}
@@ -424,19 +428,19 @@ pub(crate) fn path_rename(resolved_old: PathGet, resolved_new: PathGet) -> Resul
}
None => {
log::debug!("Inconvertible OS error: {}", err);
Err(Error::EIO)
Err(WasiError::EIO)
}
}
}
pub(crate) fn fd_filestat_get(file: &std::fs::File) -> Result<wasi::__wasi_filestat_t> {
pub(crate) fn fd_filestat_get(file: &std::fs::File) -> WasiResult<wasi::__wasi_filestat_t> {
host_impl::filestat_from_win(file)
}
pub(crate) fn path_filestat_get(
resolved: PathGet,
dirflags: wasi::__wasi_lookupflags_t,
) -> Result<wasi::__wasi_filestat_t> {
) -> WasiResult<wasi::__wasi_filestat_t> {
let path = resolved.concatenate()?;
let file = File::open(path)?;
host_impl::filestat_from_win(&file)
@@ -448,7 +452,7 @@ pub(crate) fn path_filestat_set_times(
st_atim: wasi::__wasi_timestamp_t,
mut st_mtim: wasi::__wasi_timestamp_t,
fst_flags: wasi::__wasi_fstflags_t,
) -> Result<()> {
) -> WasiResult<()> {
use winx::file::AccessMode;
let path = resolved.concatenate()?;
let file = OpenOptions::new()
@@ -457,7 +461,7 @@ pub(crate) fn path_filestat_set_times(
fd_filestat_set_times_impl(&file, st_atim, st_mtim, fst_flags)
}
pub(crate) fn path_symlink(old_path: &str, resolved: PathGet) -> Result<()> {
pub(crate) fn path_symlink(old_path: &str, resolved: PathGet) -> WasiResult<()> {
use std::os::windows::fs::{symlink_dir, symlink_file};
let old_path = concatenate(resolved.dirfd(), Path::new(old_path))?;
@@ -479,14 +483,14 @@ pub(crate) fn path_symlink(old_path: &str, resolved: PathGet) -> Result<()> {
winerror::ERROR_ACCESS_DENIED => {
// does the target exist?
if new_path.exists() {
return Err(Error::EEXIST);
return Err(WasiError::EEXIST);
}
}
winerror::ERROR_INVALID_NAME => {
// does the target without trailing slashes exist?
if let Some(path) = strip_trailing_slashes_and_concatenate(&resolved)? {
if path.exists() {
return Err(Error::EEXIST);
return Err(WasiError::EEXIST);
}
}
}
@@ -497,12 +501,12 @@ pub(crate) fn path_symlink(old_path: &str, resolved: PathGet) -> Result<()> {
}
None => {
log::debug!("Inconvertible OS error: {}", err);
Err(Error::EIO)
Err(WasiError::EIO)
}
}
}
pub(crate) fn path_unlink_file(resolved: PathGet) -> Result<()> {
pub(crate) fn path_unlink_file(resolved: PathGet) -> WasiResult<()> {
use std::fs;
let path = resolved.concatenate()?;
@@ -532,19 +536,19 @@ pub(crate) fn path_unlink_file(resolved: PathGet) -> Result<()> {
}
None => {
log::debug!("Inconvertible OS error: {}", err);
Err(Error::EIO)
Err(WasiError::EIO)
}
}
} else if file_type.is_dir() {
Err(Error::EISDIR)
Err(WasiError::EISDIR)
} else if file_type.is_file() {
fs::remove_file(path).map_err(Into::into)
} else {
Err(Error::EINVAL)
Err(WasiError::EINVAL)
}
}
pub(crate) fn path_remove_directory(resolved: PathGet) -> Result<()> {
pub(crate) fn path_remove_directory(resolved: PathGet) -> WasiResult<()> {
let path = resolved.concatenate()?;
std::fs::remove_dir(&path).map_err(Into::into)
}

View File

@@ -1,6 +1,6 @@
#![allow(non_camel_case_types)]
use crate::old::snapshot_0::hostcalls_impl::PathGet;
use crate::old::snapshot_0::{wasi, Error, Result};
use crate::old::snapshot_0::wasi::{self, WasiError, WasiResult};
use std::ffi::{OsStr, OsString};
use std::fs::File;
use std::os::windows::ffi::{OsStrExt, OsStringExt};
@@ -8,11 +8,11 @@ use std::path::{Path, PathBuf};
use winapi::shared::winerror;
pub(crate) trait PathGetExt {
fn concatenate(&self) -> Result<PathBuf>;
fn concatenate(&self) -> WasiResult<PathBuf>;
}
impl PathGetExt for PathGet {
fn concatenate(&self) -> Result<PathBuf> {
fn concatenate(&self) -> WasiResult<PathBuf> {
concatenate(self.dirfd(), Path::new(self.path()))
}
}
@@ -46,7 +46,7 @@ pub(crate) fn path_open_rights(
(needed_base, needed_inheriting)
}
pub(crate) fn openat(dirfd: &File, path: &str) -> Result<File> {
pub(crate) fn openat(dirfd: &File, path: &str) -> WasiResult<File> {
use std::fs::OpenOptions;
use std::os::windows::fs::OpenOptionsExt;
use winx::file::Flags;
@@ -63,13 +63,13 @@ pub(crate) fn openat(dirfd: &File, path: &str) -> Result<File> {
if let Some(code) = err.raw_os_error() {
log::debug!("openat error={:?}", code);
if code as u32 == winerror::ERROR_INVALID_NAME {
return Err(Error::ENOTDIR);
return Err(WasiError::ENOTDIR);
}
}
Err(err.into())
}
pub(crate) fn readlinkat(dirfd: &File, s_path: &str) -> Result<String> {
pub(crate) fn readlinkat(dirfd: &File, s_path: &str) -> WasiResult<String> {
use winx::file::get_file_path;
let path = concatenate(dirfd, Path::new(s_path))?;
@@ -83,8 +83,8 @@ pub(crate) fn readlinkat(dirfd: &File, s_path: &str) -> Result<String> {
let dir_path = PathBuf::from(strip_extended_prefix(dir_path));
let target_path = target_path
.strip_prefix(dir_path)
.map_err(|_| Error::ENOTCAPABLE)?;
let target_path = target_path.to_str().ok_or(Error::EILSEQ)?;
.map_err(|_| WasiError::ENOTCAPABLE)?;
let target_path = target_path.to_str().ok_or(WasiError::EILSEQ)?;
return Ok(target_path.to_owned());
}
Err(e) => e,
@@ -96,7 +96,7 @@ pub(crate) fn readlinkat(dirfd: &File, s_path: &str) -> Result<String> {
// strip "/" and check if exists
let path = concatenate(dirfd, Path::new(s_path.trim_end_matches('/')))?;
if path.exists() && !path.is_dir() {
return Err(Error::ENOTDIR);
return Err(WasiError::ENOTDIR);
}
}
}
@@ -113,13 +113,13 @@ pub(crate) fn strip_extended_prefix<P: AsRef<OsStr>>(path: P) -> OsString {
}
}
pub(crate) fn concatenate<P: AsRef<Path>>(dirfd: &File, path: P) -> Result<PathBuf> {
pub(crate) fn concatenate<P: AsRef<Path>>(dirfd: &File, path: P) -> WasiResult<PathBuf> {
use winx::file::get_file_path;
// WASI is not able to deal with absolute paths
// so error out if absolute
if path.as_ref().is_absolute() {
return Err(Error::ENOTCAPABLE);
return Err(WasiError::ENOTCAPABLE);
}
let dir_path = get_file_path(dirfd)?;

View File

@@ -4,7 +4,8 @@
use crate::old::snapshot_0::hostcalls_impl::{ClockEventData, FdEventData};
use crate::old::snapshot_0::memory::*;
use crate::old::snapshot_0::sys::host_impl;
use crate::old::snapshot_0::{wasi, wasi32, Error, Result};
use crate::old::snapshot_0::wasi::{self, WasiError, WasiResult};
use crate::old::snapshot_0::wasi32;
use cpu_time::{ProcessTime, ThreadTime};
use lazy_static::lazy_static;
use std::convert::TryInto;
@@ -17,7 +18,9 @@ lazy_static! {
// Timer resolution on Windows is really hard. We may consider exposing the resolution of the respective
// timers as an associated function in the future.
pub(crate) fn clock_res_get(clock_id: wasi::__wasi_clockid_t) -> Result<wasi::__wasi_timestamp_t> {
pub(crate) fn clock_res_get(
clock_id: wasi::__wasi_clockid_t,
) -> WasiResult<wasi::__wasi_timestamp_t> {
Ok(match clock_id {
// This is the best that we can do with std::time::SystemTime.
// Rust uses GetSystemTimeAsFileTime, which is said to have the resolution of
@@ -61,17 +64,19 @@ pub(crate) fn clock_res_get(clock_id: wasi::__wasi_clockid_t) -> Result<wasi::__
// The best we can do is to hardcode the value from the docs.
// https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-getthreadtimes
wasi::__WASI_CLOCKID_THREAD_CPUTIME_ID => 100,
_ => return Err(Error::EINVAL),
_ => return Err(WasiError::EINVAL),
})
}
pub(crate) fn clock_time_get(clock_id: wasi::__wasi_clockid_t) -> Result<wasi::__wasi_timestamp_t> {
pub(crate) fn clock_time_get(
clock_id: wasi::__wasi_clockid_t,
) -> WasiResult<wasi::__wasi_timestamp_t> {
let duration = match clock_id {
wasi::__WASI_CLOCKID_REALTIME => get_monotonic_time(),
wasi::__WASI_CLOCKID_MONOTONIC => get_realtime_time()?,
wasi::__WASI_CLOCKID_PROCESS_CPUTIME_ID => get_proc_cputime()?,
wasi::__WASI_CLOCKID_THREAD_CPUTIME_ID => get_thread_cputime()?,
_ => return Err(Error::EINVAL),
_ => return Err(WasiError::EINVAL),
};
duration.as_nanos().try_into().map_err(Into::into)
}
@@ -80,7 +85,7 @@ pub(crate) fn poll_oneoff(
timeout: Option<ClockEventData>,
fd_events: Vec<FdEventData>,
events: &mut Vec<wasi::__wasi_event_t>,
) -> Result<Vec<wasi::__wasi_event_t>> {
) -> WasiResult<Vec<wasi::__wasi_event_t>> {
unimplemented!("poll_oneoff")
}
@@ -94,17 +99,17 @@ fn get_monotonic_time() -> Duration {
START_MONOTONIC.elapsed()
}
fn get_realtime_time() -> Result<Duration> {
fn get_realtime_time() -> WasiResult<Duration> {
SystemTime::now()
.duration_since(UNIX_EPOCH)
.map_err(|_| Error::EFAULT)
.map_err(|_| WasiError::EFAULT)
}
fn get_proc_cputime() -> Result<Duration> {
fn get_proc_cputime() -> WasiResult<Duration> {
Ok(ProcessTime::try_now()?.as_duration())
}
fn get_thread_cputime() -> Result<Duration> {
fn get_thread_cputime() -> WasiResult<Duration> {
Ok(ThreadTime::try_now()?.as_duration())
}

View File

@@ -2,13 +2,9 @@ pub(crate) mod fdentry_impl;
pub(crate) mod host_impl;
pub(crate) mod hostcalls_impl;
use crate::old::snapshot_0::Result;
use std::fs::{File, OpenOptions};
use std::io::Result;
pub(crate) fn dev_null() -> Result<File> {
OpenOptions::new()
.read(true)
.write(true)
.open("NUL")
.map_err(Into::into)
OpenOptions::new().read(true).write(true).open("NUL")
}

View File

@@ -10,6 +10,115 @@ use wig::witx_wasi_types;
witx_wasi_types!("old/snapshot_0" "wasi_unstable");
pub type WasiResult<T> = Result<T, WasiError>;
#[derive(Clone, Copy, Debug, thiserror::Error, Eq, PartialEq)]
#[repr(u16)]
#[error("{:?} ({})", self, strerror(*self as __wasi_errno_t))]
pub enum WasiError {
ESUCCESS = __WASI_ERRNO_SUCCESS,
E2BIG = __WASI_ERRNO_2BIG,
EACCES = __WASI_ERRNO_ACCES,
EADDRINUSE = __WASI_ERRNO_ADDRINUSE,
EADDRNOTAVAIL = __WASI_ERRNO_ADDRNOTAVAIL,
EAFNOSUPPORT = __WASI_ERRNO_AFNOSUPPORT,
EAGAIN = __WASI_ERRNO_AGAIN,
EALREADY = __WASI_ERRNO_ALREADY,
EBADF = __WASI_ERRNO_BADF,
EBADMSG = __WASI_ERRNO_BADMSG,
EBUSY = __WASI_ERRNO_BUSY,
ECANCELED = __WASI_ERRNO_CANCELED,
ECHILD = __WASI_ERRNO_CHILD,
ECONNABORTED = __WASI_ERRNO_CONNABORTED,
ECONNREFUSED = __WASI_ERRNO_CONNREFUSED,
ECONNRESET = __WASI_ERRNO_CONNRESET,
EDEADLK = __WASI_ERRNO_DEADLK,
EDESTADDRREQ = __WASI_ERRNO_DESTADDRREQ,
EDOM = __WASI_ERRNO_DOM,
EDQUOT = __WASI_ERRNO_DQUOT,
EEXIST = __WASI_ERRNO_EXIST,
EFAULT = __WASI_ERRNO_FAULT,
EFBIG = __WASI_ERRNO_FBIG,
EHOSTUNREACH = __WASI_ERRNO_HOSTUNREACH,
EIDRM = __WASI_ERRNO_IDRM,
EILSEQ = __WASI_ERRNO_ILSEQ,
EINPROGRESS = __WASI_ERRNO_INPROGRESS,
EINTR = __WASI_ERRNO_INTR,
EINVAL = __WASI_ERRNO_INVAL,
EIO = __WASI_ERRNO_IO,
EISCONN = __WASI_ERRNO_ISCONN,
EISDIR = __WASI_ERRNO_ISDIR,
ELOOP = __WASI_ERRNO_LOOP,
EMFILE = __WASI_ERRNO_MFILE,
EMLINK = __WASI_ERRNO_MLINK,
EMSGSIZE = __WASI_ERRNO_MSGSIZE,
EMULTIHOP = __WASI_ERRNO_MULTIHOP,
ENAMETOOLONG = __WASI_ERRNO_NAMETOOLONG,
ENETDOWN = __WASI_ERRNO_NETDOWN,
ENETRESET = __WASI_ERRNO_NETRESET,
ENETUNREACH = __WASI_ERRNO_NETUNREACH,
ENFILE = __WASI_ERRNO_NFILE,
ENOBUFS = __WASI_ERRNO_NOBUFS,
ENODEV = __WASI_ERRNO_NODEV,
ENOENT = __WASI_ERRNO_NOENT,
ENOEXEC = __WASI_ERRNO_NOEXEC,
ENOLCK = __WASI_ERRNO_NOLCK,
ENOLINK = __WASI_ERRNO_NOLINK,
ENOMEM = __WASI_ERRNO_NOMEM,
ENOMSG = __WASI_ERRNO_NOMSG,
ENOPROTOOPT = __WASI_ERRNO_NOPROTOOPT,
ENOSPC = __WASI_ERRNO_NOSPC,
ENOSYS = __WASI_ERRNO_NOSYS,
ENOTCONN = __WASI_ERRNO_NOTCONN,
ENOTDIR = __WASI_ERRNO_NOTDIR,
ENOTEMPTY = __WASI_ERRNO_NOTEMPTY,
ENOTRECOVERABLE = __WASI_ERRNO_NOTRECOVERABLE,
ENOTSOCK = __WASI_ERRNO_NOTSOCK,
ENOTSUP = __WASI_ERRNO_NOTSUP,
ENOTTY = __WASI_ERRNO_NOTTY,
ENXIO = __WASI_ERRNO_NXIO,
EOVERFLOW = __WASI_ERRNO_OVERFLOW,
EOWNERDEAD = __WASI_ERRNO_OWNERDEAD,
EPERM = __WASI_ERRNO_PERM,
EPIPE = __WASI_ERRNO_PIPE,
EPROTO = __WASI_ERRNO_PROTO,
EPROTONOSUPPORT = __WASI_ERRNO_PROTONOSUPPORT,
EPROTOTYPE = __WASI_ERRNO_PROTOTYPE,
ERANGE = __WASI_ERRNO_RANGE,
EROFS = __WASI_ERRNO_ROFS,
ESPIPE = __WASI_ERRNO_SPIPE,
ESRCH = __WASI_ERRNO_SRCH,
ESTALE = __WASI_ERRNO_STALE,
ETIMEDOUT = __WASI_ERRNO_TIMEDOUT,
ETXTBSY = __WASI_ERRNO_TXTBSY,
EXDEV = __WASI_ERRNO_XDEV,
ENOTCAPABLE = __WASI_ERRNO_NOTCAPABLE,
}
impl WasiError {
pub fn as_raw_errno(self) -> __wasi_errno_t {
self as __wasi_errno_t
}
}
impl From<std::convert::Infallible> for WasiError {
fn from(_err: std::convert::Infallible) -> Self {
unreachable!()
}
}
impl From<std::num::TryFromIntError> for WasiError {
fn from(_err: std::num::TryFromIntError) -> Self {
Self::EOVERFLOW
}
}
impl From<std::str::Utf8Error> for WasiError {
fn from(_err: std::str::Utf8Error) -> Self {
Self::EILSEQ
}
}
pub(crate) const RIGHTS_ALL: __wasi_rights_t = __WASI_RIGHTS_FD_DATASYNC
| __WASI_RIGHTS_FD_READ
| __WASI_RIGHTS_FD_SEEK

View File

@@ -1,12 +1,12 @@
use crate::{wasi, Result};
use crate::wasi::{self, WasiResult};
use std::convert::TryFrom;
pub(crate) const O_RSYNC: yanix::file::OFlag = yanix::file::OFlag::SYNC;
pub(crate) fn stdev_from_nix(dev: libc::dev_t) -> Result<wasi::__wasi_device_t> {
pub(crate) fn stdev_from_nix(dev: libc::dev_t) -> WasiResult<wasi::__wasi_device_t> {
wasi::__wasi_device_t::try_from(dev).map_err(Into::into)
}
pub(crate) fn stino_from_nix(ino: libc::ino_t) -> Result<wasi::__wasi_inode_t> {
pub(crate) fn stino_from_nix(ino: libc::ino_t) -> WasiResult<wasi::__wasi_inode_t> {
wasi::__wasi_device_t::try_from(ino).map_err(Into::into)
}

View File

@@ -1,8 +1,8 @@
use crate::hostcalls_impl::PathGet;
use crate::{Error, Result};
use crate::wasi::{WasiError, WasiResult};
use std::os::unix::prelude::AsRawFd;
pub(crate) fn path_unlink_file(resolved: PathGet) -> Result<()> {
pub(crate) fn path_unlink_file(resolved: PathGet) -> WasiResult<()> {
use yanix::file::{unlinkat, AtFlag};
match unsafe {
unlinkat(
@@ -32,7 +32,7 @@ pub(crate) fn path_unlink_file(resolved: PathGet) -> Result<()> {
} {
Ok(stat) => {
if FileType::from_stat_st_mode(stat.st_mode) == FileType::Directory {
return Err(Error::EISDIR);
return Err(WasiError::EISDIR);
}
}
Err(err) => {
@@ -47,7 +47,7 @@ pub(crate) fn path_unlink_file(resolved: PathGet) -> Result<()> {
}
}
pub(crate) fn path_symlink(old_path: &str, resolved: PathGet) -> Result<()> {
pub(crate) fn path_symlink(old_path: &str, resolved: PathGet) -> WasiResult<()> {
use yanix::file::{fstatat, symlinkat, AtFlag};
log::debug!("path_symlink old_path = {:?}", old_path);
@@ -69,7 +69,7 @@ pub(crate) fn path_symlink(old_path: &str, resolved: PathGet) -> Result<()> {
AtFlag::SYMLINK_NOFOLLOW,
)
} {
Ok(_) => return Err(Error::EEXIST),
Ok(_) => return Err(WasiError::EEXIST),
Err(err) => {
log::debug!("path_symlink fstatat error: {:?}", err);
}
@@ -81,7 +81,7 @@ pub(crate) fn path_symlink(old_path: &str, resolved: PathGet) -> Result<()> {
}
}
pub(crate) fn path_rename(resolved_old: PathGet, resolved_new: PathGet) -> Result<()> {
pub(crate) fn path_rename(resolved_old: PathGet, resolved_new: PathGet) -> WasiResult<()> {
use yanix::file::{fstatat, renameat, AtFlag};
match unsafe {
renameat(
@@ -113,9 +113,9 @@ pub(crate) fn path_rename(resolved_old: PathGet, resolved_new: PathGet) -> Resul
Ok(_) => {
// check if destination contains a trailing slash
if resolved_new.path().contains('/') {
return Err(Error::ENOTDIR);
return Err(WasiError::ENOTDIR);
} else {
return Err(Error::ENOENT);
return Err(WasiError::ENOENT);
}
}
Err(err) => {
@@ -132,13 +132,13 @@ pub(crate) fn path_rename(resolved_old: PathGet, resolved_new: PathGet) -> Resul
pub(crate) mod fd_readdir_impl {
use crate::sys::fdentry_impl::OsHandle;
use crate::Result;
use crate::wasi::WasiResult;
use std::sync::{Mutex, MutexGuard};
use yanix::dir::Dir;
pub(crate) fn get_dir_from_os_handle<'a>(
os_handle: &'a mut OsHandle,
) -> Result<MutexGuard<'a, Dir>> {
) -> WasiResult<MutexGuard<'a, Dir>> {
let dir = match os_handle.dir {
Some(ref mut dir) => dir,
None => {

View File

@@ -1,5 +1,5 @@
use crate::fdentry::{Descriptor, OsHandleRef};
use crate::{sys::unix::sys_impl, wasi, Error, Result};
use crate::{sys::unix::sys_impl, wasi};
use std::fs::File;
use std::io;
use std::mem::ManuallyDrop;
@@ -33,7 +33,7 @@ pub(crate) fn descriptor_as_oshandle<'lifetime>(
/// This function is unsafe because it operates on a raw file descriptor.
pub(crate) unsafe fn determine_type_and_access_rights<Fd: AsRawFd>(
fd: &Fd,
) -> Result<(
) -> io::Result<(
wasi::__wasi_filetype_t,
wasi::__wasi_rights_t,
wasi::__wasi_rights_t,
@@ -57,7 +57,7 @@ pub(crate) unsafe fn determine_type_and_access_rights<Fd: AsRawFd>(
/// This function is unsafe because it operates on a raw file descriptor.
pub(crate) unsafe fn determine_type_rights<Fd: AsRawFd>(
fd: &Fd,
) -> Result<(
) -> io::Result<(
wasi::__wasi_filetype_t,
wasi::__wasi_rights_t,
wasi::__wasi_rights_t,
@@ -117,7 +117,7 @@ pub(crate) unsafe fn determine_type_rights<Fd: AsRawFd>(
wasi::RIGHTS_SOCKET_BASE,
wasi::RIGHTS_SOCKET_INHERITING,
),
_ => return Err(Error::EINVAL),
_ => return Err(io::Error::from_raw_os_error(libc::EINVAL)),
}
} else if ft.is_fifo() {
log::debug!("Host fd {:?} is a fifo", fd.as_raw_fd());
@@ -128,7 +128,7 @@ pub(crate) unsafe fn determine_type_rights<Fd: AsRawFd>(
)
} else {
log::debug!("Host fd {:?} is unknown", fd.as_raw_fd());
return Err(Error::EINVAL);
return Err(io::Error::from_raw_os_error(libc::EINVAL));
}
};

View File

@@ -3,16 +3,19 @@
#![allow(non_snake_case)]
#![allow(dead_code)]
use crate::host::FileType;
use crate::{error::FromRawOsError, helpers, sys::unix::sys_impl, wasi, Error, Result};
use crate::wasi::{self, WasiError, WasiResult};
use crate::{helpers, sys::unix::sys_impl};
use std::ffi::OsStr;
use std::io;
use std::os::unix::prelude::OsStrExt;
use yanix::file::OFlag;
pub(crate) use sys_impl::host_impl::*;
impl FromRawOsError for Error {
fn from_raw_os_error(code: i32) -> Self {
match code {
impl From<io::Error> for WasiError {
fn from(err: io::Error) -> Self {
match err.raw_os_error() {
Some(code) => match code {
libc::EPERM => Self::EPERM,
libc::ENOENT => Self::ENOENT,
libc::ESRCH => Self::ESRCH,
@@ -87,10 +90,16 @@ impl FromRawOsError for Error {
libc::ECANCELED => Self::ECANCELED,
libc::EOWNERDEAD => Self::EOWNERDEAD,
libc::ENOTRECOVERABLE => Self::ENOTRECOVERABLE,
libc::ENOTSUP => Self::ENOTSUP,
x => {
log::debug!("Unknown errno value: {}", x);
Self::EIO
}
},
None => {
log::debug!("Other I/O error: {}", err);
Self::EIO
}
}
}
}
@@ -152,13 +161,13 @@ pub(crate) fn nix_from_oflags(oflags: wasi::__wasi_oflags_t) -> OFlag {
nix_flags
}
pub(crate) fn filestat_from_nix(filestat: libc::stat) -> Result<wasi::__wasi_filestat_t> {
pub(crate) fn filestat_from_nix(filestat: libc::stat) -> WasiResult<wasi::__wasi_filestat_t> {
use std::convert::TryInto;
fn filestat_to_timestamp(secs: u64, nsecs: u64) -> Result<wasi::__wasi_timestamp_t> {
fn filestat_to_timestamp(secs: u64, nsecs: u64) -> WasiResult<wasi::__wasi_timestamp_t> {
secs.checked_mul(1_000_000_000)
.and_then(|sec_nsec| sec_nsec.checked_add(nsecs))
.ok_or(Error::EOVERFLOW)
.ok_or(WasiError::EOVERFLOW)
}
let filetype = yanix::file::FileType::from_stat_st_mode(filestat.st_mode);
@@ -193,7 +202,7 @@ pub(crate) fn filestat_from_nix(filestat: libc::stat) -> Result<wasi::__wasi_fil
///
/// NB WASI spec requires OS string to be valid UTF-8. Otherwise,
/// `__WASI_ERRNO_ILSEQ` error is returned.
pub(crate) fn path_from_host<S: AsRef<OsStr>>(s: S) -> Result<String> {
pub(crate) fn path_from_host<S: AsRef<OsStr>>(s: S) -> WasiResult<String> {
helpers::path_from_slice(s.as_ref().as_bytes()).map(String::from)
}

View File

@@ -3,8 +3,9 @@
use crate::fdentry::Descriptor;
use crate::host::Dirent;
use crate::hostcalls_impl::PathGet;
use crate::sys::{fdentry_impl::OsHandle, host_impl, unix::sys_impl};
use crate::{wasi, Error, Result};
use crate::sys::fdentry_impl::OsHandle;
use crate::sys::{host_impl, unix::sys_impl};
use crate::wasi::{self, WasiError, WasiResult};
use std::convert::TryInto;
use std::fs::File;
use std::os::unix::fs::FileExt;
@@ -16,15 +17,19 @@ pub(crate) fn fd_pread(
file: &File,
buf: &mut [u8],
offset: wasi::__wasi_filesize_t,
) -> Result<usize> {
) -> WasiResult<usize> {
file.read_at(buf, offset).map_err(Into::into)
}
pub(crate) fn fd_pwrite(file: &File, buf: &[u8], offset: wasi::__wasi_filesize_t) -> Result<usize> {
pub(crate) fn fd_pwrite(
file: &File,
buf: &[u8],
offset: wasi::__wasi_filesize_t,
) -> WasiResult<usize> {
file.write_at(buf, offset).map_err(Into::into)
}
pub(crate) fn fd_fdstat_get(fd: &File) -> Result<wasi::__wasi_fdflags_t> {
pub(crate) fn fd_fdstat_get(fd: &File) -> WasiResult<wasi::__wasi_fdflags_t> {
unsafe { yanix::fcntl::get_status_flags(fd.as_raw_fd()) }
.map(host_impl::fdflags_from_nix)
.map_err(Into::into)
@@ -33,7 +38,7 @@ pub(crate) fn fd_fdstat_get(fd: &File) -> Result<wasi::__wasi_fdflags_t> {
pub(crate) fn fd_fdstat_set_flags(
fd: &File,
fdflags: wasi::__wasi_fdflags_t,
) -> Result<Option<OsHandle>> {
) -> WasiResult<Option<OsHandle>> {
let nix_flags = host_impl::nix_from_fdflags(fdflags);
unsafe { yanix::fcntl::set_status_flags(fd.as_raw_fd(), nix_flags) }
.map(|_| None)
@@ -45,7 +50,7 @@ pub(crate) fn fd_advise(
advice: wasi::__wasi_advice_t,
offset: wasi::__wasi_filesize_t,
len: wasi::__wasi_filesize_t,
) -> Result<()> {
) -> WasiResult<()> {
use yanix::fadvise::{posix_fadvise, PosixFadviseAdvice};
let offset = offset.try_into()?;
let len = len.try_into()?;
@@ -56,17 +61,17 @@ pub(crate) fn fd_advise(
wasi::__WASI_ADVICE_NOREUSE => PosixFadviseAdvice::NoReuse,
wasi::__WASI_ADVICE_RANDOM => PosixFadviseAdvice::Random,
wasi::__WASI_ADVICE_NORMAL => PosixFadviseAdvice::Normal,
_ => return Err(Error::EINVAL),
_ => return Err(WasiError::EINVAL),
};
unsafe { posix_fadvise(file.as_raw_fd(), offset, len, host_advice) }.map_err(Into::into)
}
pub(crate) fn path_create_directory(base: &File, path: &str) -> Result<()> {
pub(crate) fn path_create_directory(base: &File, path: &str) -> WasiResult<()> {
use yanix::file::{mkdirat, Mode};
unsafe { mkdirat(base.as_raw_fd(), path, Mode::from_bits_truncate(0o777)) }.map_err(Into::into)
}
pub(crate) fn path_link(resolved_old: PathGet, resolved_new: PathGet) -> Result<()> {
pub(crate) fn path_link(resolved_old: PathGet, resolved_new: PathGet) -> WasiResult<()> {
use yanix::file::{linkat, AtFlag};
unsafe {
linkat(
@@ -86,7 +91,7 @@ pub(crate) fn path_open(
write: bool,
oflags: wasi::__wasi_oflags_t,
fs_flags: wasi::__wasi_fdflags_t,
) -> Result<Descriptor> {
) -> WasiResult<Descriptor> {
use yanix::file::{fstatat, openat, AtFlag, FileType, Mode, OFlag};
let mut nix_all_oflags = if read && write {
@@ -136,7 +141,7 @@ pub(crate) fn path_open(
} {
Ok(stat) => {
if FileType::from_stat_st_mode(stat.st_mode) == FileType::Socket {
return Err(Error::ENOTSUP);
return Err(WasiError::ENOTSUP);
}
}
Err(err) => {
@@ -158,7 +163,7 @@ pub(crate) fn path_open(
} {
Ok(stat) => {
if FileType::from_stat_st_mode(stat.st_mode) == FileType::Symlink {
return Err(Error::ELOOP);
return Err(WasiError::ELOOP);
}
}
Err(err) => {
@@ -169,7 +174,7 @@ pub(crate) fn path_open(
// FreeBSD returns EMLINK instead of ELOOP when using O_NOFOLLOW on
// a symlink.
libc::EMLINK if !(nix_all_oflags & OFlag::NOFOLLOW).is_empty() => {
return Err(Error::ELOOP);
return Err(WasiError::ELOOP);
}
_ => {}
}
@@ -184,7 +189,7 @@ pub(crate) fn path_open(
Ok(OsHandle::from(unsafe { File::from_raw_fd(new_fd) }).into())
}
pub(crate) fn path_readlink(resolved: PathGet, buf: &mut [u8]) -> Result<usize> {
pub(crate) fn path_readlink(resolved: PathGet, buf: &mut [u8]) -> WasiResult<usize> {
use std::cmp::min;
use yanix::file::readlinkat;
let read_link = unsafe { readlinkat(resolved.dirfd().as_raw_fd(), resolved.path()) }
@@ -197,7 +202,7 @@ pub(crate) fn path_readlink(resolved: PathGet, buf: &mut [u8]) -> Result<usize>
Ok(copy_len)
}
pub(crate) fn fd_filestat_get(file: &std::fs::File) -> Result<wasi::__wasi_filestat_t> {
pub(crate) fn fd_filestat_get(file: &std::fs::File) -> WasiResult<wasi::__wasi_filestat_t> {
use yanix::file::fstat;
unsafe { fstat(file.as_raw_fd()) }
.map_err(Into::into)
@@ -207,7 +212,7 @@ pub(crate) fn fd_filestat_get(file: &std::fs::File) -> Result<wasi::__wasi_files
pub(crate) fn path_filestat_get(
resolved: PathGet,
dirflags: wasi::__wasi_lookupflags_t,
) -> Result<wasi::__wasi_filestat_t> {
) -> WasiResult<wasi::__wasi_filestat_t> {
use yanix::file::{fstatat, AtFlag};
let atflags = match dirflags {
0 => AtFlag::empty(),
@@ -224,7 +229,7 @@ pub(crate) fn path_filestat_set_times(
st_atim: wasi::__wasi_timestamp_t,
st_mtim: wasi::__wasi_timestamp_t,
fst_flags: wasi::__wasi_fstflags_t,
) -> Result<()> {
) -> WasiResult<()> {
use std::time::{Duration, UNIX_EPOCH};
use yanix::filetime::*;
@@ -234,7 +239,7 @@ pub(crate) fn path_filestat_set_times(
let set_mtim_now = fst_flags & wasi::__WASI_FSTFLAGS_MTIM_NOW != 0;
if (set_atim && set_atim_now) || (set_mtim && set_mtim_now) {
return Err(Error::EINVAL);
return Err(WasiError::EINVAL);
}
let symlink_nofollow = wasi::__WASI_LOOKUPFLAGS_SYMLINK_FOLLOW != dirflags;
@@ -265,7 +270,7 @@ pub(crate) fn path_filestat_set_times(
.map_err(Into::into)
}
pub(crate) fn path_remove_directory(resolved: PathGet) -> Result<()> {
pub(crate) fn path_remove_directory(resolved: PathGet) -> WasiResult<()> {
use yanix::file::{unlinkat, AtFlag};
unsafe {
@@ -281,7 +286,7 @@ pub(crate) fn path_remove_directory(resolved: PathGet) -> Result<()> {
pub(crate) fn fd_readdir<'a>(
os_handle: &'a mut OsHandle,
cookie: wasi::__wasi_dircookie_t,
) -> Result<impl Iterator<Item = Result<Dirent>> + 'a> {
) -> WasiResult<impl Iterator<Item = WasiResult<Dirent>> + 'a> {
use yanix::dir::{DirIter, Entry, EntryExt, SeekLoc};
// Get an instance of `Dir`; this is host-specific due to intricasies

View File

@@ -1,7 +1,7 @@
#![allow(non_camel_case_types)]
#![allow(unused_unsafe)]
use crate::sys::host_impl;
use crate::{wasi, Result};
use crate::wasi::{self, WasiResult};
use std::fs::File;
use yanix::file::OFlag;
@@ -36,7 +36,7 @@ pub(crate) fn path_open_rights(
(needed_base, needed_inheriting)
}
pub(crate) fn openat(dirfd: &File, path: &str) -> Result<File> {
pub(crate) fn openat(dirfd: &File, path: &str) -> WasiResult<File> {
use std::os::unix::prelude::{AsRawFd, FromRawFd};
use yanix::file::{openat, Mode};
@@ -54,7 +54,7 @@ pub(crate) fn openat(dirfd: &File, path: &str) -> Result<File> {
.map_err(Into::into)
}
pub(crate) fn readlinkat(dirfd: &File, path: &str) -> Result<String> {
pub(crate) fn readlinkat(dirfd: &File, path: &str) -> WasiResult<String> {
use std::os::unix::prelude::AsRawFd;
use yanix::file::readlinkat;

View File

@@ -1,22 +1,24 @@
#![allow(non_camel_case_types)]
#![allow(unused_unsafe)]
use crate::hostcalls_impl::{ClockEventData, FdEventData};
use crate::{wasi, Error, Result};
use crate::wasi::{self, WasiError, WasiResult};
use std::io;
use yanix::clock::{clock_getres, clock_gettime, ClockId};
fn wasi_clock_id_to_unix(clock_id: wasi::__wasi_clockid_t) -> Result<ClockId> {
fn wasi_clock_id_to_unix(clock_id: wasi::__wasi_clockid_t) -> WasiResult<ClockId> {
// convert the supported clocks to libc types, or return EINVAL
match clock_id {
wasi::__WASI_CLOCKID_REALTIME => Ok(ClockId::Realtime),
wasi::__WASI_CLOCKID_MONOTONIC => Ok(ClockId::Monotonic),
wasi::__WASI_CLOCKID_PROCESS_CPUTIME_ID => Ok(ClockId::ProcessCPUTime),
wasi::__WASI_CLOCKID_THREAD_CPUTIME_ID => Ok(ClockId::ThreadCPUTime),
_ => Err(Error::EINVAL),
_ => Err(WasiError::EINVAL),
}
}
pub(crate) fn clock_res_get(clock_id: wasi::__wasi_clockid_t) -> Result<wasi::__wasi_timestamp_t> {
pub(crate) fn clock_res_get(
clock_id: wasi::__wasi_clockid_t,
) -> WasiResult<wasi::__wasi_timestamp_t> {
let clock_id = wasi_clock_id_to_unix(clock_id)?;
let timespec = clock_getres(clock_id)?;
@@ -26,18 +28,20 @@ pub(crate) fn clock_res_get(clock_id: wasi::__wasi_clockid_t) -> Result<wasi::__
(timespec.tv_sec as wasi::__wasi_timestamp_t)
.checked_mul(1_000_000_000)
.and_then(|sec_ns| sec_ns.checked_add(timespec.tv_nsec as wasi::__wasi_timestamp_t))
.map_or(Err(Error::EOVERFLOW), |resolution| {
.map_or(Err(WasiError::EOVERFLOW), |resolution| {
// a supported clock can never return zero; this case will probably never get hit, but
// make sure we follow the spec
if resolution == 0 {
Err(Error::EINVAL)
Err(WasiError::EINVAL)
} else {
Ok(resolution)
}
})
}
pub(crate) fn clock_time_get(clock_id: wasi::__wasi_clockid_t) -> Result<wasi::__wasi_timestamp_t> {
pub(crate) fn clock_time_get(
clock_id: wasi::__wasi_clockid_t,
) -> WasiResult<wasi::__wasi_timestamp_t> {
let clock_id = wasi_clock_id_to_unix(clock_id)?;
let timespec = clock_gettime(clock_id)?;
@@ -46,14 +50,14 @@ pub(crate) fn clock_time_get(clock_id: wasi::__wasi_clockid_t) -> Result<wasi::_
(timespec.tv_sec as wasi::__wasi_timestamp_t)
.checked_mul(1_000_000_000)
.and_then(|sec_ns| sec_ns.checked_add(timespec.tv_nsec as wasi::__wasi_timestamp_t))
.map_or(Err(Error::EOVERFLOW), Ok)
.map_or(Err(WasiError::EOVERFLOW), Ok)
}
pub(crate) fn poll_oneoff(
timeout: Option<ClockEventData>,
fd_events: Vec<FdEventData>,
events: &mut Vec<wasi::__wasi_event_t>,
) -> Result<()> {
) -> WasiResult<()> {
use std::{convert::TryInto, os::unix::prelude::AsRawFd};
use yanix::poll::{poll, PollFd, PollFlags};
@@ -122,12 +126,12 @@ fn poll_oneoff_handle_timeout_event(
fn poll_oneoff_handle_fd_event<'a>(
ready_events: impl Iterator<Item = (FdEventData<'a>, yanix::poll::PollFd)>,
events: &mut Vec<wasi::__wasi_event_t>,
) -> Result<()> {
) -> WasiResult<()> {
use crate::fdentry::Descriptor;
use std::{convert::TryInto, os::unix::prelude::AsRawFd};
use yanix::{file::fionread, poll::PollFlags};
fn query_nbytes(fd: &Descriptor) -> Result<u64> {
fn query_nbytes(fd: &Descriptor) -> WasiResult<u64> {
// fionread may overflow for large files, so use another way for regular files.
if let Descriptor::OsHandle(os_handle) = fd {
let meta = os_handle.metadata()?;

View File

@@ -1,11 +1,11 @@
use crate::{wasi, Result};
use crate::wasi::{self, WasiResult};
pub(crate) const O_RSYNC: yanix::file::OFlag = yanix::file::OFlag::RSYNC;
pub(crate) fn stdev_from_nix(dev: libc::dev_t) -> Result<wasi::__wasi_device_t> {
pub(crate) fn stdev_from_nix(dev: libc::dev_t) -> WasiResult<wasi::__wasi_device_t> {
Ok(wasi::__wasi_device_t::from(dev))
}
pub(crate) fn stino_from_nix(ino: libc::ino_t) -> Result<wasi::__wasi_inode_t> {
pub(crate) fn stino_from_nix(ino: libc::ino_t) -> WasiResult<wasi::__wasi_inode_t> {
Ok(wasi::__wasi_device_t::from(ino))
}

View File

@@ -1,9 +1,9 @@
use crate::fdentry::Descriptor;
use crate::hostcalls_impl::PathGet;
use crate::Result;
use crate::wasi::WasiResult;
use std::os::unix::prelude::AsRawFd;
pub(crate) fn path_unlink_file(resolved: PathGet) -> Result<()> {
pub(crate) fn path_unlink_file(resolved: PathGet) -> WasiResult<()> {
use yanix::file::{unlinkat, AtFlag};
unsafe {
unlinkat(
@@ -15,7 +15,7 @@ pub(crate) fn path_unlink_file(resolved: PathGet) -> Result<()> {
.map_err(Into::into)
}
pub(crate) fn path_symlink(old_path: &str, resolved: PathGet) -> Result<()> {
pub(crate) fn path_symlink(old_path: &str, resolved: PathGet) -> WasiResult<()> {
use yanix::file::symlinkat;
log::debug!("path_symlink old_path = {:?}", old_path);
@@ -25,7 +25,7 @@ pub(crate) fn path_symlink(old_path: &str, resolved: PathGet) -> Result<()> {
.map_err(Into::into)
}
pub(crate) fn path_rename(resolved_old: PathGet, resolved_new: PathGet) -> Result<()> {
pub(crate) fn path_rename(resolved_old: PathGet, resolved_new: PathGet) -> WasiResult<()> {
use yanix::file::renameat;
match (resolved_old.dirfd(), resolved_new.dirfd()) {
(Descriptor::OsHandle(resolved_old_file), Descriptor::OsHandle(resolved_new_file)) => {
@@ -47,10 +47,10 @@ pub(crate) fn path_rename(resolved_old: PathGet, resolved_new: PathGet) -> Resul
pub(crate) mod fd_readdir_impl {
use crate::sys::fdentry_impl::OsHandle;
use crate::Result;
use crate::wasi::WasiResult;
use yanix::dir::Dir;
pub(crate) fn get_dir_from_os_handle(os_handle: &mut OsHandle) -> Result<Box<Dir>> {
pub(crate) fn get_dir_from_os_handle(os_handle: &mut OsHandle) -> WasiResult<Box<Dir>> {
// We need to duplicate the fd, because `opendir(3)`:
// After a successful call to fdopendir(), fd is used internally by the implementation,
// and should not otherwise be used by the application.

View File

@@ -20,18 +20,14 @@ cfg_if::cfg_if! {
}
}
use crate::Result;
use std::fs::{File, OpenOptions};
use std::io::Result;
use std::path::Path;
pub(crate) fn dev_null() -> Result<File> {
OpenOptions::new()
.read(true)
.write(true)
.open("/dev/null")
.map_err(Into::into)
OpenOptions::new().read(true).write(true).open("/dev/null")
}
pub fn preopen_dir<P: AsRef<Path>>(path: P) -> Result<File> {
File::open(path).map_err(Into::into)
File::open(path)
}

View File

@@ -1,5 +1,5 @@
use crate::fdentry::{Descriptor, OsHandleRef};
use crate::{wasi, Error, Result};
use crate::wasi;
use std::fs::File;
use std::io;
use std::mem::ManuallyDrop;
@@ -63,7 +63,7 @@ pub(crate) fn descriptor_as_oshandle<'lifetime>(
/// This function is unsafe because it operates on a raw file descriptor.
pub(crate) unsafe fn determine_type_and_access_rights<Handle: AsRawHandle>(
handle: &Handle,
) -> Result<(
) -> io::Result<(
wasi::__wasi_filetype_t,
wasi::__wasi_rights_t,
wasi::__wasi_rights_t,
@@ -96,7 +96,7 @@ pub(crate) unsafe fn determine_type_and_access_rights<Handle: AsRawHandle>(
/// This function is unsafe because it operates on a raw file descriptor.
pub(crate) unsafe fn determine_type_rights<Handle: AsRawHandle>(
handle: &Handle,
) -> Result<(
) -> io::Result<(
wasi::__wasi_filetype_t,
wasi::__wasi_rights_t,
wasi::__wasi_rights_t,
@@ -114,7 +114,7 @@ pub(crate) unsafe fn determine_type_rights<Handle: AsRawHandle>(
} else if file_type.is_disk() {
// disk file: file, dir or disk device
let file = std::mem::ManuallyDrop::new(File::from_raw_handle(handle.as_raw_handle()));
let meta = file.metadata().map_err(|_| Error::EINVAL)?;
let meta = file.metadata()?;
if meta.is_dir() {
(
wasi::__WASI_FILETYPE_DIRECTORY,
@@ -128,7 +128,7 @@ pub(crate) unsafe fn determine_type_rights<Handle: AsRawHandle>(
wasi::RIGHTS_REGULAR_FILE_INHERITING,
)
} else {
return Err(Error::EINVAL);
return Err(io::Error::from_raw_os_error(libc::EINVAL));
}
} else if file_type.is_pipe() {
// pipe object: socket, named pipe or anonymous pipe
@@ -139,7 +139,7 @@ pub(crate) unsafe fn determine_type_rights<Handle: AsRawHandle>(
wasi::RIGHTS_SOCKET_INHERITING,
)
} else {
return Err(Error::EINVAL);
return Err(io::Error::from_raw_os_error(libc::EINVAL));
}
};
Ok((file_type, rights_base, rights_inheriting))

View File

@@ -1,6 +1,6 @@
//! WASI host types specific to Windows host.
use crate::host::FileType;
use crate::{error::FromRawOsError, wasi, Error, Result};
use crate::wasi::{self, WasiError, WasiResult};
use std::convert::TryInto;
use std::ffi::OsStr;
use std::fs::{self, File};
@@ -9,10 +9,10 @@ use std::os::windows::ffi::OsStrExt;
use std::time::{SystemTime, UNIX_EPOCH};
use winapi::shared::winerror;
impl FromRawOsError for Error {
fn from_raw_os_error(code: i32) -> Self {
// TODO: implement error mapping between Windows and WASI
match code as u32 {
impl From<io::Error> for WasiError {
fn from(err: io::Error) -> Self {
match err.raw_os_error() {
Some(code) => match code as u32 {
winerror::ERROR_SUCCESS => Self::ESUCCESS,
winerror::ERROR_BAD_ENVIRONMENT => Self::E2BIG,
winerror::ERROR_FILE_NOT_FOUND => Self::ENOENT,
@@ -20,7 +20,7 @@ impl FromRawOsError for Error {
winerror::ERROR_TOO_MANY_OPEN_FILES => Self::ENFILE,
winerror::ERROR_ACCESS_DENIED => Self::EACCES,
winerror::ERROR_SHARING_VIOLATION => Self::EACCES,
winerror::ERROR_PRIVILEGE_NOT_HELD => Self::ENOTCAPABLE, // TODO is this the correct mapping?
winerror::ERROR_PRIVILEGE_NOT_HELD => Self::ENOTCAPABLE,
winerror::ERROR_INVALID_HANDLE => Self::EBADF,
winerror::ERROR_INVALID_NAME => Self::ENOENT,
winerror::ERROR_NOT_ENOUGH_MEMORY => Self::ENOMEM,
@@ -36,7 +36,15 @@ impl FromRawOsError for Error {
winerror::ERROR_NEGATIVE_SEEK => Self::EINVAL,
winerror::ERROR_DIRECTORY => Self::ENOTDIR,
winerror::ERROR_ALREADY_EXISTS => Self::EEXIST,
_ => Self::ENOTSUP,
x => {
log::debug!("unknown error value: {}", x);
Self::EIO
}
},
None => {
log::debug!("Other I/O error: {}", err);
Self::EIO
}
}
}
}
@@ -73,15 +81,15 @@ fn change_time(file: &File) -> io::Result<i64> {
winx::file::change_time(file)
}
fn systemtime_to_timestamp(st: SystemTime) -> Result<u64> {
fn systemtime_to_timestamp(st: SystemTime) -> WasiResult<u64> {
st.duration_since(UNIX_EPOCH)
.map_err(|_| Error::EINVAL)? // date earlier than UNIX_EPOCH
.map_err(|_| WasiError::EINVAL)? // date earlier than UNIX_EPOCH
.as_nanos()
.try_into()
.map_err(Into::into) // u128 doesn't fit into u64
}
pub(crate) fn filestat_from_win(file: &File) -> Result<wasi::__wasi_filestat_t> {
pub(crate) fn filestat_from_win(file: &File) -> WasiResult<wasi::__wasi_filestat_t> {
let metadata = file.metadata()?;
Ok(wasi::__wasi_filestat_t {
dev: device_id(file)?,
@@ -99,7 +107,7 @@ pub(crate) fn filestat_from_win(file: &File) -> Result<wasi::__wasi_filestat_t>
///
/// NB WASI spec requires OS string to be valid UTF-8. Otherwise,
/// `__WASI_ERRNO_ILSEQ` error is returned.
pub(crate) fn path_from_host<S: AsRef<OsStr>>(s: S) -> Result<String> {
pub(crate) fn path_from_host<S: AsRef<OsStr>>(s: S) -> WasiResult<String> {
let vec: Vec<u16> = s.as_ref().encode_wide().collect();
String::from_utf16(&vec).map_err(|_| Error::EILSEQ)
String::from_utf16(&vec).map_err(|_| WasiError::EILSEQ)
}

View File

@@ -8,7 +8,7 @@ use crate::hostcalls_impl::{fd_filestat_set_times_impl, PathGet};
use crate::sys::fdentry_impl::{determine_type_rights, OsHandle};
use crate::sys::host_impl::{self, path_from_host};
use crate::sys::hostcalls_impl::fs_helpers::PathGetExt;
use crate::{wasi, Error, Result};
use crate::wasi::{self, WasiError, WasiResult};
use log::{debug, trace};
use std::convert::TryInto;
use std::fs::{File, Metadata, OpenOptions};
@@ -44,16 +44,20 @@ pub(crate) fn fd_pread(
file: &File,
buf: &mut [u8],
offset: wasi::__wasi_filesize_t,
) -> Result<usize> {
) -> WasiResult<usize> {
read_at(file, buf, offset).map_err(Into::into)
}
// TODO refactor common code with unix
pub(crate) fn fd_pwrite(file: &File, buf: &[u8], offset: wasi::__wasi_filesize_t) -> Result<usize> {
pub(crate) fn fd_pwrite(
file: &File,
buf: &[u8],
offset: wasi::__wasi_filesize_t,
) -> WasiResult<usize> {
write_at(file, buf, offset).map_err(Into::into)
}
pub(crate) fn fd_fdstat_get(fd: &File) -> Result<wasi::__wasi_fdflags_t> {
pub(crate) fn fd_fdstat_get(fd: &File) -> WasiResult<wasi::__wasi_fdflags_t> {
let mut fdflags = 0;
let handle = unsafe { fd.as_raw_handle() };
@@ -82,7 +86,7 @@ pub(crate) fn fd_fdstat_get(fd: &File) -> Result<wasi::__wasi_fdflags_t> {
pub(crate) fn fd_fdstat_set_flags(
fd: &File,
fdflags: wasi::__wasi_fdflags_t,
) -> Result<Option<OsHandle>> {
) -> WasiResult<Option<OsHandle>> {
let handle = unsafe { fd.as_raw_handle() };
let access_mode = winx::file::query_access_information(handle)?;
@@ -106,7 +110,7 @@ pub(crate) fn fd_advise(
advice: wasi::__wasi_advice_t,
_offset: wasi::__wasi_filesize_t,
_len: wasi::__wasi_filesize_t,
) -> Result<()> {
) -> WasiResult<()> {
match advice {
wasi::__WASI_ADVICE_DONTNEED
| wasi::__WASI_ADVICE_SEQUENTIAL
@@ -114,18 +118,18 @@ pub(crate) fn fd_advise(
| wasi::__WASI_ADVICE_NOREUSE
| wasi::__WASI_ADVICE_RANDOM
| wasi::__WASI_ADVICE_NORMAL => {}
_ => return Err(Error::EINVAL),
_ => return Err(WasiError::EINVAL),
}
Ok(())
}
pub(crate) fn path_create_directory(file: &File, path: &str) -> Result<()> {
pub(crate) fn path_create_directory(file: &File, path: &str) -> WasiResult<()> {
let path = concatenate(file, path)?;
std::fs::create_dir(&path).map_err(Into::into)
}
pub(crate) fn path_link(resolved_old: PathGet, resolved_new: PathGet) -> Result<()> {
pub(crate) fn path_link(resolved_old: PathGet, resolved_new: PathGet) -> WasiResult<()> {
unimplemented!("path_link")
}
@@ -135,7 +139,7 @@ pub(crate) fn path_open(
write: bool,
oflags: wasi::__wasi_oflags_t,
fdflags: wasi::__wasi_fdflags_t,
) -> Result<Descriptor> {
) -> WasiResult<Descriptor> {
use winx::file::{AccessMode, CreationDisposition, Flags};
let is_trunc = oflags & wasi::__WASI_OFLAGS_TRUNC != 0;
@@ -145,7 +149,7 @@ pub(crate) fn path_open(
// This is because truncation requires `GENERIC_WRITE` access, which will override the removal
// of the `FILE_WRITE_DATA` permission.
if fdflags & wasi::__WASI_FDFLAGS_APPEND != 0 {
return Err(Error::ENOTSUP);
return Err(WasiError::ENOTSUP);
}
}
@@ -172,11 +176,11 @@ pub(crate) fn path_open(
Ok(file_type) => {
// check if we are trying to open a symlink
if file_type.is_symlink() {
return Err(Error::ELOOP);
return Err(WasiError::ELOOP);
}
// check if we are trying to open a file as a dir
if file_type.is_file() && oflags & wasi::__WASI_OFLAGS_DIRECTORY != 0 {
return Err(Error::ENOTDIR);
return Err(WasiError::ENOTDIR);
}
}
Err(err) => match err.raw_os_error() {
@@ -191,7 +195,7 @@ pub(crate) fn path_open(
}
None => {
log::debug!("Inconvertible OS error: {}", err);
return Err(Error::EIO);
return Err(WasiError::EIO);
}
},
}
@@ -276,7 +280,7 @@ fn dirent_from_path<P: AsRef<Path>>(
path: P,
name: &str,
cookie: wasi::__wasi_dircookie_t,
) -> Result<Dirent> {
) -> WasiResult<Dirent> {
let path = path.as_ref();
trace!("dirent_from_path: opening {}", path.to_string_lossy());
@@ -325,7 +329,7 @@ fn dirent_from_path<P: AsRef<Path>>(
pub(crate) fn fd_readdir(
fd: &File,
cookie: wasi::__wasi_dircookie_t,
) -> Result<impl Iterator<Item = Result<Dirent>>> {
) -> WasiResult<impl Iterator<Item = WasiResult<Dirent>>> {
use winx::file::get_file_path;
let cookie = cookie.try_into()?;
@@ -361,7 +365,7 @@ pub(crate) fn fd_readdir(
Ok(iter.skip(cookie))
}
pub(crate) fn path_readlink(resolved: PathGet, buf: &mut [u8]) -> Result<usize> {
pub(crate) fn path_readlink(resolved: PathGet, buf: &mut [u8]) -> WasiResult<usize> {
use winx::file::get_file_path;
let path = resolved.concatenate()?;
@@ -375,8 +379,8 @@ pub(crate) fn path_readlink(resolved: PathGet, buf: &mut [u8]) -> Result<usize>
let dir_path = PathBuf::from(strip_extended_prefix(dir_path));
let target_path = target_path
.strip_prefix(dir_path)
.map_err(|_| Error::ENOTCAPABLE)
.and_then(|path| path.to_str().map(String::from).ok_or(Error::EILSEQ))?;
.map_err(|_| WasiError::ENOTCAPABLE)
.and_then(|path| path.to_str().map(String::from).ok_or(WasiError::EILSEQ))?;
if buf.len() > 0 {
let mut chars = target_path.chars();
@@ -398,7 +402,7 @@ pub(crate) fn path_readlink(resolved: PathGet, buf: &mut [u8]) -> Result<usize>
}
}
fn strip_trailing_slashes_and_concatenate(resolved: &PathGet) -> Result<Option<PathBuf>> {
fn strip_trailing_slashes_and_concatenate(resolved: &PathGet) -> WasiResult<Option<PathBuf>> {
if resolved.path().ends_with('/') {
let suffix = resolved.path().trim_end_matches('/');
concatenate(&resolved.dirfd().as_os_handle(), Path::new(suffix)).map(Some)
@@ -407,7 +411,7 @@ fn strip_trailing_slashes_and_concatenate(resolved: &PathGet) -> Result<Option<P
}
}
pub(crate) fn path_rename(resolved_old: PathGet, resolved_new: PathGet) -> Result<()> {
pub(crate) fn path_rename(resolved_old: PathGet, resolved_new: PathGet) -> WasiResult<()> {
use std::fs;
let old_path = resolved_old.concatenate()?;
@@ -418,12 +422,12 @@ pub(crate) fn path_rename(resolved_old: PathGet, resolved_new: PathGet) -> Resul
//
// [std::fs::rename]: https://doc.rust-lang.org/std/fs/fn.rename.html
if old_path.is_dir() && new_path.is_file() {
return Err(Error::ENOTDIR);
return Err(WasiError::ENOTDIR);
}
// Second sanity check: check we're not trying to rename a file into a path
// ending in a trailing slash.
if old_path.is_file() && resolved_new.path().ends_with('/') {
return Err(Error::ENOTDIR);
return Err(WasiError::ENOTDIR);
}
// TODO handle symlinks
@@ -439,7 +443,7 @@ pub(crate) fn path_rename(resolved_old: PathGet, resolved_new: PathGet) -> Resul
// So most likely dealing with new_path == dir.
// Eliminate case old_path == file first.
if old_path.is_file() {
return Err(Error::EISDIR);
return Err(WasiError::EISDIR);
} else {
// Ok, let's try removing an empty dir at new_path if it exists
// and is a nonempty dir.
@@ -453,7 +457,7 @@ pub(crate) fn path_rename(resolved_old: PathGet, resolved_new: PathGet) -> Resul
// a file instead of a dir, and if so, throw ENOTDIR.
if let Some(path) = strip_trailing_slashes_and_concatenate(&resolved_old)? {
if path.is_file() {
return Err(Error::ENOTDIR);
return Err(WasiError::ENOTDIR);
}
}
}
@@ -464,19 +468,19 @@ pub(crate) fn path_rename(resolved_old: PathGet, resolved_new: PathGet) -> Resul
}
None => {
log::debug!("Inconvertible OS error: {}", err);
Err(Error::EIO)
Err(WasiError::EIO)
}
}
}
pub(crate) fn fd_filestat_get(file: &std::fs::File) -> Result<wasi::__wasi_filestat_t> {
pub(crate) fn fd_filestat_get(file: &std::fs::File) -> WasiResult<wasi::__wasi_filestat_t> {
host_impl::filestat_from_win(file)
}
pub(crate) fn path_filestat_get(
resolved: PathGet,
dirflags: wasi::__wasi_lookupflags_t,
) -> Result<wasi::__wasi_filestat_t> {
) -> WasiResult<wasi::__wasi_filestat_t> {
let path = resolved.concatenate()?;
let file = File::open(path)?;
host_impl::filestat_from_win(&file)
@@ -488,7 +492,7 @@ pub(crate) fn path_filestat_set_times(
st_atim: wasi::__wasi_timestamp_t,
mut st_mtim: wasi::__wasi_timestamp_t,
fst_flags: wasi::__wasi_fstflags_t,
) -> Result<()> {
) -> WasiResult<()> {
use winx::file::AccessMode;
let path = resolved.concatenate()?;
let file = OpenOptions::new()
@@ -498,7 +502,7 @@ pub(crate) fn path_filestat_set_times(
fd_filestat_set_times_impl(&modifiable_fd, st_atim, st_mtim, fst_flags)
}
pub(crate) fn path_symlink(old_path: &str, resolved: PathGet) -> Result<()> {
pub(crate) fn path_symlink(old_path: &str, resolved: PathGet) -> WasiResult<()> {
use std::os::windows::fs::{symlink_dir, symlink_file};
let old_path = concatenate(&resolved.dirfd().as_os_handle(), Path::new(old_path))?;
@@ -520,14 +524,14 @@ pub(crate) fn path_symlink(old_path: &str, resolved: PathGet) -> Result<()> {
winerror::ERROR_ACCESS_DENIED => {
// does the target exist?
if new_path.exists() {
return Err(Error::EEXIST);
return Err(WasiError::EEXIST);
}
}
winerror::ERROR_INVALID_NAME => {
// does the target without trailing slashes exist?
if let Some(path) = strip_trailing_slashes_and_concatenate(&resolved)? {
if path.exists() {
return Err(Error::EEXIST);
return Err(WasiError::EEXIST);
}
}
}
@@ -538,12 +542,12 @@ pub(crate) fn path_symlink(old_path: &str, resolved: PathGet) -> Result<()> {
}
None => {
log::debug!("Inconvertible OS error: {}", err);
Err(Error::EIO)
Err(WasiError::EIO)
}
}
}
pub(crate) fn path_unlink_file(resolved: PathGet) -> Result<()> {
pub(crate) fn path_unlink_file(resolved: PathGet) -> WasiResult<()> {
use std::fs;
let path = resolved.concatenate()?;
@@ -573,19 +577,19 @@ pub(crate) fn path_unlink_file(resolved: PathGet) -> Result<()> {
}
None => {
log::debug!("Inconvertible OS error: {}", err);
Err(Error::EIO)
Err(WasiError::EIO)
}
}
} else if file_type.is_dir() {
Err(Error::EISDIR)
Err(WasiError::EISDIR)
} else if file_type.is_file() {
fs::remove_file(path).map_err(Into::into)
} else {
Err(Error::EINVAL)
Err(WasiError::EINVAL)
}
}
pub(crate) fn path_remove_directory(resolved: PathGet) -> Result<()> {
pub(crate) fn path_remove_directory(resolved: PathGet) -> WasiResult<()> {
let path = resolved.concatenate()?;
std::fs::remove_dir(&path).map_err(Into::into)
}

View File

@@ -1,7 +1,7 @@
#![allow(non_camel_case_types)]
use crate::fdentry::Descriptor;
use crate::hostcalls_impl::PathGet;
use crate::{wasi, Error, Result};
use crate::wasi::{self, WasiError, WasiResult};
use std::ffi::{OsStr, OsString};
use std::fs::File;
use std::os::windows::ffi::{OsStrExt, OsStringExt};
@@ -9,11 +9,11 @@ use std::path::{Path, PathBuf};
use winapi::shared::winerror;
pub(crate) trait PathGetExt {
fn concatenate(&self) -> Result<PathBuf>;
fn concatenate(&self) -> WasiResult<PathBuf>;
}
impl PathGetExt for PathGet {
fn concatenate(&self) -> Result<PathBuf> {
fn concatenate(&self) -> WasiResult<PathBuf> {
match self.dirfd() {
Descriptor::OsHandle(file) => concatenate(file, Path::new(self.path())),
Descriptor::VirtualFile(_virt) => {
@@ -55,7 +55,7 @@ pub(crate) fn path_open_rights(
(needed_base, needed_inheriting)
}
pub(crate) fn openat(dirfd: &File, path: &str) -> Result<File> {
pub(crate) fn openat(dirfd: &File, path: &str) -> WasiResult<File> {
use std::fs::OpenOptions;
use std::os::windows::fs::OpenOptionsExt;
use winx::file::Flags;
@@ -72,13 +72,13 @@ pub(crate) fn openat(dirfd: &File, path: &str) -> Result<File> {
if let Some(code) = err.raw_os_error() {
log::debug!("openat error={:?}", code);
if code as u32 == winerror::ERROR_INVALID_NAME {
return Err(Error::ENOTDIR);
return Err(WasiError::ENOTDIR);
}
}
Err(err.into())
}
pub(crate) fn readlinkat(dirfd: &File, s_path: &str) -> Result<String> {
pub(crate) fn readlinkat(dirfd: &File, s_path: &str) -> WasiResult<String> {
use winx::file::get_file_path;
let path = concatenate(dirfd, Path::new(s_path))?;
@@ -92,8 +92,8 @@ pub(crate) fn readlinkat(dirfd: &File, s_path: &str) -> Result<String> {
let dir_path = PathBuf::from(strip_extended_prefix(dir_path));
let target_path = target_path
.strip_prefix(dir_path)
.map_err(|_| Error::ENOTCAPABLE)?;
let target_path = target_path.to_str().ok_or(Error::EILSEQ)?;
.map_err(|_| WasiError::ENOTCAPABLE)?;
let target_path = target_path.to_str().ok_or(WasiError::EILSEQ)?;
return Ok(target_path.to_owned());
}
Err(e) => e,
@@ -105,7 +105,7 @@ pub(crate) fn readlinkat(dirfd: &File, s_path: &str) -> Result<String> {
// strip "/" and check if exists
let path = concatenate(dirfd, Path::new(s_path.trim_end_matches('/')))?;
if path.exists() && !path.is_dir() {
return Err(Error::ENOTDIR);
return Err(WasiError::ENOTDIR);
}
}
}
@@ -122,13 +122,13 @@ pub(crate) fn strip_extended_prefix<P: AsRef<OsStr>>(path: P) -> OsString {
}
}
pub(crate) fn concatenate<P: AsRef<Path>>(file: &File, path: P) -> Result<PathBuf> {
pub(crate) fn concatenate<P: AsRef<Path>>(file: &File, path: P) -> WasiResult<PathBuf> {
use winx::file::get_file_path;
// WASI is not able to deal with absolute paths
// so error out if absolute
if path.as_ref().is_absolute() {
return Err(Error::ENOTCAPABLE);
return Err(WasiError::ENOTCAPABLE);
}
let dir_path = get_file_path(file)?;

View File

@@ -5,7 +5,8 @@ use crate::fdentry::Descriptor;
use crate::hostcalls_impl::{ClockEventData, FdEventData};
use crate::memory::*;
use crate::sys::host_impl;
use crate::{error::WasiError, wasi, wasi32, Error, Result};
use crate::wasi::{self, WasiError, WasiResult};
use crate::wasi32;
use cpu_time::{ProcessTime, ThreadTime};
use lazy_static::lazy_static;
use log::{debug, error, trace, warn};
@@ -26,7 +27,7 @@ enum PollState {
Ready,
NotReady, // it's not ready, but we didn't wait
TimedOut, // it's not ready and a timeout has occurred
Error(WasiError), // not using the top-lever Error because it's not Clone
Error(WasiError),
}
enum WaitMode {
@@ -82,7 +83,7 @@ impl StdinPoll {
// Linux returns `POLLIN` in both cases, and we imitate this behavior.
let resp = match std::io::stdin().lock().fill_buf() {
Ok(_) => PollState::Ready,
Err(e) => PollState::Error(Error::from(e).as_wasi_error()),
Err(e) => PollState::Error(WasiError::from(e)),
};
// Notify the requestor about data in stdin. They may have already timed out,
@@ -108,7 +109,9 @@ lazy_static! {
// Timer resolution on Windows is really hard. We may consider exposing the resolution of the respective
// timers as an associated function in the future.
pub(crate) fn clock_res_get(clock_id: wasi::__wasi_clockid_t) -> Result<wasi::__wasi_timestamp_t> {
pub(crate) fn clock_res_get(
clock_id: wasi::__wasi_clockid_t,
) -> WasiResult<wasi::__wasi_timestamp_t> {
Ok(match clock_id {
// This is the best that we can do with std::time::SystemTime.
// Rust uses GetSystemTimeAsFileTime, which is said to have the resolution of
@@ -152,25 +155,28 @@ pub(crate) fn clock_res_get(clock_id: wasi::__wasi_clockid_t) -> Result<wasi::__
// The best we can do is to hardcode the value from the docs.
// https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-getthreadtimes
wasi::__WASI_CLOCKID_THREAD_CPUTIME_ID => 100,
_ => return Err(Error::EINVAL),
_ => return Err(WasiError::EINVAL),
})
}
pub(crate) fn clock_time_get(clock_id: wasi::__wasi_clockid_t) -> Result<wasi::__wasi_timestamp_t> {
pub(crate) fn clock_time_get(
clock_id: wasi::__wasi_clockid_t,
) -> WasiResult<wasi::__wasi_timestamp_t> {
let duration = match clock_id {
wasi::__WASI_CLOCKID_REALTIME => get_monotonic_time(),
wasi::__WASI_CLOCKID_MONOTONIC => get_realtime_time()?,
wasi::__WASI_CLOCKID_PROCESS_CPUTIME_ID => get_proc_cputime()?,
wasi::__WASI_CLOCKID_THREAD_CPUTIME_ID => get_thread_cputime()?,
_ => return Err(Error::EINVAL),
_ => return Err(WasiError::EINVAL),
};
duration.as_nanos().try_into().map_err(Into::into)
}
fn make_rw_event(event: &FdEventData, nbytes: Result<u64>) -> wasi::__wasi_event_t {
use crate::error::AsWasiError;
let error = nbytes.as_wasi_error();
let nbytes = nbytes.unwrap_or_default();
fn make_rw_event(event: &FdEventData, nbytes: WasiResult<u64>) -> wasi::__wasi_event_t {
let (nbytes, error) = match nbytes {
Ok(nbytes) => (nbytes, WasiError::ESUCCESS),
Err(e) => (u64::default(), e),
};
wasi::__wasi_event_t {
userdata: event.userdata,
r#type: event.r#type,
@@ -233,7 +239,7 @@ fn handle_rw_event(event: FdEventData, out_events: &mut Vec<wasi::__wasi_event_t
fn handle_error_event(
event: FdEventData,
error: Error,
error: WasiError,
out_events: &mut Vec<wasi::__wasi_event_t>,
) {
let new_event = make_rw_event(&event, Err(error));
@@ -244,7 +250,7 @@ pub(crate) fn poll_oneoff(
timeout: Option<ClockEventData>,
fd_events: Vec<FdEventData>,
events: &mut Vec<wasi::__wasi_event_t>,
) -> Result<()> {
) -> WasiResult<()> {
use std::fs::Metadata;
use std::thread;
@@ -289,7 +295,7 @@ pub(crate) fn poll_oneoff(
let ftype = unsafe { winx::file::get_file_type(os_handle.as_raw_handle()) }?;
if ftype.is_unknown() || ftype.is_char() {
debug!("poll_oneoff: unsupported file type: {:?}", ftype);
handle_error_event(event, Error::ENOTSUP, events);
handle_error_event(event, WasiError::ENOTSUP, events);
} else if ftype.is_disk() {
immediate_events.push(event);
} else if ftype.is_pipe() {
@@ -349,7 +355,7 @@ pub(crate) fn poll_oneoff(
PollState::Ready => handle_rw_event(event, events),
PollState::NotReady => {} // not immediately available, so just ignore
PollState::TimedOut => handle_timeout_event(timeout.unwrap().0, events),
PollState::Error(e) => handle_error_event(event, Error::Wasi(e), events),
PollState::Error(e) => handle_error_event(event, e, events),
}
}
}
@@ -365,7 +371,7 @@ pub(crate) fn poll_oneoff(
}
None => {
error!("Polling only pipes with no timeout not supported on Windows.");
return Err(Error::ENOTSUP);
return Err(WasiError::ENOTSUP);
}
}
}
@@ -383,17 +389,17 @@ fn get_monotonic_time() -> Duration {
START_MONOTONIC.elapsed()
}
fn get_realtime_time() -> Result<Duration> {
fn get_realtime_time() -> WasiResult<Duration> {
SystemTime::now()
.duration_since(UNIX_EPOCH)
.map_err(|_| Error::EFAULT)
.map_err(|_| WasiError::EFAULT)
}
fn get_proc_cputime() -> Result<Duration> {
fn get_proc_cputime() -> WasiResult<Duration> {
Ok(ProcessTime::try_now()?.as_duration())
}
fn get_thread_cputime() -> Result<Duration> {
fn get_thread_cputime() -> WasiResult<Duration> {
Ok(ThreadTime::try_now()?.as_duration())
}

View File

@@ -2,16 +2,12 @@ pub(crate) mod fdentry_impl;
pub(crate) mod host_impl;
pub(crate) mod hostcalls_impl;
use crate::Result;
use std::fs::{File, OpenOptions};
use std::io::Result;
use std::path::Path;
pub(crate) fn dev_null() -> Result<File> {
OpenOptions::new()
.read(true)
.write(true)
.open("NUL")
.map_err(Into::into)
OpenOptions::new().read(true).write(true).open("NUL")
}
pub fn preopen_dir<P: AsRef<Path>>(path: P) -> Result<File> {
@@ -28,5 +24,4 @@ pub fn preopen_dir<P: AsRef<Path>>(path: P) -> Result<File> {
.read(true)
.attributes(FILE_FLAG_BACKUP_SEMANTICS)
.open(path)
.map_err(Into::into)
}

View File

@@ -1,6 +1,7 @@
use crate::host::Dirent;
use crate::host::FileType;
use crate::{wasi, wasi32, Error, Result};
use crate::wasi::{self, WasiError, WasiResult};
use crate::wasi32;
use filetime::FileTime;
use log::trace;
use std::cell::RefCell;
@@ -44,8 +45,8 @@ pub(crate) trait VirtualFile: MovableFile {
fn try_clone(&self) -> io::Result<Box<dyn VirtualFile>>;
fn readlinkat(&self, _path: &Path) -> Result<String> {
Err(Error::EACCES)
fn readlinkat(&self, _path: &Path) -> WasiResult<String> {
Err(WasiError::EACCES)
}
fn openat(
@@ -55,51 +56,51 @@ pub(crate) trait VirtualFile: MovableFile {
_write: bool,
_oflags: wasi::__wasi_oflags_t,
_fd_flags: wasi::__wasi_fdflags_t,
) -> Result<Box<dyn VirtualFile>> {
Err(Error::EACCES)
) -> WasiResult<Box<dyn VirtualFile>> {
Err(WasiError::EACCES)
}
fn remove_directory(&self, _path: &str) -> Result<()> {
Err(Error::EACCES)
fn remove_directory(&self, _path: &str) -> WasiResult<()> {
Err(WasiError::EACCES)
}
fn unlink_file(&self, _path: &str) -> Result<()> {
Err(Error::EACCES)
fn unlink_file(&self, _path: &str) -> WasiResult<()> {
Err(WasiError::EACCES)
}
fn datasync(&self) -> Result<()> {
Err(Error::EINVAL)
fn datasync(&self) -> WasiResult<()> {
Err(WasiError::EINVAL)
}
fn sync(&self) -> Result<()> {
fn sync(&self) -> WasiResult<()> {
Ok(())
}
fn create_directory(&self, _path: &Path) -> Result<()> {
Err(Error::EACCES)
fn create_directory(&self, _path: &Path) -> WasiResult<()> {
Err(WasiError::EACCES)
}
fn readdir(
&self,
_cookie: wasi::__wasi_dircookie_t,
) -> Result<Box<dyn Iterator<Item = Result<Dirent>>>> {
Err(Error::EBADF)
) -> WasiResult<Box<dyn Iterator<Item = WasiResult<Dirent>>>> {
Err(WasiError::EBADF)
}
fn write_vectored(&mut self, _iovs: &[io::IoSlice]) -> Result<usize> {
Err(Error::EBADF)
fn write_vectored(&mut self, _iovs: &[io::IoSlice]) -> WasiResult<usize> {
Err(WasiError::EBADF)
}
fn pread(&self, _buf: &mut [u8], _offset: u64) -> Result<usize> {
Err(Error::EBADF)
fn pread(&self, _buf: &mut [u8], _offset: u64) -> WasiResult<usize> {
Err(WasiError::EBADF)
}
fn pwrite(&self, _buf: &mut [u8], _offset: u64) -> Result<usize> {
Err(Error::EBADF)
fn pwrite(&self, _buf: &mut [u8], _offset: u64) -> WasiResult<usize> {
Err(WasiError::EBADF)
}
fn seek(&mut self, _offset: SeekFrom) -> Result<u64> {
Err(Error::EBADF)
fn seek(&mut self, _offset: SeekFrom) -> WasiResult<u64> {
Err(WasiError::EBADF)
}
fn advise(
@@ -107,36 +108,40 @@ pub(crate) trait VirtualFile: MovableFile {
_advice: wasi::__wasi_advice_t,
_offset: wasi::__wasi_filesize_t,
_len: wasi::__wasi_filesize_t,
) -> Result<()> {
Err(Error::EBADF)
) -> WasiResult<()> {
Err(WasiError::EBADF)
}
fn allocate(
&self,
_offset: wasi::__wasi_filesize_t,
_len: wasi::__wasi_filesize_t,
) -> Result<()> {
Err(Error::EBADF)
) -> WasiResult<()> {
Err(WasiError::EBADF)
}
fn filestat_get(&self) -> Result<wasi::__wasi_filestat_t> {
Err(Error::EBADF)
fn filestat_get(&self) -> WasiResult<wasi::__wasi_filestat_t> {
Err(WasiError::EBADF)
}
fn filestat_set_times(&self, _atim: Option<FileTime>, _mtim: Option<FileTime>) -> Result<()> {
Err(Error::EBADF)
fn filestat_set_times(
&self,
_atim: Option<FileTime>,
_mtim: Option<FileTime>,
) -> WasiResult<()> {
Err(WasiError::EBADF)
}
fn filestat_set_size(&self, _st_size: wasi::__wasi_filesize_t) -> Result<()> {
Err(Error::EBADF)
fn filestat_set_size(&self, _st_size: wasi::__wasi_filesize_t) -> WasiResult<()> {
Err(WasiError::EBADF)
}
fn fdstat_set_flags(&mut self, _fdflags: wasi::__wasi_fdflags_t) -> Result<()> {
Err(Error::EBADF)
fn fdstat_set_flags(&mut self, _fdflags: wasi::__wasi_fdflags_t) -> WasiResult<()> {
Err(WasiError::EBADF)
}
fn read_vectored(&mut self, _iovs: &mut [io::IoSliceMut]) -> Result<usize> {
Err(Error::EBADF)
fn read_vectored(&mut self, _iovs: &mut [io::IoSliceMut]) -> WasiResult<usize> {
Err(WasiError::EBADF)
}
fn get_file_type(&self) -> wasi::__wasi_filetype_t;
@@ -157,23 +162,30 @@ pub trait FileContents {
/// The current number of bytes this `FileContents` describes.
fn size(&self) -> wasi::__wasi_filesize_t;
/// Resize to hold `new_size` number of bytes, or error if this is not possible.
fn resize(&mut self, new_size: wasi::__wasi_filesize_t) -> Result<()>;
fn resize(&mut self, new_size: wasi::__wasi_filesize_t) -> WasiResult<()>;
/// Write a list of `IoSlice` starting at `offset`. `offset` plus the total size of all `iovs`
/// is guaranteed to not exceed `max_size`. Implementations must not indicate more bytes have
/// been written than can be held by `iovs`.
fn pwritev(&mut self, iovs: &[io::IoSlice], offset: wasi::__wasi_filesize_t) -> Result<usize>;
fn pwritev(
&mut self,
iovs: &[io::IoSlice],
offset: wasi::__wasi_filesize_t,
) -> WasiResult<usize>;
/// Read from the file from `offset`, filling a list of `IoSlice`. The returend size must not
/// be more than the capactiy of `iovs`, and must not exceed the limit reported by
/// `self.max_size()`.
fn preadv(&self, iovs: &mut [io::IoSliceMut], offset: wasi::__wasi_filesize_t)
-> Result<usize>;
fn preadv(
&self,
iovs: &mut [io::IoSliceMut],
offset: wasi::__wasi_filesize_t,
) -> WasiResult<usize>;
/// Write contents from `buf` to this file starting at `offset`. `offset` plus the length of
/// `buf` is guaranteed to not exceed `max_size`. Implementations must not indicate more bytes
/// have been written than the size of `buf`.
fn pwrite(&mut self, buf: &[u8], offset: wasi::__wasi_filesize_t) -> Result<usize>;
fn pwrite(&mut self, buf: &[u8], offset: wasi::__wasi_filesize_t) -> WasiResult<usize>;
/// Read from the file at `offset`, filling `buf`. The returned size must not be more than the
/// capacity of `buf`, and `offset` plus the returned size must not exceed `self.max_size()`.
fn pread(&self, buf: &mut [u8], offset: wasi::__wasi_filesize_t) -> Result<usize>;
fn pread(&self, buf: &mut [u8], offset: wasi::__wasi_filesize_t) -> WasiResult<usize>;
}
impl FileContents for VecFileContents {
@@ -185,8 +197,8 @@ impl FileContents for VecFileContents {
self.content.len() as wasi::__wasi_filesize_t
}
fn resize(&mut self, new_size: wasi::__wasi_filesize_t) -> Result<()> {
let new_size: usize = new_size.try_into().map_err(|_| Error::EINVAL)?;
fn resize(&mut self, new_size: wasi::__wasi_filesize_t) -> WasiResult<()> {
let new_size: usize = new_size.try_into().map_err(|_| WasiError::EINVAL)?;
self.content.resize(new_size, 0);
Ok(())
}
@@ -195,7 +207,7 @@ impl FileContents for VecFileContents {
&self,
iovs: &mut [io::IoSliceMut],
offset: wasi::__wasi_filesize_t,
) -> Result<usize> {
) -> WasiResult<usize> {
let mut read_total = 0usize;
for iov in iovs.iter_mut() {
let read = self.pread(iov, offset)?;
@@ -204,7 +216,11 @@ impl FileContents for VecFileContents {
Ok(read_total)
}
fn pwritev(&mut self, iovs: &[io::IoSlice], offset: wasi::__wasi_filesize_t) -> Result<usize> {
fn pwritev(
&mut self,
iovs: &[io::IoSlice],
offset: wasi::__wasi_filesize_t,
) -> WasiResult<usize> {
let mut write_total = 0usize;
for iov in iovs.iter() {
let written = self.pwrite(iov, offset)?;
@@ -213,9 +229,9 @@ impl FileContents for VecFileContents {
Ok(write_total)
}
fn pread(&self, buf: &mut [u8], offset: wasi::__wasi_filesize_t) -> Result<usize> {
fn pread(&self, buf: &mut [u8], offset: wasi::__wasi_filesize_t) -> WasiResult<usize> {
trace!(" | pread(buf.len={}, offset={})", buf.len(), offset);
let offset: usize = offset.try_into().map_err(|_| Error::EINVAL)?;
let offset: usize = offset.try_into().map_err(|_| WasiError::EINVAL)?;
let data_remaining = self.content.len().saturating_sub(offset);
@@ -228,10 +244,10 @@ impl FileContents for VecFileContents {
res
}
fn pwrite(&mut self, buf: &[u8], offset: wasi::__wasi_filesize_t) -> Result<usize> {
let offset: usize = offset.try_into().map_err(|_| Error::EINVAL)?;
fn pwrite(&mut self, buf: &[u8], offset: wasi::__wasi_filesize_t) -> WasiResult<usize> {
let offset: usize = offset.try_into().map_err(|_| WasiError::EINVAL)?;
let write_end = offset.checked_add(buf.len()).ok_or(Error::EFBIG)?;
let write_end = offset.checked_add(buf.len()).ok_or(WasiError::EFBIG)?;
if write_end > self.content.len() {
self.content.resize(write_end, 0);
@@ -305,9 +321,9 @@ impl VirtualFile for InMemoryFile {
}))
}
fn readlinkat(&self, _path: &Path) -> Result<String> {
fn readlinkat(&self, _path: &Path) -> WasiResult<String> {
// no symlink support, so always say it's invalid.
Err(Error::ENOTDIR)
Err(WasiError::ENOTDIR)
}
fn openat(
@@ -317,7 +333,7 @@ impl VirtualFile for InMemoryFile {
write: bool,
oflags: wasi::__wasi_oflags_t,
fd_flags: wasi::__wasi_fdflags_t,
) -> Result<Box<dyn VirtualFile>> {
) -> WasiResult<Box<dyn VirtualFile>> {
log::trace!(
"InMemoryFile::openat(path={:?}, read={:?}, write={:?}, oflags={:?}, fd_flags={:?}",
path,
@@ -333,7 +349,7 @@ impl VirtualFile for InMemoryFile {
path
);
log::trace!(" return ENOTDIR");
return Err(Error::ENOTDIR);
return Err(WasiError::ENOTDIR);
}
if path == Path::new(".") {
@@ -344,24 +360,24 @@ impl VirtualFile for InMemoryFile {
None => self.try_clone().map_err(Into::into),
}
} else {
Err(Error::EACCES)
Err(WasiError::EACCES)
}
}
fn remove_directory(&self, _path: &str) -> Result<()> {
Err(Error::ENOTDIR)
fn remove_directory(&self, _path: &str) -> WasiResult<()> {
Err(WasiError::ENOTDIR)
}
fn unlink_file(&self, _path: &str) -> Result<()> {
Err(Error::ENOTDIR)
fn unlink_file(&self, _path: &str) -> WasiResult<()> {
Err(WasiError::ENOTDIR)
}
fn fdstat_set_flags(&mut self, fdflags: wasi::__wasi_fdflags_t) -> Result<()> {
fn fdstat_set_flags(&mut self, fdflags: wasi::__wasi_fdflags_t) -> WasiResult<()> {
self.fd_flags = fdflags;
Ok(())
}
fn write_vectored(&mut self, iovs: &[io::IoSlice]) -> Result<usize> {
fn write_vectored(&mut self, iovs: &[io::IoSlice]) -> WasiResult<usize> {
trace!("write_vectored(iovs={:?})", iovs);
let mut data = self.data.borrow_mut();
@@ -389,10 +405,10 @@ impl VirtualFile for InMemoryFile {
if let Some(end) = write_start.checked_add(max_size as wasi::__wasi_filesize_t) {
if end > data.max_size() {
return Err(Error::EFBIG);
return Err(WasiError::EFBIG);
}
} else {
return Err(Error::EFBIG);
return Err(WasiError::EFBIG);
}
trace!(" | *write_start={:?}", write_start);
@@ -407,43 +423,43 @@ impl VirtualFile for InMemoryFile {
Ok(written)
}
fn read_vectored(&mut self, iovs: &mut [io::IoSliceMut]) -> Result<usize> {
fn read_vectored(&mut self, iovs: &mut [io::IoSliceMut]) -> WasiResult<usize> {
trace!("read_vectored(iovs={:?})", iovs);
trace!(" | *read_start={:?}", self.cursor);
self.data.borrow_mut().preadv(iovs, self.cursor)
}
fn pread(&self, buf: &mut [u8], offset: wasi::__wasi_filesize_t) -> Result<usize> {
fn pread(&self, buf: &mut [u8], offset: wasi::__wasi_filesize_t) -> WasiResult<usize> {
self.data.borrow_mut().pread(buf, offset)
}
fn pwrite(&self, buf: &mut [u8], offset: wasi::__wasi_filesize_t) -> Result<usize> {
fn pwrite(&self, buf: &mut [u8], offset: wasi::__wasi_filesize_t) -> WasiResult<usize> {
self.data.borrow_mut().pwrite(buf, offset)
}
fn seek(&mut self, offset: SeekFrom) -> Result<wasi::__wasi_filesize_t> {
fn seek(&mut self, offset: SeekFrom) -> WasiResult<wasi::__wasi_filesize_t> {
let content_len = self.data.borrow().size();
match offset {
SeekFrom::Current(offset) => {
let new_cursor = if offset < 0 {
self.cursor
.checked_sub(offset.wrapping_neg() as u64)
.ok_or(Error::EINVAL)?
.ok_or(WasiError::EINVAL)?
} else {
self.cursor
.checked_add(offset as u64)
.ok_or(Error::EINVAL)?
.ok_or(WasiError::EINVAL)?
};
self.cursor = std::cmp::min(content_len, new_cursor);
}
SeekFrom::End(offset) => {
// A negative offset from the end would be past the end of the file,
let offset: u64 = offset.try_into().map_err(|_| Error::EINVAL)?;
let offset: u64 = offset.try_into().map_err(|_| WasiError::EINVAL)?;
self.cursor = content_len.saturating_sub(offset);
}
SeekFrom::Start(offset) => {
// A negative offset from the end would be before the start of the file.
let offset: u64 = offset.try_into().map_err(|_| Error::EINVAL)?;
let offset: u64 = offset.try_into().map_err(|_| WasiError::EINVAL)?;
self.cursor = std::cmp::min(content_len, offset);
}
}
@@ -456,7 +472,7 @@ impl VirtualFile for InMemoryFile {
advice: wasi::__wasi_advice_t,
_offset: wasi::__wasi_filesize_t,
_len: wasi::__wasi_filesize_t,
) -> Result<()> {
) -> WasiResult<()> {
// we'll just ignore advice for now, unless it's totally invalid
match advice {
wasi::__WASI_ADVICE_DONTNEED
@@ -465,7 +481,7 @@ impl VirtualFile for InMemoryFile {
| wasi::__WASI_ADVICE_NOREUSE
| wasi::__WASI_ADVICE_RANDOM
| wasi::__WASI_ADVICE_NORMAL => Ok(()),
_ => Err(Error::EINVAL),
_ => Err(WasiError::EINVAL),
}
}
@@ -473,12 +489,12 @@ impl VirtualFile for InMemoryFile {
&self,
offset: wasi::__wasi_filesize_t,
len: wasi::__wasi_filesize_t,
) -> Result<()> {
let new_limit = offset.checked_add(len).ok_or(Error::EFBIG)?;
) -> WasiResult<()> {
let new_limit = offset.checked_add(len).ok_or(WasiError::EFBIG)?;
let mut data = self.data.borrow_mut();
if new_limit > data.max_size() {
return Err(Error::EFBIG);
return Err(WasiError::EFBIG);
}
if new_limit > data.size() {
@@ -488,15 +504,15 @@ impl VirtualFile for InMemoryFile {
Ok(())
}
fn filestat_set_size(&self, st_size: wasi::__wasi_filesize_t) -> Result<()> {
fn filestat_set_size(&self, st_size: wasi::__wasi_filesize_t) -> WasiResult<()> {
let mut data = self.data.borrow_mut();
if st_size > data.max_size() {
return Err(Error::EFBIG);
return Err(WasiError::EFBIG);
}
data.resize(st_size)
}
fn filestat_get(&self) -> Result<wasi::__wasi_filestat_t> {
fn filestat_get(&self) -> WasiResult<wasi::__wasi_filestat_t> {
let stat = wasi::__wasi_filestat_t {
dev: 0,
ino: 0,
@@ -594,9 +610,9 @@ impl VirtualFile for VirtualDir {
}))
}
fn readlinkat(&self, _path: &Path) -> Result<String> {
fn readlinkat(&self, _path: &Path) -> WasiResult<String> {
// Files are not symbolic links or directories, faithfully report ENOTDIR.
Err(Error::ENOTDIR)
Err(WasiError::ENOTDIR)
}
fn openat(
@@ -606,7 +622,7 @@ impl VirtualFile for VirtualDir {
write: bool,
oflags: wasi::__wasi_oflags_t,
fd_flags: wasi::__wasi_fdflags_t,
) -> Result<Box<dyn VirtualFile>> {
) -> WasiResult<Box<dyn VirtualFile>> {
log::trace!(
"VirtualDir::openat(path={:?}, read={:?}, write={:?}, oflags={:?}, fd_flags={:?}",
path,
@@ -631,7 +647,7 @@ impl VirtualFile for VirtualDir {
// openat may have been passed a path with a trailing slash, but files are mapped to paths
// with trailing slashes normalized out.
let file_name = path.file_name().ok_or(Error::EINVAL)?;
let file_name = path.file_name().ok_or(WasiError::EINVAL)?;
let mut entries = self.entries.borrow_mut();
let entry_count = entries.len();
match entries.entry(Path::new(file_name).to_path_buf()) {
@@ -640,7 +656,7 @@ impl VirtualFile for VirtualDir {
if (oflags & creat_excl_mask) == creat_excl_mask {
log::trace!("VirtualDir::openat was passed oflags CREAT|EXCL, but the file {:?} exists.", file_name);
log::trace!(" return EEXIST");
return Err(Error::EEXIST);
return Err(WasiError::EEXIST);
}
if (oflags & wasi::__WASI_OFLAGS_DIRECTORY) != 0
@@ -651,7 +667,7 @@ impl VirtualFile for VirtualDir {
file_name
);
log::trace!(" return ENOTDIR");
return Err(Error::ENOTDIR);
return Err(WasiError::ENOTDIR);
}
e.get().try_clone().map_err(Into::into)
@@ -663,7 +679,7 @@ impl VirtualFile for VirtualDir {
// would have with `usize`. The limit is the full `u32` range minus two so we
// can reserve "self" and "parent" cookie values.
if entry_count >= (std::u32::MAX - RESERVED_ENTRY_COUNT) as usize {
return Err(Error::ENOSPC);
return Err(WasiError::ENOSPC);
}
log::trace!(
@@ -676,26 +692,26 @@ impl VirtualFile for VirtualDir {
file.set_parent(Some(self.try_clone().expect("can clone self")));
v.insert(file).try_clone().map_err(Into::into)
} else {
Err(Error::EACCES)
Err(WasiError::EACCES)
}
}
}
}
fn remove_directory(&self, path: &str) -> Result<()> {
fn remove_directory(&self, path: &str) -> WasiResult<()> {
let trimmed_path = path.trim_end_matches('/');
let mut entries = self.entries.borrow_mut();
match entries.entry(Path::new(trimmed_path).to_path_buf()) {
Entry::Occupied(e) => {
// first, does this name a directory?
if e.get().get_file_type() != wasi::__WASI_FILETYPE_DIRECTORY {
return Err(Error::ENOTDIR);
return Err(WasiError::ENOTDIR);
}
// Okay, but is the directory empty?
let iter = e.get().readdir(wasi::__WASI_DIRCOOKIE_START)?;
if iter.skip(RESERVED_ENTRY_COUNT as usize).next().is_some() {
return Err(Error::ENOTEMPTY);
return Err(WasiError::ENOTEMPTY);
}
// Alright, it's an empty directory. We can remove it.
@@ -711,19 +727,19 @@ impl VirtualFile for VirtualDir {
"VirtualDir::remove_directory failed to remove {}, no such entry",
trimmed_path
);
Err(Error::ENOENT)
Err(WasiError::ENOENT)
}
}
}
fn unlink_file(&self, path: &str) -> Result<()> {
fn unlink_file(&self, path: &str) -> WasiResult<()> {
let trimmed_path = path.trim_end_matches('/');
// Special case: we may be unlinking this directory itself if path is `"."`. In that case,
// fail with EISDIR, since this is a directory. Alternatively, we may be unlinking `".."`,
// which is bound the same way, as this is by definition contained in a directory.
if trimmed_path == "." || trimmed_path == ".." {
return Err(Error::EISDIR);
return Err(WasiError::EISDIR);
}
let mut entries = self.entries.borrow_mut();
@@ -731,7 +747,7 @@ impl VirtualFile for VirtualDir {
Entry::Occupied(e) => {
// Directories must be removed through `remove_directory`, not `unlink_file`.
if e.get().get_file_type() == wasi::__WASI_FILETYPE_DIRECTORY {
return Err(Error::EISDIR);
return Err(WasiError::EISDIR);
}
let removed = e.remove_entry();
@@ -746,15 +762,15 @@ impl VirtualFile for VirtualDir {
"VirtualDir::unlink_file failed to remove {}, no such entry",
trimmed_path
);
Err(Error::ENOENT)
Err(WasiError::ENOENT)
}
}
}
fn create_directory(&self, path: &Path) -> Result<()> {
fn create_directory(&self, path: &Path) -> WasiResult<()> {
let mut entries = self.entries.borrow_mut();
match entries.entry(path.to_owned()) {
Entry::Occupied(_) => Err(Error::EEXIST),
Entry::Occupied(_) => Err(WasiError::EEXIST),
Entry::Vacant(v) => {
if self.writable {
let new_dir = Box::new(VirtualDir::new(true));
@@ -762,26 +778,26 @@ impl VirtualFile for VirtualDir {
v.insert(new_dir);
Ok(())
} else {
Err(Error::EACCES)
Err(WasiError::EACCES)
}
}
}
}
fn write_vectored(&mut self, _iovs: &[io::IoSlice]) -> Result<usize> {
Err(Error::EBADF)
fn write_vectored(&mut self, _iovs: &[io::IoSlice]) -> WasiResult<usize> {
Err(WasiError::EBADF)
}
fn readdir(
&self,
cookie: wasi::__wasi_dircookie_t,
) -> Result<Box<dyn Iterator<Item = Result<Dirent>>>> {
) -> WasiResult<Box<dyn Iterator<Item = WasiResult<Dirent>>>> {
struct VirtualDirIter {
start: u32,
entries: Rc<RefCell<HashMap<PathBuf, Box<dyn VirtualFile>>>>,
}
impl Iterator for VirtualDirIter {
type Item = Result<Dirent>;
type Item = WasiResult<Dirent>;
fn next(&mut self) -> Option<Self::Item> {
log::trace!("VirtualDirIter::next continuing from {}", self.start);
@@ -850,7 +866,7 @@ impl VirtualFile for VirtualDir {
}))
}
fn filestat_get(&self) -> Result<wasi::__wasi_filestat_t> {
fn filestat_get(&self) -> WasiResult<wasi::__wasi_filestat_t> {
let stat = wasi::__wasi_filestat_t {
dev: 0,
ino: 0,

View File

@@ -10,6 +10,115 @@ use wig::witx_wasi_types;
witx_wasi_types!("snapshot" "wasi_snapshot_preview1");
pub type WasiResult<T> = Result<T, WasiError>;
#[derive(Clone, Copy, Debug, thiserror::Error, Eq, PartialEq)]
#[repr(u16)]
#[error("{:?} ({})", self, strerror(*self as __wasi_errno_t))]
pub enum WasiError {
ESUCCESS = __WASI_ERRNO_SUCCESS,
E2BIG = __WASI_ERRNO_2BIG,
EACCES = __WASI_ERRNO_ACCES,
EADDRINUSE = __WASI_ERRNO_ADDRINUSE,
EADDRNOTAVAIL = __WASI_ERRNO_ADDRNOTAVAIL,
EAFNOSUPPORT = __WASI_ERRNO_AFNOSUPPORT,
EAGAIN = __WASI_ERRNO_AGAIN,
EALREADY = __WASI_ERRNO_ALREADY,
EBADF = __WASI_ERRNO_BADF,
EBADMSG = __WASI_ERRNO_BADMSG,
EBUSY = __WASI_ERRNO_BUSY,
ECANCELED = __WASI_ERRNO_CANCELED,
ECHILD = __WASI_ERRNO_CHILD,
ECONNABORTED = __WASI_ERRNO_CONNABORTED,
ECONNREFUSED = __WASI_ERRNO_CONNREFUSED,
ECONNRESET = __WASI_ERRNO_CONNRESET,
EDEADLK = __WASI_ERRNO_DEADLK,
EDESTADDRREQ = __WASI_ERRNO_DESTADDRREQ,
EDOM = __WASI_ERRNO_DOM,
EDQUOT = __WASI_ERRNO_DQUOT,
EEXIST = __WASI_ERRNO_EXIST,
EFAULT = __WASI_ERRNO_FAULT,
EFBIG = __WASI_ERRNO_FBIG,
EHOSTUNREACH = __WASI_ERRNO_HOSTUNREACH,
EIDRM = __WASI_ERRNO_IDRM,
EILSEQ = __WASI_ERRNO_ILSEQ,
EINPROGRESS = __WASI_ERRNO_INPROGRESS,
EINTR = __WASI_ERRNO_INTR,
EINVAL = __WASI_ERRNO_INVAL,
EIO = __WASI_ERRNO_IO,
EISCONN = __WASI_ERRNO_ISCONN,
EISDIR = __WASI_ERRNO_ISDIR,
ELOOP = __WASI_ERRNO_LOOP,
EMFILE = __WASI_ERRNO_MFILE,
EMLINK = __WASI_ERRNO_MLINK,
EMSGSIZE = __WASI_ERRNO_MSGSIZE,
EMULTIHOP = __WASI_ERRNO_MULTIHOP,
ENAMETOOLONG = __WASI_ERRNO_NAMETOOLONG,
ENETDOWN = __WASI_ERRNO_NETDOWN,
ENETRESET = __WASI_ERRNO_NETRESET,
ENETUNREACH = __WASI_ERRNO_NETUNREACH,
ENFILE = __WASI_ERRNO_NFILE,
ENOBUFS = __WASI_ERRNO_NOBUFS,
ENODEV = __WASI_ERRNO_NODEV,
ENOENT = __WASI_ERRNO_NOENT,
ENOEXEC = __WASI_ERRNO_NOEXEC,
ENOLCK = __WASI_ERRNO_NOLCK,
ENOLINK = __WASI_ERRNO_NOLINK,
ENOMEM = __WASI_ERRNO_NOMEM,
ENOMSG = __WASI_ERRNO_NOMSG,
ENOPROTOOPT = __WASI_ERRNO_NOPROTOOPT,
ENOSPC = __WASI_ERRNO_NOSPC,
ENOSYS = __WASI_ERRNO_NOSYS,
ENOTCONN = __WASI_ERRNO_NOTCONN,
ENOTDIR = __WASI_ERRNO_NOTDIR,
ENOTEMPTY = __WASI_ERRNO_NOTEMPTY,
ENOTRECOVERABLE = __WASI_ERRNO_NOTRECOVERABLE,
ENOTSOCK = __WASI_ERRNO_NOTSOCK,
ENOTSUP = __WASI_ERRNO_NOTSUP,
ENOTTY = __WASI_ERRNO_NOTTY,
ENXIO = __WASI_ERRNO_NXIO,
EOVERFLOW = __WASI_ERRNO_OVERFLOW,
EOWNERDEAD = __WASI_ERRNO_OWNERDEAD,
EPERM = __WASI_ERRNO_PERM,
EPIPE = __WASI_ERRNO_PIPE,
EPROTO = __WASI_ERRNO_PROTO,
EPROTONOSUPPORT = __WASI_ERRNO_PROTONOSUPPORT,
EPROTOTYPE = __WASI_ERRNO_PROTOTYPE,
ERANGE = __WASI_ERRNO_RANGE,
EROFS = __WASI_ERRNO_ROFS,
ESPIPE = __WASI_ERRNO_SPIPE,
ESRCH = __WASI_ERRNO_SRCH,
ESTALE = __WASI_ERRNO_STALE,
ETIMEDOUT = __WASI_ERRNO_TIMEDOUT,
ETXTBSY = __WASI_ERRNO_TXTBSY,
EXDEV = __WASI_ERRNO_XDEV,
ENOTCAPABLE = __WASI_ERRNO_NOTCAPABLE,
}
impl WasiError {
pub fn as_raw_errno(self) -> __wasi_errno_t {
self as __wasi_errno_t
}
}
impl From<std::convert::Infallible> for WasiError {
fn from(_err: std::convert::Infallible) -> Self {
unreachable!()
}
}
impl From<std::num::TryFromIntError> for WasiError {
fn from(_err: std::num::TryFromIntError) -> Self {
Self::EOVERFLOW
}
}
impl From<std::str::Utf8Error> for WasiError {
fn from(_err: std::str::Utf8Error) -> Self {
Self::EILSEQ
}
}
pub(crate) const RIGHTS_ALL: __wasi_rights_t = __WASI_RIGHTS_FD_DATASYNC
| __WASI_RIGHTS_FD_READ
| __WASI_RIGHTS_FD_SEEK

View File

@@ -92,8 +92,7 @@ fn generate_wrappers(func: &witx::InterfaceFunc, old: bool) -> TokenStream {
quote! {
let ret = #call
.err()
.unwrap_or(super::Error::ESUCCESS)
.as_wasi_error();
.unwrap_or(super::wasi::WasiError::ESUCCESS);
log::trace!(" | errno={}", ret);
ret.as_raw_errno()
}