[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:
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
@@ -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(())
|
||||
}
|
||||
|
||||
@@ -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 {})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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()?;
|
||||
|
||||
@@ -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("."),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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(())
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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("."),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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>;
|
||||
|
||||
@@ -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())
|
||||
}
|
||||
|
||||
@@ -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 => {
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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};
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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)?;
|
||||
|
||||
@@ -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())
|
||||
}
|
||||
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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 => {
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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()?;
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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)?;
|
||||
|
||||
@@ -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())
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user