[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,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,92 +3,101 @@
|
||||
#![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 {
|
||||
libc::EPERM => Self::EPERM,
|
||||
libc::ENOENT => Self::ENOENT,
|
||||
libc::ESRCH => Self::ESRCH,
|
||||
libc::EINTR => Self::EINTR,
|
||||
libc::EIO => Self::EIO,
|
||||
libc::ENXIO => Self::ENXIO,
|
||||
libc::E2BIG => Self::E2BIG,
|
||||
libc::ENOEXEC => Self::ENOEXEC,
|
||||
libc::EBADF => Self::EBADF,
|
||||
libc::ECHILD => Self::ECHILD,
|
||||
libc::EAGAIN => Self::EAGAIN,
|
||||
libc::ENOMEM => Self::ENOMEM,
|
||||
libc::EACCES => Self::EACCES,
|
||||
libc::EFAULT => Self::EFAULT,
|
||||
libc::EBUSY => Self::EBUSY,
|
||||
libc::EEXIST => Self::EEXIST,
|
||||
libc::EXDEV => Self::EXDEV,
|
||||
libc::ENODEV => Self::ENODEV,
|
||||
libc::ENOTDIR => Self::ENOTDIR,
|
||||
libc::EISDIR => Self::EISDIR,
|
||||
libc::EINVAL => Self::EINVAL,
|
||||
libc::ENFILE => Self::ENFILE,
|
||||
libc::EMFILE => Self::EMFILE,
|
||||
libc::ENOTTY => Self::ENOTTY,
|
||||
libc::ETXTBSY => Self::ETXTBSY,
|
||||
libc::EFBIG => Self::EFBIG,
|
||||
libc::ENOSPC => Self::ENOSPC,
|
||||
libc::ESPIPE => Self::ESPIPE,
|
||||
libc::EROFS => Self::EROFS,
|
||||
libc::EMLINK => Self::EMLINK,
|
||||
libc::EPIPE => Self::EPIPE,
|
||||
libc::EDOM => Self::EDOM,
|
||||
libc::ERANGE => Self::ERANGE,
|
||||
libc::EDEADLK => Self::EDEADLK,
|
||||
libc::ENAMETOOLONG => Self::ENAMETOOLONG,
|
||||
libc::ENOLCK => Self::ENOLCK,
|
||||
libc::ENOSYS => Self::ENOSYS,
|
||||
libc::ENOTEMPTY => Self::ENOTEMPTY,
|
||||
libc::ELOOP => Self::ELOOP,
|
||||
libc::ENOMSG => Self::ENOMSG,
|
||||
libc::EIDRM => Self::EIDRM,
|
||||
libc::ENOLINK => Self::ENOLINK,
|
||||
libc::EPROTO => Self::EPROTO,
|
||||
libc::EMULTIHOP => Self::EMULTIHOP,
|
||||
libc::EBADMSG => Self::EBADMSG,
|
||||
libc::EOVERFLOW => Self::EOVERFLOW,
|
||||
libc::EILSEQ => Self::EILSEQ,
|
||||
libc::ENOTSOCK => Self::ENOTSOCK,
|
||||
libc::EDESTADDRREQ => Self::EDESTADDRREQ,
|
||||
libc::EMSGSIZE => Self::EMSGSIZE,
|
||||
libc::EPROTOTYPE => Self::EPROTOTYPE,
|
||||
libc::ENOPROTOOPT => Self::ENOPROTOOPT,
|
||||
libc::EPROTONOSUPPORT => Self::EPROTONOSUPPORT,
|
||||
libc::EAFNOSUPPORT => Self::EAFNOSUPPORT,
|
||||
libc::EADDRINUSE => Self::EADDRINUSE,
|
||||
libc::EADDRNOTAVAIL => Self::EADDRNOTAVAIL,
|
||||
libc::ENETDOWN => Self::ENETDOWN,
|
||||
libc::ENETUNREACH => Self::ENETUNREACH,
|
||||
libc::ENETRESET => Self::ENETRESET,
|
||||
libc::ECONNABORTED => Self::ECONNABORTED,
|
||||
libc::ECONNRESET => Self::ECONNRESET,
|
||||
libc::ENOBUFS => Self::ENOBUFS,
|
||||
libc::EISCONN => Self::EISCONN,
|
||||
libc::ENOTCONN => Self::ENOTCONN,
|
||||
libc::ETIMEDOUT => Self::ETIMEDOUT,
|
||||
libc::ECONNREFUSED => Self::ECONNREFUSED,
|
||||
libc::EHOSTUNREACH => Self::EHOSTUNREACH,
|
||||
libc::EALREADY => Self::EALREADY,
|
||||
libc::EINPROGRESS => Self::EINPROGRESS,
|
||||
libc::ESTALE => Self::ESTALE,
|
||||
libc::EDQUOT => Self::EDQUOT,
|
||||
libc::ECANCELED => Self::ECANCELED,
|
||||
libc::EOWNERDEAD => Self::EOWNERDEAD,
|
||||
libc::ENOTRECOVERABLE => Self::ENOTRECOVERABLE,
|
||||
x => {
|
||||
log::debug!("Unknown errno value: {}", x);
|
||||
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,
|
||||
libc::EINTR => Self::EINTR,
|
||||
libc::EIO => Self::EIO,
|
||||
libc::ENXIO => Self::ENXIO,
|
||||
libc::E2BIG => Self::E2BIG,
|
||||
libc::ENOEXEC => Self::ENOEXEC,
|
||||
libc::EBADF => Self::EBADF,
|
||||
libc::ECHILD => Self::ECHILD,
|
||||
libc::EAGAIN => Self::EAGAIN,
|
||||
libc::ENOMEM => Self::ENOMEM,
|
||||
libc::EACCES => Self::EACCES,
|
||||
libc::EFAULT => Self::EFAULT,
|
||||
libc::EBUSY => Self::EBUSY,
|
||||
libc::EEXIST => Self::EEXIST,
|
||||
libc::EXDEV => Self::EXDEV,
|
||||
libc::ENODEV => Self::ENODEV,
|
||||
libc::ENOTDIR => Self::ENOTDIR,
|
||||
libc::EISDIR => Self::EISDIR,
|
||||
libc::EINVAL => Self::EINVAL,
|
||||
libc::ENFILE => Self::ENFILE,
|
||||
libc::EMFILE => Self::EMFILE,
|
||||
libc::ENOTTY => Self::ENOTTY,
|
||||
libc::ETXTBSY => Self::ETXTBSY,
|
||||
libc::EFBIG => Self::EFBIG,
|
||||
libc::ENOSPC => Self::ENOSPC,
|
||||
libc::ESPIPE => Self::ESPIPE,
|
||||
libc::EROFS => Self::EROFS,
|
||||
libc::EMLINK => Self::EMLINK,
|
||||
libc::EPIPE => Self::EPIPE,
|
||||
libc::EDOM => Self::EDOM,
|
||||
libc::ERANGE => Self::ERANGE,
|
||||
libc::EDEADLK => Self::EDEADLK,
|
||||
libc::ENAMETOOLONG => Self::ENAMETOOLONG,
|
||||
libc::ENOLCK => Self::ENOLCK,
|
||||
libc::ENOSYS => Self::ENOSYS,
|
||||
libc::ENOTEMPTY => Self::ENOTEMPTY,
|
||||
libc::ELOOP => Self::ELOOP,
|
||||
libc::ENOMSG => Self::ENOMSG,
|
||||
libc::EIDRM => Self::EIDRM,
|
||||
libc::ENOLINK => Self::ENOLINK,
|
||||
libc::EPROTO => Self::EPROTO,
|
||||
libc::EMULTIHOP => Self::EMULTIHOP,
|
||||
libc::EBADMSG => Self::EBADMSG,
|
||||
libc::EOVERFLOW => Self::EOVERFLOW,
|
||||
libc::EILSEQ => Self::EILSEQ,
|
||||
libc::ENOTSOCK => Self::ENOTSOCK,
|
||||
libc::EDESTADDRREQ => Self::EDESTADDRREQ,
|
||||
libc::EMSGSIZE => Self::EMSGSIZE,
|
||||
libc::EPROTOTYPE => Self::EPROTOTYPE,
|
||||
libc::ENOPROTOOPT => Self::ENOPROTOOPT,
|
||||
libc::EPROTONOSUPPORT => Self::EPROTONOSUPPORT,
|
||||
libc::EAFNOSUPPORT => Self::EAFNOSUPPORT,
|
||||
libc::EADDRINUSE => Self::EADDRINUSE,
|
||||
libc::EADDRNOTAVAIL => Self::EADDRNOTAVAIL,
|
||||
libc::ENETDOWN => Self::ENETDOWN,
|
||||
libc::ENETUNREACH => Self::ENETUNREACH,
|
||||
libc::ENETRESET => Self::ENETRESET,
|
||||
libc::ECONNABORTED => Self::ECONNABORTED,
|
||||
libc::ECONNRESET => Self::ECONNRESET,
|
||||
libc::ENOBUFS => Self::ENOBUFS,
|
||||
libc::EISCONN => Self::EISCONN,
|
||||
libc::ENOTCONN => Self::ENOTCONN,
|
||||
libc::ETIMEDOUT => Self::ETIMEDOUT,
|
||||
libc::ECONNREFUSED => Self::ECONNREFUSED,
|
||||
libc::EHOSTUNREACH => Self::EHOSTUNREACH,
|
||||
libc::EALREADY => Self::EALREADY,
|
||||
libc::EINPROGRESS => Self::EINPROGRESS,
|
||||
libc::ESTALE => Self::ESTALE,
|
||||
libc::EDQUOT => Self::EDQUOT,
|
||||
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)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user