[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::fdentry::{Descriptor, FdEntry};
|
||||||
use crate::sys::fdentry_impl::OsHandle;
|
use crate::sys::fdentry_impl::OsHandle;
|
||||||
use crate::virtfs::{VirtualDir, VirtualDirEntry};
|
use crate::virtfs::{VirtualDir, VirtualDirEntry};
|
||||||
use crate::{wasi, Error, Result};
|
use crate::wasi::{self, WasiError, WasiResult};
|
||||||
use std::borrow::Borrow;
|
use std::borrow::Borrow;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::env;
|
use std::ffi::{self, CString, OsString};
|
||||||
use std::ffi::{CString, OsString};
|
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::path::{Path, PathBuf};
|
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 {
|
enum PendingFdEntry {
|
||||||
Thunk(fn() -> Result<FdEntry>),
|
Thunk(fn() -> io::Result<FdEntry>),
|
||||||
File(File),
|
File(File),
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -20,7 +48,7 @@ impl std::fmt::Debug for PendingFdEntry {
|
|||||||
Self::Thunk(f) => write!(
|
Self::Thunk(f) => write!(
|
||||||
fmt,
|
fmt,
|
||||||
"PendingFdEntry::Thunk({:p})",
|
"PendingFdEntry::Thunk({:p})",
|
||||||
f as *const fn() -> Result<FdEntry>
|
f as *const fn() -> io::Result<FdEntry>
|
||||||
),
|
),
|
||||||
Self::File(f) => write!(fmt, "PendingFdEntry::File({:?})", f),
|
Self::File(f) => write!(fmt, "PendingFdEntry::File({:?})", f),
|
||||||
}
|
}
|
||||||
@@ -46,17 +74,29 @@ impl From<OsString> for PendingCString {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl PendingCString {
|
impl PendingCString {
|
||||||
fn into_string(self) -> Result<String> {
|
fn into_string(self) -> WasiCtxBuilderResult<String> {
|
||||||
match self {
|
let res = match self {
|
||||||
Self::Bytes(v) => String::from_utf8(v).map_err(|_| Error::EILSEQ),
|
Self::Bytes(v) => String::from_utf8(v)?,
|
||||||
Self::OsString(s) => s.into_string().map_err(|_| Error::EILSEQ),
|
#[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`.
|
/// Create a `CString` containing valid UTF-8.
|
||||||
fn into_utf8_cstring(self) -> Result<CString> {
|
fn into_utf8_cstring(self) -> WasiCtxBuilderResult<CString> {
|
||||||
self.into_string()
|
let s = self.into_string()?;
|
||||||
.and_then(|s| CString::new(s).map_err(|_| Error::EILSEQ))
|
let s = CString::new(s)?;
|
||||||
|
Ok(s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,8 +127,7 @@ impl WasiCtxBuilder {
|
|||||||
|
|
||||||
/// Add arguments to the command-line arguments list.
|
/// Add arguments to the command-line arguments list.
|
||||||
///
|
///
|
||||||
/// Arguments must be valid UTF-8 with no NUL bytes, or else `WasiCtxBuilder::build()` will fail
|
/// Arguments must be valid UTF-8 with no NUL bytes, or else `WasiCtxBuilder::build()` will fail.
|
||||||
/// with `Error::EILSEQ`.
|
|
||||||
pub fn args<S: AsRef<[u8]>>(&mut self, args: impl IntoIterator<Item = S>) -> &mut Self {
|
pub fn args<S: AsRef<[u8]>>(&mut self, args: impl IntoIterator<Item = S>) -> &mut Self {
|
||||||
self.args
|
self.args
|
||||||
.as_mut()
|
.as_mut()
|
||||||
@@ -99,8 +138,7 @@ impl WasiCtxBuilder {
|
|||||||
|
|
||||||
/// Add an argument to the command-line arguments list.
|
/// 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
|
/// Arguments must be valid UTF-8 with no NUL bytes, or else `WasiCtxBuilder::build()` will fail.
|
||||||
/// with `Error::EILSEQ`.
|
|
||||||
pub fn arg<S: AsRef<[u8]>>(&mut self, arg: S) -> &mut Self {
|
pub fn arg<S: AsRef<[u8]>>(&mut self, arg: S) -> &mut Self {
|
||||||
self.args
|
self.args
|
||||||
.as_mut()
|
.as_mut()
|
||||||
@@ -112,7 +150,7 @@ impl WasiCtxBuilder {
|
|||||||
/// Inherit the command-line arguments from the host process.
|
/// Inherit the command-line arguments from the host process.
|
||||||
///
|
///
|
||||||
/// If any arguments from the host process contain invalid UTF-8, `WasiCtxBuilder::build()` will
|
/// 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 {
|
pub fn inherit_args(&mut self) -> &mut Self {
|
||||||
let args = self.args.as_mut().unwrap();
|
let args = self.args.as_mut().unwrap();
|
||||||
args.clear();
|
args.clear();
|
||||||
@@ -159,8 +197,7 @@ impl WasiCtxBuilder {
|
|||||||
/// Inherit the environment variables from the host process.
|
/// Inherit the environment variables from the host process.
|
||||||
///
|
///
|
||||||
/// If any environment variables from the host process contain invalid Unicode (UTF-16 for
|
/// 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
|
/// Windows, UTF-8 for other platforms), `WasiCtxBuilder::build()` will fail.
|
||||||
/// `Error::EILSEQ`.
|
|
||||||
pub fn inherit_env(&mut self) -> &mut Self {
|
pub fn inherit_env(&mut self) -> &mut Self {
|
||||||
let env = self.env.as_mut().unwrap();
|
let env = self.env.as_mut().unwrap();
|
||||||
env.clear();
|
env.clear();
|
||||||
@@ -171,7 +208,7 @@ impl WasiCtxBuilder {
|
|||||||
/// Add an entry to the environment.
|
/// Add an entry to the environment.
|
||||||
///
|
///
|
||||||
/// Environment variable keys and values must be valid UTF-8 with no NUL bytes, or else
|
/// 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 {
|
pub fn env<S: AsRef<[u8]>>(&mut self, k: S, v: S) -> &mut Self {
|
||||||
self.env
|
self.env
|
||||||
.as_mut()
|
.as_mut()
|
||||||
@@ -183,7 +220,7 @@ impl WasiCtxBuilder {
|
|||||||
/// Add entries to the environment.
|
/// Add entries to the environment.
|
||||||
///
|
///
|
||||||
/// Environment variable keys and values must be valid UTF-8 with no NUL bytes, or else
|
/// 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)>>(
|
pub fn envs<S: AsRef<[u8]>, T: Borrow<(S, S)>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
envs: impl IntoIterator<Item = T>,
|
envs: impl IntoIterator<Item = T>,
|
||||||
@@ -270,22 +307,22 @@ impl WasiCtxBuilder {
|
|||||||
/// Build a `WasiCtx`, consuming this `WasiCtxBuilder`.
|
/// Build a `WasiCtx`, consuming this `WasiCtxBuilder`.
|
||||||
///
|
///
|
||||||
/// If any of the arguments or environment variables in this builder cannot be converted into
|
/// 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`.
|
/// `CString`s, either due to NUL bytes or Unicode conversions, this will fail.
|
||||||
pub fn build(&mut self) -> Result<WasiCtx> {
|
pub fn build(&mut self) -> WasiCtxBuilderResult<WasiCtx> {
|
||||||
// Process arguments and environment variables into `CString`s, failing quickly if they
|
// Process arguments and environment variables into `CString`s, failing quickly if they
|
||||||
// contain any NUL bytes, or if conversion from `OsString` fails.
|
// contain any NUL bytes, or if conversion from `OsString` fails.
|
||||||
let args = self
|
let args = self
|
||||||
.args
|
.args
|
||||||
.take()
|
.take()
|
||||||
.ok_or(Error::EINVAL)?
|
.unwrap()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|arg| arg.into_utf8_cstring())
|
.map(|arg| arg.into_utf8_cstring())
|
||||||
.collect::<Result<Vec<CString>>>()?;
|
.collect::<WasiCtxBuilderResult<Vec<CString>>>()?;
|
||||||
|
|
||||||
let env = self
|
let env = self
|
||||||
.env
|
.env
|
||||||
.take()
|
.take()
|
||||||
.ok_or(Error::EINVAL)?
|
.unwrap()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(k, v)| {
|
.map(|(k, v)| {
|
||||||
k.into_string().and_then(|mut pair| {
|
k.into_string().and_then(|mut pair| {
|
||||||
@@ -294,15 +331,16 @@ impl WasiCtxBuilder {
|
|||||||
pair.push_str(v.as_str());
|
pair.push_str(v.as_str());
|
||||||
// We have valid UTF-8, but the keys and values have not yet been checked
|
// We have valid UTF-8, but the keys and values have not yet been checked
|
||||||
// for NULs, so we do a final check here.
|
// 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();
|
let mut fds: HashMap<wasi::__wasi_fd_t, FdEntry> = HashMap::new();
|
||||||
// Populate the non-preopen fds.
|
// 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);
|
log::debug!("WasiCtx inserting ({:?}, {:?})", fd, pending);
|
||||||
match pending {
|
match pending {
|
||||||
PendingFdEntry::Thunk(f) => {
|
PendingFdEntry::Thunk(f) => {
|
||||||
@@ -317,20 +355,22 @@ impl WasiCtxBuilder {
|
|||||||
// so we start from there. This variable is initially 2, though, because the loop
|
// so we start from there. This variable is initially 2, though, because the loop
|
||||||
// immediately does the increment and check for overflow.
|
// immediately does the increment and check for overflow.
|
||||||
let mut preopen_fd: wasi::__wasi_fd_t = 2;
|
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
|
// 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.
|
// 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 {
|
match &dir {
|
||||||
Descriptor::OsHandle(handle) => {
|
Descriptor::OsHandle(handle) => {
|
||||||
if !handle.metadata()?.is_dir() {
|
if !handle.metadata()?.is_dir() {
|
||||||
return Err(Error::EBADF);
|
return Err(WasiCtxBuilderError::NotADirectory(guest_path));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Descriptor::VirtualFile(virt) => {
|
Descriptor::VirtualFile(virt) => {
|
||||||
if virt.get_file_type() != wasi::__WASI_FILETYPE_DIRECTORY {
|
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 => {
|
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
|
// 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.
|
// collisions if we restore that functionality in the future.
|
||||||
while fds.contains_key(&preopen_fd) {
|
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)?;
|
let mut fe = FdEntry::from(dir)?;
|
||||||
fe.preopen_path = Some(guest_path);
|
fe.preopen_path = Some(guest_path);
|
||||||
@@ -369,7 +411,7 @@ impl WasiCtx {
|
|||||||
/// - Environment variables are inherited from the host process.
|
/// - Environment variables are inherited from the host process.
|
||||||
///
|
///
|
||||||
/// To override these behaviors, use `WasiCtxBuilder`.
|
/// 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()
|
WasiCtxBuilder::new()
|
||||||
.args(args)
|
.args(args)
|
||||||
.inherit_stdio()
|
.inherit_stdio()
|
||||||
@@ -383,30 +425,30 @@ impl WasiCtx {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Get an immutable `FdEntry` corresponding to the specified raw WASI `fd`.
|
/// 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> {
|
pub(crate) unsafe fn get_fd_entry(&self, fd: wasi::__wasi_fd_t) -> WasiResult<&FdEntry> {
|
||||||
self.fds.get(&fd).ok_or(Error::EBADF)
|
self.fds.get(&fd).ok_or(WasiError::EBADF)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get a mutable `FdEntry` corresponding to the specified raw WASI `fd`.
|
/// Get a mutable `FdEntry` corresponding to the specified raw WASI `fd`.
|
||||||
pub(crate) unsafe fn get_fd_entry_mut(
|
pub(crate) unsafe fn get_fd_entry_mut(
|
||||||
&mut self,
|
&mut self,
|
||||||
fd: wasi::__wasi_fd_t,
|
fd: wasi::__wasi_fd_t,
|
||||||
) -> Result<&mut FdEntry> {
|
) -> WasiResult<&mut FdEntry> {
|
||||||
self.fds.get_mut(&fd).ok_or(Error::EBADF)
|
self.fds.get_mut(&fd).ok_or(WasiError::EBADF)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Insert the specified `FdEntry` into the `WasiCtx` object.
|
/// Insert the specified `FdEntry` into the `WasiCtx` object.
|
||||||
///
|
///
|
||||||
/// The `FdEntry` will automatically get another free raw WASI `fd` assigned. Note that
|
/// 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.
|
/// 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.
|
// Never insert where stdio handles are expected to be.
|
||||||
let mut fd = 3;
|
let mut fd = 3;
|
||||||
while self.fds.contains_key(&fd) {
|
while self.fds.contains_key(&fd) {
|
||||||
if let Some(next_fd) = fd.checked_add(1) {
|
if let Some(next_fd) = fd.checked_add(1) {
|
||||||
fd = next_fd;
|
fd = next_fd;
|
||||||
} else {
|
} else {
|
||||||
return Err(Error::EMFILE);
|
return Err(WasiError::EMFILE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.fds.insert(fd, fe);
|
self.fds.insert(fd, fe);
|
||||||
@@ -424,7 +466,7 @@ impl WasiCtx {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Remove `FdEntry` corresponding to the specified raw WASI `fd` from the `WasiCtx` object.
|
/// 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> {
|
pub(crate) fn remove_fd_entry(&mut self, fd: wasi::__wasi_fd_t) -> WasiResult<FdEntry> {
|
||||||
self.fds.remove(&fd).ok_or(Error::EBADF)
|
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,
|
descriptor_as_oshandle, determine_type_and_access_rights, OsHandle,
|
||||||
};
|
};
|
||||||
use crate::virtfs::VirtualFile;
|
use crate::virtfs::VirtualFile;
|
||||||
use crate::{wasi, Error, Result};
|
use crate::wasi::{self, WasiError, WasiResult};
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use std::mem::ManuallyDrop;
|
use std::mem::ManuallyDrop;
|
||||||
use std::ops::{Deref, DerefMut};
|
use std::ops::{Deref, DerefMut};
|
||||||
@@ -56,22 +56,22 @@ impl Descriptor {
|
|||||||
/// Return a reference to the `OsHandle` or `VirtualFile` treating it as an
|
/// Return a reference to the `OsHandle` or `VirtualFile` treating it as an
|
||||||
/// actual file/dir, and allowing operations which require an actual file and
|
/// actual file/dir, and allowing operations which require an actual file and
|
||||||
/// not just a stream or socket file descriptor.
|
/// 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 {
|
match self {
|
||||||
Self::OsHandle(_) => Ok(self),
|
Self::OsHandle(_) => Ok(self),
|
||||||
Self::VirtualFile(_) => Ok(self),
|
Self::VirtualFile(_) => Ok(self),
|
||||||
_ => Err(Error::EBADF),
|
_ => Err(WasiError::EBADF),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Like `as_file`, but return a mutable reference.
|
/// Like `as_file`, but return a mutable reference.
|
||||||
pub(crate) fn as_file_mut<'descriptor>(
|
pub(crate) fn as_file_mut<'descriptor>(
|
||||||
&'descriptor mut self,
|
&'descriptor mut self,
|
||||||
) -> Result<&'descriptor mut Descriptor> {
|
) -> WasiResult<&'descriptor mut Descriptor> {
|
||||||
match self {
|
match self {
|
||||||
Self::OsHandle(_) => Ok(self),
|
Self::OsHandle(_) => Ok(self),
|
||||||
Self::VirtualFile(_) => Ok(self),
|
Self::VirtualFile(_) => Ok(self),
|
||||||
_ => Err(Error::EBADF),
|
_ => Err(WasiError::EBADF),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,7 +100,7 @@ pub(crate) struct FdEntry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl FdEntry {
|
impl FdEntry {
|
||||||
pub(crate) fn from(file: Descriptor) -> Result<Self> {
|
pub(crate) fn from(file: Descriptor) -> io::Result<Self> {
|
||||||
match file {
|
match file {
|
||||||
Descriptor::OsHandle(handle) => unsafe { determine_type_and_access_rights(&handle) }
|
Descriptor::OsHandle(handle) => unsafe { determine_type_and_access_rights(&handle) }
|
||||||
.map(|(file_type, rights_base, rights_inheriting)| Self {
|
.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(
|
unsafe { determine_type_and_access_rights(&io::stdin()) }.map(
|
||||||
|(file_type, rights_base, rights_inheriting)| Self {
|
|(file_type, rights_base, rights_inheriting)| Self {
|
||||||
file_type,
|
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(
|
unsafe { determine_type_and_access_rights(&io::stdout()) }.map(
|
||||||
|(file_type, rights_base, rights_inheriting)| Self {
|
|(file_type, rights_base, rights_inheriting)| Self {
|
||||||
file_type,
|
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(
|
unsafe { determine_type_and_access_rights(&io::stderr()) }.map(
|
||||||
|(file_type, rights_base, rights_inheriting)| Self {
|
|(file_type, rights_base, rights_inheriting)| Self {
|
||||||
file_type,
|
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())
|
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 `FdEntry` can only be converted into a valid `Descriptor` object if
|
||||||
/// the specified set of base rights `rights_base`, and inheriting rights `rights_inheriting`
|
/// 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
|
/// 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(
|
pub(crate) fn as_descriptor(
|
||||||
&self,
|
&self,
|
||||||
rights_base: wasi::__wasi_rights_t,
|
rights_base: wasi::__wasi_rights_t,
|
||||||
rights_inheriting: wasi::__wasi_rights_t,
|
rights_inheriting: wasi::__wasi_rights_t,
|
||||||
) -> Result<&Descriptor> {
|
) -> WasiResult<&Descriptor> {
|
||||||
self.validate_rights(rights_base, rights_inheriting)?;
|
self.validate_rights(rights_base, rights_inheriting)?;
|
||||||
Ok(&self.descriptor)
|
Ok(&self.descriptor)
|
||||||
}
|
}
|
||||||
@@ -191,12 +191,12 @@ impl FdEntry {
|
|||||||
/// The `FdEntry` can only be converted into a valid `Descriptor` object if
|
/// 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`
|
/// 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
|
/// 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(
|
pub(crate) fn as_descriptor_mut(
|
||||||
&mut self,
|
&mut self,
|
||||||
rights_base: wasi::__wasi_rights_t,
|
rights_base: wasi::__wasi_rights_t,
|
||||||
rights_inheriting: wasi::__wasi_rights_t,
|
rights_inheriting: wasi::__wasi_rights_t,
|
||||||
) -> Result<&mut Descriptor> {
|
) -> WasiResult<&mut Descriptor> {
|
||||||
self.validate_rights(rights_base, rights_inheriting)?;
|
self.validate_rights(rights_base, rights_inheriting)?;
|
||||||
Ok(&mut self.descriptor)
|
Ok(&mut self.descriptor)
|
||||||
}
|
}
|
||||||
@@ -205,12 +205,12 @@ impl FdEntry {
|
|||||||
/// inheriting rights `rights_inheriting`; i.e., if rights attached to this `FdEntry` object
|
/// inheriting rights `rights_inheriting`; i.e., if rights attached to this `FdEntry` object
|
||||||
/// are a superset.
|
/// are a superset.
|
||||||
///
|
///
|
||||||
/// Upon unsuccessful check, `Error::ENOTCAPABLE` is returned.
|
/// Upon unsuccessful check, `WasiError::ENOTCAPABLE` is returned.
|
||||||
fn validate_rights(
|
fn validate_rights(
|
||||||
&self,
|
&self,
|
||||||
rights_base: wasi::__wasi_rights_t,
|
rights_base: wasi::__wasi_rights_t,
|
||||||
rights_inheriting: wasi::__wasi_rights_t,
|
rights_inheriting: wasi::__wasi_rights_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
let missing_base = !self.rights_base & rights_base;
|
let missing_base = !self.rights_base & rights_base;
|
||||||
let missing_inheriting = !self.rights_inheriting & rights_inheriting;
|
let missing_inheriting = !self.rights_inheriting & rights_inheriting;
|
||||||
if missing_base != 0 || missing_inheriting != 0 {
|
if missing_base != 0 || missing_inheriting != 0 {
|
||||||
@@ -226,7 +226,7 @@ impl FdEntry {
|
|||||||
missing_base,
|
missing_base,
|
||||||
missing_inheriting
|
missing_inheriting
|
||||||
);
|
);
|
||||||
Err(Error::ENOTCAPABLE)
|
Err(WasiError::ENOTCAPABLE)
|
||||||
} else {
|
} else {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
use crate::fs::Metadata;
|
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;
|
use std::io;
|
||||||
|
|
||||||
/// A reference to an open file on the filesystem.
|
/// 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`].
|
/// 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
|
/// [`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 {
|
unsafe {
|
||||||
hostcalls_impl::fd_sync(self.ctx, &mut [], self.fd)?;
|
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`].
|
/// 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
|
/// [`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 {
|
unsafe {
|
||||||
hostcalls_impl::fd_datasync(self.ctx, &mut [], self.fd)?;
|
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`].
|
/// 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
|
/// [`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 {
|
unsafe {
|
||||||
hostcalls_impl::fd_filestat_set_size(self.ctx, &mut [], self.fd, size)?;
|
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`].
|
/// This corresponds to [`std::fs::File::metadata`].
|
||||||
///
|
///
|
||||||
/// [`std::fs::File::metadata`]: https://doc.rust-lang.org/std/fs/struct.File.html#method.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 {})
|
Ok(Metadata {})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
use crate::{Error, Result};
|
use crate::wasi::WasiResult;
|
||||||
use std::str;
|
use std::str;
|
||||||
|
|
||||||
/// Creates not-owned WASI path from byte slice.
|
/// Creates not-owned WASI path from byte slice.
|
||||||
///
|
///
|
||||||
/// NB WASI spec requires bytes to be valid UTF-8. Otherwise,
|
/// NB WASI spec requires bytes to be valid UTF-8. Otherwise,
|
||||||
/// `__WASI_ERRNO_ILSEQ` error is returned.
|
/// `__WASI_ERRNO_ILSEQ` error is returned.
|
||||||
pub(crate) fn path_from_slice<'a>(s: &'a [u8]) -> Result<&'a str> {
|
pub(crate) fn path_from_slice<'a>(s: &'a [u8]) -> WasiResult<&'a str> {
|
||||||
str::from_utf8(s).map_err(|_| Error::EILSEQ)
|
let s = str::from_utf8(s)?;
|
||||||
|
Ok(s)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,6 @@
|
|||||||
#![allow(non_snake_case)]
|
#![allow(non_snake_case)]
|
||||||
|
|
||||||
use crate::wasi::*;
|
use crate::wasi::*;
|
||||||
use crate::{Error, Result};
|
|
||||||
use std::{convert::TryInto, io, mem, slice};
|
use std::{convert::TryInto, io, mem, slice};
|
||||||
use wig::witx_host_types;
|
use wig::witx_host_types;
|
||||||
|
|
||||||
@@ -67,11 +66,13 @@ pub struct Dirent {
|
|||||||
impl Dirent {
|
impl Dirent {
|
||||||
/// Serialize the directory entry to the format define by `__wasi_fd_readdir`,
|
/// Serialize the directory entry to the format define by `__wasi_fd_readdir`,
|
||||||
/// so that the serialized entries can be concatenated by the implementation.
|
/// 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 name = self.name.as_bytes();
|
||||||
let namlen = name.len();
|
let namlen = name.len();
|
||||||
let dirent_size = mem::size_of::<__wasi_dirent_t>();
|
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);
|
let mut raw = Vec::<u8>::with_capacity(offset);
|
||||||
raw.resize(offset, 0);
|
raw.resize(offset, 0);
|
||||||
|
|||||||
@@ -8,7 +8,8 @@ use crate::memory::*;
|
|||||||
use crate::sandboxed_tty_writer::SandboxedTTYWriter;
|
use crate::sandboxed_tty_writer::SandboxedTTYWriter;
|
||||||
use crate::sys::hostcalls_impl::fs_helpers::path_open_rights;
|
use crate::sys::hostcalls_impl::fs_helpers::path_open_rights;
|
||||||
use crate::sys::{host_impl, hostcalls_impl};
|
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 filetime::{set_file_handle_times, FileTime};
|
||||||
use log::trace;
|
use log::trace;
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
@@ -20,13 +21,13 @@ pub(crate) unsafe fn fd_close(
|
|||||||
wasi_ctx: &mut WasiCtx,
|
wasi_ctx: &mut WasiCtx,
|
||||||
_memory: &mut [u8],
|
_memory: &mut [u8],
|
||||||
fd: wasi::__wasi_fd_t,
|
fd: wasi::__wasi_fd_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
trace!("fd_close(fd={:?})", fd);
|
trace!("fd_close(fd={:?})", fd);
|
||||||
|
|
||||||
if let Ok(fe) = wasi_ctx.get_fd_entry(fd) {
|
if let Ok(fe) = wasi_ctx.get_fd_entry(fd) {
|
||||||
// can't close preopened files
|
// can't close preopened files
|
||||||
if fe.preopen_path.is_some() {
|
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,
|
wasi_ctx: &WasiCtx,
|
||||||
_memory: &mut [u8],
|
_memory: &mut [u8],
|
||||||
fd: wasi::__wasi_fd_t,
|
fd: wasi::__wasi_fd_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
trace!("fd_datasync(fd={:?})", fd);
|
trace!("fd_datasync(fd={:?})", fd);
|
||||||
|
|
||||||
let file = wasi_ctx
|
let file = wasi_ctx
|
||||||
@@ -60,7 +61,7 @@ pub(crate) unsafe fn fd_pread(
|
|||||||
iovs_len: wasi32::size_t,
|
iovs_len: wasi32::size_t,
|
||||||
offset: wasi::__wasi_filesize_t,
|
offset: wasi::__wasi_filesize_t,
|
||||||
nread: wasi32::uintptr_t,
|
nread: wasi32::uintptr_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
trace!(
|
trace!(
|
||||||
"fd_pread(fd={:?}, iovs_ptr={:#x?}, iovs_len={:?}, offset={}, nread={:#x?})",
|
"fd_pread(fd={:?}, iovs_ptr={:#x?}, iovs_len={:?}, offset={}, nread={:#x?})",
|
||||||
fd,
|
fd,
|
||||||
@@ -78,7 +79,7 @@ pub(crate) unsafe fn fd_pread(
|
|||||||
let iovs = dec_iovec_slice(memory, iovs_ptr, iovs_len)?;
|
let iovs = dec_iovec_slice(memory, iovs_ptr, iovs_len)?;
|
||||||
|
|
||||||
if offset > i64::max_value() as u64 {
|
if offset > i64::max_value() as u64 {
|
||||||
return Err(Error::EIO);
|
return Err(WasiError::EIO);
|
||||||
}
|
}
|
||||||
let buf_size = iovs
|
let buf_size = iovs
|
||||||
.iter()
|
.iter()
|
||||||
@@ -90,7 +91,7 @@ pub(crate) unsafe fn fd_pread(
|
|||||||
cast_iovlen
|
cast_iovlen
|
||||||
})
|
})
|
||||||
.fold(Some(0u32), |len, iov| len.and_then(|x| x.checked_add(iov)))
|
.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 mut buf = vec![0; buf_size as usize];
|
||||||
let host_nread = match file {
|
let host_nread = match file {
|
||||||
Descriptor::OsHandle(fd) => hostcalls_impl::fd_pread(&fd, &mut buf, offset)?,
|
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,
|
iovs_len: wasi32::size_t,
|
||||||
offset: wasi::__wasi_filesize_t,
|
offset: wasi::__wasi_filesize_t,
|
||||||
nwritten: wasi32::uintptr_t,
|
nwritten: wasi32::uintptr_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
trace!(
|
trace!(
|
||||||
"fd_pwrite(fd={:?}, iovs_ptr={:#x?}, iovs_len={:?}, offset={}, nwritten={:#x?})",
|
"fd_pwrite(fd={:?}, iovs_ptr={:#x?}, iovs_len={:?}, offset={}, nwritten={:#x?})",
|
||||||
fd,
|
fd,
|
||||||
@@ -148,7 +149,7 @@ pub(crate) unsafe fn fd_pwrite(
|
|||||||
let iovs = dec_ciovec_slice(memory, iovs_ptr, iovs_len)?;
|
let iovs = dec_ciovec_slice(memory, iovs_ptr, iovs_len)?;
|
||||||
|
|
||||||
if offset > i64::max_value() as u64 {
|
if offset > i64::max_value() as u64 {
|
||||||
return Err(Error::EIO);
|
return Err(WasiError::EIO);
|
||||||
}
|
}
|
||||||
let buf_size = iovs
|
let buf_size = iovs
|
||||||
.iter()
|
.iter()
|
||||||
@@ -160,7 +161,7 @@ pub(crate) unsafe fn fd_pwrite(
|
|||||||
cast_iovlen
|
cast_iovlen
|
||||||
})
|
})
|
||||||
.fold(Some(0u32), |len, iov| len.and_then(|x| x.checked_add(iov)))
|
.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);
|
let mut buf = Vec::with_capacity(buf_size as usize);
|
||||||
for iov in &iovs {
|
for iov in &iovs {
|
||||||
buf.extend_from_slice(std::slice::from_raw_parts(
|
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_ptr: wasi32::uintptr_t,
|
||||||
iovs_len: wasi32::size_t,
|
iovs_len: wasi32::size_t,
|
||||||
nread: wasi32::uintptr_t,
|
nread: wasi32::uintptr_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
trace!(
|
trace!(
|
||||||
"fd_read(fd={:?}, iovs_ptr={:#x?}, iovs_len={:?}, nread={:#x?})",
|
"fd_read(fd={:?}, iovs_ptr={:#x?}, iovs_len={:?}, nread={:#x?})",
|
||||||
fd,
|
fd,
|
||||||
@@ -212,7 +213,7 @@ pub(crate) unsafe fn fd_read(
|
|||||||
Descriptor::OsHandle(file) => file.read_vectored(&mut iovs).map_err(Into::into),
|
Descriptor::OsHandle(file) => file.read_vectored(&mut iovs).map_err(Into::into),
|
||||||
Descriptor::VirtualFile(virt) => virt.read_vectored(&mut iovs),
|
Descriptor::VirtualFile(virt) => virt.read_vectored(&mut iovs),
|
||||||
Descriptor::Stdin => io::stdin().read_vectored(&mut iovs).map_err(Into::into),
|
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?;
|
let host_nread = maybe_host_nread?;
|
||||||
@@ -227,11 +228,11 @@ pub(crate) unsafe fn fd_renumber(
|
|||||||
_memory: &mut [u8],
|
_memory: &mut [u8],
|
||||||
from: wasi::__wasi_fd_t,
|
from: wasi::__wasi_fd_t,
|
||||||
to: wasi::__wasi_fd_t,
|
to: wasi::__wasi_fd_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
trace!("fd_renumber(from={:?}, to={:?})", from, to);
|
trace!("fd_renumber(from={:?}, to={:?})", from, to);
|
||||||
|
|
||||||
if !wasi_ctx.contains_fd_entry(from) {
|
if !wasi_ctx.contains_fd_entry(from) {
|
||||||
return Err(Error::EBADF);
|
return Err(WasiError::EBADF);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't allow renumbering over a pre-opened resource.
|
// 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.
|
// userspace is capable of removing entries from its tables as well.
|
||||||
let from_fe = wasi_ctx.get_fd_entry(from)?;
|
let from_fe = wasi_ctx.get_fd_entry(from)?;
|
||||||
if from_fe.preopen_path.is_some() {
|
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 let Ok(to_fe) = wasi_ctx.get_fd_entry(to) {
|
||||||
if to_fe.preopen_path.is_some() {
|
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,
|
offset: wasi::__wasi_filedelta_t,
|
||||||
whence: wasi::__wasi_whence_t,
|
whence: wasi::__wasi_whence_t,
|
||||||
newoffset: wasi32::uintptr_t,
|
newoffset: wasi32::uintptr_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
trace!(
|
trace!(
|
||||||
"fd_seek(fd={:?}, offset={:?}, whence={}, newoffset={:#x?})",
|
"fd_seek(fd={:?}, offset={:?}, whence={}, newoffset={:#x?})",
|
||||||
fd,
|
fd,
|
||||||
@@ -283,7 +284,7 @@ pub(crate) unsafe fn fd_seek(
|
|||||||
wasi::__WASI_WHENCE_CUR => SeekFrom::Current(offset),
|
wasi::__WASI_WHENCE_CUR => SeekFrom::Current(offset),
|
||||||
wasi::__WASI_WHENCE_END => SeekFrom::End(offset),
|
wasi::__WASI_WHENCE_END => SeekFrom::End(offset),
|
||||||
wasi::__WASI_WHENCE_SET => SeekFrom::Start(offset as u64),
|
wasi::__WASI_WHENCE_SET => SeekFrom::Start(offset as u64),
|
||||||
_ => return Err(Error::EINVAL),
|
_ => return Err(WasiError::EINVAL),
|
||||||
};
|
};
|
||||||
let host_newoffset = match file {
|
let host_newoffset = match file {
|
||||||
Descriptor::OsHandle(fd) => fd.seek(pos)?,
|
Descriptor::OsHandle(fd) => fd.seek(pos)?,
|
||||||
@@ -305,7 +306,7 @@ pub(crate) unsafe fn fd_tell(
|
|||||||
memory: &mut [u8],
|
memory: &mut [u8],
|
||||||
fd: wasi::__wasi_fd_t,
|
fd: wasi::__wasi_fd_t,
|
||||||
newoffset: wasi32::uintptr_t,
|
newoffset: wasi32::uintptr_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
trace!("fd_tell(fd={:?}, newoffset={:#x?})", fd, newoffset);
|
trace!("fd_tell(fd={:?}, newoffset={:#x?})", fd, newoffset);
|
||||||
|
|
||||||
let file = wasi_ctx
|
let file = wasi_ctx
|
||||||
@@ -333,7 +334,7 @@ pub(crate) unsafe fn fd_fdstat_get(
|
|||||||
memory: &mut [u8],
|
memory: &mut [u8],
|
||||||
fd: wasi::__wasi_fd_t,
|
fd: wasi::__wasi_fd_t,
|
||||||
fdstat_ptr: wasi32::uintptr_t, // *mut wasi::__wasi_fdstat_t
|
fdstat_ptr: wasi32::uintptr_t, // *mut wasi::__wasi_fdstat_t
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
trace!("fd_fdstat_get(fd={:?}, fdstat_ptr={:#x?})", fd, fdstat_ptr);
|
trace!("fd_fdstat_get(fd={:?}, fdstat_ptr={:#x?})", fd, fdstat_ptr);
|
||||||
|
|
||||||
let mut fdstat = dec_fdstat_byref(memory, 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],
|
_memory: &mut [u8],
|
||||||
fd: wasi::__wasi_fd_t,
|
fd: wasi::__wasi_fd_t,
|
||||||
fdflags: wasi::__wasi_fdflags_t,
|
fdflags: wasi::__wasi_fdflags_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
trace!("fd_fdstat_set_flags(fd={:?}, fdflags={:#x?})", fd, fdflags);
|
trace!("fd_fdstat_set_flags(fd={:?}, fdflags={:#x?})", fd, fdflags);
|
||||||
|
|
||||||
let descriptor = wasi_ctx
|
let descriptor = wasi_ctx
|
||||||
@@ -400,7 +401,7 @@ pub(crate) unsafe fn fd_fdstat_set_rights(
|
|||||||
fd: wasi::__wasi_fd_t,
|
fd: wasi::__wasi_fd_t,
|
||||||
fs_rights_base: wasi::__wasi_rights_t,
|
fs_rights_base: wasi::__wasi_rights_t,
|
||||||
fs_rights_inheriting: wasi::__wasi_rights_t,
|
fs_rights_inheriting: wasi::__wasi_rights_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
trace!(
|
trace!(
|
||||||
"fd_fdstat_set_rights(fd={:?}, fs_rights_base={:#x?}, fs_rights_inheriting={:#x?})",
|
"fd_fdstat_set_rights(fd={:?}, fs_rights_base={:#x?}, fs_rights_inheriting={:#x?})",
|
||||||
fd,
|
fd,
|
||||||
@@ -412,7 +413,7 @@ pub(crate) unsafe fn fd_fdstat_set_rights(
|
|||||||
if fe.rights_base & fs_rights_base != fs_rights_base
|
if fe.rights_base & fs_rights_base != fs_rights_base
|
||||||
|| fe.rights_inheriting & fs_rights_inheriting != fs_rights_inheriting
|
|| 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_base = fs_rights_base;
|
||||||
fe.rights_inheriting = fs_rights_inheriting;
|
fe.rights_inheriting = fs_rights_inheriting;
|
||||||
@@ -424,7 +425,7 @@ pub(crate) unsafe fn fd_sync(
|
|||||||
wasi_ctx: &WasiCtx,
|
wasi_ctx: &WasiCtx,
|
||||||
_memory: &mut [u8],
|
_memory: &mut [u8],
|
||||||
fd: wasi::__wasi_fd_t,
|
fd: wasi::__wasi_fd_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
trace!("fd_sync(fd={:?})", fd);
|
trace!("fd_sync(fd={:?})", fd);
|
||||||
|
|
||||||
let file = wasi_ctx
|
let file = wasi_ctx
|
||||||
@@ -449,7 +450,7 @@ pub(crate) unsafe fn fd_write(
|
|||||||
iovs_ptr: wasi32::uintptr_t,
|
iovs_ptr: wasi32::uintptr_t,
|
||||||
iovs_len: wasi32::size_t,
|
iovs_len: wasi32::size_t,
|
||||||
nwritten: wasi32::uintptr_t,
|
nwritten: wasi32::uintptr_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
trace!(
|
trace!(
|
||||||
"fd_write(fd={:?}, iovs_ptr={:#x?}, iovs_len={:?}, nwritten={:#x?})",
|
"fd_write(fd={:?}, iovs_ptr={:#x?}, iovs_len={:?}, nwritten={:#x?})",
|
||||||
fd,
|
fd,
|
||||||
@@ -480,7 +481,7 @@ pub(crate) unsafe fn fd_write(
|
|||||||
virt.write_vectored(&iovs)?
|
virt.write_vectored(&iovs)?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Descriptor::Stdin => return Err(Error::EBADF),
|
Descriptor::Stdin => return Err(WasiError::EBADF),
|
||||||
Descriptor::Stdout => {
|
Descriptor::Stdout => {
|
||||||
// lock for the duration of the scope
|
// lock for the duration of the scope
|
||||||
let stdout = io::stdout();
|
let stdout = io::stdout();
|
||||||
@@ -512,7 +513,7 @@ pub(crate) unsafe fn fd_advise(
|
|||||||
offset: wasi::__wasi_filesize_t,
|
offset: wasi::__wasi_filesize_t,
|
||||||
len: wasi::__wasi_filesize_t,
|
len: wasi::__wasi_filesize_t,
|
||||||
advice: wasi::__wasi_advice_t,
|
advice: wasi::__wasi_advice_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
trace!(
|
trace!(
|
||||||
"fd_advise(fd={:?}, offset={}, len={}, advice={:?})",
|
"fd_advise(fd={:?}, offset={}, len={}, advice={:?})",
|
||||||
fd,
|
fd,
|
||||||
@@ -543,7 +544,7 @@ pub(crate) unsafe fn fd_allocate(
|
|||||||
fd: wasi::__wasi_fd_t,
|
fd: wasi::__wasi_fd_t,
|
||||||
offset: wasi::__wasi_filesize_t,
|
offset: wasi::__wasi_filesize_t,
|
||||||
len: wasi::__wasi_filesize_t,
|
len: wasi::__wasi_filesize_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
trace!("fd_allocate(fd={:?}, offset={}, len={})", fd, offset, len);
|
trace!("fd_allocate(fd={:?}, offset={}, len={})", fd, offset, len);
|
||||||
|
|
||||||
let file = wasi_ctx
|
let file = wasi_ctx
|
||||||
@@ -556,10 +557,10 @@ pub(crate) unsafe fn fd_allocate(
|
|||||||
let metadata = fd.metadata()?;
|
let metadata = fd.metadata()?;
|
||||||
|
|
||||||
let current_size = metadata.len();
|
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
|
// This check will be unnecessary when rust-lang/rust#63326 is fixed
|
||||||
if wanted_size > i64::max_value() as u64 {
|
if wanted_size > i64::max_value() as u64 {
|
||||||
return Err(Error::E2BIG);
|
return Err(WasiError::E2BIG);
|
||||||
}
|
}
|
||||||
|
|
||||||
if wanted_size > current_size {
|
if wanted_size > current_size {
|
||||||
@@ -583,7 +584,7 @@ pub(crate) unsafe fn path_create_directory(
|
|||||||
dirfd: wasi::__wasi_fd_t,
|
dirfd: wasi::__wasi_fd_t,
|
||||||
path_ptr: wasi32::uintptr_t,
|
path_ptr: wasi32::uintptr_t,
|
||||||
path_len: wasi32::size_t,
|
path_len: wasi32::size_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
trace!(
|
trace!(
|
||||||
"path_create_directory(dirfd={:?}, path_ptr={:#x?}, path_len={})",
|
"path_create_directory(dirfd={:?}, path_ptr={:#x?}, path_len={})",
|
||||||
dirfd,
|
dirfd,
|
||||||
@@ -612,7 +613,7 @@ pub(crate) unsafe fn path_link(
|
|||||||
new_dirfd: wasi::__wasi_fd_t,
|
new_dirfd: wasi::__wasi_fd_t,
|
||||||
new_path_ptr: wasi32::uintptr_t,
|
new_path_ptr: wasi32::uintptr_t,
|
||||||
new_path_len: wasi32::size_t,
|
new_path_len: wasi32::size_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
trace!(
|
trace!(
|
||||||
"path_link(old_dirfd={:?}, old_flags={:?}, old_path_ptr={:#x?}, old_path_len={}, new_dirfd={:?}, new_path_ptr={:#x?}, new_path_len={})",
|
"path_link(old_dirfd={:?}, old_flags={:?}, old_path_ptr={:#x?}, old_path_len={}, new_dirfd={:?}, new_path_ptr={:#x?}, new_path_len={})",
|
||||||
old_dirfd,
|
old_dirfd,
|
||||||
@@ -664,7 +665,7 @@ pub(crate) unsafe fn path_open(
|
|||||||
fs_rights_inheriting: wasi::__wasi_rights_t,
|
fs_rights_inheriting: wasi::__wasi_rights_t,
|
||||||
fs_flags: wasi::__wasi_fdflags_t,
|
fs_flags: wasi::__wasi_fdflags_t,
|
||||||
fd_out_ptr: wasi32::uintptr_t,
|
fd_out_ptr: wasi32::uintptr_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
trace!(
|
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?})",
|
"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,
|
dirfd,
|
||||||
@@ -739,7 +740,7 @@ pub(crate) unsafe fn path_readlink(
|
|||||||
buf_ptr: wasi32::uintptr_t,
|
buf_ptr: wasi32::uintptr_t,
|
||||||
buf_len: wasi32::size_t,
|
buf_len: wasi32::size_t,
|
||||||
buf_used: wasi32::uintptr_t,
|
buf_used: wasi32::uintptr_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
trace!(
|
trace!(
|
||||||
"path_readlink(dirfd={:?}, path_ptr={:#x?}, path_len={:?}, buf_ptr={:#x?}, buf_len={}, buf_used={:#x?})",
|
"path_readlink(dirfd={:?}, path_ptr={:#x?}, path_len={:?}, buf_ptr={:#x?}, buf_len={}, buf_used={:#x?})",
|
||||||
dirfd,
|
dirfd,
|
||||||
@@ -783,7 +784,7 @@ pub(crate) unsafe fn path_rename(
|
|||||||
new_dirfd: wasi::__wasi_fd_t,
|
new_dirfd: wasi::__wasi_fd_t,
|
||||||
new_path_ptr: wasi32::uintptr_t,
|
new_path_ptr: wasi32::uintptr_t,
|
||||||
new_path_len: wasi32::size_t,
|
new_path_len: wasi32::size_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
trace!(
|
trace!(
|
||||||
"path_rename(old_dirfd={:?}, old_path_ptr={:#x?}, old_path_len={:?}, new_dirfd={:?}, new_path_ptr={:#x?}, new_path_len={:?})",
|
"path_rename(old_dirfd={:?}, old_path_ptr={:#x?}, old_path_len={:?}, new_dirfd={:?}, new_path_ptr={:#x?}, new_path_len={:?})",
|
||||||
old_dirfd,
|
old_dirfd,
|
||||||
@@ -838,7 +839,7 @@ pub(crate) unsafe fn fd_filestat_get(
|
|||||||
memory: &mut [u8],
|
memory: &mut [u8],
|
||||||
fd: wasi::__wasi_fd_t,
|
fd: wasi::__wasi_fd_t,
|
||||||
filestat_ptr: wasi32::uintptr_t,
|
filestat_ptr: wasi32::uintptr_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
trace!(
|
trace!(
|
||||||
"fd_filestat_get(fd={:?}, filestat_ptr={:#x?})",
|
"fd_filestat_get(fd={:?}, filestat_ptr={:#x?})",
|
||||||
fd,
|
fd,
|
||||||
@@ -871,7 +872,7 @@ pub(crate) unsafe fn fd_filestat_set_times(
|
|||||||
st_atim: wasi::__wasi_timestamp_t,
|
st_atim: wasi::__wasi_timestamp_t,
|
||||||
st_mtim: wasi::__wasi_timestamp_t,
|
st_mtim: wasi::__wasi_timestamp_t,
|
||||||
fst_flags: wasi::__wasi_fstflags_t,
|
fst_flags: wasi::__wasi_fstflags_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
trace!(
|
trace!(
|
||||||
"fd_filestat_set_times(fd={:?}, st_atim={}, st_mtim={}, fst_flags={:#x?})",
|
"fd_filestat_set_times(fd={:?}, st_atim={}, st_mtim={}, fst_flags={:#x?})",
|
||||||
fd,
|
fd,
|
||||||
@@ -893,14 +894,14 @@ pub(crate) fn fd_filestat_set_times_impl(
|
|||||||
st_atim: wasi::__wasi_timestamp_t,
|
st_atim: wasi::__wasi_timestamp_t,
|
||||||
st_mtim: wasi::__wasi_timestamp_t,
|
st_mtim: wasi::__wasi_timestamp_t,
|
||||||
fst_flags: wasi::__wasi_fstflags_t,
|
fst_flags: wasi::__wasi_fstflags_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
let set_atim = fst_flags & wasi::__WASI_FSTFLAGS_ATIM != 0;
|
let set_atim = fst_flags & wasi::__WASI_FSTFLAGS_ATIM != 0;
|
||||||
let set_atim_now = fst_flags & wasi::__WASI_FSTFLAGS_ATIM_NOW != 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 = fst_flags & wasi::__WASI_FSTFLAGS_MTIM != 0;
|
||||||
let set_mtim_now = fst_flags & wasi::__WASI_FSTFLAGS_MTIM_NOW != 0;
|
let set_mtim_now = fst_flags & wasi::__WASI_FSTFLAGS_MTIM_NOW != 0;
|
||||||
|
|
||||||
if (set_atim && set_atim_now) || (set_mtim && set_mtim_now) {
|
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 atim = if set_atim {
|
||||||
let time = UNIX_EPOCH + Duration::from_nanos(st_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],
|
_memory: &mut [u8],
|
||||||
fd: wasi::__wasi_fd_t,
|
fd: wasi::__wasi_fd_t,
|
||||||
st_size: wasi::__wasi_filesize_t,
|
st_size: wasi::__wasi_filesize_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
trace!("fd_filestat_set_size(fd={:?}, st_size={})", fd, st_size);
|
trace!("fd_filestat_set_size(fd={:?}, st_size={})", fd, st_size);
|
||||||
|
|
||||||
let file = wasi_ctx
|
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
|
// This check will be unnecessary when rust-lang/rust#63326 is fixed
|
||||||
if st_size > i64::max_value() as u64 {
|
if st_size > i64::max_value() as u64 {
|
||||||
return Err(Error::E2BIG);
|
return Err(WasiError::E2BIG);
|
||||||
}
|
}
|
||||||
match file {
|
match file {
|
||||||
Descriptor::OsHandle(fd) => fd.set_len(st_size).map_err(Into::into),
|
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_ptr: wasi32::uintptr_t,
|
||||||
path_len: wasi32::size_t,
|
path_len: wasi32::size_t,
|
||||||
filestat_ptr: wasi32::uintptr_t,
|
filestat_ptr: wasi32::uintptr_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
trace!(
|
trace!(
|
||||||
"path_filestat_get(dirfd={:?}, dirflags={:?}, path_ptr={:#x?}, path_len={}, filestat_ptr={:#x?})",
|
"path_filestat_get(dirfd={:?}, dirflags={:?}, path_ptr={:#x?}, path_len={}, filestat_ptr={:#x?})",
|
||||||
dirfd,
|
dirfd,
|
||||||
@@ -1013,7 +1014,7 @@ pub(crate) unsafe fn path_filestat_set_times(
|
|||||||
st_atim: wasi::__wasi_timestamp_t,
|
st_atim: wasi::__wasi_timestamp_t,
|
||||||
st_mtim: wasi::__wasi_timestamp_t,
|
st_mtim: wasi::__wasi_timestamp_t,
|
||||||
fst_flags: wasi::__wasi_fstflags_t,
|
fst_flags: wasi::__wasi_fstflags_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
trace!(
|
trace!(
|
||||||
"path_filestat_set_times(dirfd={:?}, dirflags={:?}, path_ptr={:#x?}, path_len={}, st_atim={}, st_mtim={}, fst_flags={:#x?})",
|
"path_filestat_set_times(dirfd={:?}, dirflags={:?}, path_ptr={:#x?}, path_len={}, st_atim={}, st_mtim={}, fst_flags={:#x?})",
|
||||||
dirfd,
|
dirfd,
|
||||||
@@ -1056,7 +1057,7 @@ pub(crate) unsafe fn path_symlink(
|
|||||||
dirfd: wasi::__wasi_fd_t,
|
dirfd: wasi::__wasi_fd_t,
|
||||||
new_path_ptr: wasi32::uintptr_t,
|
new_path_ptr: wasi32::uintptr_t,
|
||||||
new_path_len: wasi32::size_t,
|
new_path_len: wasi32::size_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
trace!(
|
trace!(
|
||||||
"path_symlink(old_path_ptr={:#x?}, old_path_len={}, dirfd={:?}, new_path_ptr={:#x?}, new_path_len={})",
|
"path_symlink(old_path_ptr={:#x?}, old_path_len={}, dirfd={:?}, new_path_ptr={:#x?}, new_path_len={})",
|
||||||
old_path_ptr,
|
old_path_ptr,
|
||||||
@@ -1089,7 +1090,7 @@ pub(crate) unsafe fn path_unlink_file(
|
|||||||
dirfd: wasi::__wasi_fd_t,
|
dirfd: wasi::__wasi_fd_t,
|
||||||
path_ptr: wasi32::uintptr_t,
|
path_ptr: wasi32::uintptr_t,
|
||||||
path_len: wasi32::size_t,
|
path_len: wasi32::size_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
trace!(
|
trace!(
|
||||||
"path_unlink_file(dirfd={:?}, path_ptr={:#x?}, path_len={})",
|
"path_unlink_file(dirfd={:?}, path_ptr={:#x?}, path_len={})",
|
||||||
dirfd,
|
dirfd,
|
||||||
@@ -1116,7 +1117,7 @@ pub(crate) unsafe fn path_remove_directory(
|
|||||||
dirfd: wasi::__wasi_fd_t,
|
dirfd: wasi::__wasi_fd_t,
|
||||||
path_ptr: wasi32::uintptr_t,
|
path_ptr: wasi32::uintptr_t,
|
||||||
path_len: wasi32::size_t,
|
path_len: wasi32::size_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
trace!(
|
trace!(
|
||||||
"path_remove_directory(dirfd={:?}, path_ptr={:#x?}, path_len={})",
|
"path_remove_directory(dirfd={:?}, path_ptr={:#x?}, path_len={})",
|
||||||
dirfd,
|
dirfd,
|
||||||
@@ -1151,7 +1152,7 @@ pub(crate) unsafe fn fd_prestat_get(
|
|||||||
memory: &mut [u8],
|
memory: &mut [u8],
|
||||||
fd: wasi::__wasi_fd_t,
|
fd: wasi::__wasi_fd_t,
|
||||||
prestat_ptr: wasi32::uintptr_t,
|
prestat_ptr: wasi32::uintptr_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
trace!(
|
trace!(
|
||||||
"fd_prestat_get(fd={:?}, prestat_ptr={:#x?})",
|
"fd_prestat_get(fd={:?}, prestat_ptr={:#x?})",
|
||||||
fd,
|
fd,
|
||||||
@@ -1160,9 +1161,9 @@ pub(crate) unsafe fn fd_prestat_get(
|
|||||||
|
|
||||||
// TODO: should we validate any rights here?
|
// TODO: should we validate any rights here?
|
||||||
let fe = wasi_ctx.get_fd_entry(fd)?;
|
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 {
|
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())?;
|
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,
|
fd: wasi::__wasi_fd_t,
|
||||||
path_ptr: wasi32::uintptr_t,
|
path_ptr: wasi32::uintptr_t,
|
||||||
path_len: wasi32::size_t,
|
path_len: wasi32::size_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
trace!(
|
trace!(
|
||||||
"fd_prestat_dir_name(fd={:?}, path_ptr={:#x?}, path_len={})",
|
"fd_prestat_dir_name(fd={:?}, path_ptr={:#x?}, path_len={})",
|
||||||
fd,
|
fd,
|
||||||
@@ -1197,15 +1198,15 @@ pub(crate) unsafe fn fd_prestat_dir_name(
|
|||||||
|
|
||||||
// TODO: should we validate any rights here?
|
// TODO: should we validate any rights here?
|
||||||
let fe = wasi_ctx.get_fd_entry(fd)?;
|
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 {
|
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())?;
|
let path = host_impl::path_from_host(po_path.as_os_str())?;
|
||||||
|
|
||||||
if path.len() > dec_usize(path_len) {
|
if path.len() > dec_usize(path_len) {
|
||||||
return Err(Error::ENAMETOOLONG);
|
return Err(WasiError::ENAMETOOLONG);
|
||||||
}
|
}
|
||||||
|
|
||||||
trace!(" | (path_ptr,path_len)='{}'", path);
|
trace!(" | (path_ptr,path_len)='{}'", path);
|
||||||
@@ -1221,7 +1222,7 @@ pub(crate) unsafe fn fd_readdir(
|
|||||||
buf_len: wasi32::size_t,
|
buf_len: wasi32::size_t,
|
||||||
cookie: wasi::__wasi_dircookie_t,
|
cookie: wasi::__wasi_dircookie_t,
|
||||||
buf_used: wasi32::uintptr_t,
|
buf_used: wasi32::uintptr_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
trace!(
|
trace!(
|
||||||
"fd_readdir(fd={:?}, buf={:#x?}, buf_len={}, cookie={:#x?}, buf_used={:#x?})",
|
"fd_readdir(fd={:?}, buf={:#x?}, buf_len={}, cookie={:#x?}, buf_used={:#x?})",
|
||||||
fd,
|
fd,
|
||||||
@@ -1241,10 +1242,10 @@ pub(crate) unsafe fn fd_readdir(
|
|||||||
|
|
||||||
trace!(" | (buf,buf_len)={:?}", host_buf);
|
trace!(" | (buf,buf_len)={:?}", host_buf);
|
||||||
|
|
||||||
fn copy_entities<T: Iterator<Item = Result<Dirent>>>(
|
fn copy_entities<T: Iterator<Item = WasiResult<Dirent>>>(
|
||||||
iter: T,
|
iter: T,
|
||||||
mut host_buf: &mut [u8],
|
mut host_buf: &mut [u8],
|
||||||
) -> Result<usize> {
|
) -> WasiResult<usize> {
|
||||||
let mut host_bufused = 0;
|
let mut host_bufused = 0;
|
||||||
for dirent in iter {
|
for dirent in iter {
|
||||||
let dirent_raw = dirent?.to_wasi_raw()?;
|
let dirent_raw = dirent?.to_wasi_raw()?;
|
||||||
|
|||||||
@@ -2,7 +2,8 @@
|
|||||||
use crate::sys::fdentry_impl::OsHandle;
|
use crate::sys::fdentry_impl::OsHandle;
|
||||||
use crate::sys::host_impl;
|
use crate::sys::host_impl;
|
||||||
use crate::sys::hostcalls_impl::fs_helpers::*;
|
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};
|
use std::path::{Component, Path};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@@ -20,7 +21,7 @@ impl PathGet {
|
|||||||
&self.path
|
&self.path
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn path_create_directory(self) -> Result<()> {
|
pub(crate) fn path_create_directory(self) -> WasiResult<()> {
|
||||||
match &self.dirfd {
|
match &self.dirfd {
|
||||||
Descriptor::OsHandle(file) => {
|
Descriptor::OsHandle(file) => {
|
||||||
crate::sys::hostcalls_impl::path_create_directory(&file, &self.path)
|
crate::sys::hostcalls_impl::path_create_directory(&file, &self.path)
|
||||||
@@ -38,7 +39,7 @@ impl PathGet {
|
|||||||
write: bool,
|
write: bool,
|
||||||
oflags: u16,
|
oflags: u16,
|
||||||
fs_flags: u16,
|
fs_flags: u16,
|
||||||
) -> Result<Descriptor> {
|
) -> WasiResult<Descriptor> {
|
||||||
match &self.dirfd {
|
match &self.dirfd {
|
||||||
Descriptor::OsHandle(_) => {
|
Descriptor::OsHandle(_) => {
|
||||||
crate::sys::hostcalls_impl::path_open(self, read, write, oflags, fs_flags)
|
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 }
|
PathRef { dirfd, path }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn open(&self) -> Result<Descriptor> {
|
fn open(&self) -> WasiResult<Descriptor> {
|
||||||
match self.dirfd {
|
match self.dirfd {
|
||||||
Descriptor::OsHandle(file) => Ok(Descriptor::OsHandle(OsHandle::from(openat(
|
Descriptor::OsHandle(file) => Ok(Descriptor::OsHandle(OsHandle::from(openat(
|
||||||
&file, &self.path,
|
&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 {
|
match self.dirfd {
|
||||||
Descriptor::OsHandle(file) => readlinkat(file, self.path),
|
Descriptor::OsHandle(file) => readlinkat(file, self.path),
|
||||||
Descriptor::VirtualFile(virt) => {
|
Descriptor::VirtualFile(virt) => {
|
||||||
@@ -107,17 +108,17 @@ pub(crate) fn path_get(
|
|||||||
dirflags: wasi::__wasi_lookupflags_t,
|
dirflags: wasi::__wasi_lookupflags_t,
|
||||||
path: &str,
|
path: &str,
|
||||||
needs_final_component: bool,
|
needs_final_component: bool,
|
||||||
) -> Result<PathGet> {
|
) -> WasiResult<PathGet> {
|
||||||
const MAX_SYMLINK_EXPANSIONS: usize = 128;
|
const MAX_SYMLINK_EXPANSIONS: usize = 128;
|
||||||
|
|
||||||
if path.contains('\0') {
|
if path.contains('\0') {
|
||||||
// if contains NUL, return EILSEQ
|
// if contains NUL, return EILSEQ
|
||||||
return Err(Error::EILSEQ);
|
return Err(WasiError::EILSEQ);
|
||||||
}
|
}
|
||||||
|
|
||||||
if fe.file_type != wasi::__WASI_FILETYPE_DIRECTORY {
|
if fe.file_type != wasi::__WASI_FILETYPE_DIRECTORY {
|
||||||
// if `dirfd` doesn't refer to a directory, return `ENOTDIR`.
|
// if `dirfd` doesn't refer to a directory, return `ENOTDIR`.
|
||||||
return Err(Error::ENOTDIR);
|
return Err(WasiError::ENOTDIR);
|
||||||
}
|
}
|
||||||
|
|
||||||
let dirfd = fe
|
let dirfd = fe
|
||||||
@@ -148,7 +149,7 @@ pub(crate) fn path_get(
|
|||||||
let ends_with_slash = cur_path.ends_with('/');
|
let ends_with_slash = cur_path.ends_with('/');
|
||||||
let mut components = Path::new(&cur_path).components();
|
let mut components = Path::new(&cur_path).components();
|
||||||
let head = match components.next() {
|
let head = match components.next() {
|
||||||
None => return Err(Error::ENOENT),
|
None => return Err(WasiError::ENOENT),
|
||||||
Some(p) => p,
|
Some(p) => p,
|
||||||
};
|
};
|
||||||
let tail = components.as_path();
|
let tail = components.as_path();
|
||||||
@@ -166,18 +167,18 @@ pub(crate) fn path_get(
|
|||||||
match head {
|
match head {
|
||||||
Component::Prefix(_) | Component::RootDir => {
|
Component::Prefix(_) | Component::RootDir => {
|
||||||
// path is absolute!
|
// path is absolute!
|
||||||
return Err(Error::ENOTCAPABLE);
|
return Err(WasiError::ENOTCAPABLE);
|
||||||
}
|
}
|
||||||
Component::CurDir => {
|
Component::CurDir => {
|
||||||
// "." so skip
|
// "." so skip
|
||||||
}
|
}
|
||||||
Component::ParentDir => {
|
Component::ParentDir => {
|
||||||
// ".." so pop a dir
|
// ".." 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
|
// we're not allowed to pop past the original directory
|
||||||
if dir_stack.is_empty() {
|
if dir_stack.is_empty() {
|
||||||
return Err(Error::ENOTCAPABLE);
|
return Err(WasiError::ENOTCAPABLE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Component::Normal(head) => {
|
Component::Normal(head) => {
|
||||||
@@ -188,14 +189,17 @@ pub(crate) fn path_get(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !path_stack.is_empty() || (ends_with_slash && !needs_final_component) {
|
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(
|
||||||
.open()
|
dir_stack.last().ok_or(WasiError::ENOTCAPABLE)?,
|
||||||
|
&head,
|
||||||
|
)
|
||||||
|
.open()
|
||||||
{
|
{
|
||||||
Ok(new_dir) => {
|
Ok(new_dir) => {
|
||||||
dir_stack.push(new_dir);
|
dir_stack.push(new_dir);
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
match e.as_wasi_error() {
|
match e {
|
||||||
WasiError::ELOOP
|
WasiError::ELOOP
|
||||||
| WasiError::EMLINK
|
| WasiError::EMLINK
|
||||||
| WasiError::ENOTDIR =>
|
| WasiError::ENOTDIR =>
|
||||||
@@ -204,14 +208,14 @@ pub(crate) fn path_get(
|
|||||||
{
|
{
|
||||||
// attempt symlink expansion
|
// attempt symlink expansion
|
||||||
let mut link_path = PathRef::new(
|
let mut link_path = PathRef::new(
|
||||||
dir_stack.last().ok_or(Error::ENOTCAPABLE)?,
|
dir_stack.last().ok_or(WasiError::ENOTCAPABLE)?,
|
||||||
&head,
|
&head,
|
||||||
)
|
)
|
||||||
.readlink()?;
|
.readlink()?;
|
||||||
|
|
||||||
symlink_expansions += 1;
|
symlink_expansions += 1;
|
||||||
if symlink_expansions > MAX_SYMLINK_EXPANSIONS {
|
if symlink_expansions > MAX_SYMLINK_EXPANSIONS {
|
||||||
return Err(Error::ELOOP);
|
return Err(WasiError::ELOOP);
|
||||||
}
|
}
|
||||||
|
|
||||||
if head.ends_with('/') {
|
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
|
// if there's a trailing slash, or if `LOOKUP_SYMLINK_FOLLOW` is set, attempt
|
||||||
// symlink expansion
|
// symlink expansion
|
||||||
match PathRef::new(dir_stack.last().ok_or(Error::ENOTCAPABLE)?, &head)
|
match PathRef::new(
|
||||||
.readlink()
|
dir_stack.last().ok_or(WasiError::ENOTCAPABLE)?,
|
||||||
|
&head,
|
||||||
|
)
|
||||||
|
.readlink()
|
||||||
{
|
{
|
||||||
Ok(mut link_path) => {
|
Ok(mut link_path) => {
|
||||||
symlink_expansions += 1;
|
symlink_expansions += 1;
|
||||||
if symlink_expansions > MAX_SYMLINK_EXPANSIONS {
|
if symlink_expansions > MAX_SYMLINK_EXPANSIONS {
|
||||||
return Err(Error::ELOOP);
|
return Err(WasiError::ELOOP);
|
||||||
}
|
}
|
||||||
|
|
||||||
if head.ends_with('/') {
|
if head.ends_with('/') {
|
||||||
@@ -260,12 +267,12 @@ pub(crate) fn path_get(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
if e.as_wasi_error() != WasiError::EINVAL
|
if e != WasiError::EINVAL
|
||||||
&& e.as_wasi_error() != WasiError::ENOENT
|
&& e != WasiError::ENOENT
|
||||||
// this handles the cases when trying to link to
|
// this handles the cases when trying to link to
|
||||||
// a destination that already exists, and the target
|
// a destination that already exists, and the target
|
||||||
// path contains a slash
|
// path contains a slash
|
||||||
&& e.as_wasi_error() != WasiError::ENOTDIR
|
&& e != WasiError::ENOTDIR
|
||||||
{
|
{
|
||||||
return Err(e);
|
return Err(e);
|
||||||
}
|
}
|
||||||
@@ -275,7 +282,7 @@ pub(crate) fn path_get(
|
|||||||
|
|
||||||
// not a symlink, so we're done;
|
// not a symlink, so we're done;
|
||||||
return Ok(PathGet {
|
return Ok(PathGet {
|
||||||
dirfd: dir_stack.pop().ok_or(Error::ENOTCAPABLE)?,
|
dirfd: dir_stack.pop().ok_or(WasiError::ENOTCAPABLE)?,
|
||||||
path: head,
|
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
|
// 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
|
// input path has trailing slashes and `needs_final_component` is not set
|
||||||
return Ok(PathGet {
|
return Ok(PathGet {
|
||||||
dirfd: dir_stack.pop().ok_or(Error::ENOTCAPABLE)?,
|
dirfd: dir_stack.pop().ok_or(WasiError::ENOTCAPABLE)?,
|
||||||
path: String::from("."),
|
path: String::from("."),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,8 @@ use crate::ctx::WasiCtx;
|
|||||||
use crate::fdentry::Descriptor;
|
use crate::fdentry::Descriptor;
|
||||||
use crate::memory::*;
|
use crate::memory::*;
|
||||||
use crate::sys::hostcalls_impl;
|
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 log::{error, trace};
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
|
|
||||||
@@ -12,7 +13,7 @@ pub(crate) fn args_get(
|
|||||||
memory: &mut [u8],
|
memory: &mut [u8],
|
||||||
argv_ptr: wasi32::uintptr_t,
|
argv_ptr: wasi32::uintptr_t,
|
||||||
argv_buf: wasi32::uintptr_t,
|
argv_buf: wasi32::uintptr_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
trace!(
|
trace!(
|
||||||
"args_get(argv_ptr={:#x?}, argv_buf={:#x?})",
|
"args_get(argv_ptr={:#x?}, argv_buf={:#x?})",
|
||||||
argv_ptr,
|
argv_ptr,
|
||||||
@@ -31,7 +32,9 @@ pub(crate) fn args_get(
|
|||||||
argv.push(arg_ptr);
|
argv.push(arg_ptr);
|
||||||
|
|
||||||
let len = wasi32::uintptr_t::try_from(arg_bytes.len())?;
|
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)
|
enc_slice_of_wasi32_uintptr(memory, argv.as_slice(), argv_ptr)
|
||||||
@@ -42,7 +45,7 @@ pub(crate) fn args_sizes_get(
|
|||||||
memory: &mut [u8],
|
memory: &mut [u8],
|
||||||
argc_ptr: wasi32::uintptr_t,
|
argc_ptr: wasi32::uintptr_t,
|
||||||
argv_buf_size_ptr: wasi32::uintptr_t,
|
argv_buf_size_ptr: wasi32::uintptr_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
trace!(
|
trace!(
|
||||||
"args_sizes_get(argc_ptr={:#x?}, argv_buf_size_ptr={:#x?})",
|
"args_sizes_get(argc_ptr={:#x?}, argv_buf_size_ptr={:#x?})",
|
||||||
argc_ptr,
|
argc_ptr,
|
||||||
@@ -70,7 +73,7 @@ pub(crate) fn environ_get(
|
|||||||
memory: &mut [u8],
|
memory: &mut [u8],
|
||||||
environ_ptr: wasi32::uintptr_t,
|
environ_ptr: wasi32::uintptr_t,
|
||||||
environ_buf: wasi32::uintptr_t,
|
environ_buf: wasi32::uintptr_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
trace!(
|
trace!(
|
||||||
"environ_get(environ_ptr={:#x?}, environ_buf={:#x?})",
|
"environ_get(environ_ptr={:#x?}, environ_buf={:#x?})",
|
||||||
environ_ptr,
|
environ_ptr,
|
||||||
@@ -91,7 +94,7 @@ pub(crate) fn environ_get(
|
|||||||
let len = wasi32::uintptr_t::try_from(env_bytes.len())?;
|
let len = wasi32::uintptr_t::try_from(env_bytes.len())?;
|
||||||
environ_buf_offset = environ_buf_offset
|
environ_buf_offset = environ_buf_offset
|
||||||
.checked_add(len)
|
.checked_add(len)
|
||||||
.ok_or(Error::EOVERFLOW)?;
|
.ok_or(WasiError::EOVERFLOW)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
enc_slice_of_wasi32_uintptr(memory, environ.as_slice(), environ_ptr)
|
enc_slice_of_wasi32_uintptr(memory, environ.as_slice(), environ_ptr)
|
||||||
@@ -102,7 +105,7 @@ pub(crate) fn environ_sizes_get(
|
|||||||
memory: &mut [u8],
|
memory: &mut [u8],
|
||||||
environ_count_ptr: wasi32::uintptr_t,
|
environ_count_ptr: wasi32::uintptr_t,
|
||||||
environ_size_ptr: wasi32::uintptr_t,
|
environ_size_ptr: wasi32::uintptr_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
trace!(
|
trace!(
|
||||||
"environ_sizes_get(environ_count_ptr={:#x?}, environ_size_ptr={:#x?})",
|
"environ_sizes_get(environ_count_ptr={:#x?}, environ_size_ptr={:#x?})",
|
||||||
environ_count_ptr,
|
environ_count_ptr,
|
||||||
@@ -116,7 +119,7 @@ pub(crate) fn environ_sizes_get(
|
|||||||
.try_fold(0, |acc: u32, pair| {
|
.try_fold(0, |acc: u32, pair| {
|
||||||
acc.checked_add(pair.as_bytes_with_nul().len() as u32)
|
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);
|
trace!(" | *environ_count_ptr={:?}", environ_count);
|
||||||
|
|
||||||
@@ -132,14 +135,14 @@ pub(crate) fn random_get(
|
|||||||
memory: &mut [u8],
|
memory: &mut [u8],
|
||||||
buf_ptr: wasi32::uintptr_t,
|
buf_ptr: wasi32::uintptr_t,
|
||||||
buf_len: wasi32::size_t,
|
buf_len: wasi32::size_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
trace!("random_get(buf_ptr={:#x?}, buf_len={:?})", buf_ptr, buf_len);
|
trace!("random_get(buf_ptr={:#x?}, buf_len={:?})", buf_ptr, buf_len);
|
||||||
|
|
||||||
let buf = dec_slice_of_mut_u8(memory, buf_ptr, buf_len)?;
|
let buf = dec_slice_of_mut_u8(memory, buf_ptr, buf_len)?;
|
||||||
|
|
||||||
getrandom::getrandom(buf).map_err(|err| {
|
getrandom::getrandom(buf).map_err(|err| {
|
||||||
error!("getrandom failure: {:?}", err);
|
error!("getrandom failure: {:?}", err);
|
||||||
Error::EIO
|
WasiError::EIO
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -148,7 +151,7 @@ pub(crate) fn clock_res_get(
|
|||||||
memory: &mut [u8],
|
memory: &mut [u8],
|
||||||
clock_id: wasi::__wasi_clockid_t,
|
clock_id: wasi::__wasi_clockid_t,
|
||||||
resolution_ptr: wasi32::uintptr_t,
|
resolution_ptr: wasi32::uintptr_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
trace!(
|
trace!(
|
||||||
"clock_res_get(clock_id={:?}, resolution_ptr={:#x?})",
|
"clock_res_get(clock_id={:?}, resolution_ptr={:#x?})",
|
||||||
clock_id,
|
clock_id,
|
||||||
@@ -168,7 +171,7 @@ pub(crate) fn clock_time_get(
|
|||||||
clock_id: wasi::__wasi_clockid_t,
|
clock_id: wasi::__wasi_clockid_t,
|
||||||
precision: wasi::__wasi_timestamp_t,
|
precision: wasi::__wasi_timestamp_t,
|
||||||
time_ptr: wasi32::uintptr_t,
|
time_ptr: wasi32::uintptr_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
trace!(
|
trace!(
|
||||||
"clock_time_get(clock_id={:?}, precision={:?}, time_ptr={:#x?})",
|
"clock_time_get(clock_id={:?}, precision={:?}, time_ptr={:#x?})",
|
||||||
clock_id,
|
clock_id,
|
||||||
@@ -183,7 +186,7 @@ pub(crate) fn clock_time_get(
|
|||||||
enc_timestamp_byref(memory, time_ptr, time)
|
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()");
|
trace!("sched_yield()");
|
||||||
|
|
||||||
std::thread::yield_now();
|
std::thread::yield_now();
|
||||||
@@ -198,7 +201,7 @@ pub(crate) fn poll_oneoff(
|
|||||||
output: wasi32::uintptr_t,
|
output: wasi32::uintptr_t,
|
||||||
nsubscriptions: wasi32::size_t,
|
nsubscriptions: wasi32::size_t,
|
||||||
nevents: wasi32::uintptr_t,
|
nevents: wasi32::uintptr_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
trace!(
|
trace!(
|
||||||
"poll_oneoff(input={:#x?}, output={:#x?}, nsubscriptions={}, nevents={:#x?})",
|
"poll_oneoff(input={:#x?}, output={:#x?}, nsubscriptions={}, nevents={:#x?})",
|
||||||
input,
|
input,
|
||||||
@@ -208,7 +211,7 @@ pub(crate) fn poll_oneoff(
|
|||||||
);
|
);
|
||||||
|
|
||||||
if u64::from(nsubscriptions) > wasi::__wasi_filesize_t::max_value() {
|
if u64::from(nsubscriptions) > wasi::__wasi_filesize_t::max_value() {
|
||||||
return Err(Error::EINVAL);
|
return Err(WasiError::EINVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
enc_int_byref(memory, nevents, 0)?;
|
enc_int_byref(memory, nevents, 0)?;
|
||||||
@@ -222,7 +225,7 @@ pub(crate) fn poll_oneoff(
|
|||||||
// As mandated by the WASI spec:
|
// As mandated by the WASI spec:
|
||||||
// > If `nsubscriptions` is 0, returns `errno::inval`.
|
// > If `nsubscriptions` is 0, returns `errno::inval`.
|
||||||
if subscriptions.is_empty() {
|
if subscriptions.is_empty() {
|
||||||
return Err(Error::EINVAL);
|
return Err(WasiError::EINVAL);
|
||||||
}
|
}
|
||||||
for subscription in subscriptions {
|
for subscription in subscriptions {
|
||||||
match subscription.u.tag {
|
match subscription.u.tag {
|
||||||
@@ -258,7 +261,7 @@ pub(crate) fn poll_oneoff(
|
|||||||
Err(err) => {
|
Err(err) => {
|
||||||
let event = wasi::__wasi_event_t {
|
let event = wasi::__wasi_event_t {
|
||||||
userdata: subscription.userdata,
|
userdata: subscription.userdata,
|
||||||
error: err.as_wasi_error().as_raw_errno(),
|
error: err.as_raw_errno(),
|
||||||
r#type: wasi::__WASI_EVENTTYPE_FD_READ,
|
r#type: wasi::__WASI_EVENTTYPE_FD_READ,
|
||||||
fd_readwrite: wasi::__wasi_event_fd_readwrite_t {
|
fd_readwrite: wasi::__wasi_event_fd_readwrite_t {
|
||||||
nbytes: 0,
|
nbytes: 0,
|
||||||
@@ -286,7 +289,7 @@ pub(crate) fn poll_oneoff(
|
|||||||
Err(err) => {
|
Err(err) => {
|
||||||
let event = wasi::__wasi_event_t {
|
let event = wasi::__wasi_event_t {
|
||||||
userdata: subscription.userdata,
|
userdata: subscription.userdata,
|
||||||
error: err.as_wasi_error().as_raw_errno(),
|
error: err.as_raw_errno(),
|
||||||
r#type: wasi::__WASI_EVENTTYPE_FD_WRITE,
|
r#type: wasi::__WASI_EVENTTYPE_FD_WRITE,
|
||||||
fd_readwrite: wasi::__wasi_event_fd_readwrite_t {
|
fd_readwrite: wasi::__wasi_event_fd_readwrite_t {
|
||||||
nbytes: 0,
|
nbytes: 0,
|
||||||
@@ -310,7 +313,7 @@ pub(crate) fn poll_oneoff(
|
|||||||
// events have been filtered out as errors in the code above.
|
// events have been filtered out as errors in the code above.
|
||||||
hostcalls_impl::poll_oneoff(timeout, fd_events, &mut events)?;
|
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)?;
|
enc_events(memory, output, nsubscriptions, events)?;
|
||||||
|
|
||||||
@@ -319,7 +322,9 @@ pub(crate) fn poll_oneoff(
|
|||||||
enc_int_byref(memory, nevents, events_count)
|
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;
|
use std::time::SystemTime;
|
||||||
|
|
||||||
if wasi_clock.flags != wasi::__WASI_SUBCLOCKFLAGS_SUBSCRIPTION_CLOCK_ABSTIME {
|
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()
|
let now: u128 = SystemTime::now()
|
||||||
.duration_since(SystemTime::UNIX_EPOCH)
|
.duration_since(SystemTime::UNIX_EPOCH)
|
||||||
.map_err(|_| Error::ENOTCAPABLE)?
|
.map_err(|_| WasiError::ENOTCAPABLE)?
|
||||||
.as_nanos();
|
.as_nanos();
|
||||||
let deadline = u128::from(wasi_clock.timeout);
|
let deadline = u128::from(wasi_clock.timeout);
|
||||||
Ok(deadline.saturating_sub(now))
|
Ok(deadline.saturating_sub(now))
|
||||||
@@ -357,6 +362,6 @@ pub(crate) fn proc_raise(
|
|||||||
_wasi_ctx: &WasiCtx,
|
_wasi_ctx: &WasiCtx,
|
||||||
_memory: &mut [u8],
|
_memory: &mut [u8],
|
||||||
_sig: wasi::__wasi_signal_t,
|
_sig: wasi::__wasi_signal_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
unimplemented!("proc_raise")
|
unimplemented!("proc_raise")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
use crate::ctx::WasiCtx;
|
use crate::ctx::WasiCtx;
|
||||||
use crate::{wasi, wasi32, Result};
|
use crate::wasi::{self, WasiResult};
|
||||||
|
use crate::wasi32;
|
||||||
|
|
||||||
pub fn sock_recv(
|
pub fn sock_recv(
|
||||||
_wasi_ctx: &WasiCtx,
|
_wasi_ctx: &WasiCtx,
|
||||||
@@ -10,7 +11,7 @@ pub fn sock_recv(
|
|||||||
_ri_flags: wasi::__wasi_riflags_t,
|
_ri_flags: wasi::__wasi_riflags_t,
|
||||||
_ro_datalen: wasi32::uintptr_t,
|
_ro_datalen: wasi32::uintptr_t,
|
||||||
_ro_flags: wasi32::uintptr_t,
|
_ro_flags: wasi32::uintptr_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
unimplemented!("sock_recv")
|
unimplemented!("sock_recv")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -22,7 +23,7 @@ pub fn sock_send(
|
|||||||
_si_data_len: wasi32::size_t,
|
_si_data_len: wasi32::size_t,
|
||||||
_si_flags: wasi::__wasi_siflags_t,
|
_si_flags: wasi::__wasi_siflags_t,
|
||||||
_so_datalen: wasi32::uintptr_t,
|
_so_datalen: wasi32::uintptr_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
unimplemented!("sock_send")
|
unimplemented!("sock_send")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -31,6 +32,6 @@ pub fn sock_shutdown(
|
|||||||
_memory: &mut [u8],
|
_memory: &mut [u8],
|
||||||
_sock: wasi::__wasi_fd_t,
|
_sock: wasi::__wasi_fd_t,
|
||||||
_how: wasi::__wasi_sdflags_t,
|
_how: wasi::__wasi_sdflags_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
unimplemented!("sock_shutdown")
|
unimplemented!("sock_shutdown")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,6 @@
|
|||||||
)]
|
)]
|
||||||
|
|
||||||
mod ctx;
|
mod ctx;
|
||||||
mod error;
|
|
||||||
mod fdentry;
|
mod fdentry;
|
||||||
pub mod fs;
|
pub mod fs;
|
||||||
mod helpers;
|
mod helpers;
|
||||||
@@ -43,6 +42,3 @@ pub mod hostcalls {
|
|||||||
|
|
||||||
pub use ctx::{WasiCtx, WasiCtxBuilder};
|
pub use ctx::{WasiCtx, WasiCtxBuilder};
|
||||||
pub use sys::preopen_dir;
|
pub use sys::preopen_dir;
|
||||||
|
|
||||||
pub use error::Error;
|
|
||||||
pub(crate) use error::Result;
|
|
||||||
|
|||||||
@@ -8,38 +8,39 @@
|
|||||||
//! are not held for long durations.
|
//! are not held for long durations.
|
||||||
|
|
||||||
#![allow(unused)]
|
#![allow(unused)]
|
||||||
use crate::{host, wasi, wasi32, Error, Result};
|
use crate::wasi::{self, WasiError, WasiResult};
|
||||||
|
use crate::{host, wasi32};
|
||||||
use num::PrimInt;
|
use num::PrimInt;
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
use std::mem::{align_of, size_of};
|
use std::mem::{align_of, size_of};
|
||||||
use std::{ptr, slice};
|
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
|
// 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
|
// translate the pointer
|
||||||
memory
|
memory
|
||||||
.get(ptr as usize..checked_len)
|
.get(ptr as usize..checked_len)
|
||||||
.ok_or(Error::EFAULT)
|
.ok_or(WasiError::EFAULT)
|
||||||
.map(|mem| mem.as_ptr())
|
.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
|
// 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
|
// translate the pointer
|
||||||
memory
|
memory
|
||||||
.get_mut(ptr as usize..checked_len)
|
.get_mut(ptr as usize..checked_len)
|
||||||
.ok_or(Error::EFAULT)
|
.ok_or(WasiError::EFAULT)
|
||||||
.map(|mem| mem.as_mut_ptr())
|
.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
|
// check that the ptr is aligned
|
||||||
if ptr as usize % align_of::<T>() != 0 {
|
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) })
|
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>(
|
fn dec_ptr_to_mut<'memory, T>(
|
||||||
memory: &'memory mut [u8],
|
memory: &'memory mut [u8],
|
||||||
ptr: wasi32::uintptr_t,
|
ptr: wasi32::uintptr_t,
|
||||||
) -> Result<&'memory mut T> {
|
) -> WasiResult<&'memory mut T> {
|
||||||
// check that the ptr is aligned
|
// check that the ptr is aligned
|
||||||
if ptr as usize % align_of::<T>() != 0 {
|
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) })
|
dec_ptr_mut(memory, ptr, size_of::<T>()).map(|p| unsafe { &mut *(p as *mut T) })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This function does not perform endianness conversions!
|
/// 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) })
|
dec_ptr_to::<T>(memory, ptr).map(|p| unsafe { ptr::read(p) })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This function does not perform endianness conversions!
|
/// 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) })
|
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
|
where
|
||||||
T: PrimInt,
|
T: PrimInt,
|
||||||
{
|
{
|
||||||
dec_raw_byref::<T>(memory, ptr).map(|i| PrimInt::from_le(i))
|
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
|
where
|
||||||
T: PrimInt,
|
T: PrimInt,
|
||||||
{
|
{
|
||||||
enc_raw_byref::<T>(memory, ptr, PrimInt::to_le(t))
|
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
|
// check alignment, and that length doesn't overflow
|
||||||
if ptr as usize % align_of::<T>() != 0 {
|
if ptr as usize % align_of::<T>() != 0 {
|
||||||
return Err(Error::EINVAL);
|
return Err(WasiError::EINVAL);
|
||||||
}
|
}
|
||||||
let len = dec_usize(len);
|
let len = dec_usize(len);
|
||||||
let len_bytes = if let Some(len) = size_of::<T>().checked_mul(len) {
|
let len_bytes = if let Some(len) = size_of::<T>().checked_mul(len) {
|
||||||
len
|
len
|
||||||
} else {
|
} else {
|
||||||
return Err(Error::EOVERFLOW);
|
return Err(WasiError::EOVERFLOW);
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok((len, len_bytes))
|
Ok((len, len_bytes))
|
||||||
@@ -100,7 +101,7 @@ fn dec_raw_slice_of<'memory, T>(
|
|||||||
memory: &'memory [u8],
|
memory: &'memory [u8],
|
||||||
ptr: wasi32::uintptr_t,
|
ptr: wasi32::uintptr_t,
|
||||||
len: wasi32::size_t,
|
len: wasi32::size_t,
|
||||||
) -> Result<&'memory [T]> {
|
) -> WasiResult<&'memory [T]> {
|
||||||
let (len, len_bytes) = check_slice_of::<T>(ptr, len)?;
|
let (len, len_bytes) = check_slice_of::<T>(ptr, len)?;
|
||||||
let ptr = dec_ptr(memory, ptr, len_bytes)? as *const T;
|
let ptr = dec_ptr(memory, ptr, len_bytes)? as *const T;
|
||||||
Ok(unsafe { slice::from_raw_parts(ptr, len) })
|
Ok(unsafe { slice::from_raw_parts(ptr, len) })
|
||||||
@@ -110,7 +111,7 @@ fn dec_raw_slice_of_mut<'memory, T>(
|
|||||||
memory: &'memory mut [u8],
|
memory: &'memory mut [u8],
|
||||||
ptr: wasi32::uintptr_t,
|
ptr: wasi32::uintptr_t,
|
||||||
len: wasi32::size_t,
|
len: wasi32::size_t,
|
||||||
) -> Result<&'memory mut [T]> {
|
) -> WasiResult<&'memory mut [T]> {
|
||||||
let (len, len_bytes) = check_slice_of::<T>(ptr, len)?;
|
let (len, len_bytes) = check_slice_of::<T>(ptr, len)?;
|
||||||
let ptr = dec_ptr_mut(memory, ptr, len_bytes)? as *mut T;
|
let ptr = dec_ptr_mut(memory, ptr, len_bytes)? as *mut T;
|
||||||
Ok(unsafe { slice::from_raw_parts_mut(ptr, len) })
|
Ok(unsafe { slice::from_raw_parts_mut(ptr, len) })
|
||||||
@@ -120,16 +121,16 @@ fn raw_slice_for_enc<'memory, T>(
|
|||||||
memory: &'memory mut [u8],
|
memory: &'memory mut [u8],
|
||||||
slice: &[T],
|
slice: &[T],
|
||||||
ptr: wasi32::uintptr_t,
|
ptr: wasi32::uintptr_t,
|
||||||
) -> Result<&'memory mut [T]> {
|
) -> WasiResult<&'memory mut [T]> {
|
||||||
// check alignment
|
// check alignment
|
||||||
if ptr as usize % align_of::<T>() != 0 {
|
if ptr as usize % align_of::<T>() != 0 {
|
||||||
return Err(Error::EINVAL);
|
return Err(WasiError::EINVAL);
|
||||||
}
|
}
|
||||||
// check that length doesn't overflow
|
// check that length doesn't overflow
|
||||||
let len_bytes = if let Some(len) = size_of::<T>().checked_mul(slice.len()) {
|
let len_bytes = if let Some(len) = size_of::<T>().checked_mul(slice.len()) {
|
||||||
len
|
len
|
||||||
} else {
|
} else {
|
||||||
return Err(Error::EOVERFLOW);
|
return Err(WasiError::EOVERFLOW);
|
||||||
};
|
};
|
||||||
|
|
||||||
// get the pointer into guest memory
|
// get the pointer into guest memory
|
||||||
@@ -142,7 +143,7 @@ pub(crate) fn dec_slice_of_u8<'memory>(
|
|||||||
memory: &'memory [u8],
|
memory: &'memory [u8],
|
||||||
ptr: wasi32::uintptr_t,
|
ptr: wasi32::uintptr_t,
|
||||||
len: wasi32::size_t,
|
len: wasi32::size_t,
|
||||||
) -> Result<&'memory [u8]> {
|
) -> WasiResult<&'memory [u8]> {
|
||||||
dec_raw_slice_of::<u8>(memory, ptr, len)
|
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],
|
memory: &'memory mut [u8],
|
||||||
ptr: wasi32::uintptr_t,
|
ptr: wasi32::uintptr_t,
|
||||||
len: wasi32::size_t,
|
len: wasi32::size_t,
|
||||||
) -> Result<&'memory mut [u8]> {
|
) -> WasiResult<&'memory mut [u8]> {
|
||||||
dec_raw_slice_of_mut::<u8>(memory, ptr, len)
|
dec_raw_slice_of_mut::<u8>(memory, ptr, len)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -158,7 +159,7 @@ pub(crate) fn enc_slice_of_u8(
|
|||||||
memory: &mut [u8],
|
memory: &mut [u8],
|
||||||
slice: &[u8],
|
slice: &[u8],
|
||||||
ptr: wasi32::uintptr_t,
|
ptr: wasi32::uintptr_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
let output = raw_slice_for_enc::<u8>(memory, slice, ptr)?;
|
let output = raw_slice_for_enc::<u8>(memory, slice, ptr)?;
|
||||||
|
|
||||||
output.copy_from_slice(slice);
|
output.copy_from_slice(slice);
|
||||||
@@ -170,7 +171,7 @@ pub(crate) fn enc_slice_of_wasi32_uintptr(
|
|||||||
memory: &mut [u8],
|
memory: &mut [u8],
|
||||||
slice: &[wasi32::uintptr_t],
|
slice: &[wasi32::uintptr_t],
|
||||||
ptr: 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();
|
let mut output_iter = raw_slice_for_enc::<wasi32::uintptr_t>(memory, slice, ptr)?.into_iter();
|
||||||
|
|
||||||
for p in slice {
|
for p in slice {
|
||||||
@@ -182,7 +183,10 @@ pub(crate) fn enc_slice_of_wasi32_uintptr(
|
|||||||
|
|
||||||
macro_rules! dec_enc_scalar {
|
macro_rules! dec_enc_scalar {
|
||||||
($ty:ident, $dec_byref:ident, $enc_byref:ident) => {
|
($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)
|
dec_int_byref::<wasi::$ty>(memory, ptr)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -190,7 +194,7 @@ macro_rules! dec_enc_scalar {
|
|||||||
memory: &mut [u8],
|
memory: &mut [u8],
|
||||||
ptr: wasi32::uintptr_t,
|
ptr: wasi32::uintptr_t,
|
||||||
x: wasi::$ty,
|
x: wasi::$ty,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
enc_int_byref::<wasi::$ty>(memory, ptr, x)
|
enc_int_byref::<wasi::$ty>(memory, ptr, x)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -200,7 +204,7 @@ pub(crate) fn dec_ciovec_slice(
|
|||||||
memory: &[u8],
|
memory: &[u8],
|
||||||
ptr: wasi32::uintptr_t,
|
ptr: wasi32::uintptr_t,
|
||||||
len: wasi32::size_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)?;
|
let raw_slice = dec_raw_slice_of::<wasi32::__wasi_ciovec_t>(memory, ptr, len)?;
|
||||||
|
|
||||||
raw_slice
|
raw_slice
|
||||||
@@ -220,7 +224,7 @@ pub(crate) fn dec_iovec_slice(
|
|||||||
memory: &[u8],
|
memory: &[u8],
|
||||||
ptr: wasi32::uintptr_t,
|
ptr: wasi32::uintptr_t,
|
||||||
len: wasi32::size_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)?;
|
let raw_slice = dec_raw_slice_of::<wasi32::__wasi_iovec_t>(memory, ptr, len)?;
|
||||||
|
|
||||||
raw_slice
|
raw_slice
|
||||||
@@ -248,7 +252,7 @@ dec_enc_scalar!(__wasi_linkcount_t, dev_linkcount_byref, enc_linkcount_byref);
|
|||||||
pub(crate) fn dec_filestat_byref(
|
pub(crate) fn dec_filestat_byref(
|
||||||
memory: &mut [u8],
|
memory: &mut [u8],
|
||||||
filestat_ptr: wasi32::uintptr_t,
|
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)?;
|
let raw = dec_raw_byref::<wasi::__wasi_filestat_t>(memory, filestat_ptr)?;
|
||||||
|
|
||||||
Ok(wasi::__wasi_filestat_t {
|
Ok(wasi::__wasi_filestat_t {
|
||||||
@@ -267,7 +271,7 @@ pub(crate) fn enc_filestat_byref(
|
|||||||
memory: &mut [u8],
|
memory: &mut [u8],
|
||||||
filestat_ptr: wasi32::uintptr_t,
|
filestat_ptr: wasi32::uintptr_t,
|
||||||
filestat: wasi::__wasi_filestat_t,
|
filestat: wasi::__wasi_filestat_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
let raw = wasi::__wasi_filestat_t {
|
let raw = wasi::__wasi_filestat_t {
|
||||||
dev: PrimInt::to_le(filestat.dev),
|
dev: PrimInt::to_le(filestat.dev),
|
||||||
ino: PrimInt::to_le(filestat.ino),
|
ino: PrimInt::to_le(filestat.ino),
|
||||||
@@ -285,7 +289,7 @@ pub(crate) fn enc_filestat_byref(
|
|||||||
pub(crate) fn dec_fdstat_byref(
|
pub(crate) fn dec_fdstat_byref(
|
||||||
memory: &mut [u8],
|
memory: &mut [u8],
|
||||||
fdstat_ptr: wasi32::uintptr_t,
|
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)?;
|
let raw = dec_raw_byref::<wasi::__wasi_fdstat_t>(memory, fdstat_ptr)?;
|
||||||
|
|
||||||
Ok(wasi::__wasi_fdstat_t {
|
Ok(wasi::__wasi_fdstat_t {
|
||||||
@@ -300,7 +304,7 @@ pub(crate) fn enc_fdstat_byref(
|
|||||||
memory: &mut [u8],
|
memory: &mut [u8],
|
||||||
fdstat_ptr: wasi32::uintptr_t,
|
fdstat_ptr: wasi32::uintptr_t,
|
||||||
fdstat: wasi::__wasi_fdstat_t,
|
fdstat: wasi::__wasi_fdstat_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
let raw = wasi::__wasi_fdstat_t {
|
let raw = wasi::__wasi_fdstat_t {
|
||||||
fs_filetype: PrimInt::to_le(fdstat.fs_filetype),
|
fs_filetype: PrimInt::to_le(fdstat.fs_filetype),
|
||||||
fs_flags: PrimInt::to_le(fdstat.fs_flags),
|
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(
|
pub(crate) fn dec_prestat_byref(
|
||||||
memory: &mut [u8],
|
memory: &mut [u8],
|
||||||
prestat_ptr: wasi32::uintptr_t,
|
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)?;
|
let raw = dec_raw_byref::<wasi32::__wasi_prestat_t>(memory, prestat_ptr)?;
|
||||||
|
|
||||||
match PrimInt::from_le(raw.tag) {
|
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],
|
memory: &mut [u8],
|
||||||
prestat_ptr: wasi32::uintptr_t,
|
prestat_ptr: wasi32::uintptr_t,
|
||||||
prestat: host::__wasi_prestat_t,
|
prestat: host::__wasi_prestat_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
let raw = match prestat.tag {
|
let raw = match prestat.tag {
|
||||||
wasi::__WASI_PREOPENTYPE_DIR => Ok(wasi32::__wasi_prestat_t {
|
wasi::__WASI_PREOPENTYPE_DIR => Ok(wasi32::__wasi_prestat_t {
|
||||||
tag: PrimInt::to_le(wasi::__WASI_PREOPENTYPE_DIR),
|
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)
|
enc_raw_byref::<wasi32::__wasi_prestat_t>(memory, prestat_ptr, raw)
|
||||||
@@ -377,7 +381,7 @@ pub(crate) fn enc_usize_byref(
|
|||||||
memory: &mut [u8],
|
memory: &mut [u8],
|
||||||
usize_ptr: wasi32::uintptr_t,
|
usize_ptr: wasi32::uintptr_t,
|
||||||
host_usize: usize,
|
host_usize: usize,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
enc_int_byref::<wasi32::size_t>(memory, usize_ptr, enc_usize(host_usize))
|
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],
|
memory: &mut [u8],
|
||||||
input: wasi32::uintptr_t,
|
input: wasi32::uintptr_t,
|
||||||
nsubscriptions: wasi32::size_t,
|
nsubscriptions: wasi32::size_t,
|
||||||
) -> Result<Vec<wasi::__wasi_subscription_t>> {
|
) -> WasiResult<Vec<wasi::__wasi_subscription_t>> {
|
||||||
let raw_input_slice =
|
let raw_input_slice =
|
||||||
dec_raw_slice_of::<wasi::__wasi_subscription_t>(memory, input, nsubscriptions)?;
|
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 {
|
Ok(wasi::__wasi_subscription_t {
|
||||||
userdata,
|
userdata,
|
||||||
u: wasi::__wasi_subscription_u_t { tag, u },
|
u: wasi::__wasi_subscription_u_t { tag, u },
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.collect::<Result<Vec<_>>>()
|
.collect::<WasiResult<Vec<_>>>()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn enc_events(
|
pub(crate) fn enc_events(
|
||||||
@@ -450,7 +454,7 @@ pub(crate) fn enc_events(
|
|||||||
output: wasi32::uintptr_t,
|
output: wasi32::uintptr_t,
|
||||||
nsubscriptions: wasi32::size_t,
|
nsubscriptions: wasi32::size_t,
|
||||||
events: Vec<wasi::__wasi_event_t>,
|
events: Vec<wasi::__wasi_event_t>,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
let mut raw_output_iter =
|
let mut raw_output_iter =
|
||||||
dec_raw_slice_of_mut::<wasi::__wasi_event_t>(memory, output, nsubscriptions)?.into_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::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::borrow::Borrow;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::env;
|
use std::ffi::{self, CString, OsString};
|
||||||
use std::ffi::{CString, OsString};
|
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::path::{Path, PathBuf};
|
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 {
|
enum PendingFdEntry {
|
||||||
Thunk(fn() -> Result<FdEntry>),
|
Thunk(fn() -> io::Result<FdEntry>),
|
||||||
File(File),
|
File(File),
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -18,7 +46,7 @@ impl std::fmt::Debug for PendingFdEntry {
|
|||||||
Self::Thunk(f) => write!(
|
Self::Thunk(f) => write!(
|
||||||
fmt,
|
fmt,
|
||||||
"PendingFdEntry::Thunk({:p})",
|
"PendingFdEntry::Thunk({:p})",
|
||||||
f as *const fn() -> Result<FdEntry>
|
f as *const fn() -> io::Result<FdEntry>
|
||||||
),
|
),
|
||||||
Self::File(f) => write!(fmt, "PendingFdEntry::File({:?})", f),
|
Self::File(f) => write!(fmt, "PendingFdEntry::File({:?})", f),
|
||||||
}
|
}
|
||||||
@@ -44,17 +72,29 @@ impl From<OsString> for PendingCString {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl PendingCString {
|
impl PendingCString {
|
||||||
fn into_string(self) -> Result<String> {
|
fn into_string(self) -> WasiCtxBuilderResult<String> {
|
||||||
match self {
|
let res = match self {
|
||||||
Self::Bytes(v) => String::from_utf8(v).map_err(|_| Error::EILSEQ),
|
Self::Bytes(v) => String::from_utf8(v)?,
|
||||||
Self::OsString(s) => s.into_string().map_err(|_| Error::EILSEQ),
|
#[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`.
|
/// Create a `CString` containing valid UTF-8, or fail.
|
||||||
fn into_utf8_cstring(self) -> Result<CString> {
|
fn into_utf8_cstring(self) -> WasiCtxBuilderResult<CString> {
|
||||||
self.into_string()
|
let s = self.into_string()?;
|
||||||
.and_then(|s| CString::new(s).map_err(|_| Error::EILSEQ))
|
let s = CString::new(s)?;
|
||||||
|
Ok(s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,8 +125,7 @@ impl WasiCtxBuilder {
|
|||||||
|
|
||||||
/// Add arguments to the command-line arguments list.
|
/// Add arguments to the command-line arguments list.
|
||||||
///
|
///
|
||||||
/// Arguments must be valid UTF-8 with no NUL bytes, or else `WasiCtxBuilder::build()` will fail
|
/// Arguments must be valid UTF-8 with no NUL bytes, or else `WasiCtxBuilder::build()` will fail.
|
||||||
/// with `Error::EILSEQ`.
|
|
||||||
pub fn args<S: AsRef<[u8]>>(mut self, args: impl IntoIterator<Item = S>) -> Self {
|
pub fn args<S: AsRef<[u8]>>(mut self, args: impl IntoIterator<Item = S>) -> Self {
|
||||||
self.args = args
|
self.args = args
|
||||||
.into_iter()
|
.into_iter()
|
||||||
@@ -97,8 +136,7 @@ impl WasiCtxBuilder {
|
|||||||
|
|
||||||
/// Add an argument to the command-line arguments list.
|
/// 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
|
/// Arguments must be valid UTF-8 with no NUL bytes, or else `WasiCtxBuilder::build()` will fail.
|
||||||
/// with `Error::EILSEQ`.
|
|
||||||
pub fn arg<S: AsRef<[u8]>>(mut self, arg: S) -> Self {
|
pub fn arg<S: AsRef<[u8]>>(mut self, arg: S) -> Self {
|
||||||
self.args.push(arg.as_ref().to_vec().into());
|
self.args.push(arg.as_ref().to_vec().into());
|
||||||
self
|
self
|
||||||
@@ -107,7 +145,7 @@ impl WasiCtxBuilder {
|
|||||||
/// Inherit the command-line arguments from the host process.
|
/// Inherit the command-line arguments from the host process.
|
||||||
///
|
///
|
||||||
/// If any arguments from the host process contain invalid UTF-8, `WasiCtxBuilder::build()` will
|
/// 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 {
|
pub fn inherit_args(mut self) -> Self {
|
||||||
self.args = env::args_os().map(PendingCString::OsString).collect();
|
self.args = env::args_os().map(PendingCString::OsString).collect();
|
||||||
self
|
self
|
||||||
@@ -127,8 +165,7 @@ impl WasiCtxBuilder {
|
|||||||
/// Inherit the environment variables from the host process.
|
/// Inherit the environment variables from the host process.
|
||||||
///
|
///
|
||||||
/// If any environment variables from the host process contain invalid Unicode (UTF-16 for
|
/// 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
|
/// Windows, UTF-8 for other platforms), `WasiCtxBuilder::build()` will fail.
|
||||||
/// `Error::EILSEQ`.
|
|
||||||
pub fn inherit_env(mut self) -> Self {
|
pub fn inherit_env(mut self) -> Self {
|
||||||
self.env = std::env::vars_os()
|
self.env = std::env::vars_os()
|
||||||
.map(|(k, v)| (k.into(), v.into()))
|
.map(|(k, v)| (k.into(), v.into()))
|
||||||
@@ -139,7 +176,7 @@ impl WasiCtxBuilder {
|
|||||||
/// Add an entry to the environment.
|
/// Add an entry to the environment.
|
||||||
///
|
///
|
||||||
/// Environment variable keys and values must be valid UTF-8 with no NUL bytes, or else
|
/// 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 {
|
pub fn env<S: AsRef<[u8]>>(mut self, k: S, v: S) -> Self {
|
||||||
self.env
|
self.env
|
||||||
.insert(k.as_ref().to_vec().into(), v.as_ref().to_vec().into());
|
.insert(k.as_ref().to_vec().into(), v.as_ref().to_vec().into());
|
||||||
@@ -149,7 +186,7 @@ impl WasiCtxBuilder {
|
|||||||
/// Add entries to the environment.
|
/// Add entries to the environment.
|
||||||
///
|
///
|
||||||
/// Environment variable keys and values must be valid UTF-8 with no NUL bytes, or else
|
/// 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)>>(
|
pub fn envs<S: AsRef<[u8]>, T: Borrow<(S, S)>>(
|
||||||
mut self,
|
mut self,
|
||||||
envs: impl IntoIterator<Item = T>,
|
envs: impl IntoIterator<Item = T>,
|
||||||
@@ -191,15 +228,15 @@ impl WasiCtxBuilder {
|
|||||||
/// Build a `WasiCtx`, consuming this `WasiCtxBuilder`.
|
/// Build a `WasiCtx`, consuming this `WasiCtxBuilder`.
|
||||||
///
|
///
|
||||||
/// If any of the arguments or environment variables in this builder cannot be converted into
|
/// 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`.
|
/// `CString`s, either due to NUL bytes or Unicode conversions, this returns an error.
|
||||||
pub fn build(self) -> Result<WasiCtx> {
|
pub fn build(self) -> WasiCtxBuilderResult<WasiCtx> {
|
||||||
// Process arguments and environment variables into `CString`s, failing quickly if they
|
// Process arguments and environment variables into `CString`s, failing quickly if they
|
||||||
// contain any NUL bytes, or if conversion from `OsString` fails.
|
// contain any NUL bytes, or if conversion from `OsString` fails.
|
||||||
let args = self
|
let args = self
|
||||||
.args
|
.args
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|arg| arg.into_utf8_cstring())
|
.map(|arg| arg.into_utf8_cstring())
|
||||||
.collect::<Result<Vec<CString>>>()?;
|
.collect::<WasiCtxBuilderResult<Vec<CString>>>()?;
|
||||||
|
|
||||||
let env = self
|
let env = self
|
||||||
.env
|
.env
|
||||||
@@ -211,11 +248,12 @@ impl WasiCtxBuilder {
|
|||||||
pair.push_str(v.as_str());
|
pair.push_str(v.as_str());
|
||||||
// We have valid UTF-8, but the keys and values have not yet been checked
|
// We have valid UTF-8, but the keys and values have not yet been checked
|
||||||
// for NULs, so we do a final check here.
|
// 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();
|
let mut fds: HashMap<wasi::__wasi_fd_t, FdEntry> = HashMap::new();
|
||||||
// Populate the non-preopen fds.
|
// Populate the non-preopen fds.
|
||||||
@@ -237,16 +275,20 @@ impl WasiCtxBuilder {
|
|||||||
for (guest_path, dir) in self.preopens {
|
for (guest_path, dir) in self.preopens {
|
||||||
// We do the increment at the beginning of the loop body, so that we don't overflow
|
// 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.
|
// 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() {
|
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
|
// 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.
|
// collisions if we restore that functionality in the future.
|
||||||
while fds.contains_key(&preopen_fd) {
|
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)?;
|
let mut fe = FdEntry::from(dir)?;
|
||||||
fe.preopen_path = Some(guest_path);
|
fe.preopen_path = Some(guest_path);
|
||||||
@@ -274,7 +316,7 @@ impl WasiCtx {
|
|||||||
/// - Environment variables are inherited from the host process.
|
/// - Environment variables are inherited from the host process.
|
||||||
///
|
///
|
||||||
/// To override these behaviors, use `WasiCtxBuilder`.
|
/// 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()
|
WasiCtxBuilder::new()
|
||||||
.args(args)
|
.args(args)
|
||||||
.inherit_stdio()
|
.inherit_stdio()
|
||||||
@@ -288,30 +330,30 @@ impl WasiCtx {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Get an immutable `FdEntry` corresponding to the specified raw WASI `fd`.
|
/// 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> {
|
pub(crate) unsafe fn get_fd_entry(&self, fd: wasi::__wasi_fd_t) -> WasiResult<&FdEntry> {
|
||||||
self.fds.get(&fd).ok_or(Error::EBADF)
|
self.fds.get(&fd).ok_or(WasiError::EBADF)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get a mutable `FdEntry` corresponding to the specified raw WASI `fd`.
|
/// Get a mutable `FdEntry` corresponding to the specified raw WASI `fd`.
|
||||||
pub(crate) unsafe fn get_fd_entry_mut(
|
pub(crate) unsafe fn get_fd_entry_mut(
|
||||||
&mut self,
|
&mut self,
|
||||||
fd: wasi::__wasi_fd_t,
|
fd: wasi::__wasi_fd_t,
|
||||||
) -> Result<&mut FdEntry> {
|
) -> WasiResult<&mut FdEntry> {
|
||||||
self.fds.get_mut(&fd).ok_or(Error::EBADF)
|
self.fds.get_mut(&fd).ok_or(WasiError::EBADF)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Insert the specified `FdEntry` into the `WasiCtx` object.
|
/// Insert the specified `FdEntry` into the `WasiCtx` object.
|
||||||
///
|
///
|
||||||
/// The `FdEntry` will automatically get another free raw WASI `fd` assigned. Note that
|
/// 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.
|
/// 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.
|
// Never insert where stdio handles are expected to be.
|
||||||
let mut fd = 3;
|
let mut fd = 3;
|
||||||
while self.fds.contains_key(&fd) {
|
while self.fds.contains_key(&fd) {
|
||||||
if let Some(next_fd) = fd.checked_add(1) {
|
if let Some(next_fd) = fd.checked_add(1) {
|
||||||
fd = next_fd;
|
fd = next_fd;
|
||||||
} else {
|
} else {
|
||||||
return Err(Error::EMFILE);
|
return Err(WasiError::EMFILE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.fds.insert(fd, fe);
|
self.fds.insert(fd, fe);
|
||||||
@@ -329,7 +371,7 @@ impl WasiCtx {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Remove `FdEntry` corresponding to the specified raw WASI `fd` from the `WasiCtx` object.
|
/// 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> {
|
pub(crate) fn remove_fd_entry(&mut self, fd: wasi::__wasi_fd_t) -> WasiResult<FdEntry> {
|
||||||
self.fds.remove(&fd).ok_or(Error::EBADF)
|
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::{
|
use crate::old::snapshot_0::sys::fdentry_impl::{
|
||||||
descriptor_as_oshandle, determine_type_and_access_rights, OsHandle,
|
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::marker::PhantomData;
|
||||||
use std::mem::ManuallyDrop;
|
use std::mem::ManuallyDrop;
|
||||||
use std::ops::{Deref, DerefMut};
|
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
|
/// 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
|
/// allowing operations which require an actual file and not just a stream or
|
||||||
/// socket file descriptor.
|
/// socket file descriptor.
|
||||||
pub(crate) fn as_file(&self) -> Result<&OsHandle> {
|
pub(crate) fn as_file(&self) -> WasiResult<&OsHandle> {
|
||||||
match self {
|
match self {
|
||||||
Self::OsHandle(file) => Ok(file),
|
Self::OsHandle(file) => Ok(file),
|
||||||
_ => Err(Error::EBADF),
|
_ => Err(WasiError::EBADF),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Like `as_file`, but return a mutable reference.
|
/// 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 {
|
match self {
|
||||||
Self::OsHandle(file) => Ok(file),
|
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`.
|
/// Create an FdEntry with *maximal* possible rights from a given `File`.
|
||||||
/// If this is not desired, the rights of the resulting `FdEntry` should
|
/// If this is not desired, the rights of the resulting `FdEntry` should
|
||||||
/// be manually restricted.
|
/// 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(
|
unsafe { determine_type_and_access_rights(&file) }.map(
|
||||||
|(file_type, rights_base, rights_inheriting)| Self {
|
|(file_type, rights_base, rights_inheriting)| Self {
|
||||||
file_type,
|
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(
|
unsafe { determine_type_and_access_rights(&io::stdin()) }.map(
|
||||||
|(file_type, rights_base, rights_inheriting)| Self {
|
|(file_type, rights_base, rights_inheriting)| Self {
|
||||||
file_type,
|
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(
|
unsafe { determine_type_and_access_rights(&io::stdout()) }.map(
|
||||||
|(file_type, rights_base, rights_inheriting)| Self {
|
|(file_type, rights_base, rights_inheriting)| Self {
|
||||||
file_type,
|
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(
|
unsafe { determine_type_and_access_rights(&io::stderr()) }.map(
|
||||||
|(file_type, rights_base, rights_inheriting)| Self {
|
|(file_type, rights_base, rights_inheriting)| Self {
|
||||||
file_type,
|
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()?)
|
Self::from(dev_null()?)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -127,7 +127,7 @@ impl FdEntry {
|
|||||||
&self,
|
&self,
|
||||||
rights_base: wasi::__wasi_rights_t,
|
rights_base: wasi::__wasi_rights_t,
|
||||||
rights_inheriting: wasi::__wasi_rights_t,
|
rights_inheriting: wasi::__wasi_rights_t,
|
||||||
) -> Result<&Descriptor> {
|
) -> WasiResult<&Descriptor> {
|
||||||
self.validate_rights(rights_base, rights_inheriting)?;
|
self.validate_rights(rights_base, rights_inheriting)?;
|
||||||
Ok(&self.descriptor)
|
Ok(&self.descriptor)
|
||||||
}
|
}
|
||||||
@@ -143,7 +143,7 @@ impl FdEntry {
|
|||||||
&mut self,
|
&mut self,
|
||||||
rights_base: wasi::__wasi_rights_t,
|
rights_base: wasi::__wasi_rights_t,
|
||||||
rights_inheriting: wasi::__wasi_rights_t,
|
rights_inheriting: wasi::__wasi_rights_t,
|
||||||
) -> Result<&mut Descriptor> {
|
) -> WasiResult<&mut Descriptor> {
|
||||||
self.validate_rights(rights_base, rights_inheriting)?;
|
self.validate_rights(rights_base, rights_inheriting)?;
|
||||||
Ok(&mut self.descriptor)
|
Ok(&mut self.descriptor)
|
||||||
}
|
}
|
||||||
@@ -157,10 +157,10 @@ impl FdEntry {
|
|||||||
&self,
|
&self,
|
||||||
rights_base: wasi::__wasi_rights_t,
|
rights_base: wasi::__wasi_rights_t,
|
||||||
rights_inheriting: 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
|
if !self.rights_base & rights_base != 0 || !self.rights_inheriting & rights_inheriting != 0
|
||||||
{
|
{
|
||||||
Err(Error::ENOTCAPABLE)
|
Err(WasiError::ENOTCAPABLE)
|
||||||
} else {
|
} else {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
use crate::old::snapshot_0::{Error, Result};
|
use crate::old::snapshot_0::wasi::WasiResult;
|
||||||
use std::str;
|
use std::str;
|
||||||
|
|
||||||
/// Creates not-owned WASI path from byte slice.
|
/// Creates not-owned WASI path from byte slice.
|
||||||
///
|
///
|
||||||
/// NB WASI spec requires bytes to be valid UTF-8. Otherwise,
|
/// NB WASI spec requires bytes to be valid UTF-8. Otherwise,
|
||||||
/// `__WASI_ERRNO_ILSEQ` error is returned.
|
/// `__WASI_ERRNO_ILSEQ` error is returned.
|
||||||
pub(crate) fn path_from_slice<'a>(s: &'a [u8]) -> Result<&'a str> {
|
pub(crate) fn path_from_slice<'a>(s: &'a [u8]) -> WasiResult<&'a str> {
|
||||||
str::from_utf8(s).map_err(|_| Error::EILSEQ)
|
let s = str::from_utf8(s)?;
|
||||||
|
Ok(s)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,6 @@
|
|||||||
#![allow(non_snake_case)]
|
#![allow(non_snake_case)]
|
||||||
|
|
||||||
use crate::old::snapshot_0::wasi::*;
|
use crate::old::snapshot_0::wasi::*;
|
||||||
use crate::old::snapshot_0::{Error, Result};
|
|
||||||
use std::{convert::TryInto, io, mem, slice};
|
use std::{convert::TryInto, io, mem, slice};
|
||||||
use wig::witx_host_types;
|
use wig::witx_host_types;
|
||||||
|
|
||||||
@@ -52,11 +51,13 @@ pub(crate) struct Dirent {
|
|||||||
impl Dirent {
|
impl Dirent {
|
||||||
/// Serialize the directory entry to the format define by `__wasi_fd_readdir`,
|
/// Serialize the directory entry to the format define by `__wasi_fd_readdir`,
|
||||||
/// so that the serialized entries can be concatenated by the implementation.
|
/// 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 name = self.name.as_bytes();
|
||||||
let namlen = name.len();
|
let namlen = name.len();
|
||||||
let dirent_size = mem::size_of::<__wasi_dirent_t>();
|
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);
|
let mut raw = Vec::<u8>::with_capacity(offset);
|
||||||
raw.resize(offset, 0);
|
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::fdentry_impl::determine_type_rights;
|
||||||
use crate::old::snapshot_0::sys::hostcalls_impl::fs_helpers::path_open_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::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 crate::sandboxed_tty_writer::SandboxedTTYWriter;
|
||||||
use filetime::{set_file_handle_times, FileTime};
|
use filetime::{set_file_handle_times, FileTime};
|
||||||
use log::trace;
|
use log::trace;
|
||||||
@@ -20,13 +21,13 @@ pub(crate) unsafe fn fd_close(
|
|||||||
wasi_ctx: &mut WasiCtx,
|
wasi_ctx: &mut WasiCtx,
|
||||||
_mem: &mut [u8],
|
_mem: &mut [u8],
|
||||||
fd: wasi::__wasi_fd_t,
|
fd: wasi::__wasi_fd_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
trace!("fd_close(fd={:?})", fd);
|
trace!("fd_close(fd={:?})", fd);
|
||||||
|
|
||||||
if let Ok(fe) = wasi_ctx.get_fd_entry(fd) {
|
if let Ok(fe) = wasi_ctx.get_fd_entry(fd) {
|
||||||
// can't close preopened files
|
// can't close preopened files
|
||||||
if fe.preopen_path.is_some() {
|
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,
|
wasi_ctx: &WasiCtx,
|
||||||
_mem: &mut [u8],
|
_mem: &mut [u8],
|
||||||
fd: wasi::__wasi_fd_t,
|
fd: wasi::__wasi_fd_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
trace!("fd_datasync(fd={:?})", fd);
|
trace!("fd_datasync(fd={:?})", fd);
|
||||||
|
|
||||||
let fd = wasi_ctx
|
let fd = wasi_ctx
|
||||||
@@ -57,7 +58,7 @@ pub(crate) unsafe fn fd_pread(
|
|||||||
iovs_len: wasi32::size_t,
|
iovs_len: wasi32::size_t,
|
||||||
offset: wasi::__wasi_filesize_t,
|
offset: wasi::__wasi_filesize_t,
|
||||||
nread: wasi32::uintptr_t,
|
nread: wasi32::uintptr_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
trace!(
|
trace!(
|
||||||
"fd_pread(fd={:?}, iovs_ptr={:#x?}, iovs_len={:?}, offset={}, nread={:#x?})",
|
"fd_pread(fd={:?}, iovs_ptr={:#x?}, iovs_len={:?}, offset={}, nread={:#x?})",
|
||||||
fd,
|
fd,
|
||||||
@@ -75,7 +76,7 @@ pub(crate) unsafe fn fd_pread(
|
|||||||
let iovs = dec_iovec_slice(memory, iovs_ptr, iovs_len)?;
|
let iovs = dec_iovec_slice(memory, iovs_ptr, iovs_len)?;
|
||||||
|
|
||||||
if offset > i64::max_value() as u64 {
|
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 buf_size = iovs.iter().map(|v| v.buf_len).sum();
|
||||||
let mut buf = vec![0; buf_size];
|
let mut buf = vec![0; buf_size];
|
||||||
@@ -106,7 +107,7 @@ pub(crate) unsafe fn fd_pwrite(
|
|||||||
iovs_len: wasi32::size_t,
|
iovs_len: wasi32::size_t,
|
||||||
offset: wasi::__wasi_filesize_t,
|
offset: wasi::__wasi_filesize_t,
|
||||||
nwritten: wasi32::uintptr_t,
|
nwritten: wasi32::uintptr_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
trace!(
|
trace!(
|
||||||
"fd_pwrite(fd={:?}, iovs_ptr={:#x?}, iovs_len={:?}, offset={}, nwritten={:#x?})",
|
"fd_pwrite(fd={:?}, iovs_ptr={:#x?}, iovs_len={:?}, offset={}, nwritten={:#x?})",
|
||||||
fd,
|
fd,
|
||||||
@@ -126,7 +127,7 @@ pub(crate) unsafe fn fd_pwrite(
|
|||||||
let iovs = dec_ciovec_slice(memory, iovs_ptr, iovs_len)?;
|
let iovs = dec_ciovec_slice(memory, iovs_ptr, iovs_len)?;
|
||||||
|
|
||||||
if offset > i64::max_value() as u64 {
|
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 buf_size = iovs.iter().map(|v| v.buf_len).sum();
|
||||||
let mut buf = Vec::with_capacity(buf_size);
|
let mut buf = Vec::with_capacity(buf_size);
|
||||||
@@ -150,7 +151,7 @@ pub(crate) unsafe fn fd_read(
|
|||||||
iovs_ptr: wasi32::uintptr_t,
|
iovs_ptr: wasi32::uintptr_t,
|
||||||
iovs_len: wasi32::size_t,
|
iovs_len: wasi32::size_t,
|
||||||
nread: wasi32::uintptr_t,
|
nread: wasi32::uintptr_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
trace!(
|
trace!(
|
||||||
"fd_read(fd={:?}, iovs_ptr={:#x?}, iovs_len={:?}, nread={:#x?})",
|
"fd_read(fd={:?}, iovs_ptr={:#x?}, iovs_len={:?}, nread={:#x?})",
|
||||||
fd,
|
fd,
|
||||||
@@ -171,7 +172,7 @@ pub(crate) unsafe fn fd_read(
|
|||||||
{
|
{
|
||||||
Descriptor::OsHandle(file) => file.read_vectored(&mut iovs),
|
Descriptor::OsHandle(file) => file.read_vectored(&mut iovs),
|
||||||
Descriptor::Stdin => io::stdin().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?;
|
let host_nread = maybe_host_nread?;
|
||||||
@@ -186,11 +187,11 @@ pub(crate) unsafe fn fd_renumber(
|
|||||||
_mem: &mut [u8],
|
_mem: &mut [u8],
|
||||||
from: wasi::__wasi_fd_t,
|
from: wasi::__wasi_fd_t,
|
||||||
to: wasi::__wasi_fd_t,
|
to: wasi::__wasi_fd_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
trace!("fd_renumber(from={:?}, to={:?})", from, to);
|
trace!("fd_renumber(from={:?}, to={:?})", from, to);
|
||||||
|
|
||||||
if !wasi_ctx.contains_fd_entry(from) {
|
if !wasi_ctx.contains_fd_entry(from) {
|
||||||
return Err(Error::EBADF);
|
return Err(WasiError::EBADF);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't allow renumbering over a pre-opened resource.
|
// 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.
|
// userspace is capable of removing entries from its tables as well.
|
||||||
let from_fe = wasi_ctx.get_fd_entry(from)?;
|
let from_fe = wasi_ctx.get_fd_entry(from)?;
|
||||||
if from_fe.preopen_path.is_some() {
|
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 let Ok(to_fe) = wasi_ctx.get_fd_entry(to) {
|
||||||
if to_fe.preopen_path.is_some() {
|
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,
|
offset: wasi::__wasi_filedelta_t,
|
||||||
whence: wasi::__wasi_whence_t,
|
whence: wasi::__wasi_whence_t,
|
||||||
newoffset: wasi32::uintptr_t,
|
newoffset: wasi32::uintptr_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
trace!(
|
trace!(
|
||||||
"fd_seek(fd={:?}, offset={:?}, whence={}, newoffset={:#x?})",
|
"fd_seek(fd={:?}, offset={:?}, whence={}, newoffset={:#x?})",
|
||||||
fd,
|
fd,
|
||||||
@@ -242,7 +243,7 @@ pub(crate) unsafe fn fd_seek(
|
|||||||
wasi::__WASI_WHENCE_CUR => SeekFrom::Current(offset),
|
wasi::__WASI_WHENCE_CUR => SeekFrom::Current(offset),
|
||||||
wasi::__WASI_WHENCE_END => SeekFrom::End(offset),
|
wasi::__WASI_WHENCE_END => SeekFrom::End(offset),
|
||||||
wasi::__WASI_WHENCE_SET => SeekFrom::Start(offset as u64),
|
wasi::__WASI_WHENCE_SET => SeekFrom::Start(offset as u64),
|
||||||
_ => return Err(Error::EINVAL),
|
_ => return Err(WasiError::EINVAL),
|
||||||
};
|
};
|
||||||
let host_newoffset = fd.seek(pos)?;
|
let host_newoffset = fd.seek(pos)?;
|
||||||
|
|
||||||
@@ -256,7 +257,7 @@ pub(crate) unsafe fn fd_tell(
|
|||||||
memory: &mut [u8],
|
memory: &mut [u8],
|
||||||
fd: wasi::__wasi_fd_t,
|
fd: wasi::__wasi_fd_t,
|
||||||
newoffset: wasi32::uintptr_t,
|
newoffset: wasi32::uintptr_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
trace!("fd_tell(fd={:?}, newoffset={:#x?})", fd, newoffset);
|
trace!("fd_tell(fd={:?}, newoffset={:#x?})", fd, newoffset);
|
||||||
|
|
||||||
let fd = wasi_ctx
|
let fd = wasi_ctx
|
||||||
@@ -276,7 +277,7 @@ pub(crate) unsafe fn fd_fdstat_get(
|
|||||||
memory: &mut [u8],
|
memory: &mut [u8],
|
||||||
fd: wasi::__wasi_fd_t,
|
fd: wasi::__wasi_fd_t,
|
||||||
fdstat_ptr: wasi32::uintptr_t, // *mut wasi::__wasi_fdstat_t
|
fdstat_ptr: wasi32::uintptr_t, // *mut wasi::__wasi_fdstat_t
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
trace!("fd_fdstat_get(fd={:?}, fdstat_ptr={:#x?})", fd, fdstat_ptr);
|
trace!("fd_fdstat_get(fd={:?}, fdstat_ptr={:#x?})", fd, fdstat_ptr);
|
||||||
|
|
||||||
let mut fdstat = dec_fdstat_byref(memory, 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],
|
_mem: &mut [u8],
|
||||||
fd: wasi::__wasi_fd_t,
|
fd: wasi::__wasi_fd_t,
|
||||||
fdflags: wasi::__wasi_fdflags_t,
|
fdflags: wasi::__wasi_fdflags_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
trace!("fd_fdstat_set_flags(fd={:?}, fdflags={:#x?})", fd, fdflags);
|
trace!("fd_fdstat_set_flags(fd={:?}, fdflags={:#x?})", fd, fdflags);
|
||||||
|
|
||||||
let fd = wasi_ctx
|
let fd = wasi_ctx
|
||||||
@@ -320,7 +321,7 @@ pub(crate) unsafe fn fd_fdstat_set_rights(
|
|||||||
fd: wasi::__wasi_fd_t,
|
fd: wasi::__wasi_fd_t,
|
||||||
fs_rights_base: wasi::__wasi_rights_t,
|
fs_rights_base: wasi::__wasi_rights_t,
|
||||||
fs_rights_inheriting: wasi::__wasi_rights_t,
|
fs_rights_inheriting: wasi::__wasi_rights_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
trace!(
|
trace!(
|
||||||
"fd_fdstat_set_rights(fd={:?}, fs_rights_base={:#x?}, fs_rights_inheriting={:#x?})",
|
"fd_fdstat_set_rights(fd={:?}, fs_rights_base={:#x?}, fs_rights_inheriting={:#x?})",
|
||||||
fd,
|
fd,
|
||||||
@@ -332,7 +333,7 @@ pub(crate) unsafe fn fd_fdstat_set_rights(
|
|||||||
if fe.rights_base & fs_rights_base != fs_rights_base
|
if fe.rights_base & fs_rights_base != fs_rights_base
|
||||||
|| fe.rights_inheriting & fs_rights_inheriting != fs_rights_inheriting
|
|| 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_base = fs_rights_base;
|
||||||
fe.rights_inheriting = fs_rights_inheriting;
|
fe.rights_inheriting = fs_rights_inheriting;
|
||||||
@@ -344,7 +345,7 @@ pub(crate) unsafe fn fd_sync(
|
|||||||
wasi_ctx: &WasiCtx,
|
wasi_ctx: &WasiCtx,
|
||||||
_mem: &mut [u8],
|
_mem: &mut [u8],
|
||||||
fd: wasi::__wasi_fd_t,
|
fd: wasi::__wasi_fd_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
trace!("fd_sync(fd={:?})", fd);
|
trace!("fd_sync(fd={:?})", fd);
|
||||||
|
|
||||||
let fd = wasi_ctx
|
let fd = wasi_ctx
|
||||||
@@ -361,7 +362,7 @@ pub(crate) unsafe fn fd_write(
|
|||||||
iovs_ptr: wasi32::uintptr_t,
|
iovs_ptr: wasi32::uintptr_t,
|
||||||
iovs_len: wasi32::size_t,
|
iovs_len: wasi32::size_t,
|
||||||
nwritten: wasi32::uintptr_t,
|
nwritten: wasi32::uintptr_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
trace!(
|
trace!(
|
||||||
"fd_write(fd={:?}, iovs_ptr={:#x?}, iovs_len={:?}, nwritten={:#x?})",
|
"fd_write(fd={:?}, iovs_ptr={:#x?}, iovs_len={:?}, nwritten={:#x?})",
|
||||||
fd,
|
fd,
|
||||||
@@ -385,7 +386,7 @@ pub(crate) unsafe fn fd_write(
|
|||||||
file.write_vectored(&iovs)?
|
file.write_vectored(&iovs)?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Descriptor::Stdin => return Err(Error::EBADF),
|
Descriptor::Stdin => return Err(WasiError::EBADF),
|
||||||
Descriptor::Stdout => {
|
Descriptor::Stdout => {
|
||||||
// lock for the duration of the scope
|
// lock for the duration of the scope
|
||||||
let stdout = io::stdout();
|
let stdout = io::stdout();
|
||||||
@@ -417,7 +418,7 @@ pub(crate) unsafe fn fd_advise(
|
|||||||
offset: wasi::__wasi_filesize_t,
|
offset: wasi::__wasi_filesize_t,
|
||||||
len: wasi::__wasi_filesize_t,
|
len: wasi::__wasi_filesize_t,
|
||||||
advice: wasi::__wasi_advice_t,
|
advice: wasi::__wasi_advice_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
trace!(
|
trace!(
|
||||||
"fd_advise(fd={:?}, offset={}, len={}, advice={:?})",
|
"fd_advise(fd={:?}, offset={}, len={}, advice={:?})",
|
||||||
fd,
|
fd,
|
||||||
@@ -440,7 +441,7 @@ pub(crate) unsafe fn fd_allocate(
|
|||||||
fd: wasi::__wasi_fd_t,
|
fd: wasi::__wasi_fd_t,
|
||||||
offset: wasi::__wasi_filesize_t,
|
offset: wasi::__wasi_filesize_t,
|
||||||
len: wasi::__wasi_filesize_t,
|
len: wasi::__wasi_filesize_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
trace!("fd_allocate(fd={:?}, offset={}, len={})", fd, offset, len);
|
trace!("fd_allocate(fd={:?}, offset={}, len={})", fd, offset, len);
|
||||||
|
|
||||||
let fd = wasi_ctx
|
let fd = wasi_ctx
|
||||||
@@ -451,10 +452,10 @@ pub(crate) unsafe fn fd_allocate(
|
|||||||
let metadata = fd.metadata()?;
|
let metadata = fd.metadata()?;
|
||||||
|
|
||||||
let current_size = metadata.len();
|
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
|
// This check will be unnecessary when rust-lang/rust#63326 is fixed
|
||||||
if wanted_size > i64::max_value() as u64 {
|
if wanted_size > i64::max_value() as u64 {
|
||||||
return Err(Error::E2BIG);
|
return Err(WasiError::E2BIG);
|
||||||
}
|
}
|
||||||
|
|
||||||
if wanted_size > current_size {
|
if wanted_size > current_size {
|
||||||
@@ -470,7 +471,7 @@ pub(crate) unsafe fn path_create_directory(
|
|||||||
dirfd: wasi::__wasi_fd_t,
|
dirfd: wasi::__wasi_fd_t,
|
||||||
path_ptr: wasi32::uintptr_t,
|
path_ptr: wasi32::uintptr_t,
|
||||||
path_len: wasi32::size_t,
|
path_len: wasi32::size_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
trace!(
|
trace!(
|
||||||
"path_create_directory(dirfd={:?}, path_ptr={:#x?}, path_len={})",
|
"path_create_directory(dirfd={:?}, path_ptr={:#x?}, path_len={})",
|
||||||
dirfd,
|
dirfd,
|
||||||
@@ -499,7 +500,7 @@ pub(crate) unsafe fn path_link(
|
|||||||
new_dirfd: wasi::__wasi_fd_t,
|
new_dirfd: wasi::__wasi_fd_t,
|
||||||
new_path_ptr: wasi32::uintptr_t,
|
new_path_ptr: wasi32::uintptr_t,
|
||||||
new_path_len: wasi32::size_t,
|
new_path_len: wasi32::size_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
trace!(
|
trace!(
|
||||||
"path_link(old_dirfd={:?}, old_flags={:?}, old_path_ptr={:#x?}, old_path_len={}, new_dirfd={:?}, new_path_ptr={:#x?}, new_path_len={})",
|
"path_link(old_dirfd={:?}, old_flags={:?}, old_path_ptr={:#x?}, old_path_len={}, new_dirfd={:?}, new_path_ptr={:#x?}, new_path_len={})",
|
||||||
old_dirfd,
|
old_dirfd,
|
||||||
@@ -551,7 +552,7 @@ pub(crate) unsafe fn path_open(
|
|||||||
fs_rights_inheriting: wasi::__wasi_rights_t,
|
fs_rights_inheriting: wasi::__wasi_rights_t,
|
||||||
fs_flags: wasi::__wasi_fdflags_t,
|
fs_flags: wasi::__wasi_fdflags_t,
|
||||||
fd_out_ptr: wasi32::uintptr_t,
|
fd_out_ptr: wasi32::uintptr_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
trace!(
|
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?})",
|
"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,
|
dirfd,
|
||||||
@@ -616,7 +617,7 @@ pub(crate) unsafe fn path_readlink(
|
|||||||
buf_ptr: wasi32::uintptr_t,
|
buf_ptr: wasi32::uintptr_t,
|
||||||
buf_len: wasi32::size_t,
|
buf_len: wasi32::size_t,
|
||||||
buf_used: wasi32::uintptr_t,
|
buf_used: wasi32::uintptr_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
trace!(
|
trace!(
|
||||||
"path_readlink(dirfd={:?}, path_ptr={:#x?}, path_len={:?}, buf_ptr={:#x?}, buf_len={}, buf_used={:#x?})",
|
"path_readlink(dirfd={:?}, path_ptr={:#x?}, path_len={:?}, buf_ptr={:#x?}, buf_len={}, buf_used={:#x?})",
|
||||||
dirfd,
|
dirfd,
|
||||||
@@ -655,7 +656,7 @@ pub(crate) unsafe fn path_rename(
|
|||||||
new_dirfd: wasi::__wasi_fd_t,
|
new_dirfd: wasi::__wasi_fd_t,
|
||||||
new_path_ptr: wasi32::uintptr_t,
|
new_path_ptr: wasi32::uintptr_t,
|
||||||
new_path_len: wasi32::size_t,
|
new_path_len: wasi32::size_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
trace!(
|
trace!(
|
||||||
"path_rename(old_dirfd={:?}, old_path_ptr={:#x?}, old_path_len={:?}, new_dirfd={:?}, new_path_ptr={:#x?}, new_path_len={:?})",
|
"path_rename(old_dirfd={:?}, old_path_ptr={:#x?}, old_path_len={:?}, new_dirfd={:?}, new_path_ptr={:#x?}, new_path_len={:?})",
|
||||||
old_dirfd,
|
old_dirfd,
|
||||||
@@ -702,7 +703,7 @@ pub(crate) unsafe fn fd_filestat_get(
|
|||||||
memory: &mut [u8],
|
memory: &mut [u8],
|
||||||
fd: wasi::__wasi_fd_t,
|
fd: wasi::__wasi_fd_t,
|
||||||
filestat_ptr: wasi32::uintptr_t,
|
filestat_ptr: wasi32::uintptr_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
trace!(
|
trace!(
|
||||||
"fd_filestat_get(fd={:?}, filestat_ptr={:#x?})",
|
"fd_filestat_get(fd={:?}, filestat_ptr={:#x?})",
|
||||||
fd,
|
fd,
|
||||||
@@ -724,7 +725,7 @@ pub(crate) unsafe fn fd_filestat_set_times(
|
|||||||
st_atim: wasi::__wasi_timestamp_t,
|
st_atim: wasi::__wasi_timestamp_t,
|
||||||
st_mtim: wasi::__wasi_timestamp_t,
|
st_mtim: wasi::__wasi_timestamp_t,
|
||||||
fst_flags: wasi::__wasi_fstflags_t,
|
fst_flags: wasi::__wasi_fstflags_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
trace!(
|
trace!(
|
||||||
"fd_filestat_set_times(fd={:?}, st_atim={}, st_mtim={}, fst_flags={:#x?})",
|
"fd_filestat_set_times(fd={:?}, st_atim={}, st_mtim={}, fst_flags={:#x?})",
|
||||||
fd,
|
fd,
|
||||||
@@ -746,14 +747,14 @@ pub(crate) fn fd_filestat_set_times_impl(
|
|||||||
st_atim: wasi::__wasi_timestamp_t,
|
st_atim: wasi::__wasi_timestamp_t,
|
||||||
st_mtim: wasi::__wasi_timestamp_t,
|
st_mtim: wasi::__wasi_timestamp_t,
|
||||||
fst_flags: wasi::__wasi_fstflags_t,
|
fst_flags: wasi::__wasi_fstflags_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
let set_atim = fst_flags & wasi::__WASI_FSTFLAGS_ATIM != 0;
|
let set_atim = fst_flags & wasi::__WASI_FSTFLAGS_ATIM != 0;
|
||||||
let set_atim_now = fst_flags & wasi::__WASI_FSTFLAGS_ATIM_NOW != 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 = fst_flags & wasi::__WASI_FSTFLAGS_MTIM != 0;
|
||||||
let set_mtim_now = fst_flags & wasi::__WASI_FSTFLAGS_MTIM_NOW != 0;
|
let set_mtim_now = fst_flags & wasi::__WASI_FSTFLAGS_MTIM_NOW != 0;
|
||||||
|
|
||||||
if (set_atim && set_atim_now) || (set_mtim && set_mtim_now) {
|
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 atim = if set_atim {
|
||||||
let time = UNIX_EPOCH + Duration::from_nanos(st_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],
|
_mem: &mut [u8],
|
||||||
fd: wasi::__wasi_fd_t,
|
fd: wasi::__wasi_fd_t,
|
||||||
st_size: wasi::__wasi_filesize_t,
|
st_size: wasi::__wasi_filesize_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
trace!("fd_filestat_set_size(fd={:?}, st_size={})", fd, st_size);
|
trace!("fd_filestat_set_size(fd={:?}, st_size={})", fd, st_size);
|
||||||
|
|
||||||
let fd = wasi_ctx
|
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
|
// This check will be unnecessary when rust-lang/rust#63326 is fixed
|
||||||
if st_size > i64::max_value() as u64 {
|
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)
|
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_ptr: wasi32::uintptr_t,
|
||||||
path_len: wasi32::size_t,
|
path_len: wasi32::size_t,
|
||||||
filestat_ptr: wasi32::uintptr_t,
|
filestat_ptr: wasi32::uintptr_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
trace!(
|
trace!(
|
||||||
"path_filestat_get(dirfd={:?}, dirflags={:?}, path_ptr={:#x?}, path_len={}, filestat_ptr={:#x?})",
|
"path_filestat_get(dirfd={:?}, dirflags={:?}, path_ptr={:#x?}, path_len={}, filestat_ptr={:#x?})",
|
||||||
dirfd,
|
dirfd,
|
||||||
@@ -845,7 +846,7 @@ pub(crate) unsafe fn path_filestat_set_times(
|
|||||||
st_atim: wasi::__wasi_timestamp_t,
|
st_atim: wasi::__wasi_timestamp_t,
|
||||||
st_mtim: wasi::__wasi_timestamp_t,
|
st_mtim: wasi::__wasi_timestamp_t,
|
||||||
fst_flags: wasi::__wasi_fstflags_t,
|
fst_flags: wasi::__wasi_fstflags_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
trace!(
|
trace!(
|
||||||
"path_filestat_set_times(dirfd={:?}, dirflags={:?}, path_ptr={:#x?}, path_len={}, st_atim={}, st_mtim={}, fst_flags={:#x?})",
|
"path_filestat_set_times(dirfd={:?}, dirflags={:?}, path_ptr={:#x?}, path_len={}, st_atim={}, st_mtim={}, fst_flags={:#x?})",
|
||||||
dirfd,
|
dirfd,
|
||||||
@@ -881,7 +882,7 @@ pub(crate) unsafe fn path_symlink(
|
|||||||
dirfd: wasi::__wasi_fd_t,
|
dirfd: wasi::__wasi_fd_t,
|
||||||
new_path_ptr: wasi32::uintptr_t,
|
new_path_ptr: wasi32::uintptr_t,
|
||||||
new_path_len: wasi32::size_t,
|
new_path_len: wasi32::size_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
trace!(
|
trace!(
|
||||||
"path_symlink(old_path_ptr={:#x?}, old_path_len={}, dirfd={:?}, new_path_ptr={:#x?}, new_path_len={})",
|
"path_symlink(old_path_ptr={:#x?}, old_path_len={}, dirfd={:?}, new_path_ptr={:#x?}, new_path_len={})",
|
||||||
old_path_ptr,
|
old_path_ptr,
|
||||||
@@ -909,7 +910,7 @@ pub(crate) unsafe fn path_unlink_file(
|
|||||||
dirfd: wasi::__wasi_fd_t,
|
dirfd: wasi::__wasi_fd_t,
|
||||||
path_ptr: wasi32::uintptr_t,
|
path_ptr: wasi32::uintptr_t,
|
||||||
path_len: wasi32::size_t,
|
path_len: wasi32::size_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
trace!(
|
trace!(
|
||||||
"path_unlink_file(dirfd={:?}, path_ptr={:#x?}, path_len={})",
|
"path_unlink_file(dirfd={:?}, path_ptr={:#x?}, path_len={})",
|
||||||
dirfd,
|
dirfd,
|
||||||
@@ -933,7 +934,7 @@ pub(crate) unsafe fn path_remove_directory(
|
|||||||
dirfd: wasi::__wasi_fd_t,
|
dirfd: wasi::__wasi_fd_t,
|
||||||
path_ptr: wasi32::uintptr_t,
|
path_ptr: wasi32::uintptr_t,
|
||||||
path_len: wasi32::size_t,
|
path_len: wasi32::size_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
trace!(
|
trace!(
|
||||||
"path_remove_directory(dirfd={:?}, path_ptr={:#x?}, path_len={})",
|
"path_remove_directory(dirfd={:?}, path_ptr={:#x?}, path_len={})",
|
||||||
dirfd,
|
dirfd,
|
||||||
@@ -965,7 +966,7 @@ pub(crate) unsafe fn fd_prestat_get(
|
|||||||
memory: &mut [u8],
|
memory: &mut [u8],
|
||||||
fd: wasi::__wasi_fd_t,
|
fd: wasi::__wasi_fd_t,
|
||||||
prestat_ptr: wasi32::uintptr_t,
|
prestat_ptr: wasi32::uintptr_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
trace!(
|
trace!(
|
||||||
"fd_prestat_get(fd={:?}, prestat_ptr={:#x?})",
|
"fd_prestat_get(fd={:?}, prestat_ptr={:#x?})",
|
||||||
fd,
|
fd,
|
||||||
@@ -974,9 +975,9 @@ pub(crate) unsafe fn fd_prestat_get(
|
|||||||
|
|
||||||
// TODO: should we validate any rights here?
|
// TODO: should we validate any rights here?
|
||||||
let fe = wasi_ctx.get_fd_entry(fd)?;
|
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 {
|
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())?;
|
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,
|
fd: wasi::__wasi_fd_t,
|
||||||
path_ptr: wasi32::uintptr_t,
|
path_ptr: wasi32::uintptr_t,
|
||||||
path_len: wasi32::size_t,
|
path_len: wasi32::size_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
trace!(
|
trace!(
|
||||||
"fd_prestat_dir_name(fd={:?}, path_ptr={:#x?}, path_len={})",
|
"fd_prestat_dir_name(fd={:?}, path_ptr={:#x?}, path_len={})",
|
||||||
fd,
|
fd,
|
||||||
@@ -1011,15 +1012,15 @@ pub(crate) unsafe fn fd_prestat_dir_name(
|
|||||||
|
|
||||||
// TODO: should we validate any rights here?
|
// TODO: should we validate any rights here?
|
||||||
let fe = wasi_ctx.get_fd_entry(fd)?;
|
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 {
|
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())?;
|
let path = host_impl::path_from_host(po_path.as_os_str())?;
|
||||||
|
|
||||||
if path.len() > dec_usize(path_len) {
|
if path.len() > dec_usize(path_len) {
|
||||||
return Err(Error::ENAMETOOLONG);
|
return Err(WasiError::ENAMETOOLONG);
|
||||||
}
|
}
|
||||||
|
|
||||||
trace!(" | (path_ptr,path_len)='{}'", path);
|
trace!(" | (path_ptr,path_len)='{}'", path);
|
||||||
@@ -1035,7 +1036,7 @@ pub(crate) unsafe fn fd_readdir(
|
|||||||
buf_len: wasi32::size_t,
|
buf_len: wasi32::size_t,
|
||||||
cookie: wasi::__wasi_dircookie_t,
|
cookie: wasi::__wasi_dircookie_t,
|
||||||
buf_used: wasi32::uintptr_t,
|
buf_used: wasi32::uintptr_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
trace!(
|
trace!(
|
||||||
"fd_readdir(fd={:?}, buf={:#x?}, buf_len={}, cookie={:#x?}, buf_used={:#x?})",
|
"fd_readdir(fd={:?}, buf={:#x?}, buf_len={}, cookie={:#x?}, buf_used={:#x?})",
|
||||||
fd,
|
fd,
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
#![allow(non_camel_case_types)]
|
#![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::host_impl;
|
||||||
use crate::old::snapshot_0::sys::hostcalls_impl::fs_helpers::*;
|
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::fs::File;
|
||||||
use std::path::{Component, Path};
|
use std::path::{Component, Path};
|
||||||
|
|
||||||
@@ -31,17 +32,17 @@ pub(crate) fn path_get(
|
|||||||
dirflags: wasi::__wasi_lookupflags_t,
|
dirflags: wasi::__wasi_lookupflags_t,
|
||||||
path: &str,
|
path: &str,
|
||||||
needs_final_component: bool,
|
needs_final_component: bool,
|
||||||
) -> Result<PathGet> {
|
) -> WasiResult<PathGet> {
|
||||||
const MAX_SYMLINK_EXPANSIONS: usize = 128;
|
const MAX_SYMLINK_EXPANSIONS: usize = 128;
|
||||||
|
|
||||||
if path.contains('\0') {
|
if path.contains('\0') {
|
||||||
// if contains NUL, return EILSEQ
|
// if contains NUL, return EILSEQ
|
||||||
return Err(Error::EILSEQ);
|
return Err(WasiError::EILSEQ);
|
||||||
}
|
}
|
||||||
|
|
||||||
if fe.file_type != wasi::__WASI_FILETYPE_DIRECTORY {
|
if fe.file_type != wasi::__WASI_FILETYPE_DIRECTORY {
|
||||||
// if `dirfd` doesn't refer to a directory, return `ENOTDIR`.
|
// if `dirfd` doesn't refer to a directory, return `ENOTDIR`.
|
||||||
return Err(Error::ENOTDIR);
|
return Err(WasiError::ENOTDIR);
|
||||||
}
|
}
|
||||||
|
|
||||||
let dirfd = fe
|
let dirfd = fe
|
||||||
@@ -72,7 +73,7 @@ pub(crate) fn path_get(
|
|||||||
let ends_with_slash = cur_path.ends_with('/');
|
let ends_with_slash = cur_path.ends_with('/');
|
||||||
let mut components = Path::new(&cur_path).components();
|
let mut components = Path::new(&cur_path).components();
|
||||||
let head = match components.next() {
|
let head = match components.next() {
|
||||||
None => return Err(Error::ENOENT),
|
None => return Err(WasiError::ENOENT),
|
||||||
Some(p) => p,
|
Some(p) => p,
|
||||||
};
|
};
|
||||||
let tail = components.as_path();
|
let tail = components.as_path();
|
||||||
@@ -90,18 +91,18 @@ pub(crate) fn path_get(
|
|||||||
match head {
|
match head {
|
||||||
Component::Prefix(_) | Component::RootDir => {
|
Component::Prefix(_) | Component::RootDir => {
|
||||||
// path is absolute!
|
// path is absolute!
|
||||||
return Err(Error::ENOTCAPABLE);
|
return Err(WasiError::ENOTCAPABLE);
|
||||||
}
|
}
|
||||||
Component::CurDir => {
|
Component::CurDir => {
|
||||||
// "." so skip
|
// "." so skip
|
||||||
}
|
}
|
||||||
Component::ParentDir => {
|
Component::ParentDir => {
|
||||||
// ".." so pop a dir
|
// ".." 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
|
// we're not allowed to pop past the original directory
|
||||||
if dir_stack.is_empty() {
|
if dir_stack.is_empty() {
|
||||||
return Err(Error::ENOTCAPABLE);
|
return Err(WasiError::ENOTCAPABLE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Component::Normal(head) => {
|
Component::Normal(head) => {
|
||||||
@@ -112,12 +113,12 @@ pub(crate) fn path_get(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !path_stack.is_empty() || (ends_with_slash && !needs_final_component) {
|
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) => {
|
Ok(new_dir) => {
|
||||||
dir_stack.push(new_dir);
|
dir_stack.push(new_dir);
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
match e.as_wasi_error() {
|
match e {
|
||||||
WasiError::ELOOP
|
WasiError::ELOOP
|
||||||
| WasiError::EMLINK
|
| WasiError::EMLINK
|
||||||
| WasiError::ENOTDIR =>
|
| WasiError::ENOTDIR =>
|
||||||
@@ -126,13 +127,13 @@ pub(crate) fn path_get(
|
|||||||
{
|
{
|
||||||
// attempt symlink expansion
|
// attempt symlink expansion
|
||||||
let mut link_path = readlinkat(
|
let mut link_path = readlinkat(
|
||||||
dir_stack.last().ok_or(Error::ENOTCAPABLE)?,
|
dir_stack.last().ok_or(WasiError::ENOTCAPABLE)?,
|
||||||
&head,
|
&head,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
symlink_expansions += 1;
|
symlink_expansions += 1;
|
||||||
if symlink_expansions > MAX_SYMLINK_EXPANSIONS {
|
if symlink_expansions > MAX_SYMLINK_EXPANSIONS {
|
||||||
return Err(Error::ELOOP);
|
return Err(WasiError::ELOOP);
|
||||||
}
|
}
|
||||||
|
|
||||||
if head.ends_with('/') {
|
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
|
// if there's a trailing slash, or if `LOOKUP_SYMLINK_FOLLOW` is set, attempt
|
||||||
// symlink expansion
|
// 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) => {
|
Ok(mut link_path) => {
|
||||||
symlink_expansions += 1;
|
symlink_expansions += 1;
|
||||||
if symlink_expansions > MAX_SYMLINK_EXPANSIONS {
|
if symlink_expansions > MAX_SYMLINK_EXPANSIONS {
|
||||||
return Err(Error::ELOOP);
|
return Err(WasiError::ELOOP);
|
||||||
}
|
}
|
||||||
|
|
||||||
if head.ends_with('/') {
|
if head.ends_with('/') {
|
||||||
@@ -179,12 +181,12 @@ pub(crate) fn path_get(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
if e.as_wasi_error() != WasiError::EINVAL
|
if e != WasiError::EINVAL
|
||||||
&& e.as_wasi_error() != WasiError::ENOENT
|
&& e != WasiError::ENOENT
|
||||||
// this handles the cases when trying to link to
|
// this handles the cases when trying to link to
|
||||||
// a destination that already exists, and the target
|
// a destination that already exists, and the target
|
||||||
// path contains a slash
|
// path contains a slash
|
||||||
&& e.as_wasi_error() != WasiError::ENOTDIR
|
&& e != WasiError::ENOTDIR
|
||||||
{
|
{
|
||||||
return Err(e);
|
return Err(e);
|
||||||
}
|
}
|
||||||
@@ -194,7 +196,7 @@ pub(crate) fn path_get(
|
|||||||
|
|
||||||
// not a symlink, so we're done;
|
// not a symlink, so we're done;
|
||||||
return Ok(PathGet {
|
return Ok(PathGet {
|
||||||
dirfd: dir_stack.pop().ok_or(Error::ENOTCAPABLE)?,
|
dirfd: dir_stack.pop().ok_or(WasiError::ENOTCAPABLE)?,
|
||||||
path: head,
|
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
|
// 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
|
// input path has trailing slashes and `needs_final_component` is not set
|
||||||
return Ok(PathGet {
|
return Ok(PathGet {
|
||||||
dirfd: dir_stack.pop().ok_or(Error::ENOTCAPABLE)?,
|
dirfd: dir_stack.pop().ok_or(WasiError::ENOTCAPABLE)?,
|
||||||
path: String::from("."),
|
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::fdentry::Descriptor;
|
||||||
use crate::old::snapshot_0::memory::*;
|
use crate::old::snapshot_0::memory::*;
|
||||||
use crate::old::snapshot_0::sys::hostcalls_impl;
|
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 log::{error, trace};
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
|
|
||||||
@@ -12,7 +13,7 @@ pub(crate) fn args_get(
|
|||||||
memory: &mut [u8],
|
memory: &mut [u8],
|
||||||
argv_ptr: wasi32::uintptr_t,
|
argv_ptr: wasi32::uintptr_t,
|
||||||
argv_buf: wasi32::uintptr_t,
|
argv_buf: wasi32::uintptr_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
trace!(
|
trace!(
|
||||||
"args_get(argv_ptr={:#x?}, argv_buf={:#x?})",
|
"args_get(argv_ptr={:#x?}, argv_buf={:#x?})",
|
||||||
argv_ptr,
|
argv_ptr,
|
||||||
@@ -31,7 +32,9 @@ pub(crate) fn args_get(
|
|||||||
argv.push(arg_ptr);
|
argv.push(arg_ptr);
|
||||||
|
|
||||||
let len = wasi32::uintptr_t::try_from(arg_bytes.len())?;
|
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)
|
enc_slice_of_wasi32_uintptr(memory, argv.as_slice(), argv_ptr)
|
||||||
@@ -42,7 +45,7 @@ pub(crate) fn args_sizes_get(
|
|||||||
memory: &mut [u8],
|
memory: &mut [u8],
|
||||||
argc_ptr: wasi32::uintptr_t,
|
argc_ptr: wasi32::uintptr_t,
|
||||||
argv_buf_size_ptr: wasi32::uintptr_t,
|
argv_buf_size_ptr: wasi32::uintptr_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
trace!(
|
trace!(
|
||||||
"args_sizes_get(argc_ptr={:#x?}, argv_buf_size_ptr={:#x?})",
|
"args_sizes_get(argc_ptr={:#x?}, argv_buf_size_ptr={:#x?})",
|
||||||
argc_ptr,
|
argc_ptr,
|
||||||
@@ -70,7 +73,7 @@ pub(crate) fn environ_get(
|
|||||||
memory: &mut [u8],
|
memory: &mut [u8],
|
||||||
environ_ptr: wasi32::uintptr_t,
|
environ_ptr: wasi32::uintptr_t,
|
||||||
environ_buf: wasi32::uintptr_t,
|
environ_buf: wasi32::uintptr_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
trace!(
|
trace!(
|
||||||
"environ_get(environ_ptr={:#x?}, environ_buf={:#x?})",
|
"environ_get(environ_ptr={:#x?}, environ_buf={:#x?})",
|
||||||
environ_ptr,
|
environ_ptr,
|
||||||
@@ -91,7 +94,7 @@ pub(crate) fn environ_get(
|
|||||||
let len = wasi32::uintptr_t::try_from(env_bytes.len())?;
|
let len = wasi32::uintptr_t::try_from(env_bytes.len())?;
|
||||||
environ_buf_offset = environ_buf_offset
|
environ_buf_offset = environ_buf_offset
|
||||||
.checked_add(len)
|
.checked_add(len)
|
||||||
.ok_or(Error::EOVERFLOW)?;
|
.ok_or(WasiError::EOVERFLOW)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
enc_slice_of_wasi32_uintptr(memory, environ.as_slice(), environ_ptr)
|
enc_slice_of_wasi32_uintptr(memory, environ.as_slice(), environ_ptr)
|
||||||
@@ -102,7 +105,7 @@ pub(crate) fn environ_sizes_get(
|
|||||||
memory: &mut [u8],
|
memory: &mut [u8],
|
||||||
environ_count_ptr: wasi32::uintptr_t,
|
environ_count_ptr: wasi32::uintptr_t,
|
||||||
environ_size_ptr: wasi32::uintptr_t,
|
environ_size_ptr: wasi32::uintptr_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
trace!(
|
trace!(
|
||||||
"environ_sizes_get(environ_count_ptr={:#x?}, environ_size_ptr={:#x?})",
|
"environ_sizes_get(environ_count_ptr={:#x?}, environ_size_ptr={:#x?})",
|
||||||
environ_count_ptr,
|
environ_count_ptr,
|
||||||
@@ -116,7 +119,7 @@ pub(crate) fn environ_sizes_get(
|
|||||||
.try_fold(0, |acc: u32, pair| {
|
.try_fold(0, |acc: u32, pair| {
|
||||||
acc.checked_add(pair.as_bytes_with_nul().len() as u32)
|
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);
|
trace!(" | *environ_count_ptr={:?}", environ_count);
|
||||||
|
|
||||||
@@ -132,14 +135,14 @@ pub(crate) fn random_get(
|
|||||||
memory: &mut [u8],
|
memory: &mut [u8],
|
||||||
buf_ptr: wasi32::uintptr_t,
|
buf_ptr: wasi32::uintptr_t,
|
||||||
buf_len: wasi32::size_t,
|
buf_len: wasi32::size_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
trace!("random_get(buf_ptr={:#x?}, buf_len={:?})", buf_ptr, buf_len);
|
trace!("random_get(buf_ptr={:#x?}, buf_len={:?})", buf_ptr, buf_len);
|
||||||
|
|
||||||
let buf = dec_slice_of_mut_u8(memory, buf_ptr, buf_len)?;
|
let buf = dec_slice_of_mut_u8(memory, buf_ptr, buf_len)?;
|
||||||
|
|
||||||
getrandom::getrandom(buf).map_err(|err| {
|
getrandom::getrandom(buf).map_err(|err| {
|
||||||
error!("getrandom failure: {:?}", err);
|
error!("getrandom failure: {:?}", err);
|
||||||
Error::EIO
|
WasiError::EIO
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -148,7 +151,7 @@ pub(crate) fn clock_res_get(
|
|||||||
memory: &mut [u8],
|
memory: &mut [u8],
|
||||||
clock_id: wasi::__wasi_clockid_t,
|
clock_id: wasi::__wasi_clockid_t,
|
||||||
resolution_ptr: wasi32::uintptr_t,
|
resolution_ptr: wasi32::uintptr_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
trace!(
|
trace!(
|
||||||
"clock_res_get(clock_id={:?}, resolution_ptr={:#x?})",
|
"clock_res_get(clock_id={:?}, resolution_ptr={:#x?})",
|
||||||
clock_id,
|
clock_id,
|
||||||
@@ -168,7 +171,7 @@ pub(crate) fn clock_time_get(
|
|||||||
clock_id: wasi::__wasi_clockid_t,
|
clock_id: wasi::__wasi_clockid_t,
|
||||||
precision: wasi::__wasi_timestamp_t,
|
precision: wasi::__wasi_timestamp_t,
|
||||||
time_ptr: wasi32::uintptr_t,
|
time_ptr: wasi32::uintptr_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
trace!(
|
trace!(
|
||||||
"clock_time_get(clock_id={:?}, precision={:?}, time_ptr={:#x?})",
|
"clock_time_get(clock_id={:?}, precision={:?}, time_ptr={:#x?})",
|
||||||
clock_id,
|
clock_id,
|
||||||
@@ -183,7 +186,7 @@ pub(crate) fn clock_time_get(
|
|||||||
enc_timestamp_byref(memory, time_ptr, time)
|
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()");
|
trace!("sched_yield()");
|
||||||
|
|
||||||
std::thread::yield_now();
|
std::thread::yield_now();
|
||||||
@@ -198,7 +201,7 @@ pub(crate) fn poll_oneoff(
|
|||||||
output: wasi32::uintptr_t,
|
output: wasi32::uintptr_t,
|
||||||
nsubscriptions: wasi32::size_t,
|
nsubscriptions: wasi32::size_t,
|
||||||
nevents: wasi32::uintptr_t,
|
nevents: wasi32::uintptr_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
trace!(
|
trace!(
|
||||||
"poll_oneoff(input={:#x?}, output={:#x?}, nsubscriptions={}, nevents={:#x?})",
|
"poll_oneoff(input={:#x?}, output={:#x?}, nsubscriptions={}, nevents={:#x?})",
|
||||||
input,
|
input,
|
||||||
@@ -208,7 +211,7 @@ pub(crate) fn poll_oneoff(
|
|||||||
);
|
);
|
||||||
|
|
||||||
if u64::from(nsubscriptions) > wasi::__wasi_filesize_t::max_value() {
|
if u64::from(nsubscriptions) > wasi::__wasi_filesize_t::max_value() {
|
||||||
return Err(Error::EINVAL);
|
return Err(WasiError::EINVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
enc_int_byref(memory, nevents, 0)?;
|
enc_int_byref(memory, nevents, 0)?;
|
||||||
@@ -253,7 +256,7 @@ pub(crate) fn poll_oneoff(
|
|||||||
Err(err) => {
|
Err(err) => {
|
||||||
let event = wasi::__wasi_event_t {
|
let event = wasi::__wasi_event_t {
|
||||||
userdata: subscription.userdata,
|
userdata: subscription.userdata,
|
||||||
error: err.as_wasi_error().as_raw_errno(),
|
error: err.as_raw_errno(),
|
||||||
r#type: wasi::__WASI_EVENTTYPE_FD_READ,
|
r#type: wasi::__WASI_EVENTTYPE_FD_READ,
|
||||||
fd_readwrite: wasi::__wasi_event_fd_readwrite_t {
|
fd_readwrite: wasi::__wasi_event_fd_readwrite_t {
|
||||||
nbytes: 0,
|
nbytes: 0,
|
||||||
@@ -281,7 +284,7 @@ pub(crate) fn poll_oneoff(
|
|||||||
Err(err) => {
|
Err(err) => {
|
||||||
let event = wasi::__wasi_event_t {
|
let event = wasi::__wasi_event_t {
|
||||||
userdata: subscription.userdata,
|
userdata: subscription.userdata,
|
||||||
error: err.as_wasi_error().as_raw_errno(),
|
error: err.as_raw_errno(),
|
||||||
r#type: wasi::__WASI_EVENTTYPE_FD_WRITE,
|
r#type: wasi::__WASI_EVENTTYPE_FD_WRITE,
|
||||||
fd_readwrite: wasi::__wasi_event_fd_readwrite_t {
|
fd_readwrite: wasi::__wasi_event_fd_readwrite_t {
|
||||||
nbytes: 0,
|
nbytes: 0,
|
||||||
@@ -301,7 +304,7 @@ pub(crate) fn poll_oneoff(
|
|||||||
|
|
||||||
hostcalls_impl::poll_oneoff(timeout, fd_events, &mut events)?;
|
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)?;
|
enc_events(memory, output, nsubscriptions, events)?;
|
||||||
|
|
||||||
@@ -310,7 +313,9 @@ pub(crate) fn poll_oneoff(
|
|||||||
enc_int_byref(memory, nevents, events_count)
|
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;
|
use std::time::SystemTime;
|
||||||
|
|
||||||
if wasi_clock.flags != wasi::__WASI_SUBCLOCKFLAGS_SUBSCRIPTION_CLOCK_ABSTIME {
|
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()
|
let now: u128 = SystemTime::now()
|
||||||
.duration_since(SystemTime::UNIX_EPOCH)
|
.duration_since(SystemTime::UNIX_EPOCH)
|
||||||
.map_err(|_| Error::ENOTCAPABLE)?
|
.map_err(|_| WasiError::ENOTCAPABLE)?
|
||||||
.as_nanos();
|
.as_nanos();
|
||||||
let deadline = u128::from(wasi_clock.timeout);
|
let deadline = u128::from(wasi_clock.timeout);
|
||||||
Ok(deadline.saturating_sub(now))
|
Ok(deadline.saturating_sub(now))
|
||||||
@@ -348,6 +353,6 @@ pub(crate) fn proc_raise(
|
|||||||
_wasi_ctx: &WasiCtx,
|
_wasi_ctx: &WasiCtx,
|
||||||
_memory: &mut [u8],
|
_memory: &mut [u8],
|
||||||
_sig: wasi::__wasi_signal_t,
|
_sig: wasi::__wasi_signal_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
unimplemented!("proc_raise")
|
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(
|
pub fn sock_recv(
|
||||||
_wasi_ctx: &WasiCtx,
|
_wasi_ctx: &WasiCtx,
|
||||||
@@ -9,7 +10,7 @@ pub fn sock_recv(
|
|||||||
_ri_flags: wasi::__wasi_riflags_t,
|
_ri_flags: wasi::__wasi_riflags_t,
|
||||||
_ro_datalen: wasi32::uintptr_t,
|
_ro_datalen: wasi32::uintptr_t,
|
||||||
_ro_flags: wasi32::uintptr_t,
|
_ro_flags: wasi32::uintptr_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
unimplemented!("sock_recv")
|
unimplemented!("sock_recv")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -21,7 +22,7 @@ pub fn sock_send(
|
|||||||
_si_data_len: wasi32::size_t,
|
_si_data_len: wasi32::size_t,
|
||||||
_si_flags: wasi::__wasi_siflags_t,
|
_si_flags: wasi::__wasi_siflags_t,
|
||||||
_so_datalen: wasi32::uintptr_t,
|
_so_datalen: wasi32::uintptr_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
unimplemented!("sock_send")
|
unimplemented!("sock_send")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -30,6 +31,6 @@ pub fn sock_shutdown(
|
|||||||
_memory: &mut [u8],
|
_memory: &mut [u8],
|
||||||
_sock: wasi::__wasi_fd_t,
|
_sock: wasi::__wasi_fd_t,
|
||||||
_how: wasi::__wasi_sdflags_t,
|
_how: wasi::__wasi_sdflags_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
unimplemented!("sock_shutdown")
|
unimplemented!("sock_shutdown")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,38 +8,39 @@
|
|||||||
//! are not held for long durations.
|
//! are not held for long durations.
|
||||||
|
|
||||||
#![allow(unused)]
|
#![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 num::PrimInt;
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
use std::mem::{align_of, size_of};
|
use std::mem::{align_of, size_of};
|
||||||
use std::{ptr, slice};
|
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
|
// 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
|
// translate the pointer
|
||||||
memory
|
memory
|
||||||
.get(ptr as usize..checked_len)
|
.get(ptr as usize..checked_len)
|
||||||
.ok_or(Error::EFAULT)
|
.ok_or(WasiError::EFAULT)
|
||||||
.map(|mem| mem.as_ptr())
|
.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
|
// 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
|
// translate the pointer
|
||||||
memory
|
memory
|
||||||
.get_mut(ptr as usize..checked_len)
|
.get_mut(ptr as usize..checked_len)
|
||||||
.ok_or(Error::EFAULT)
|
.ok_or(WasiError::EFAULT)
|
||||||
.map(|mem| mem.as_mut_ptr())
|
.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
|
// check that the ptr is aligned
|
||||||
if ptr as usize % align_of::<T>() != 0 {
|
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) })
|
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>(
|
fn dec_ptr_to_mut<'memory, T>(
|
||||||
memory: &'memory mut [u8],
|
memory: &'memory mut [u8],
|
||||||
ptr: wasi32::uintptr_t,
|
ptr: wasi32::uintptr_t,
|
||||||
) -> Result<&'memory mut T> {
|
) -> WasiResult<&'memory mut T> {
|
||||||
// check that the ptr is aligned
|
// check that the ptr is aligned
|
||||||
if ptr as usize % align_of::<T>() != 0 {
|
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) })
|
dec_ptr_mut(memory, ptr, size_of::<T>()).map(|p| unsafe { &mut *(p as *mut T) })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This function does not perform endianness conversions!
|
/// 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) })
|
dec_ptr_to::<T>(memory, ptr).map(|p| unsafe { ptr::read(p) })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This function does not perform endianness conversions!
|
/// 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) })
|
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
|
where
|
||||||
T: PrimInt,
|
T: PrimInt,
|
||||||
{
|
{
|
||||||
dec_raw_byref::<T>(memory, ptr).map(|i| PrimInt::from_le(i))
|
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
|
where
|
||||||
T: PrimInt,
|
T: PrimInt,
|
||||||
{
|
{
|
||||||
enc_raw_byref::<T>(memory, ptr, PrimInt::to_le(t))
|
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
|
// check alignment, and that length doesn't overflow
|
||||||
if ptr as usize % align_of::<T>() != 0 {
|
if ptr as usize % align_of::<T>() != 0 {
|
||||||
return Err(Error::EINVAL);
|
return Err(WasiError::EINVAL);
|
||||||
}
|
}
|
||||||
let len = dec_usize(len);
|
let len = dec_usize(len);
|
||||||
let len_bytes = if let Some(len) = size_of::<T>().checked_mul(len) {
|
let len_bytes = if let Some(len) = size_of::<T>().checked_mul(len) {
|
||||||
len
|
len
|
||||||
} else {
|
} else {
|
||||||
return Err(Error::EOVERFLOW);
|
return Err(WasiError::EOVERFLOW);
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok((len, len_bytes))
|
Ok((len, len_bytes))
|
||||||
@@ -100,7 +101,7 @@ fn dec_raw_slice_of<'memory, T>(
|
|||||||
memory: &'memory [u8],
|
memory: &'memory [u8],
|
||||||
ptr: wasi32::uintptr_t,
|
ptr: wasi32::uintptr_t,
|
||||||
len: wasi32::size_t,
|
len: wasi32::size_t,
|
||||||
) -> Result<&'memory [T]> {
|
) -> WasiResult<&'memory [T]> {
|
||||||
let (len, len_bytes) = check_slice_of::<T>(ptr, len)?;
|
let (len, len_bytes) = check_slice_of::<T>(ptr, len)?;
|
||||||
let ptr = dec_ptr(memory, ptr, len_bytes)? as *const T;
|
let ptr = dec_ptr(memory, ptr, len_bytes)? as *const T;
|
||||||
Ok(unsafe { slice::from_raw_parts(ptr, len) })
|
Ok(unsafe { slice::from_raw_parts(ptr, len) })
|
||||||
@@ -110,7 +111,7 @@ fn dec_raw_slice_of_mut<'memory, T>(
|
|||||||
memory: &'memory mut [u8],
|
memory: &'memory mut [u8],
|
||||||
ptr: wasi32::uintptr_t,
|
ptr: wasi32::uintptr_t,
|
||||||
len: wasi32::size_t,
|
len: wasi32::size_t,
|
||||||
) -> Result<&'memory mut [T]> {
|
) -> WasiResult<&'memory mut [T]> {
|
||||||
let (len, len_bytes) = check_slice_of::<T>(ptr, len)?;
|
let (len, len_bytes) = check_slice_of::<T>(ptr, len)?;
|
||||||
let ptr = dec_ptr_mut(memory, ptr, len_bytes)? as *mut T;
|
let ptr = dec_ptr_mut(memory, ptr, len_bytes)? as *mut T;
|
||||||
Ok(unsafe { slice::from_raw_parts_mut(ptr, len) })
|
Ok(unsafe { slice::from_raw_parts_mut(ptr, len) })
|
||||||
@@ -120,16 +121,16 @@ fn raw_slice_for_enc<'memory, T>(
|
|||||||
memory: &'memory mut [u8],
|
memory: &'memory mut [u8],
|
||||||
slice: &[T],
|
slice: &[T],
|
||||||
ptr: wasi32::uintptr_t,
|
ptr: wasi32::uintptr_t,
|
||||||
) -> Result<&'memory mut [T]> {
|
) -> WasiResult<&'memory mut [T]> {
|
||||||
// check alignment
|
// check alignment
|
||||||
if ptr as usize % align_of::<T>() != 0 {
|
if ptr as usize % align_of::<T>() != 0 {
|
||||||
return Err(Error::EINVAL);
|
return Err(WasiError::EINVAL);
|
||||||
}
|
}
|
||||||
// check that length doesn't overflow
|
// check that length doesn't overflow
|
||||||
let len_bytes = if let Some(len) = size_of::<T>().checked_mul(slice.len()) {
|
let len_bytes = if let Some(len) = size_of::<T>().checked_mul(slice.len()) {
|
||||||
len
|
len
|
||||||
} else {
|
} else {
|
||||||
return Err(Error::EOVERFLOW);
|
return Err(WasiError::EOVERFLOW);
|
||||||
};
|
};
|
||||||
|
|
||||||
// get the pointer into guest memory
|
// get the pointer into guest memory
|
||||||
@@ -142,7 +143,7 @@ pub(crate) fn dec_slice_of_u8<'memory>(
|
|||||||
memory: &'memory [u8],
|
memory: &'memory [u8],
|
||||||
ptr: wasi32::uintptr_t,
|
ptr: wasi32::uintptr_t,
|
||||||
len: wasi32::size_t,
|
len: wasi32::size_t,
|
||||||
) -> Result<&'memory [u8]> {
|
) -> WasiResult<&'memory [u8]> {
|
||||||
dec_raw_slice_of::<u8>(memory, ptr, len)
|
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],
|
memory: &'memory mut [u8],
|
||||||
ptr: wasi32::uintptr_t,
|
ptr: wasi32::uintptr_t,
|
||||||
len: wasi32::size_t,
|
len: wasi32::size_t,
|
||||||
) -> Result<&'memory mut [u8]> {
|
) -> WasiResult<&'memory mut [u8]> {
|
||||||
dec_raw_slice_of_mut::<u8>(memory, ptr, len)
|
dec_raw_slice_of_mut::<u8>(memory, ptr, len)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -158,7 +159,7 @@ pub(crate) fn enc_slice_of_u8(
|
|||||||
memory: &mut [u8],
|
memory: &mut [u8],
|
||||||
slice: &[u8],
|
slice: &[u8],
|
||||||
ptr: wasi32::uintptr_t,
|
ptr: wasi32::uintptr_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
let output = raw_slice_for_enc::<u8>(memory, slice, ptr)?;
|
let output = raw_slice_for_enc::<u8>(memory, slice, ptr)?;
|
||||||
|
|
||||||
output.copy_from_slice(slice);
|
output.copy_from_slice(slice);
|
||||||
@@ -170,7 +171,7 @@ pub(crate) fn enc_slice_of_wasi32_uintptr(
|
|||||||
memory: &mut [u8],
|
memory: &mut [u8],
|
||||||
slice: &[wasi32::uintptr_t],
|
slice: &[wasi32::uintptr_t],
|
||||||
ptr: 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();
|
let mut output_iter = raw_slice_for_enc::<wasi32::uintptr_t>(memory, slice, ptr)?.into_iter();
|
||||||
|
|
||||||
for p in slice {
|
for p in slice {
|
||||||
@@ -182,7 +183,10 @@ pub(crate) fn enc_slice_of_wasi32_uintptr(
|
|||||||
|
|
||||||
macro_rules! dec_enc_scalar {
|
macro_rules! dec_enc_scalar {
|
||||||
($ty:ident, $dec_byref:ident, $enc_byref:ident) => {
|
($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)
|
dec_int_byref::<wasi::$ty>(memory, ptr)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -190,7 +194,7 @@ macro_rules! dec_enc_scalar {
|
|||||||
memory: &mut [u8],
|
memory: &mut [u8],
|
||||||
ptr: wasi32::uintptr_t,
|
ptr: wasi32::uintptr_t,
|
||||||
x: wasi::$ty,
|
x: wasi::$ty,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
enc_int_byref::<wasi::$ty>(memory, ptr, x)
|
enc_int_byref::<wasi::$ty>(memory, ptr, x)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -200,7 +204,7 @@ pub(crate) fn dec_ciovec_slice(
|
|||||||
memory: &[u8],
|
memory: &[u8],
|
||||||
ptr: wasi32::uintptr_t,
|
ptr: wasi32::uintptr_t,
|
||||||
len: wasi32::size_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)?;
|
let raw_slice = dec_raw_slice_of::<wasi32::__wasi_ciovec_t>(memory, ptr, len)?;
|
||||||
|
|
||||||
raw_slice
|
raw_slice
|
||||||
@@ -220,7 +224,7 @@ pub(crate) fn dec_iovec_slice(
|
|||||||
memory: &[u8],
|
memory: &[u8],
|
||||||
ptr: wasi32::uintptr_t,
|
ptr: wasi32::uintptr_t,
|
||||||
len: wasi32::size_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)?;
|
let raw_slice = dec_raw_slice_of::<wasi32::__wasi_iovec_t>(memory, ptr, len)?;
|
||||||
|
|
||||||
raw_slice
|
raw_slice
|
||||||
@@ -248,7 +252,7 @@ dec_enc_scalar!(__wasi_linkcount_t, dev_linkcount_byref, enc_linkcount_byref);
|
|||||||
pub(crate) fn dec_filestat_byref(
|
pub(crate) fn dec_filestat_byref(
|
||||||
memory: &mut [u8],
|
memory: &mut [u8],
|
||||||
filestat_ptr: wasi32::uintptr_t,
|
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)?;
|
let raw = dec_raw_byref::<wasi::__wasi_filestat_t>(memory, filestat_ptr)?;
|
||||||
|
|
||||||
Ok(wasi::__wasi_filestat_t {
|
Ok(wasi::__wasi_filestat_t {
|
||||||
@@ -267,7 +271,7 @@ pub(crate) fn enc_filestat_byref(
|
|||||||
memory: &mut [u8],
|
memory: &mut [u8],
|
||||||
filestat_ptr: wasi32::uintptr_t,
|
filestat_ptr: wasi32::uintptr_t,
|
||||||
filestat: wasi::__wasi_filestat_t,
|
filestat: wasi::__wasi_filestat_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
let raw = wasi::__wasi_filestat_t {
|
let raw = wasi::__wasi_filestat_t {
|
||||||
dev: PrimInt::to_le(filestat.dev),
|
dev: PrimInt::to_le(filestat.dev),
|
||||||
ino: PrimInt::to_le(filestat.ino),
|
ino: PrimInt::to_le(filestat.ino),
|
||||||
@@ -285,7 +289,7 @@ pub(crate) fn enc_filestat_byref(
|
|||||||
pub(crate) fn dec_fdstat_byref(
|
pub(crate) fn dec_fdstat_byref(
|
||||||
memory: &mut [u8],
|
memory: &mut [u8],
|
||||||
fdstat_ptr: wasi32::uintptr_t,
|
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)?;
|
let raw = dec_raw_byref::<wasi::__wasi_fdstat_t>(memory, fdstat_ptr)?;
|
||||||
|
|
||||||
Ok(wasi::__wasi_fdstat_t {
|
Ok(wasi::__wasi_fdstat_t {
|
||||||
@@ -300,7 +304,7 @@ pub(crate) fn enc_fdstat_byref(
|
|||||||
memory: &mut [u8],
|
memory: &mut [u8],
|
||||||
fdstat_ptr: wasi32::uintptr_t,
|
fdstat_ptr: wasi32::uintptr_t,
|
||||||
fdstat: wasi::__wasi_fdstat_t,
|
fdstat: wasi::__wasi_fdstat_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
let raw = wasi::__wasi_fdstat_t {
|
let raw = wasi::__wasi_fdstat_t {
|
||||||
fs_filetype: PrimInt::to_le(fdstat.fs_filetype),
|
fs_filetype: PrimInt::to_le(fdstat.fs_filetype),
|
||||||
fs_flags: PrimInt::to_le(fdstat.fs_flags),
|
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(
|
pub(crate) fn dec_prestat_byref(
|
||||||
memory: &mut [u8],
|
memory: &mut [u8],
|
||||||
prestat_ptr: wasi32::uintptr_t,
|
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)?;
|
let raw = dec_raw_byref::<wasi32::__wasi_prestat_t>(memory, prestat_ptr)?;
|
||||||
|
|
||||||
match PrimInt::from_le(raw.tag) {
|
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],
|
memory: &mut [u8],
|
||||||
prestat_ptr: wasi32::uintptr_t,
|
prestat_ptr: wasi32::uintptr_t,
|
||||||
prestat: host::__wasi_prestat_t,
|
prestat: host::__wasi_prestat_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
let raw = match prestat.tag {
|
let raw = match prestat.tag {
|
||||||
wasi::__WASI_PREOPENTYPE_DIR => Ok(wasi32::__wasi_prestat_t {
|
wasi::__WASI_PREOPENTYPE_DIR => Ok(wasi32::__wasi_prestat_t {
|
||||||
tag: PrimInt::to_le(wasi::__WASI_PREOPENTYPE_DIR),
|
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)
|
enc_raw_byref::<wasi32::__wasi_prestat_t>(memory, prestat_ptr, raw)
|
||||||
@@ -377,7 +381,7 @@ pub(crate) fn enc_usize_byref(
|
|||||||
memory: &mut [u8],
|
memory: &mut [u8],
|
||||||
usize_ptr: wasi32::uintptr_t,
|
usize_ptr: wasi32::uintptr_t,
|
||||||
host_usize: usize,
|
host_usize: usize,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
enc_int_byref::<wasi32::size_t>(memory, usize_ptr, enc_usize(host_usize))
|
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],
|
memory: &mut [u8],
|
||||||
input: wasi32::uintptr_t,
|
input: wasi32::uintptr_t,
|
||||||
nsubscriptions: wasi32::size_t,
|
nsubscriptions: wasi32::size_t,
|
||||||
) -> Result<Vec<wasi::__wasi_subscription_t>> {
|
) -> WasiResult<Vec<wasi::__wasi_subscription_t>> {
|
||||||
let raw_input_slice =
|
let raw_input_slice =
|
||||||
dec_raw_slice_of::<wasi::__wasi_subscription_t>(memory, input, nsubscriptions)?;
|
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 {
|
Ok(wasi::__wasi_subscription_t {
|
||||||
userdata,
|
userdata,
|
||||||
u: wasi::__wasi_subscription_u_t { tag, u },
|
u: wasi::__wasi_subscription_u_t { tag, u },
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.collect::<Result<Vec<_>>>()
|
.collect::<WasiResult<Vec<_>>>()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn enc_events(
|
pub(crate) fn enc_events(
|
||||||
@@ -451,7 +455,7 @@ pub(crate) fn enc_events(
|
|||||||
output: wasi32::uintptr_t,
|
output: wasi32::uintptr_t,
|
||||||
nsubscriptions: wasi32::size_t,
|
nsubscriptions: wasi32::size_t,
|
||||||
events: Vec<wasi::__wasi_event_t>,
|
events: Vec<wasi::__wasi_event_t>,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
let mut raw_output_iter =
|
let mut raw_output_iter =
|
||||||
dec_raw_slice_of_mut::<wasi::__wasi_event_t>(memory, output, nsubscriptions)?.into_iter();
|
dec_raw_slice_of_mut::<wasi::__wasi_event_t>(memory, output, nsubscriptions)?.into_iter();
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
mod ctx;
|
mod ctx;
|
||||||
mod error;
|
|
||||||
mod fdentry;
|
mod fdentry;
|
||||||
mod helpers;
|
mod helpers;
|
||||||
mod host;
|
mod host;
|
||||||
@@ -14,6 +13,3 @@ pub mod hostcalls {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub use ctx::{WasiCtx, WasiCtxBuilder};
|
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;
|
use std::convert::TryFrom;
|
||||||
|
|
||||||
pub(crate) const O_RSYNC: yanix::file::OFlag = yanix::file::OFlag::SYNC;
|
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)
|
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)
|
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())
|
Ok(nlink.into())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
use crate::old::snapshot_0::hostcalls_impl::PathGet;
|
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;
|
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};
|
use yanix::file::{unlinkat, AtFlag};
|
||||||
match unsafe {
|
match unsafe {
|
||||||
unlinkat(
|
unlinkat(
|
||||||
@@ -32,7 +32,7 @@ pub(crate) fn path_unlink_file(resolved: PathGet) -> Result<()> {
|
|||||||
} {
|
} {
|
||||||
Ok(stat) => {
|
Ok(stat) => {
|
||||||
if FileType::from_stat_st_mode(stat.st_mode) == FileType::Directory {
|
if FileType::from_stat_st_mode(stat.st_mode) == FileType::Directory {
|
||||||
return Err(Error::EISDIR);
|
return Err(WasiError::EISDIR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(err) => {
|
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};
|
use yanix::file::{fstatat, symlinkat, AtFlag};
|
||||||
|
|
||||||
log::debug!("path_symlink old_path = {:?}", old_path);
|
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,
|
AtFlag::SYMLINK_NOFOLLOW,
|
||||||
)
|
)
|
||||||
} {
|
} {
|
||||||
Ok(_) => return Err(Error::EEXIST),
|
Ok(_) => return Err(WasiError::EEXIST),
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
log::debug!("path_symlink fstatat error: {:?}", 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};
|
use yanix::file::{fstatat, renameat, AtFlag};
|
||||||
match unsafe {
|
match unsafe {
|
||||||
renameat(
|
renameat(
|
||||||
@@ -113,9 +113,9 @@ pub(crate) fn path_rename(resolved_old: PathGet, resolved_new: PathGet) -> Resul
|
|||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
// check if destination contains a trailing slash
|
// check if destination contains a trailing slash
|
||||||
if resolved_new.path().contains('/') {
|
if resolved_new.path().contains('/') {
|
||||||
return Err(Error::ENOTDIR);
|
return Err(WasiError::ENOTDIR);
|
||||||
} else {
|
} else {
|
||||||
return Err(Error::ENOENT);
|
return Err(WasiError::ENOENT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
@@ -132,13 +132,13 @@ pub(crate) fn path_rename(resolved_old: PathGet, resolved_new: PathGet) -> Resul
|
|||||||
|
|
||||||
pub(crate) mod fd_readdir_impl {
|
pub(crate) mod fd_readdir_impl {
|
||||||
use crate::old::snapshot_0::sys::fdentry_impl::OsHandle;
|
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 std::sync::{Mutex, MutexGuard};
|
||||||
use yanix::dir::Dir;
|
use yanix::dir::Dir;
|
||||||
|
|
||||||
pub(crate) fn get_dir_from_os_handle<'a>(
|
pub(crate) fn get_dir_from_os_handle<'a>(
|
||||||
os_handle: &'a mut OsHandle,
|
os_handle: &'a mut OsHandle,
|
||||||
) -> Result<MutexGuard<'a, Dir>> {
|
) -> WasiResult<MutexGuard<'a, Dir>> {
|
||||||
let dir = match os_handle.dir {
|
let dir = match os_handle.dir {
|
||||||
Some(ref mut dir) => dir,
|
Some(ref mut dir) => dir,
|
||||||
None => {
|
None => {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use crate::old::snapshot_0::fdentry::{Descriptor, OsHandleRef};
|
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::fs::File;
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::mem::ManuallyDrop;
|
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.
|
/// This function is unsafe because it operates on a raw file descriptor.
|
||||||
pub(crate) unsafe fn determine_type_and_access_rights<Fd: AsRawFd>(
|
pub(crate) unsafe fn determine_type_and_access_rights<Fd: AsRawFd>(
|
||||||
fd: &Fd,
|
fd: &Fd,
|
||||||
) -> Result<(
|
) -> io::Result<(
|
||||||
wasi::__wasi_filetype_t,
|
wasi::__wasi_filetype_t,
|
||||||
wasi::__wasi_rights_t,
|
wasi::__wasi_rights_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.
|
/// This function is unsafe because it operates on a raw file descriptor.
|
||||||
pub(crate) unsafe fn determine_type_rights<Fd: AsRawFd>(
|
pub(crate) unsafe fn determine_type_rights<Fd: AsRawFd>(
|
||||||
fd: &Fd,
|
fd: &Fd,
|
||||||
) -> Result<(
|
) -> io::Result<(
|
||||||
wasi::__wasi_filetype_t,
|
wasi::__wasi_filetype_t,
|
||||||
wasi::__wasi_rights_t,
|
wasi::__wasi_rights_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_BASE,
|
||||||
wasi::RIGHTS_SOCKET_INHERITING,
|
wasi::RIGHTS_SOCKET_INHERITING,
|
||||||
),
|
),
|
||||||
_ => return Err(Error::EINVAL),
|
_ => return Err(io::Error::from_raw_os_error(libc::EINVAL)),
|
||||||
}
|
}
|
||||||
} else if ft.is_fifo() {
|
} else if ft.is_fifo() {
|
||||||
log::debug!("Host fd {:?} is a fifo", fd.as_raw_fd());
|
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 {
|
} else {
|
||||||
log::debug!("Host fd {:?} is unknown", fd.as_raw_fd());
|
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,94 +3,101 @@
|
|||||||
#![allow(non_snake_case)]
|
#![allow(non_snake_case)]
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
use crate::old::snapshot_0::host::FileType;
|
use crate::old::snapshot_0::host::FileType;
|
||||||
use crate::old::snapshot_0::{
|
use crate::old::snapshot_0::wasi::{self, WasiError, WasiResult};
|
||||||
error::FromRawOsError, helpers, sys::unix::sys_impl, wasi, Error, Result,
|
use crate::old::snapshot_0::{helpers, sys::unix::sys_impl};
|
||||||
};
|
|
||||||
use std::ffi::OsStr;
|
use std::ffi::OsStr;
|
||||||
|
use std::io;
|
||||||
use std::os::unix::prelude::OsStrExt;
|
use std::os::unix::prelude::OsStrExt;
|
||||||
use yanix::file::OFlag;
|
use yanix::file::OFlag;
|
||||||
|
|
||||||
pub(crate) use sys_impl::host_impl::*;
|
pub(crate) use sys_impl::host_impl::*;
|
||||||
|
|
||||||
impl FromRawOsError for Error {
|
impl From<io::Error> for WasiError {
|
||||||
fn from_raw_os_error(code: i32) -> Self {
|
fn from(err: io::Error) -> Self {
|
||||||
match code {
|
match err.raw_os_error() {
|
||||||
libc::EPERM => Self::EPERM,
|
Some(code) => match code {
|
||||||
libc::ENOENT => Self::ENOENT,
|
libc::EPERM => Self::EPERM,
|
||||||
libc::ESRCH => Self::ESRCH,
|
libc::ENOENT => Self::ENOENT,
|
||||||
libc::EINTR => Self::EINTR,
|
libc::ESRCH => Self::ESRCH,
|
||||||
libc::EIO => Self::EIO,
|
libc::EINTR => Self::EINTR,
|
||||||
libc::ENXIO => Self::ENXIO,
|
libc::EIO => Self::EIO,
|
||||||
libc::E2BIG => Self::E2BIG,
|
libc::ENXIO => Self::ENXIO,
|
||||||
libc::ENOEXEC => Self::ENOEXEC,
|
libc::E2BIG => Self::E2BIG,
|
||||||
libc::EBADF => Self::EBADF,
|
libc::ENOEXEC => Self::ENOEXEC,
|
||||||
libc::ECHILD => Self::ECHILD,
|
libc::EBADF => Self::EBADF,
|
||||||
libc::EAGAIN => Self::EAGAIN,
|
libc::ECHILD => Self::ECHILD,
|
||||||
libc::ENOMEM => Self::ENOMEM,
|
libc::EAGAIN => Self::EAGAIN,
|
||||||
libc::EACCES => Self::EACCES,
|
libc::ENOMEM => Self::ENOMEM,
|
||||||
libc::EFAULT => Self::EFAULT,
|
libc::EACCES => Self::EACCES,
|
||||||
libc::EBUSY => Self::EBUSY,
|
libc::EFAULT => Self::EFAULT,
|
||||||
libc::EEXIST => Self::EEXIST,
|
libc::EBUSY => Self::EBUSY,
|
||||||
libc::EXDEV => Self::EXDEV,
|
libc::EEXIST => Self::EEXIST,
|
||||||
libc::ENODEV => Self::ENODEV,
|
libc::EXDEV => Self::EXDEV,
|
||||||
libc::ENOTDIR => Self::ENOTDIR,
|
libc::ENODEV => Self::ENODEV,
|
||||||
libc::EISDIR => Self::EISDIR,
|
libc::ENOTDIR => Self::ENOTDIR,
|
||||||
libc::EINVAL => Self::EINVAL,
|
libc::EISDIR => Self::EISDIR,
|
||||||
libc::ENFILE => Self::ENFILE,
|
libc::EINVAL => Self::EINVAL,
|
||||||
libc::EMFILE => Self::EMFILE,
|
libc::ENFILE => Self::ENFILE,
|
||||||
libc::ENOTTY => Self::ENOTTY,
|
libc::EMFILE => Self::EMFILE,
|
||||||
libc::ETXTBSY => Self::ETXTBSY,
|
libc::ENOTTY => Self::ENOTTY,
|
||||||
libc::EFBIG => Self::EFBIG,
|
libc::ETXTBSY => Self::ETXTBSY,
|
||||||
libc::ENOSPC => Self::ENOSPC,
|
libc::EFBIG => Self::EFBIG,
|
||||||
libc::ESPIPE => Self::ESPIPE,
|
libc::ENOSPC => Self::ENOSPC,
|
||||||
libc::EROFS => Self::EROFS,
|
libc::ESPIPE => Self::ESPIPE,
|
||||||
libc::EMLINK => Self::EMLINK,
|
libc::EROFS => Self::EROFS,
|
||||||
libc::EPIPE => Self::EPIPE,
|
libc::EMLINK => Self::EMLINK,
|
||||||
libc::EDOM => Self::EDOM,
|
libc::EPIPE => Self::EPIPE,
|
||||||
libc::ERANGE => Self::ERANGE,
|
libc::EDOM => Self::EDOM,
|
||||||
libc::EDEADLK => Self::EDEADLK,
|
libc::ERANGE => Self::ERANGE,
|
||||||
libc::ENAMETOOLONG => Self::ENAMETOOLONG,
|
libc::EDEADLK => Self::EDEADLK,
|
||||||
libc::ENOLCK => Self::ENOLCK,
|
libc::ENAMETOOLONG => Self::ENAMETOOLONG,
|
||||||
libc::ENOSYS => Self::ENOSYS,
|
libc::ENOLCK => Self::ENOLCK,
|
||||||
libc::ENOTEMPTY => Self::ENOTEMPTY,
|
libc::ENOSYS => Self::ENOSYS,
|
||||||
libc::ELOOP => Self::ELOOP,
|
libc::ENOTEMPTY => Self::ENOTEMPTY,
|
||||||
libc::ENOMSG => Self::ENOMSG,
|
libc::ELOOP => Self::ELOOP,
|
||||||
libc::EIDRM => Self::EIDRM,
|
libc::ENOMSG => Self::ENOMSG,
|
||||||
libc::ENOLINK => Self::ENOLINK,
|
libc::EIDRM => Self::EIDRM,
|
||||||
libc::EPROTO => Self::EPROTO,
|
libc::ENOLINK => Self::ENOLINK,
|
||||||
libc::EMULTIHOP => Self::EMULTIHOP,
|
libc::EPROTO => Self::EPROTO,
|
||||||
libc::EBADMSG => Self::EBADMSG,
|
libc::EMULTIHOP => Self::EMULTIHOP,
|
||||||
libc::EOVERFLOW => Self::EOVERFLOW,
|
libc::EBADMSG => Self::EBADMSG,
|
||||||
libc::EILSEQ => Self::EILSEQ,
|
libc::EOVERFLOW => Self::EOVERFLOW,
|
||||||
libc::ENOTSOCK => Self::ENOTSOCK,
|
libc::EILSEQ => Self::EILSEQ,
|
||||||
libc::EDESTADDRREQ => Self::EDESTADDRREQ,
|
libc::ENOTSOCK => Self::ENOTSOCK,
|
||||||
libc::EMSGSIZE => Self::EMSGSIZE,
|
libc::EDESTADDRREQ => Self::EDESTADDRREQ,
|
||||||
libc::EPROTOTYPE => Self::EPROTOTYPE,
|
libc::EMSGSIZE => Self::EMSGSIZE,
|
||||||
libc::ENOPROTOOPT => Self::ENOPROTOOPT,
|
libc::EPROTOTYPE => Self::EPROTOTYPE,
|
||||||
libc::EPROTONOSUPPORT => Self::EPROTONOSUPPORT,
|
libc::ENOPROTOOPT => Self::ENOPROTOOPT,
|
||||||
libc::EAFNOSUPPORT => Self::EAFNOSUPPORT,
|
libc::EPROTONOSUPPORT => Self::EPROTONOSUPPORT,
|
||||||
libc::EADDRINUSE => Self::EADDRINUSE,
|
libc::EAFNOSUPPORT => Self::EAFNOSUPPORT,
|
||||||
libc::EADDRNOTAVAIL => Self::EADDRNOTAVAIL,
|
libc::EADDRINUSE => Self::EADDRINUSE,
|
||||||
libc::ENETDOWN => Self::ENETDOWN,
|
libc::EADDRNOTAVAIL => Self::EADDRNOTAVAIL,
|
||||||
libc::ENETUNREACH => Self::ENETUNREACH,
|
libc::ENETDOWN => Self::ENETDOWN,
|
||||||
libc::ENETRESET => Self::ENETRESET,
|
libc::ENETUNREACH => Self::ENETUNREACH,
|
||||||
libc::ECONNABORTED => Self::ECONNABORTED,
|
libc::ENETRESET => Self::ENETRESET,
|
||||||
libc::ECONNRESET => Self::ECONNRESET,
|
libc::ECONNABORTED => Self::ECONNABORTED,
|
||||||
libc::ENOBUFS => Self::ENOBUFS,
|
libc::ECONNRESET => Self::ECONNRESET,
|
||||||
libc::EISCONN => Self::EISCONN,
|
libc::ENOBUFS => Self::ENOBUFS,
|
||||||
libc::ENOTCONN => Self::ENOTCONN,
|
libc::EISCONN => Self::EISCONN,
|
||||||
libc::ETIMEDOUT => Self::ETIMEDOUT,
|
libc::ENOTCONN => Self::ENOTCONN,
|
||||||
libc::ECONNREFUSED => Self::ECONNREFUSED,
|
libc::ETIMEDOUT => Self::ETIMEDOUT,
|
||||||
libc::EHOSTUNREACH => Self::EHOSTUNREACH,
|
libc::ECONNREFUSED => Self::ECONNREFUSED,
|
||||||
libc::EALREADY => Self::EALREADY,
|
libc::EHOSTUNREACH => Self::EHOSTUNREACH,
|
||||||
libc::EINPROGRESS => Self::EINPROGRESS,
|
libc::EALREADY => Self::EALREADY,
|
||||||
libc::ESTALE => Self::ESTALE,
|
libc::EINPROGRESS => Self::EINPROGRESS,
|
||||||
libc::EDQUOT => Self::EDQUOT,
|
libc::ESTALE => Self::ESTALE,
|
||||||
libc::ECANCELED => Self::ECANCELED,
|
libc::EDQUOT => Self::EDQUOT,
|
||||||
libc::EOWNERDEAD => Self::EOWNERDEAD,
|
libc::ECANCELED => Self::ECANCELED,
|
||||||
libc::ENOTRECOVERABLE => Self::ENOTRECOVERABLE,
|
libc::EOWNERDEAD => Self::EOWNERDEAD,
|
||||||
x => {
|
libc::ENOTRECOVERABLE => Self::ENOTRECOVERABLE,
|
||||||
log::debug!("Unknown errno value: {}", x);
|
libc::ENOTSUP => Self::ENOTSUP,
|
||||||
|
x => {
|
||||||
|
log::debug!("Unknown errno value: {}", x);
|
||||||
|
Self::EIO
|
||||||
|
}
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
log::debug!("Other I/O error: {}", err);
|
||||||
Self::EIO
|
Self::EIO
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -154,13 +161,13 @@ pub(crate) fn nix_from_oflags(oflags: wasi::__wasi_oflags_t) -> OFlag {
|
|||||||
nix_flags
|
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;
|
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)
|
secs.checked_mul(1_000_000_000)
|
||||||
.and_then(|sec_nsec| sec_nsec.checked_add(nsecs))
|
.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);
|
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,
|
/// NB WASI spec requires OS string to be valid UTF-8. Otherwise,
|
||||||
/// `__WASI_ERRNO_ILSEQ` error is returned.
|
/// `__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)
|
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::host::Dirent;
|
||||||
use crate::old::snapshot_0::hostcalls_impl::PathGet;
|
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::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::convert::TryInto;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::os::unix::fs::FileExt;
|
use std::os::unix::fs::FileExt;
|
||||||
@@ -15,21 +15,25 @@ pub(crate) fn fd_pread(
|
|||||||
file: &File,
|
file: &File,
|
||||||
buf: &mut [u8],
|
buf: &mut [u8],
|
||||||
offset: wasi::__wasi_filesize_t,
|
offset: wasi::__wasi_filesize_t,
|
||||||
) -> Result<usize> {
|
) -> WasiResult<usize> {
|
||||||
file.read_at(buf, offset).map_err(Into::into)
|
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)
|
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()) }
|
unsafe { yanix::fcntl::get_status_flags(fd.as_raw_fd()) }
|
||||||
.map(host_impl::fdflags_from_nix)
|
.map(host_impl::fdflags_from_nix)
|
||||||
.map_err(Into::into)
|
.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);
|
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)
|
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,
|
advice: wasi::__wasi_advice_t,
|
||||||
offset: wasi::__wasi_filesize_t,
|
offset: wasi::__wasi_filesize_t,
|
||||||
len: wasi::__wasi_filesize_t,
|
len: wasi::__wasi_filesize_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
use yanix::fadvise::{posix_fadvise, PosixFadviseAdvice};
|
use yanix::fadvise::{posix_fadvise, PosixFadviseAdvice};
|
||||||
let offset = offset.try_into()?;
|
let offset = offset.try_into()?;
|
||||||
let len = len.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_NOREUSE => PosixFadviseAdvice::NoReuse,
|
||||||
wasi::__WASI_ADVICE_RANDOM => PosixFadviseAdvice::Random,
|
wasi::__WASI_ADVICE_RANDOM => PosixFadviseAdvice::Random,
|
||||||
wasi::__WASI_ADVICE_NORMAL => PosixFadviseAdvice::Normal,
|
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)
|
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};
|
use yanix::file::{mkdirat, Mode};
|
||||||
unsafe {
|
unsafe {
|
||||||
mkdirat(
|
mkdirat(
|
||||||
@@ -67,7 +71,7 @@ pub(crate) fn path_create_directory(resolved: PathGet) -> Result<()> {
|
|||||||
.map_err(Into::into)
|
.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};
|
use yanix::file::{linkat, AtFlag};
|
||||||
unsafe {
|
unsafe {
|
||||||
linkat(
|
linkat(
|
||||||
@@ -87,7 +91,7 @@ pub(crate) fn path_open(
|
|||||||
write: bool,
|
write: bool,
|
||||||
oflags: wasi::__wasi_oflags_t,
|
oflags: wasi::__wasi_oflags_t,
|
||||||
fs_flags: wasi::__wasi_fdflags_t,
|
fs_flags: wasi::__wasi_fdflags_t,
|
||||||
) -> Result<File> {
|
) -> WasiResult<File> {
|
||||||
use yanix::file::{fstatat, openat, AtFlag, FileType, Mode, OFlag};
|
use yanix::file::{fstatat, openat, AtFlag, FileType, Mode, OFlag};
|
||||||
|
|
||||||
let mut nix_all_oflags = if read && write {
|
let mut nix_all_oflags = if read && write {
|
||||||
@@ -136,7 +140,7 @@ pub(crate) fn path_open(
|
|||||||
} {
|
} {
|
||||||
Ok(stat) => {
|
Ok(stat) => {
|
||||||
if FileType::from_stat_st_mode(stat.st_mode) == FileType::Socket {
|
if FileType::from_stat_st_mode(stat.st_mode) == FileType::Socket {
|
||||||
return Err(Error::ENOTSUP);
|
return Err(WasiError::ENOTSUP);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
@@ -158,7 +162,7 @@ pub(crate) fn path_open(
|
|||||||
} {
|
} {
|
||||||
Ok(stat) => {
|
Ok(stat) => {
|
||||||
if FileType::from_stat_st_mode(stat.st_mode) == FileType::Symlink {
|
if FileType::from_stat_st_mode(stat.st_mode) == FileType::Symlink {
|
||||||
return Err(Error::ELOOP);
|
return Err(WasiError::ELOOP);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
@@ -169,7 +173,7 @@ pub(crate) fn path_open(
|
|||||||
// FreeBSD returns EMLINK instead of ELOOP when using O_NOFOLLOW on
|
// FreeBSD returns EMLINK instead of ELOOP when using O_NOFOLLOW on
|
||||||
// a symlink.
|
// a symlink.
|
||||||
libc::EMLINK if !(nix_all_oflags & OFlag::NOFOLLOW).is_empty() => {
|
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) })
|
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 std::cmp::min;
|
||||||
use yanix::file::readlinkat;
|
use yanix::file::readlinkat;
|
||||||
let read_link = unsafe { readlinkat(resolved.dirfd().as_raw_fd(), resolved.path()) }
|
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)
|
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;
|
use yanix::file::fstat;
|
||||||
unsafe { fstat(file.as_raw_fd()) }
|
unsafe { fstat(file.as_raw_fd()) }
|
||||||
.map_err(Into::into)
|
.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(
|
pub(crate) fn path_filestat_get(
|
||||||
resolved: PathGet,
|
resolved: PathGet,
|
||||||
dirflags: wasi::__wasi_lookupflags_t,
|
dirflags: wasi::__wasi_lookupflags_t,
|
||||||
) -> Result<wasi::__wasi_filestat_t> {
|
) -> WasiResult<wasi::__wasi_filestat_t> {
|
||||||
use yanix::file::{fstatat, AtFlag};
|
use yanix::file::{fstatat, AtFlag};
|
||||||
let atflags = match dirflags {
|
let atflags = match dirflags {
|
||||||
0 => AtFlag::empty(),
|
0 => AtFlag::empty(),
|
||||||
@@ -224,7 +228,7 @@ pub(crate) fn path_filestat_set_times(
|
|||||||
st_atim: wasi::__wasi_timestamp_t,
|
st_atim: wasi::__wasi_timestamp_t,
|
||||||
st_mtim: wasi::__wasi_timestamp_t,
|
st_mtim: wasi::__wasi_timestamp_t,
|
||||||
fst_flags: wasi::__wasi_fstflags_t,
|
fst_flags: wasi::__wasi_fstflags_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
use std::time::{Duration, UNIX_EPOCH};
|
use std::time::{Duration, UNIX_EPOCH};
|
||||||
use yanix::filetime::*;
|
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;
|
let set_mtim_now = fst_flags & wasi::__WASI_FSTFLAGS_MTIM_NOW != 0;
|
||||||
|
|
||||||
if (set_atim && set_atim_now) || (set_mtim && set_mtim_now) {
|
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;
|
let symlink_nofollow = wasi::__WASI_LOOKUPFLAGS_SYMLINK_FOLLOW != dirflags;
|
||||||
@@ -265,7 +269,7 @@ pub(crate) fn path_filestat_set_times(
|
|||||||
.map_err(Into::into)
|
.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};
|
use yanix::file::{unlinkat, AtFlag};
|
||||||
unsafe {
|
unsafe {
|
||||||
unlinkat(
|
unlinkat(
|
||||||
@@ -280,7 +284,7 @@ pub(crate) fn path_remove_directory(resolved: PathGet) -> Result<()> {
|
|||||||
pub(crate) fn fd_readdir<'a>(
|
pub(crate) fn fd_readdir<'a>(
|
||||||
os_handle: &'a mut OsHandle,
|
os_handle: &'a mut OsHandle,
|
||||||
cookie: wasi::__wasi_dircookie_t,
|
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};
|
use yanix::dir::{DirIter, Entry, EntryExt, SeekLoc};
|
||||||
|
|
||||||
// Get an instance of `Dir`; this is host-specific due to intricasies
|
// Get an instance of `Dir`; this is host-specific due to intricasies
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#![allow(non_camel_case_types)]
|
#![allow(non_camel_case_types)]
|
||||||
#![allow(unused_unsafe)]
|
#![allow(unused_unsafe)]
|
||||||
use crate::old::snapshot_0::sys::host_impl;
|
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 std::fs::File;
|
||||||
use yanix::file::OFlag;
|
use yanix::file::OFlag;
|
||||||
|
|
||||||
@@ -36,7 +36,7 @@ pub(crate) fn path_open_rights(
|
|||||||
(needed_base, needed_inheriting)
|
(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 std::os::unix::prelude::{AsRawFd, FromRawFd};
|
||||||
use yanix::file::{openat, Mode};
|
use yanix::file::{openat, Mode};
|
||||||
|
|
||||||
@@ -54,7 +54,7 @@ pub(crate) fn openat(dirfd: &File, path: &str) -> Result<File> {
|
|||||||
.map_err(Into::into)
|
.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 std::os::unix::prelude::AsRawFd;
|
||||||
use yanix::file::readlinkat;
|
use yanix::file::readlinkat;
|
||||||
|
|
||||||
|
|||||||
@@ -1,22 +1,24 @@
|
|||||||
#![allow(non_camel_case_types)]
|
#![allow(non_camel_case_types)]
|
||||||
#![allow(unused_unsafe)]
|
#![allow(unused_unsafe)]
|
||||||
use crate::old::snapshot_0::hostcalls_impl::{ClockEventData, FdEventData};
|
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 std::io;
|
||||||
use yanix::clock::{clock_getres, clock_gettime, ClockId};
|
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
|
// convert the supported clocks to libc types, or return EINVAL
|
||||||
match clock_id {
|
match clock_id {
|
||||||
wasi::__WASI_CLOCKID_REALTIME => Ok(ClockId::Realtime),
|
wasi::__WASI_CLOCKID_REALTIME => Ok(ClockId::Realtime),
|
||||||
wasi::__WASI_CLOCKID_MONOTONIC => Ok(ClockId::Monotonic),
|
wasi::__WASI_CLOCKID_MONOTONIC => Ok(ClockId::Monotonic),
|
||||||
wasi::__WASI_CLOCKID_PROCESS_CPUTIME_ID => Ok(ClockId::ProcessCPUTime),
|
wasi::__WASI_CLOCKID_PROCESS_CPUTIME_ID => Ok(ClockId::ProcessCPUTime),
|
||||||
wasi::__WASI_CLOCKID_THREAD_CPUTIME_ID => Ok(ClockId::ThreadCPUTime),
|
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 clock_id = wasi_clock_id_to_unix(clock_id)?;
|
||||||
let timespec = clock_getres(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)
|
(timespec.tv_sec as wasi::__wasi_timestamp_t)
|
||||||
.checked_mul(1_000_000_000)
|
.checked_mul(1_000_000_000)
|
||||||
.and_then(|sec_ns| sec_ns.checked_add(timespec.tv_nsec as wasi::__wasi_timestamp_t))
|
.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
|
// a supported clock can never return zero; this case will probably never get hit, but
|
||||||
// make sure we follow the spec
|
// make sure we follow the spec
|
||||||
if resolution == 0 {
|
if resolution == 0 {
|
||||||
Err(Error::EINVAL)
|
Err(WasiError::EINVAL)
|
||||||
} else {
|
} else {
|
||||||
Ok(resolution)
|
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 clock_id = wasi_clock_id_to_unix(clock_id)?;
|
||||||
let timespec = clock_gettime(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)
|
(timespec.tv_sec as wasi::__wasi_timestamp_t)
|
||||||
.checked_mul(1_000_000_000)
|
.checked_mul(1_000_000_000)
|
||||||
.and_then(|sec_ns| sec_ns.checked_add(timespec.tv_nsec as wasi::__wasi_timestamp_t))
|
.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(
|
pub(crate) fn poll_oneoff(
|
||||||
timeout: Option<ClockEventData>,
|
timeout: Option<ClockEventData>,
|
||||||
fd_events: Vec<FdEventData>,
|
fd_events: Vec<FdEventData>,
|
||||||
events: &mut Vec<wasi::__wasi_event_t>,
|
events: &mut Vec<wasi::__wasi_event_t>,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
use std::{convert::TryInto, os::unix::prelude::AsRawFd};
|
use std::{convert::TryInto, os::unix::prelude::AsRawFd};
|
||||||
use yanix::poll::{poll, PollFd, PollFlags};
|
use yanix::poll::{poll, PollFd, PollFlags};
|
||||||
|
|
||||||
@@ -122,7 +126,7 @@ fn poll_oneoff_handle_timeout_event(
|
|||||||
fn poll_oneoff_handle_fd_event<'a>(
|
fn poll_oneoff_handle_fd_event<'a>(
|
||||||
ready_events: impl Iterator<Item = (FdEventData<'a>, yanix::poll::PollFd)>,
|
ready_events: impl Iterator<Item = (FdEventData<'a>, yanix::poll::PollFd)>,
|
||||||
events: &mut Vec<wasi::__wasi_event_t>,
|
events: &mut Vec<wasi::__wasi_event_t>,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
use std::{convert::TryInto, os::unix::prelude::AsRawFd};
|
use std::{convert::TryInto, os::unix::prelude::AsRawFd};
|
||||||
use yanix::{file::fionread, poll::PollFlags};
|
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;
|
use std::convert::TryInto;
|
||||||
|
|
||||||
pub(crate) const O_RSYNC: yanix::file::OFlag = yanix::file::OFlag::RSYNC;
|
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))
|
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))
|
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)
|
nlink.try_into().map_err(Into::into)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
use crate::old::snapshot_0::hostcalls_impl::PathGet;
|
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;
|
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};
|
use yanix::file::{unlinkat, AtFlag};
|
||||||
unsafe {
|
unsafe {
|
||||||
unlinkat(
|
unlinkat(
|
||||||
@@ -14,7 +14,7 @@ pub(crate) fn path_unlink_file(resolved: PathGet) -> Result<()> {
|
|||||||
.map_err(Into::into)
|
.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;
|
use yanix::file::symlinkat;
|
||||||
|
|
||||||
log::debug!("path_symlink old_path = {:?}", old_path);
|
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)
|
.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;
|
use yanix::file::renameat;
|
||||||
unsafe {
|
unsafe {
|
||||||
renameat(
|
renameat(
|
||||||
@@ -39,10 +39,10 @@ pub(crate) fn path_rename(resolved_old: PathGet, resolved_new: PathGet) -> Resul
|
|||||||
|
|
||||||
pub(crate) mod fd_readdir_impl {
|
pub(crate) mod fd_readdir_impl {
|
||||||
use crate::old::snapshot_0::sys::fdentry_impl::OsHandle;
|
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;
|
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)`:
|
// We need to duplicate the fd, because `opendir(3)`:
|
||||||
// After a successful call to fdopendir(), fd is used internally by the implementation,
|
// After a successful call to fdopendir(), fd is used internally by the implementation,
|
||||||
// and should not otherwise be used by the application.
|
// 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::fs::{File, OpenOptions};
|
||||||
|
use std::io::Result;
|
||||||
|
|
||||||
pub(crate) fn dev_null() -> Result<File> {
|
pub(crate) fn dev_null() -> Result<File> {
|
||||||
OpenOptions::new()
|
OpenOptions::new().read(true).write(true).open("/dev/null")
|
||||||
.read(true)
|
|
||||||
.write(true)
|
|
||||||
.open("/dev/null")
|
|
||||||
.map_err(Into::into)
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use crate::old::snapshot_0::fdentry::{Descriptor, OsHandleRef};
|
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::fs::File;
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::mem::ManuallyDrop;
|
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.
|
/// This function is unsafe because it operates on a raw file handle.
|
||||||
pub(crate) unsafe fn determine_type_and_access_rights<Handle: AsRawHandle>(
|
pub(crate) unsafe fn determine_type_and_access_rights<Handle: AsRawHandle>(
|
||||||
handle: &Handle,
|
handle: &Handle,
|
||||||
) -> Result<(
|
) -> io::Result<(
|
||||||
wasi::__wasi_filetype_t,
|
wasi::__wasi_filetype_t,
|
||||||
wasi::__wasi_rights_t,
|
wasi::__wasi_rights_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.
|
/// This function is unsafe because it operates on a raw file handle.
|
||||||
pub(crate) unsafe fn determine_type_rights<Handle: AsRawHandle>(
|
pub(crate) unsafe fn determine_type_rights<Handle: AsRawHandle>(
|
||||||
handle: &Handle,
|
handle: &Handle,
|
||||||
) -> Result<(
|
) -> io::Result<(
|
||||||
wasi::__wasi_filetype_t,
|
wasi::__wasi_filetype_t,
|
||||||
wasi::__wasi_rights_t,
|
wasi::__wasi_rights_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() {
|
} else if file_type.is_disk() {
|
||||||
// disk file: file, dir or disk device
|
// disk file: file, dir or disk device
|
||||||
let file = std::mem::ManuallyDrop::new(File::from_raw_handle(handle.as_raw_handle()));
|
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() {
|
if meta.is_dir() {
|
||||||
(
|
(
|
||||||
wasi::__WASI_FILETYPE_DIRECTORY,
|
wasi::__WASI_FILETYPE_DIRECTORY,
|
||||||
@@ -120,7 +120,7 @@ pub(crate) unsafe fn determine_type_rights<Handle: AsRawHandle>(
|
|||||||
wasi::RIGHTS_REGULAR_FILE_INHERITING,
|
wasi::RIGHTS_REGULAR_FILE_INHERITING,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
return Err(Error::EINVAL);
|
return Err(io::Error::from_raw_os_error(libc::EINVAL));
|
||||||
}
|
}
|
||||||
} else if file_type.is_pipe() {
|
} else if file_type.is_pipe() {
|
||||||
// pipe object: socket, named pipe or anonymous 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,
|
wasi::RIGHTS_SOCKET_INHERITING,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
return Err(Error::EINVAL);
|
return Err(io::Error::from_raw_os_error(libc::EINVAL));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Ok((file_type, rights_base, rights_inheriting))
|
Ok((file_type, rights_base, rights_inheriting))
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
#![allow(non_snake_case)]
|
#![allow(non_snake_case)]
|
||||||
#![allow(unused)]
|
#![allow(unused)]
|
||||||
use crate::old::snapshot_0::host::FileType;
|
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::convert::TryInto;
|
||||||
use std::ffi::OsStr;
|
use std::ffi::OsStr;
|
||||||
use std::fs::OpenOptions;
|
use std::fs::OpenOptions;
|
||||||
@@ -15,34 +15,42 @@ use std::time::{SystemTime, UNIX_EPOCH};
|
|||||||
use winapi::shared::winerror;
|
use winapi::shared::winerror;
|
||||||
use winx::file::{AccessMode, Attributes, CreationDisposition, Flags};
|
use winx::file::{AccessMode, Attributes, CreationDisposition, Flags};
|
||||||
|
|
||||||
impl FromRawOsError for Error {
|
impl From<io::Error> for WasiError {
|
||||||
fn from_raw_os_error(code: i32) -> Self {
|
fn from(err: io::Error) -> Self {
|
||||||
// TODO: implement error mapping between Windows and WASI
|
match err.raw_os_error() {
|
||||||
match code as u32 {
|
Some(code) => match code as u32 {
|
||||||
winerror::ERROR_SUCCESS => Self::ESUCCESS,
|
winerror::ERROR_SUCCESS => Self::ESUCCESS,
|
||||||
winerror::ERROR_BAD_ENVIRONMENT => Self::E2BIG,
|
winerror::ERROR_BAD_ENVIRONMENT => Self::E2BIG,
|
||||||
winerror::ERROR_FILE_NOT_FOUND => Self::ENOENT,
|
winerror::ERROR_FILE_NOT_FOUND => Self::ENOENT,
|
||||||
winerror::ERROR_PATH_NOT_FOUND => Self::ENOENT,
|
winerror::ERROR_PATH_NOT_FOUND => Self::ENOENT,
|
||||||
winerror::ERROR_TOO_MANY_OPEN_FILES => Self::ENFILE,
|
winerror::ERROR_TOO_MANY_OPEN_FILES => Self::ENFILE,
|
||||||
winerror::ERROR_ACCESS_DENIED => Self::EACCES,
|
winerror::ERROR_ACCESS_DENIED => Self::EACCES,
|
||||||
winerror::ERROR_SHARING_VIOLATION => 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_HANDLE => Self::EBADF,
|
||||||
winerror::ERROR_INVALID_NAME => Self::ENOENT,
|
winerror::ERROR_INVALID_NAME => Self::ENOENT,
|
||||||
winerror::ERROR_NOT_ENOUGH_MEMORY => Self::ENOMEM,
|
winerror::ERROR_NOT_ENOUGH_MEMORY => Self::ENOMEM,
|
||||||
winerror::ERROR_OUTOFMEMORY => Self::ENOMEM,
|
winerror::ERROR_OUTOFMEMORY => Self::ENOMEM,
|
||||||
winerror::ERROR_DIR_NOT_EMPTY => Self::ENOTEMPTY,
|
winerror::ERROR_DIR_NOT_EMPTY => Self::ENOTEMPTY,
|
||||||
winerror::ERROR_NOT_READY => Self::EBUSY,
|
winerror::ERROR_NOT_READY => Self::EBUSY,
|
||||||
winerror::ERROR_BUSY => Self::EBUSY,
|
winerror::ERROR_BUSY => Self::EBUSY,
|
||||||
winerror::ERROR_NOT_SUPPORTED => Self::ENOTSUP,
|
winerror::ERROR_NOT_SUPPORTED => Self::ENOTSUP,
|
||||||
winerror::ERROR_FILE_EXISTS => Self::EEXIST,
|
winerror::ERROR_FILE_EXISTS => Self::EEXIST,
|
||||||
winerror::ERROR_BROKEN_PIPE => Self::EPIPE,
|
winerror::ERROR_BROKEN_PIPE => Self::EPIPE,
|
||||||
winerror::ERROR_BUFFER_OVERFLOW => Self::ENAMETOOLONG,
|
winerror::ERROR_BUFFER_OVERFLOW => Self::ENAMETOOLONG,
|
||||||
winerror::ERROR_NOT_A_REPARSE_POINT => Self::EINVAL,
|
winerror::ERROR_NOT_A_REPARSE_POINT => Self::EINVAL,
|
||||||
winerror::ERROR_NEGATIVE_SEEK => Self::EINVAL,
|
winerror::ERROR_NEGATIVE_SEEK => Self::EINVAL,
|
||||||
winerror::ERROR_DIRECTORY => Self::ENOTDIR,
|
winerror::ERROR_DIRECTORY => Self::ENOTDIR,
|
||||||
winerror::ERROR_ALREADY_EXISTS => Self::EEXIST,
|
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)
|
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)
|
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()
|
.as_nanos()
|
||||||
.try_into()
|
.try_into()
|
||||||
.map_err(Into::into) // u128 doesn't fit into u64
|
.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()?;
|
let metadata = file.metadata()?;
|
||||||
Ok(wasi::__wasi_filestat_t {
|
Ok(wasi::__wasi_filestat_t {
|
||||||
dev: device_id(file)?,
|
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,
|
/// NB WASI spec requires OS string to be valid UTF-8. Otherwise,
|
||||||
/// `__WASI_ERRNO_ILSEQ` error is returned.
|
/// `__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();
|
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::fdentry_impl::determine_type_rights;
|
||||||
use crate::old::snapshot_0::sys::host_impl::{self, path_from_host};
|
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::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 log::{debug, trace};
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
use std::fs::{File, Metadata, OpenOptions};
|
use std::fs::{File, Metadata, OpenOptions};
|
||||||
@@ -44,16 +44,20 @@ pub(crate) fn fd_pread(
|
|||||||
file: &File,
|
file: &File,
|
||||||
buf: &mut [u8],
|
buf: &mut [u8],
|
||||||
offset: wasi::__wasi_filesize_t,
|
offset: wasi::__wasi_filesize_t,
|
||||||
) -> Result<usize> {
|
) -> WasiResult<usize> {
|
||||||
read_at(file, buf, offset).map_err(Into::into)
|
read_at(file, buf, offset).map_err(Into::into)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO refactor common code with unix
|
// 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)
|
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 mut fdflags = 0;
|
||||||
|
|
||||||
let handle = unsafe { fd.as_raw_handle() };
|
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)
|
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")
|
unimplemented!("fd_fdstat_set_flags")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,7 +92,7 @@ pub(crate) fn fd_advise(
|
|||||||
advice: wasi::__wasi_advice_t,
|
advice: wasi::__wasi_advice_t,
|
||||||
_offset: wasi::__wasi_filesize_t,
|
_offset: wasi::__wasi_filesize_t,
|
||||||
_len: wasi::__wasi_filesize_t,
|
_len: wasi::__wasi_filesize_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
match advice {
|
match advice {
|
||||||
wasi::__WASI_ADVICE_DONTNEED
|
wasi::__WASI_ADVICE_DONTNEED
|
||||||
| wasi::__WASI_ADVICE_SEQUENTIAL
|
| wasi::__WASI_ADVICE_SEQUENTIAL
|
||||||
@@ -96,18 +100,18 @@ pub(crate) fn fd_advise(
|
|||||||
| wasi::__WASI_ADVICE_NOREUSE
|
| wasi::__WASI_ADVICE_NOREUSE
|
||||||
| wasi::__WASI_ADVICE_RANDOM
|
| wasi::__WASI_ADVICE_RANDOM
|
||||||
| wasi::__WASI_ADVICE_NORMAL => {}
|
| wasi::__WASI_ADVICE_NORMAL => {}
|
||||||
_ => return Err(Error::EINVAL),
|
_ => return Err(WasiError::EINVAL),
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn path_create_directory(resolved: PathGet) -> Result<()> {
|
pub(crate) fn path_create_directory(resolved: PathGet) -> WasiResult<()> {
|
||||||
let path = resolved.concatenate()?;
|
let path = resolved.concatenate()?;
|
||||||
std::fs::create_dir(&path).map_err(Into::into)
|
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")
|
unimplemented!("path_link")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -117,7 +121,7 @@ pub(crate) fn path_open(
|
|||||||
write: bool,
|
write: bool,
|
||||||
oflags: wasi::__wasi_oflags_t,
|
oflags: wasi::__wasi_oflags_t,
|
||||||
fdflags: wasi::__wasi_fdflags_t,
|
fdflags: wasi::__wasi_fdflags_t,
|
||||||
) -> Result<File> {
|
) -> WasiResult<File> {
|
||||||
use winx::file::{AccessMode, CreationDisposition, Flags};
|
use winx::file::{AccessMode, CreationDisposition, Flags};
|
||||||
|
|
||||||
// convert open flags
|
// convert open flags
|
||||||
@@ -143,11 +147,11 @@ pub(crate) fn path_open(
|
|||||||
Ok(file_type) => {
|
Ok(file_type) => {
|
||||||
// check if we are trying to open a symlink
|
// check if we are trying to open a symlink
|
||||||
if file_type.is_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
|
// check if we are trying to open a file as a dir
|
||||||
if file_type.is_file() && oflags & wasi::__WASI_OFLAGS_DIRECTORY != 0 {
|
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() {
|
Err(err) => match err.raw_os_error() {
|
||||||
@@ -162,7 +166,7 @@ pub(crate) fn path_open(
|
|||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
log::debug!("Inconvertible OS error: {}", err);
|
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,
|
path: P,
|
||||||
name: &str,
|
name: &str,
|
||||||
cookie: wasi::__wasi_dircookie_t,
|
cookie: wasi::__wasi_dircookie_t,
|
||||||
) -> Result<Dirent> {
|
) -> WasiResult<Dirent> {
|
||||||
let path = path.as_ref();
|
let path = path.as_ref();
|
||||||
trace!("dirent_from_path: opening {}", path.to_string_lossy());
|
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(
|
pub(crate) fn fd_readdir(
|
||||||
fd: &File,
|
fd: &File,
|
||||||
cookie: wasi::__wasi_dircookie_t,
|
cookie: wasi::__wasi_dircookie_t,
|
||||||
) -> Result<impl Iterator<Item = Result<Dirent>>> {
|
) -> WasiResult<impl Iterator<Item = WasiResult<Dirent>>> {
|
||||||
use winx::file::get_file_path;
|
use winx::file::get_file_path;
|
||||||
|
|
||||||
let cookie = cookie.try_into()?;
|
let cookie = cookie.try_into()?;
|
||||||
@@ -321,7 +325,7 @@ pub(crate) fn fd_readdir(
|
|||||||
Ok(iter.skip(cookie))
|
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;
|
use winx::file::get_file_path;
|
||||||
|
|
||||||
let path = resolved.concatenate()?;
|
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 dir_path = PathBuf::from(strip_extended_prefix(dir_path));
|
||||||
let target_path = target_path
|
let target_path = target_path
|
||||||
.strip_prefix(dir_path)
|
.strip_prefix(dir_path)
|
||||||
.map_err(|_| Error::ENOTCAPABLE)
|
.map_err(|_| WasiError::ENOTCAPABLE)
|
||||||
.and_then(|path| path.to_str().map(String::from).ok_or(Error::EILSEQ))?;
|
.and_then(|path| path.to_str().map(String::from).ok_or(WasiError::EILSEQ))?;
|
||||||
|
|
||||||
if buf.len() > 0 {
|
if buf.len() > 0 {
|
||||||
let mut chars = target_path.chars();
|
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('/') {
|
if resolved.path().ends_with('/') {
|
||||||
let suffix = resolved.path().trim_end_matches('/');
|
let suffix = resolved.path().trim_end_matches('/');
|
||||||
concatenate(resolved.dirfd(), Path::new(suffix)).map(Some)
|
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;
|
use std::fs;
|
||||||
|
|
||||||
let old_path = resolved_old.concatenate()?;
|
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
|
// [std::fs::rename]: https://doc.rust-lang.org/std/fs/fn.rename.html
|
||||||
if old_path.is_dir() && new_path.is_file() {
|
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
|
// Second sanity check: check we're not trying to rename a file into a path
|
||||||
// ending in a trailing slash.
|
// ending in a trailing slash.
|
||||||
if old_path.is_file() && resolved_new.path().ends_with('/') {
|
if old_path.is_file() && resolved_new.path().ends_with('/') {
|
||||||
return Err(Error::ENOTDIR);
|
return Err(WasiError::ENOTDIR);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO handle symlinks
|
// 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.
|
// So most likely dealing with new_path == dir.
|
||||||
// Eliminate case old_path == file first.
|
// Eliminate case old_path == file first.
|
||||||
if old_path.is_file() {
|
if old_path.is_file() {
|
||||||
return Err(Error::EISDIR);
|
return Err(WasiError::EISDIR);
|
||||||
} else {
|
} else {
|
||||||
// Ok, let's try removing an empty dir at new_path if it exists
|
// Ok, let's try removing an empty dir at new_path if it exists
|
||||||
// and is a nonempty dir.
|
// 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.
|
// a file instead of a dir, and if so, throw ENOTDIR.
|
||||||
if let Some(path) = strip_trailing_slashes_and_concatenate(&resolved_old)? {
|
if let Some(path) = strip_trailing_slashes_and_concatenate(&resolved_old)? {
|
||||||
if path.is_file() {
|
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 => {
|
None => {
|
||||||
log::debug!("Inconvertible OS error: {}", err);
|
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)
|
host_impl::filestat_from_win(file)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn path_filestat_get(
|
pub(crate) fn path_filestat_get(
|
||||||
resolved: PathGet,
|
resolved: PathGet,
|
||||||
dirflags: wasi::__wasi_lookupflags_t,
|
dirflags: wasi::__wasi_lookupflags_t,
|
||||||
) -> Result<wasi::__wasi_filestat_t> {
|
) -> WasiResult<wasi::__wasi_filestat_t> {
|
||||||
let path = resolved.concatenate()?;
|
let path = resolved.concatenate()?;
|
||||||
let file = File::open(path)?;
|
let file = File::open(path)?;
|
||||||
host_impl::filestat_from_win(&file)
|
host_impl::filestat_from_win(&file)
|
||||||
@@ -448,7 +452,7 @@ pub(crate) fn path_filestat_set_times(
|
|||||||
st_atim: wasi::__wasi_timestamp_t,
|
st_atim: wasi::__wasi_timestamp_t,
|
||||||
mut st_mtim: wasi::__wasi_timestamp_t,
|
mut st_mtim: wasi::__wasi_timestamp_t,
|
||||||
fst_flags: wasi::__wasi_fstflags_t,
|
fst_flags: wasi::__wasi_fstflags_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
use winx::file::AccessMode;
|
use winx::file::AccessMode;
|
||||||
let path = resolved.concatenate()?;
|
let path = resolved.concatenate()?;
|
||||||
let file = OpenOptions::new()
|
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)
|
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};
|
use std::os::windows::fs::{symlink_dir, symlink_file};
|
||||||
|
|
||||||
let old_path = concatenate(resolved.dirfd(), Path::new(old_path))?;
|
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 => {
|
winerror::ERROR_ACCESS_DENIED => {
|
||||||
// does the target exist?
|
// does the target exist?
|
||||||
if new_path.exists() {
|
if new_path.exists() {
|
||||||
return Err(Error::EEXIST);
|
return Err(WasiError::EEXIST);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
winerror::ERROR_INVALID_NAME => {
|
winerror::ERROR_INVALID_NAME => {
|
||||||
// does the target without trailing slashes exist?
|
// does the target without trailing slashes exist?
|
||||||
if let Some(path) = strip_trailing_slashes_and_concatenate(&resolved)? {
|
if let Some(path) = strip_trailing_slashes_and_concatenate(&resolved)? {
|
||||||
if path.exists() {
|
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 => {
|
None => {
|
||||||
log::debug!("Inconvertible OS error: {}", err);
|
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;
|
use std::fs;
|
||||||
|
|
||||||
let path = resolved.concatenate()?;
|
let path = resolved.concatenate()?;
|
||||||
@@ -532,19 +536,19 @@ pub(crate) fn path_unlink_file(resolved: PathGet) -> Result<()> {
|
|||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
log::debug!("Inconvertible OS error: {}", err);
|
log::debug!("Inconvertible OS error: {}", err);
|
||||||
Err(Error::EIO)
|
Err(WasiError::EIO)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if file_type.is_dir() {
|
} else if file_type.is_dir() {
|
||||||
Err(Error::EISDIR)
|
Err(WasiError::EISDIR)
|
||||||
} else if file_type.is_file() {
|
} else if file_type.is_file() {
|
||||||
fs::remove_file(path).map_err(Into::into)
|
fs::remove_file(path).map_err(Into::into)
|
||||||
} else {
|
} 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()?;
|
let path = resolved.concatenate()?;
|
||||||
std::fs::remove_dir(&path).map_err(Into::into)
|
std::fs::remove_dir(&path).map_err(Into::into)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#![allow(non_camel_case_types)]
|
#![allow(non_camel_case_types)]
|
||||||
use crate::old::snapshot_0::hostcalls_impl::PathGet;
|
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::ffi::{OsStr, OsString};
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::os::windows::ffi::{OsStrExt, OsStringExt};
|
use std::os::windows::ffi::{OsStrExt, OsStringExt};
|
||||||
@@ -8,11 +8,11 @@ use std::path::{Path, PathBuf};
|
|||||||
use winapi::shared::winerror;
|
use winapi::shared::winerror;
|
||||||
|
|
||||||
pub(crate) trait PathGetExt {
|
pub(crate) trait PathGetExt {
|
||||||
fn concatenate(&self) -> Result<PathBuf>;
|
fn concatenate(&self) -> WasiResult<PathBuf>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PathGetExt for PathGet {
|
impl PathGetExt for PathGet {
|
||||||
fn concatenate(&self) -> Result<PathBuf> {
|
fn concatenate(&self) -> WasiResult<PathBuf> {
|
||||||
concatenate(self.dirfd(), Path::new(self.path()))
|
concatenate(self.dirfd(), Path::new(self.path()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -46,7 +46,7 @@ pub(crate) fn path_open_rights(
|
|||||||
(needed_base, needed_inheriting)
|
(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::fs::OpenOptions;
|
||||||
use std::os::windows::fs::OpenOptionsExt;
|
use std::os::windows::fs::OpenOptionsExt;
|
||||||
use winx::file::Flags;
|
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() {
|
if let Some(code) = err.raw_os_error() {
|
||||||
log::debug!("openat error={:?}", code);
|
log::debug!("openat error={:?}", code);
|
||||||
if code as u32 == winerror::ERROR_INVALID_NAME {
|
if code as u32 == winerror::ERROR_INVALID_NAME {
|
||||||
return Err(Error::ENOTDIR);
|
return Err(WasiError::ENOTDIR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(err.into())
|
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;
|
use winx::file::get_file_path;
|
||||||
|
|
||||||
let path = concatenate(dirfd, Path::new(s_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 dir_path = PathBuf::from(strip_extended_prefix(dir_path));
|
||||||
let target_path = target_path
|
let target_path = target_path
|
||||||
.strip_prefix(dir_path)
|
.strip_prefix(dir_path)
|
||||||
.map_err(|_| Error::ENOTCAPABLE)?;
|
.map_err(|_| WasiError::ENOTCAPABLE)?;
|
||||||
let target_path = target_path.to_str().ok_or(Error::EILSEQ)?;
|
let target_path = target_path.to_str().ok_or(WasiError::EILSEQ)?;
|
||||||
return Ok(target_path.to_owned());
|
return Ok(target_path.to_owned());
|
||||||
}
|
}
|
||||||
Err(e) => e,
|
Err(e) => e,
|
||||||
@@ -96,7 +96,7 @@ pub(crate) fn readlinkat(dirfd: &File, s_path: &str) -> Result<String> {
|
|||||||
// strip "/" and check if exists
|
// strip "/" and check if exists
|
||||||
let path = concatenate(dirfd, Path::new(s_path.trim_end_matches('/')))?;
|
let path = concatenate(dirfd, Path::new(s_path.trim_end_matches('/')))?;
|
||||||
if path.exists() && !path.is_dir() {
|
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;
|
use winx::file::get_file_path;
|
||||||
|
|
||||||
// WASI is not able to deal with absolute paths
|
// WASI is not able to deal with absolute paths
|
||||||
// so error out if absolute
|
// so error out if absolute
|
||||||
if path.as_ref().is_absolute() {
|
if path.as_ref().is_absolute() {
|
||||||
return Err(Error::ENOTCAPABLE);
|
return Err(WasiError::ENOTCAPABLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
let dir_path = get_file_path(dirfd)?;
|
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::hostcalls_impl::{ClockEventData, FdEventData};
|
||||||
use crate::old::snapshot_0::memory::*;
|
use crate::old::snapshot_0::memory::*;
|
||||||
use crate::old::snapshot_0::sys::host_impl;
|
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 cpu_time::{ProcessTime, ThreadTime};
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use std::convert::TryInto;
|
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
|
// Timer resolution on Windows is really hard. We may consider exposing the resolution of the respective
|
||||||
// timers as an associated function in the future.
|
// 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 {
|
Ok(match clock_id {
|
||||||
// This is the best that we can do with std::time::SystemTime.
|
// This is the best that we can do with std::time::SystemTime.
|
||||||
// Rust uses GetSystemTimeAsFileTime, which is said to have the resolution of
|
// 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.
|
// 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
|
// https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-getthreadtimes
|
||||||
wasi::__WASI_CLOCKID_THREAD_CPUTIME_ID => 100,
|
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 {
|
let duration = match clock_id {
|
||||||
wasi::__WASI_CLOCKID_REALTIME => get_monotonic_time(),
|
wasi::__WASI_CLOCKID_REALTIME => get_monotonic_time(),
|
||||||
wasi::__WASI_CLOCKID_MONOTONIC => get_realtime_time()?,
|
wasi::__WASI_CLOCKID_MONOTONIC => get_realtime_time()?,
|
||||||
wasi::__WASI_CLOCKID_PROCESS_CPUTIME_ID => get_proc_cputime()?,
|
wasi::__WASI_CLOCKID_PROCESS_CPUTIME_ID => get_proc_cputime()?,
|
||||||
wasi::__WASI_CLOCKID_THREAD_CPUTIME_ID => get_thread_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)
|
duration.as_nanos().try_into().map_err(Into::into)
|
||||||
}
|
}
|
||||||
@@ -80,7 +85,7 @@ pub(crate) fn poll_oneoff(
|
|||||||
timeout: Option<ClockEventData>,
|
timeout: Option<ClockEventData>,
|
||||||
fd_events: Vec<FdEventData>,
|
fd_events: Vec<FdEventData>,
|
||||||
events: &mut Vec<wasi::__wasi_event_t>,
|
events: &mut Vec<wasi::__wasi_event_t>,
|
||||||
) -> Result<Vec<wasi::__wasi_event_t>> {
|
) -> WasiResult<Vec<wasi::__wasi_event_t>> {
|
||||||
unimplemented!("poll_oneoff")
|
unimplemented!("poll_oneoff")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,17 +99,17 @@ fn get_monotonic_time() -> Duration {
|
|||||||
START_MONOTONIC.elapsed()
|
START_MONOTONIC.elapsed()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_realtime_time() -> Result<Duration> {
|
fn get_realtime_time() -> WasiResult<Duration> {
|
||||||
SystemTime::now()
|
SystemTime::now()
|
||||||
.duration_since(UNIX_EPOCH)
|
.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())
|
Ok(ProcessTime::try_now()?.as_duration())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_thread_cputime() -> Result<Duration> {
|
fn get_thread_cputime() -> WasiResult<Duration> {
|
||||||
Ok(ThreadTime::try_now()?.as_duration())
|
Ok(ThreadTime::try_now()?.as_duration())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,13 +2,9 @@ pub(crate) mod fdentry_impl;
|
|||||||
pub(crate) mod host_impl;
|
pub(crate) mod host_impl;
|
||||||
pub(crate) mod hostcalls_impl;
|
pub(crate) mod hostcalls_impl;
|
||||||
|
|
||||||
use crate::old::snapshot_0::Result;
|
|
||||||
use std::fs::{File, OpenOptions};
|
use std::fs::{File, OpenOptions};
|
||||||
|
use std::io::Result;
|
||||||
|
|
||||||
pub(crate) fn dev_null() -> Result<File> {
|
pub(crate) fn dev_null() -> Result<File> {
|
||||||
OpenOptions::new()
|
OpenOptions::new().read(true).write(true).open("NUL")
|
||||||
.read(true)
|
|
||||||
.write(true)
|
|
||||||
.open("NUL")
|
|
||||||
.map_err(Into::into)
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,115 @@ use wig::witx_wasi_types;
|
|||||||
|
|
||||||
witx_wasi_types!("old/snapshot_0" "wasi_unstable");
|
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
|
pub(crate) const RIGHTS_ALL: __wasi_rights_t = __WASI_RIGHTS_FD_DATASYNC
|
||||||
| __WASI_RIGHTS_FD_READ
|
| __WASI_RIGHTS_FD_READ
|
||||||
| __WASI_RIGHTS_FD_SEEK
|
| __WASI_RIGHTS_FD_SEEK
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
use crate::{wasi, Result};
|
use crate::wasi::{self, WasiResult};
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
|
|
||||||
pub(crate) const O_RSYNC: yanix::file::OFlag = yanix::file::OFlag::SYNC;
|
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)
|
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)
|
wasi::__wasi_device_t::try_from(ino).map_err(Into::into)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
use crate::hostcalls_impl::PathGet;
|
use crate::hostcalls_impl::PathGet;
|
||||||
use crate::{Error, Result};
|
use crate::wasi::{WasiError, WasiResult};
|
||||||
use std::os::unix::prelude::AsRawFd;
|
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};
|
use yanix::file::{unlinkat, AtFlag};
|
||||||
match unsafe {
|
match unsafe {
|
||||||
unlinkat(
|
unlinkat(
|
||||||
@@ -32,7 +32,7 @@ pub(crate) fn path_unlink_file(resolved: PathGet) -> Result<()> {
|
|||||||
} {
|
} {
|
||||||
Ok(stat) => {
|
Ok(stat) => {
|
||||||
if FileType::from_stat_st_mode(stat.st_mode) == FileType::Directory {
|
if FileType::from_stat_st_mode(stat.st_mode) == FileType::Directory {
|
||||||
return Err(Error::EISDIR);
|
return Err(WasiError::EISDIR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(err) => {
|
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};
|
use yanix::file::{fstatat, symlinkat, AtFlag};
|
||||||
|
|
||||||
log::debug!("path_symlink old_path = {:?}", old_path);
|
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,
|
AtFlag::SYMLINK_NOFOLLOW,
|
||||||
)
|
)
|
||||||
} {
|
} {
|
||||||
Ok(_) => return Err(Error::EEXIST),
|
Ok(_) => return Err(WasiError::EEXIST),
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
log::debug!("path_symlink fstatat error: {:?}", 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};
|
use yanix::file::{fstatat, renameat, AtFlag};
|
||||||
match unsafe {
|
match unsafe {
|
||||||
renameat(
|
renameat(
|
||||||
@@ -113,9 +113,9 @@ pub(crate) fn path_rename(resolved_old: PathGet, resolved_new: PathGet) -> Resul
|
|||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
// check if destination contains a trailing slash
|
// check if destination contains a trailing slash
|
||||||
if resolved_new.path().contains('/') {
|
if resolved_new.path().contains('/') {
|
||||||
return Err(Error::ENOTDIR);
|
return Err(WasiError::ENOTDIR);
|
||||||
} else {
|
} else {
|
||||||
return Err(Error::ENOENT);
|
return Err(WasiError::ENOENT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
@@ -132,13 +132,13 @@ pub(crate) fn path_rename(resolved_old: PathGet, resolved_new: PathGet) -> Resul
|
|||||||
|
|
||||||
pub(crate) mod fd_readdir_impl {
|
pub(crate) mod fd_readdir_impl {
|
||||||
use crate::sys::fdentry_impl::OsHandle;
|
use crate::sys::fdentry_impl::OsHandle;
|
||||||
use crate::Result;
|
use crate::wasi::WasiResult;
|
||||||
use std::sync::{Mutex, MutexGuard};
|
use std::sync::{Mutex, MutexGuard};
|
||||||
use yanix::dir::Dir;
|
use yanix::dir::Dir;
|
||||||
|
|
||||||
pub(crate) fn get_dir_from_os_handle<'a>(
|
pub(crate) fn get_dir_from_os_handle<'a>(
|
||||||
os_handle: &'a mut OsHandle,
|
os_handle: &'a mut OsHandle,
|
||||||
) -> Result<MutexGuard<'a, Dir>> {
|
) -> WasiResult<MutexGuard<'a, Dir>> {
|
||||||
let dir = match os_handle.dir {
|
let dir = match os_handle.dir {
|
||||||
Some(ref mut dir) => dir,
|
Some(ref mut dir) => dir,
|
||||||
None => {
|
None => {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use crate::fdentry::{Descriptor, OsHandleRef};
|
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::fs::File;
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::mem::ManuallyDrop;
|
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.
|
/// This function is unsafe because it operates on a raw file descriptor.
|
||||||
pub(crate) unsafe fn determine_type_and_access_rights<Fd: AsRawFd>(
|
pub(crate) unsafe fn determine_type_and_access_rights<Fd: AsRawFd>(
|
||||||
fd: &Fd,
|
fd: &Fd,
|
||||||
) -> Result<(
|
) -> io::Result<(
|
||||||
wasi::__wasi_filetype_t,
|
wasi::__wasi_filetype_t,
|
||||||
wasi::__wasi_rights_t,
|
wasi::__wasi_rights_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.
|
/// This function is unsafe because it operates on a raw file descriptor.
|
||||||
pub(crate) unsafe fn determine_type_rights<Fd: AsRawFd>(
|
pub(crate) unsafe fn determine_type_rights<Fd: AsRawFd>(
|
||||||
fd: &Fd,
|
fd: &Fd,
|
||||||
) -> Result<(
|
) -> io::Result<(
|
||||||
wasi::__wasi_filetype_t,
|
wasi::__wasi_filetype_t,
|
||||||
wasi::__wasi_rights_t,
|
wasi::__wasi_rights_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_BASE,
|
||||||
wasi::RIGHTS_SOCKET_INHERITING,
|
wasi::RIGHTS_SOCKET_INHERITING,
|
||||||
),
|
),
|
||||||
_ => return Err(Error::EINVAL),
|
_ => return Err(io::Error::from_raw_os_error(libc::EINVAL)),
|
||||||
}
|
}
|
||||||
} else if ft.is_fifo() {
|
} else if ft.is_fifo() {
|
||||||
log::debug!("Host fd {:?} is a fifo", fd.as_raw_fd());
|
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 {
|
} else {
|
||||||
log::debug!("Host fd {:?} is unknown", fd.as_raw_fd());
|
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(non_snake_case)]
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
use crate::host::FileType;
|
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::ffi::OsStr;
|
||||||
|
use std::io;
|
||||||
use std::os::unix::prelude::OsStrExt;
|
use std::os::unix::prelude::OsStrExt;
|
||||||
use yanix::file::OFlag;
|
use yanix::file::OFlag;
|
||||||
|
|
||||||
pub(crate) use sys_impl::host_impl::*;
|
pub(crate) use sys_impl::host_impl::*;
|
||||||
|
|
||||||
impl FromRawOsError for Error {
|
impl From<io::Error> for WasiError {
|
||||||
fn from_raw_os_error(code: i32) -> Self {
|
fn from(err: io::Error) -> Self {
|
||||||
match code {
|
match err.raw_os_error() {
|
||||||
libc::EPERM => Self::EPERM,
|
Some(code) => match code {
|
||||||
libc::ENOENT => Self::ENOENT,
|
libc::EPERM => Self::EPERM,
|
||||||
libc::ESRCH => Self::ESRCH,
|
libc::ENOENT => Self::ENOENT,
|
||||||
libc::EINTR => Self::EINTR,
|
libc::ESRCH => Self::ESRCH,
|
||||||
libc::EIO => Self::EIO,
|
libc::EINTR => Self::EINTR,
|
||||||
libc::ENXIO => Self::ENXIO,
|
libc::EIO => Self::EIO,
|
||||||
libc::E2BIG => Self::E2BIG,
|
libc::ENXIO => Self::ENXIO,
|
||||||
libc::ENOEXEC => Self::ENOEXEC,
|
libc::E2BIG => Self::E2BIG,
|
||||||
libc::EBADF => Self::EBADF,
|
libc::ENOEXEC => Self::ENOEXEC,
|
||||||
libc::ECHILD => Self::ECHILD,
|
libc::EBADF => Self::EBADF,
|
||||||
libc::EAGAIN => Self::EAGAIN,
|
libc::ECHILD => Self::ECHILD,
|
||||||
libc::ENOMEM => Self::ENOMEM,
|
libc::EAGAIN => Self::EAGAIN,
|
||||||
libc::EACCES => Self::EACCES,
|
libc::ENOMEM => Self::ENOMEM,
|
||||||
libc::EFAULT => Self::EFAULT,
|
libc::EACCES => Self::EACCES,
|
||||||
libc::EBUSY => Self::EBUSY,
|
libc::EFAULT => Self::EFAULT,
|
||||||
libc::EEXIST => Self::EEXIST,
|
libc::EBUSY => Self::EBUSY,
|
||||||
libc::EXDEV => Self::EXDEV,
|
libc::EEXIST => Self::EEXIST,
|
||||||
libc::ENODEV => Self::ENODEV,
|
libc::EXDEV => Self::EXDEV,
|
||||||
libc::ENOTDIR => Self::ENOTDIR,
|
libc::ENODEV => Self::ENODEV,
|
||||||
libc::EISDIR => Self::EISDIR,
|
libc::ENOTDIR => Self::ENOTDIR,
|
||||||
libc::EINVAL => Self::EINVAL,
|
libc::EISDIR => Self::EISDIR,
|
||||||
libc::ENFILE => Self::ENFILE,
|
libc::EINVAL => Self::EINVAL,
|
||||||
libc::EMFILE => Self::EMFILE,
|
libc::ENFILE => Self::ENFILE,
|
||||||
libc::ENOTTY => Self::ENOTTY,
|
libc::EMFILE => Self::EMFILE,
|
||||||
libc::ETXTBSY => Self::ETXTBSY,
|
libc::ENOTTY => Self::ENOTTY,
|
||||||
libc::EFBIG => Self::EFBIG,
|
libc::ETXTBSY => Self::ETXTBSY,
|
||||||
libc::ENOSPC => Self::ENOSPC,
|
libc::EFBIG => Self::EFBIG,
|
||||||
libc::ESPIPE => Self::ESPIPE,
|
libc::ENOSPC => Self::ENOSPC,
|
||||||
libc::EROFS => Self::EROFS,
|
libc::ESPIPE => Self::ESPIPE,
|
||||||
libc::EMLINK => Self::EMLINK,
|
libc::EROFS => Self::EROFS,
|
||||||
libc::EPIPE => Self::EPIPE,
|
libc::EMLINK => Self::EMLINK,
|
||||||
libc::EDOM => Self::EDOM,
|
libc::EPIPE => Self::EPIPE,
|
||||||
libc::ERANGE => Self::ERANGE,
|
libc::EDOM => Self::EDOM,
|
||||||
libc::EDEADLK => Self::EDEADLK,
|
libc::ERANGE => Self::ERANGE,
|
||||||
libc::ENAMETOOLONG => Self::ENAMETOOLONG,
|
libc::EDEADLK => Self::EDEADLK,
|
||||||
libc::ENOLCK => Self::ENOLCK,
|
libc::ENAMETOOLONG => Self::ENAMETOOLONG,
|
||||||
libc::ENOSYS => Self::ENOSYS,
|
libc::ENOLCK => Self::ENOLCK,
|
||||||
libc::ENOTEMPTY => Self::ENOTEMPTY,
|
libc::ENOSYS => Self::ENOSYS,
|
||||||
libc::ELOOP => Self::ELOOP,
|
libc::ENOTEMPTY => Self::ENOTEMPTY,
|
||||||
libc::ENOMSG => Self::ENOMSG,
|
libc::ELOOP => Self::ELOOP,
|
||||||
libc::EIDRM => Self::EIDRM,
|
libc::ENOMSG => Self::ENOMSG,
|
||||||
libc::ENOLINK => Self::ENOLINK,
|
libc::EIDRM => Self::EIDRM,
|
||||||
libc::EPROTO => Self::EPROTO,
|
libc::ENOLINK => Self::ENOLINK,
|
||||||
libc::EMULTIHOP => Self::EMULTIHOP,
|
libc::EPROTO => Self::EPROTO,
|
||||||
libc::EBADMSG => Self::EBADMSG,
|
libc::EMULTIHOP => Self::EMULTIHOP,
|
||||||
libc::EOVERFLOW => Self::EOVERFLOW,
|
libc::EBADMSG => Self::EBADMSG,
|
||||||
libc::EILSEQ => Self::EILSEQ,
|
libc::EOVERFLOW => Self::EOVERFLOW,
|
||||||
libc::ENOTSOCK => Self::ENOTSOCK,
|
libc::EILSEQ => Self::EILSEQ,
|
||||||
libc::EDESTADDRREQ => Self::EDESTADDRREQ,
|
libc::ENOTSOCK => Self::ENOTSOCK,
|
||||||
libc::EMSGSIZE => Self::EMSGSIZE,
|
libc::EDESTADDRREQ => Self::EDESTADDRREQ,
|
||||||
libc::EPROTOTYPE => Self::EPROTOTYPE,
|
libc::EMSGSIZE => Self::EMSGSIZE,
|
||||||
libc::ENOPROTOOPT => Self::ENOPROTOOPT,
|
libc::EPROTOTYPE => Self::EPROTOTYPE,
|
||||||
libc::EPROTONOSUPPORT => Self::EPROTONOSUPPORT,
|
libc::ENOPROTOOPT => Self::ENOPROTOOPT,
|
||||||
libc::EAFNOSUPPORT => Self::EAFNOSUPPORT,
|
libc::EPROTONOSUPPORT => Self::EPROTONOSUPPORT,
|
||||||
libc::EADDRINUSE => Self::EADDRINUSE,
|
libc::EAFNOSUPPORT => Self::EAFNOSUPPORT,
|
||||||
libc::EADDRNOTAVAIL => Self::EADDRNOTAVAIL,
|
libc::EADDRINUSE => Self::EADDRINUSE,
|
||||||
libc::ENETDOWN => Self::ENETDOWN,
|
libc::EADDRNOTAVAIL => Self::EADDRNOTAVAIL,
|
||||||
libc::ENETUNREACH => Self::ENETUNREACH,
|
libc::ENETDOWN => Self::ENETDOWN,
|
||||||
libc::ENETRESET => Self::ENETRESET,
|
libc::ENETUNREACH => Self::ENETUNREACH,
|
||||||
libc::ECONNABORTED => Self::ECONNABORTED,
|
libc::ENETRESET => Self::ENETRESET,
|
||||||
libc::ECONNRESET => Self::ECONNRESET,
|
libc::ECONNABORTED => Self::ECONNABORTED,
|
||||||
libc::ENOBUFS => Self::ENOBUFS,
|
libc::ECONNRESET => Self::ECONNRESET,
|
||||||
libc::EISCONN => Self::EISCONN,
|
libc::ENOBUFS => Self::ENOBUFS,
|
||||||
libc::ENOTCONN => Self::ENOTCONN,
|
libc::EISCONN => Self::EISCONN,
|
||||||
libc::ETIMEDOUT => Self::ETIMEDOUT,
|
libc::ENOTCONN => Self::ENOTCONN,
|
||||||
libc::ECONNREFUSED => Self::ECONNREFUSED,
|
libc::ETIMEDOUT => Self::ETIMEDOUT,
|
||||||
libc::EHOSTUNREACH => Self::EHOSTUNREACH,
|
libc::ECONNREFUSED => Self::ECONNREFUSED,
|
||||||
libc::EALREADY => Self::EALREADY,
|
libc::EHOSTUNREACH => Self::EHOSTUNREACH,
|
||||||
libc::EINPROGRESS => Self::EINPROGRESS,
|
libc::EALREADY => Self::EALREADY,
|
||||||
libc::ESTALE => Self::ESTALE,
|
libc::EINPROGRESS => Self::EINPROGRESS,
|
||||||
libc::EDQUOT => Self::EDQUOT,
|
libc::ESTALE => Self::ESTALE,
|
||||||
libc::ECANCELED => Self::ECANCELED,
|
libc::EDQUOT => Self::EDQUOT,
|
||||||
libc::EOWNERDEAD => Self::EOWNERDEAD,
|
libc::ECANCELED => Self::ECANCELED,
|
||||||
libc::ENOTRECOVERABLE => Self::ENOTRECOVERABLE,
|
libc::EOWNERDEAD => Self::EOWNERDEAD,
|
||||||
x => {
|
libc::ENOTRECOVERABLE => Self::ENOTRECOVERABLE,
|
||||||
log::debug!("Unknown errno value: {}", x);
|
libc::ENOTSUP => Self::ENOTSUP,
|
||||||
|
x => {
|
||||||
|
log::debug!("Unknown errno value: {}", x);
|
||||||
|
Self::EIO
|
||||||
|
}
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
log::debug!("Other I/O error: {}", err);
|
||||||
Self::EIO
|
Self::EIO
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -152,13 +161,13 @@ pub(crate) fn nix_from_oflags(oflags: wasi::__wasi_oflags_t) -> OFlag {
|
|||||||
nix_flags
|
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;
|
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)
|
secs.checked_mul(1_000_000_000)
|
||||||
.and_then(|sec_nsec| sec_nsec.checked_add(nsecs))
|
.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);
|
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,
|
/// NB WASI spec requires OS string to be valid UTF-8. Otherwise,
|
||||||
/// `__WASI_ERRNO_ILSEQ` error is returned.
|
/// `__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)
|
helpers::path_from_slice(s.as_ref().as_bytes()).map(String::from)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,8 +3,9 @@
|
|||||||
use crate::fdentry::Descriptor;
|
use crate::fdentry::Descriptor;
|
||||||
use crate::host::Dirent;
|
use crate::host::Dirent;
|
||||||
use crate::hostcalls_impl::PathGet;
|
use crate::hostcalls_impl::PathGet;
|
||||||
use crate::sys::{fdentry_impl::OsHandle, host_impl, unix::sys_impl};
|
use crate::sys::fdentry_impl::OsHandle;
|
||||||
use crate::{wasi, Error, Result};
|
use crate::sys::{host_impl, unix::sys_impl};
|
||||||
|
use crate::wasi::{self, WasiError, WasiResult};
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::os::unix::fs::FileExt;
|
use std::os::unix::fs::FileExt;
|
||||||
@@ -16,15 +17,19 @@ pub(crate) fn fd_pread(
|
|||||||
file: &File,
|
file: &File,
|
||||||
buf: &mut [u8],
|
buf: &mut [u8],
|
||||||
offset: wasi::__wasi_filesize_t,
|
offset: wasi::__wasi_filesize_t,
|
||||||
) -> Result<usize> {
|
) -> WasiResult<usize> {
|
||||||
file.read_at(buf, offset).map_err(Into::into)
|
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)
|
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()) }
|
unsafe { yanix::fcntl::get_status_flags(fd.as_raw_fd()) }
|
||||||
.map(host_impl::fdflags_from_nix)
|
.map(host_impl::fdflags_from_nix)
|
||||||
.map_err(Into::into)
|
.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(
|
pub(crate) fn fd_fdstat_set_flags(
|
||||||
fd: &File,
|
fd: &File,
|
||||||
fdflags: wasi::__wasi_fdflags_t,
|
fdflags: wasi::__wasi_fdflags_t,
|
||||||
) -> Result<Option<OsHandle>> {
|
) -> WasiResult<Option<OsHandle>> {
|
||||||
let nix_flags = host_impl::nix_from_fdflags(fdflags);
|
let nix_flags = host_impl::nix_from_fdflags(fdflags);
|
||||||
unsafe { yanix::fcntl::set_status_flags(fd.as_raw_fd(), nix_flags) }
|
unsafe { yanix::fcntl::set_status_flags(fd.as_raw_fd(), nix_flags) }
|
||||||
.map(|_| None)
|
.map(|_| None)
|
||||||
@@ -45,7 +50,7 @@ pub(crate) fn fd_advise(
|
|||||||
advice: wasi::__wasi_advice_t,
|
advice: wasi::__wasi_advice_t,
|
||||||
offset: wasi::__wasi_filesize_t,
|
offset: wasi::__wasi_filesize_t,
|
||||||
len: wasi::__wasi_filesize_t,
|
len: wasi::__wasi_filesize_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
use yanix::fadvise::{posix_fadvise, PosixFadviseAdvice};
|
use yanix::fadvise::{posix_fadvise, PosixFadviseAdvice};
|
||||||
let offset = offset.try_into()?;
|
let offset = offset.try_into()?;
|
||||||
let len = len.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_NOREUSE => PosixFadviseAdvice::NoReuse,
|
||||||
wasi::__WASI_ADVICE_RANDOM => PosixFadviseAdvice::Random,
|
wasi::__WASI_ADVICE_RANDOM => PosixFadviseAdvice::Random,
|
||||||
wasi::__WASI_ADVICE_NORMAL => PosixFadviseAdvice::Normal,
|
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)
|
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};
|
use yanix::file::{mkdirat, Mode};
|
||||||
unsafe { mkdirat(base.as_raw_fd(), path, Mode::from_bits_truncate(0o777)) }.map_err(Into::into)
|
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};
|
use yanix::file::{linkat, AtFlag};
|
||||||
unsafe {
|
unsafe {
|
||||||
linkat(
|
linkat(
|
||||||
@@ -86,7 +91,7 @@ pub(crate) fn path_open(
|
|||||||
write: bool,
|
write: bool,
|
||||||
oflags: wasi::__wasi_oflags_t,
|
oflags: wasi::__wasi_oflags_t,
|
||||||
fs_flags: wasi::__wasi_fdflags_t,
|
fs_flags: wasi::__wasi_fdflags_t,
|
||||||
) -> Result<Descriptor> {
|
) -> WasiResult<Descriptor> {
|
||||||
use yanix::file::{fstatat, openat, AtFlag, FileType, Mode, OFlag};
|
use yanix::file::{fstatat, openat, AtFlag, FileType, Mode, OFlag};
|
||||||
|
|
||||||
let mut nix_all_oflags = if read && write {
|
let mut nix_all_oflags = if read && write {
|
||||||
@@ -136,7 +141,7 @@ pub(crate) fn path_open(
|
|||||||
} {
|
} {
|
||||||
Ok(stat) => {
|
Ok(stat) => {
|
||||||
if FileType::from_stat_st_mode(stat.st_mode) == FileType::Socket {
|
if FileType::from_stat_st_mode(stat.st_mode) == FileType::Socket {
|
||||||
return Err(Error::ENOTSUP);
|
return Err(WasiError::ENOTSUP);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
@@ -158,7 +163,7 @@ pub(crate) fn path_open(
|
|||||||
} {
|
} {
|
||||||
Ok(stat) => {
|
Ok(stat) => {
|
||||||
if FileType::from_stat_st_mode(stat.st_mode) == FileType::Symlink {
|
if FileType::from_stat_st_mode(stat.st_mode) == FileType::Symlink {
|
||||||
return Err(Error::ELOOP);
|
return Err(WasiError::ELOOP);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
@@ -169,7 +174,7 @@ pub(crate) fn path_open(
|
|||||||
// FreeBSD returns EMLINK instead of ELOOP when using O_NOFOLLOW on
|
// FreeBSD returns EMLINK instead of ELOOP when using O_NOFOLLOW on
|
||||||
// a symlink.
|
// a symlink.
|
||||||
libc::EMLINK if !(nix_all_oflags & OFlag::NOFOLLOW).is_empty() => {
|
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())
|
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 std::cmp::min;
|
||||||
use yanix::file::readlinkat;
|
use yanix::file::readlinkat;
|
||||||
let read_link = unsafe { readlinkat(resolved.dirfd().as_raw_fd(), resolved.path()) }
|
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)
|
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;
|
use yanix::file::fstat;
|
||||||
unsafe { fstat(file.as_raw_fd()) }
|
unsafe { fstat(file.as_raw_fd()) }
|
||||||
.map_err(Into::into)
|
.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(
|
pub(crate) fn path_filestat_get(
|
||||||
resolved: PathGet,
|
resolved: PathGet,
|
||||||
dirflags: wasi::__wasi_lookupflags_t,
|
dirflags: wasi::__wasi_lookupflags_t,
|
||||||
) -> Result<wasi::__wasi_filestat_t> {
|
) -> WasiResult<wasi::__wasi_filestat_t> {
|
||||||
use yanix::file::{fstatat, AtFlag};
|
use yanix::file::{fstatat, AtFlag};
|
||||||
let atflags = match dirflags {
|
let atflags = match dirflags {
|
||||||
0 => AtFlag::empty(),
|
0 => AtFlag::empty(),
|
||||||
@@ -224,7 +229,7 @@ pub(crate) fn path_filestat_set_times(
|
|||||||
st_atim: wasi::__wasi_timestamp_t,
|
st_atim: wasi::__wasi_timestamp_t,
|
||||||
st_mtim: wasi::__wasi_timestamp_t,
|
st_mtim: wasi::__wasi_timestamp_t,
|
||||||
fst_flags: wasi::__wasi_fstflags_t,
|
fst_flags: wasi::__wasi_fstflags_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
use std::time::{Duration, UNIX_EPOCH};
|
use std::time::{Duration, UNIX_EPOCH};
|
||||||
use yanix::filetime::*;
|
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;
|
let set_mtim_now = fst_flags & wasi::__WASI_FSTFLAGS_MTIM_NOW != 0;
|
||||||
|
|
||||||
if (set_atim && set_atim_now) || (set_mtim && set_mtim_now) {
|
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;
|
let symlink_nofollow = wasi::__WASI_LOOKUPFLAGS_SYMLINK_FOLLOW != dirflags;
|
||||||
@@ -265,7 +270,7 @@ pub(crate) fn path_filestat_set_times(
|
|||||||
.map_err(Into::into)
|
.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};
|
use yanix::file::{unlinkat, AtFlag};
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
@@ -281,7 +286,7 @@ pub(crate) fn path_remove_directory(resolved: PathGet) -> Result<()> {
|
|||||||
pub(crate) fn fd_readdir<'a>(
|
pub(crate) fn fd_readdir<'a>(
|
||||||
os_handle: &'a mut OsHandle,
|
os_handle: &'a mut OsHandle,
|
||||||
cookie: wasi::__wasi_dircookie_t,
|
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};
|
use yanix::dir::{DirIter, Entry, EntryExt, SeekLoc};
|
||||||
|
|
||||||
// Get an instance of `Dir`; this is host-specific due to intricasies
|
// Get an instance of `Dir`; this is host-specific due to intricasies
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#![allow(non_camel_case_types)]
|
#![allow(non_camel_case_types)]
|
||||||
#![allow(unused_unsafe)]
|
#![allow(unused_unsafe)]
|
||||||
use crate::sys::host_impl;
|
use crate::sys::host_impl;
|
||||||
use crate::{wasi, Result};
|
use crate::wasi::{self, WasiResult};
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use yanix::file::OFlag;
|
use yanix::file::OFlag;
|
||||||
|
|
||||||
@@ -36,7 +36,7 @@ pub(crate) fn path_open_rights(
|
|||||||
(needed_base, needed_inheriting)
|
(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 std::os::unix::prelude::{AsRawFd, FromRawFd};
|
||||||
use yanix::file::{openat, Mode};
|
use yanix::file::{openat, Mode};
|
||||||
|
|
||||||
@@ -54,7 +54,7 @@ pub(crate) fn openat(dirfd: &File, path: &str) -> Result<File> {
|
|||||||
.map_err(Into::into)
|
.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 std::os::unix::prelude::AsRawFd;
|
||||||
use yanix::file::readlinkat;
|
use yanix::file::readlinkat;
|
||||||
|
|
||||||
|
|||||||
@@ -1,22 +1,24 @@
|
|||||||
#![allow(non_camel_case_types)]
|
#![allow(non_camel_case_types)]
|
||||||
#![allow(unused_unsafe)]
|
#![allow(unused_unsafe)]
|
||||||
use crate::hostcalls_impl::{ClockEventData, FdEventData};
|
use crate::hostcalls_impl::{ClockEventData, FdEventData};
|
||||||
use crate::{wasi, Error, Result};
|
use crate::wasi::{self, WasiError, WasiResult};
|
||||||
use std::io;
|
use std::io;
|
||||||
use yanix::clock::{clock_getres, clock_gettime, ClockId};
|
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
|
// convert the supported clocks to libc types, or return EINVAL
|
||||||
match clock_id {
|
match clock_id {
|
||||||
wasi::__WASI_CLOCKID_REALTIME => Ok(ClockId::Realtime),
|
wasi::__WASI_CLOCKID_REALTIME => Ok(ClockId::Realtime),
|
||||||
wasi::__WASI_CLOCKID_MONOTONIC => Ok(ClockId::Monotonic),
|
wasi::__WASI_CLOCKID_MONOTONIC => Ok(ClockId::Monotonic),
|
||||||
wasi::__WASI_CLOCKID_PROCESS_CPUTIME_ID => Ok(ClockId::ProcessCPUTime),
|
wasi::__WASI_CLOCKID_PROCESS_CPUTIME_ID => Ok(ClockId::ProcessCPUTime),
|
||||||
wasi::__WASI_CLOCKID_THREAD_CPUTIME_ID => Ok(ClockId::ThreadCPUTime),
|
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 clock_id = wasi_clock_id_to_unix(clock_id)?;
|
||||||
let timespec = clock_getres(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)
|
(timespec.tv_sec as wasi::__wasi_timestamp_t)
|
||||||
.checked_mul(1_000_000_000)
|
.checked_mul(1_000_000_000)
|
||||||
.and_then(|sec_ns| sec_ns.checked_add(timespec.tv_nsec as wasi::__wasi_timestamp_t))
|
.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
|
// a supported clock can never return zero; this case will probably never get hit, but
|
||||||
// make sure we follow the spec
|
// make sure we follow the spec
|
||||||
if resolution == 0 {
|
if resolution == 0 {
|
||||||
Err(Error::EINVAL)
|
Err(WasiError::EINVAL)
|
||||||
} else {
|
} else {
|
||||||
Ok(resolution)
|
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 clock_id = wasi_clock_id_to_unix(clock_id)?;
|
||||||
let timespec = clock_gettime(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)
|
(timespec.tv_sec as wasi::__wasi_timestamp_t)
|
||||||
.checked_mul(1_000_000_000)
|
.checked_mul(1_000_000_000)
|
||||||
.and_then(|sec_ns| sec_ns.checked_add(timespec.tv_nsec as wasi::__wasi_timestamp_t))
|
.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(
|
pub(crate) fn poll_oneoff(
|
||||||
timeout: Option<ClockEventData>,
|
timeout: Option<ClockEventData>,
|
||||||
fd_events: Vec<FdEventData>,
|
fd_events: Vec<FdEventData>,
|
||||||
events: &mut Vec<wasi::__wasi_event_t>,
|
events: &mut Vec<wasi::__wasi_event_t>,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
use std::{convert::TryInto, os::unix::prelude::AsRawFd};
|
use std::{convert::TryInto, os::unix::prelude::AsRawFd};
|
||||||
use yanix::poll::{poll, PollFd, PollFlags};
|
use yanix::poll::{poll, PollFd, PollFlags};
|
||||||
|
|
||||||
@@ -122,12 +126,12 @@ fn poll_oneoff_handle_timeout_event(
|
|||||||
fn poll_oneoff_handle_fd_event<'a>(
|
fn poll_oneoff_handle_fd_event<'a>(
|
||||||
ready_events: impl Iterator<Item = (FdEventData<'a>, yanix::poll::PollFd)>,
|
ready_events: impl Iterator<Item = (FdEventData<'a>, yanix::poll::PollFd)>,
|
||||||
events: &mut Vec<wasi::__wasi_event_t>,
|
events: &mut Vec<wasi::__wasi_event_t>,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
use crate::fdentry::Descriptor;
|
use crate::fdentry::Descriptor;
|
||||||
use std::{convert::TryInto, os::unix::prelude::AsRawFd};
|
use std::{convert::TryInto, os::unix::prelude::AsRawFd};
|
||||||
use yanix::{file::fionread, poll::PollFlags};
|
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.
|
// fionread may overflow for large files, so use another way for regular files.
|
||||||
if let Descriptor::OsHandle(os_handle) = fd {
|
if let Descriptor::OsHandle(os_handle) = fd {
|
||||||
let meta = os_handle.metadata()?;
|
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) 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))
|
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))
|
Ok(wasi::__wasi_device_t::from(ino))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
use crate::fdentry::Descriptor;
|
use crate::fdentry::Descriptor;
|
||||||
use crate::hostcalls_impl::PathGet;
|
use crate::hostcalls_impl::PathGet;
|
||||||
use crate::Result;
|
use crate::wasi::WasiResult;
|
||||||
use std::os::unix::prelude::AsRawFd;
|
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};
|
use yanix::file::{unlinkat, AtFlag};
|
||||||
unsafe {
|
unsafe {
|
||||||
unlinkat(
|
unlinkat(
|
||||||
@@ -15,7 +15,7 @@ pub(crate) fn path_unlink_file(resolved: PathGet) -> Result<()> {
|
|||||||
.map_err(Into::into)
|
.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;
|
use yanix::file::symlinkat;
|
||||||
|
|
||||||
log::debug!("path_symlink old_path = {:?}", old_path);
|
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)
|
.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;
|
use yanix::file::renameat;
|
||||||
match (resolved_old.dirfd(), resolved_new.dirfd()) {
|
match (resolved_old.dirfd(), resolved_new.dirfd()) {
|
||||||
(Descriptor::OsHandle(resolved_old_file), Descriptor::OsHandle(resolved_new_file)) => {
|
(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 {
|
pub(crate) mod fd_readdir_impl {
|
||||||
use crate::sys::fdentry_impl::OsHandle;
|
use crate::sys::fdentry_impl::OsHandle;
|
||||||
use crate::Result;
|
use crate::wasi::WasiResult;
|
||||||
use yanix::dir::Dir;
|
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)`:
|
// We need to duplicate the fd, because `opendir(3)`:
|
||||||
// After a successful call to fdopendir(), fd is used internally by the implementation,
|
// After a successful call to fdopendir(), fd is used internally by the implementation,
|
||||||
// and should not otherwise be used by the application.
|
// 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::fs::{File, OpenOptions};
|
||||||
|
use std::io::Result;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
pub(crate) fn dev_null() -> Result<File> {
|
pub(crate) fn dev_null() -> Result<File> {
|
||||||
OpenOptions::new()
|
OpenOptions::new().read(true).write(true).open("/dev/null")
|
||||||
.read(true)
|
|
||||||
.write(true)
|
|
||||||
.open("/dev/null")
|
|
||||||
.map_err(Into::into)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn preopen_dir<P: AsRef<Path>>(path: P) -> Result<File> {
|
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::fdentry::{Descriptor, OsHandleRef};
|
||||||
use crate::{wasi, Error, Result};
|
use crate::wasi;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::mem::ManuallyDrop;
|
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.
|
/// This function is unsafe because it operates on a raw file descriptor.
|
||||||
pub(crate) unsafe fn determine_type_and_access_rights<Handle: AsRawHandle>(
|
pub(crate) unsafe fn determine_type_and_access_rights<Handle: AsRawHandle>(
|
||||||
handle: &Handle,
|
handle: &Handle,
|
||||||
) -> Result<(
|
) -> io::Result<(
|
||||||
wasi::__wasi_filetype_t,
|
wasi::__wasi_filetype_t,
|
||||||
wasi::__wasi_rights_t,
|
wasi::__wasi_rights_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.
|
/// This function is unsafe because it operates on a raw file descriptor.
|
||||||
pub(crate) unsafe fn determine_type_rights<Handle: AsRawHandle>(
|
pub(crate) unsafe fn determine_type_rights<Handle: AsRawHandle>(
|
||||||
handle: &Handle,
|
handle: &Handle,
|
||||||
) -> Result<(
|
) -> io::Result<(
|
||||||
wasi::__wasi_filetype_t,
|
wasi::__wasi_filetype_t,
|
||||||
wasi::__wasi_rights_t,
|
wasi::__wasi_rights_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() {
|
} else if file_type.is_disk() {
|
||||||
// disk file: file, dir or disk device
|
// disk file: file, dir or disk device
|
||||||
let file = std::mem::ManuallyDrop::new(File::from_raw_handle(handle.as_raw_handle()));
|
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() {
|
if meta.is_dir() {
|
||||||
(
|
(
|
||||||
wasi::__WASI_FILETYPE_DIRECTORY,
|
wasi::__WASI_FILETYPE_DIRECTORY,
|
||||||
@@ -128,7 +128,7 @@ pub(crate) unsafe fn determine_type_rights<Handle: AsRawHandle>(
|
|||||||
wasi::RIGHTS_REGULAR_FILE_INHERITING,
|
wasi::RIGHTS_REGULAR_FILE_INHERITING,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
return Err(Error::EINVAL);
|
return Err(io::Error::from_raw_os_error(libc::EINVAL));
|
||||||
}
|
}
|
||||||
} else if file_type.is_pipe() {
|
} else if file_type.is_pipe() {
|
||||||
// pipe object: socket, named pipe or anonymous 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,
|
wasi::RIGHTS_SOCKET_INHERITING,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
return Err(Error::EINVAL);
|
return Err(io::Error::from_raw_os_error(libc::EINVAL));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Ok((file_type, rights_base, rights_inheriting))
|
Ok((file_type, rights_base, rights_inheriting))
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
//! WASI host types specific to Windows host.
|
//! WASI host types specific to Windows host.
|
||||||
use crate::host::FileType;
|
use crate::host::FileType;
|
||||||
use crate::{error::FromRawOsError, wasi, Error, Result};
|
use crate::wasi::{self, WasiError, WasiResult};
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
use std::ffi::OsStr;
|
use std::ffi::OsStr;
|
||||||
use std::fs::{self, File};
|
use std::fs::{self, File};
|
||||||
@@ -9,34 +9,42 @@ use std::os::windows::ffi::OsStrExt;
|
|||||||
use std::time::{SystemTime, UNIX_EPOCH};
|
use std::time::{SystemTime, UNIX_EPOCH};
|
||||||
use winapi::shared::winerror;
|
use winapi::shared::winerror;
|
||||||
|
|
||||||
impl FromRawOsError for Error {
|
impl From<io::Error> for WasiError {
|
||||||
fn from_raw_os_error(code: i32) -> Self {
|
fn from(err: io::Error) -> Self {
|
||||||
// TODO: implement error mapping between Windows and WASI
|
match err.raw_os_error() {
|
||||||
match code as u32 {
|
Some(code) => match code as u32 {
|
||||||
winerror::ERROR_SUCCESS => Self::ESUCCESS,
|
winerror::ERROR_SUCCESS => Self::ESUCCESS,
|
||||||
winerror::ERROR_BAD_ENVIRONMENT => Self::E2BIG,
|
winerror::ERROR_BAD_ENVIRONMENT => Self::E2BIG,
|
||||||
winerror::ERROR_FILE_NOT_FOUND => Self::ENOENT,
|
winerror::ERROR_FILE_NOT_FOUND => Self::ENOENT,
|
||||||
winerror::ERROR_PATH_NOT_FOUND => Self::ENOENT,
|
winerror::ERROR_PATH_NOT_FOUND => Self::ENOENT,
|
||||||
winerror::ERROR_TOO_MANY_OPEN_FILES => Self::ENFILE,
|
winerror::ERROR_TOO_MANY_OPEN_FILES => Self::ENFILE,
|
||||||
winerror::ERROR_ACCESS_DENIED => Self::EACCES,
|
winerror::ERROR_ACCESS_DENIED => Self::EACCES,
|
||||||
winerror::ERROR_SHARING_VIOLATION => 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_HANDLE => Self::EBADF,
|
||||||
winerror::ERROR_INVALID_NAME => Self::ENOENT,
|
winerror::ERROR_INVALID_NAME => Self::ENOENT,
|
||||||
winerror::ERROR_NOT_ENOUGH_MEMORY => Self::ENOMEM,
|
winerror::ERROR_NOT_ENOUGH_MEMORY => Self::ENOMEM,
|
||||||
winerror::ERROR_OUTOFMEMORY => Self::ENOMEM,
|
winerror::ERROR_OUTOFMEMORY => Self::ENOMEM,
|
||||||
winerror::ERROR_DIR_NOT_EMPTY => Self::ENOTEMPTY,
|
winerror::ERROR_DIR_NOT_EMPTY => Self::ENOTEMPTY,
|
||||||
winerror::ERROR_NOT_READY => Self::EBUSY,
|
winerror::ERROR_NOT_READY => Self::EBUSY,
|
||||||
winerror::ERROR_BUSY => Self::EBUSY,
|
winerror::ERROR_BUSY => Self::EBUSY,
|
||||||
winerror::ERROR_NOT_SUPPORTED => Self::ENOTSUP,
|
winerror::ERROR_NOT_SUPPORTED => Self::ENOTSUP,
|
||||||
winerror::ERROR_FILE_EXISTS => Self::EEXIST,
|
winerror::ERROR_FILE_EXISTS => Self::EEXIST,
|
||||||
winerror::ERROR_BROKEN_PIPE => Self::EPIPE,
|
winerror::ERROR_BROKEN_PIPE => Self::EPIPE,
|
||||||
winerror::ERROR_BUFFER_OVERFLOW => Self::ENAMETOOLONG,
|
winerror::ERROR_BUFFER_OVERFLOW => Self::ENAMETOOLONG,
|
||||||
winerror::ERROR_NOT_A_REPARSE_POINT => Self::EINVAL,
|
winerror::ERROR_NOT_A_REPARSE_POINT => Self::EINVAL,
|
||||||
winerror::ERROR_NEGATIVE_SEEK => Self::EINVAL,
|
winerror::ERROR_NEGATIVE_SEEK => Self::EINVAL,
|
||||||
winerror::ERROR_DIRECTORY => Self::ENOTDIR,
|
winerror::ERROR_DIRECTORY => Self::ENOTDIR,
|
||||||
winerror::ERROR_ALREADY_EXISTS => Self::EEXIST,
|
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)
|
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)
|
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()
|
.as_nanos()
|
||||||
.try_into()
|
.try_into()
|
||||||
.map_err(Into::into) // u128 doesn't fit into u64
|
.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()?;
|
let metadata = file.metadata()?;
|
||||||
Ok(wasi::__wasi_filestat_t {
|
Ok(wasi::__wasi_filestat_t {
|
||||||
dev: device_id(file)?,
|
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,
|
/// NB WASI spec requires OS string to be valid UTF-8. Otherwise,
|
||||||
/// `__WASI_ERRNO_ILSEQ` error is returned.
|
/// `__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();
|
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::fdentry_impl::{determine_type_rights, OsHandle};
|
||||||
use crate::sys::host_impl::{self, path_from_host};
|
use crate::sys::host_impl::{self, path_from_host};
|
||||||
use crate::sys::hostcalls_impl::fs_helpers::PathGetExt;
|
use crate::sys::hostcalls_impl::fs_helpers::PathGetExt;
|
||||||
use crate::{wasi, Error, Result};
|
use crate::wasi::{self, WasiError, WasiResult};
|
||||||
use log::{debug, trace};
|
use log::{debug, trace};
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
use std::fs::{File, Metadata, OpenOptions};
|
use std::fs::{File, Metadata, OpenOptions};
|
||||||
@@ -44,16 +44,20 @@ pub(crate) fn fd_pread(
|
|||||||
file: &File,
|
file: &File,
|
||||||
buf: &mut [u8],
|
buf: &mut [u8],
|
||||||
offset: wasi::__wasi_filesize_t,
|
offset: wasi::__wasi_filesize_t,
|
||||||
) -> Result<usize> {
|
) -> WasiResult<usize> {
|
||||||
read_at(file, buf, offset).map_err(Into::into)
|
read_at(file, buf, offset).map_err(Into::into)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO refactor common code with unix
|
// 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)
|
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 mut fdflags = 0;
|
||||||
|
|
||||||
let handle = unsafe { fd.as_raw_handle() };
|
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(
|
pub(crate) fn fd_fdstat_set_flags(
|
||||||
fd: &File,
|
fd: &File,
|
||||||
fdflags: wasi::__wasi_fdflags_t,
|
fdflags: wasi::__wasi_fdflags_t,
|
||||||
) -> Result<Option<OsHandle>> {
|
) -> WasiResult<Option<OsHandle>> {
|
||||||
let handle = unsafe { fd.as_raw_handle() };
|
let handle = unsafe { fd.as_raw_handle() };
|
||||||
|
|
||||||
let access_mode = winx::file::query_access_information(handle)?;
|
let access_mode = winx::file::query_access_information(handle)?;
|
||||||
@@ -106,7 +110,7 @@ pub(crate) fn fd_advise(
|
|||||||
advice: wasi::__wasi_advice_t,
|
advice: wasi::__wasi_advice_t,
|
||||||
_offset: wasi::__wasi_filesize_t,
|
_offset: wasi::__wasi_filesize_t,
|
||||||
_len: wasi::__wasi_filesize_t,
|
_len: wasi::__wasi_filesize_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
match advice {
|
match advice {
|
||||||
wasi::__WASI_ADVICE_DONTNEED
|
wasi::__WASI_ADVICE_DONTNEED
|
||||||
| wasi::__WASI_ADVICE_SEQUENTIAL
|
| wasi::__WASI_ADVICE_SEQUENTIAL
|
||||||
@@ -114,18 +118,18 @@ pub(crate) fn fd_advise(
|
|||||||
| wasi::__WASI_ADVICE_NOREUSE
|
| wasi::__WASI_ADVICE_NOREUSE
|
||||||
| wasi::__WASI_ADVICE_RANDOM
|
| wasi::__WASI_ADVICE_RANDOM
|
||||||
| wasi::__WASI_ADVICE_NORMAL => {}
|
| wasi::__WASI_ADVICE_NORMAL => {}
|
||||||
_ => return Err(Error::EINVAL),
|
_ => return Err(WasiError::EINVAL),
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
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)?;
|
let path = concatenate(file, path)?;
|
||||||
std::fs::create_dir(&path).map_err(Into::into)
|
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")
|
unimplemented!("path_link")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -135,7 +139,7 @@ pub(crate) fn path_open(
|
|||||||
write: bool,
|
write: bool,
|
||||||
oflags: wasi::__wasi_oflags_t,
|
oflags: wasi::__wasi_oflags_t,
|
||||||
fdflags: wasi::__wasi_fdflags_t,
|
fdflags: wasi::__wasi_fdflags_t,
|
||||||
) -> Result<Descriptor> {
|
) -> WasiResult<Descriptor> {
|
||||||
use winx::file::{AccessMode, CreationDisposition, Flags};
|
use winx::file::{AccessMode, CreationDisposition, Flags};
|
||||||
|
|
||||||
let is_trunc = oflags & wasi::__WASI_OFLAGS_TRUNC != 0;
|
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
|
// This is because truncation requires `GENERIC_WRITE` access, which will override the removal
|
||||||
// of the `FILE_WRITE_DATA` permission.
|
// of the `FILE_WRITE_DATA` permission.
|
||||||
if fdflags & wasi::__WASI_FDFLAGS_APPEND != 0 {
|
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) => {
|
Ok(file_type) => {
|
||||||
// check if we are trying to open a symlink
|
// check if we are trying to open a symlink
|
||||||
if file_type.is_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
|
// check if we are trying to open a file as a dir
|
||||||
if file_type.is_file() && oflags & wasi::__WASI_OFLAGS_DIRECTORY != 0 {
|
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() {
|
Err(err) => match err.raw_os_error() {
|
||||||
@@ -191,7 +195,7 @@ pub(crate) fn path_open(
|
|||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
log::debug!("Inconvertible OS error: {}", err);
|
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,
|
path: P,
|
||||||
name: &str,
|
name: &str,
|
||||||
cookie: wasi::__wasi_dircookie_t,
|
cookie: wasi::__wasi_dircookie_t,
|
||||||
) -> Result<Dirent> {
|
) -> WasiResult<Dirent> {
|
||||||
let path = path.as_ref();
|
let path = path.as_ref();
|
||||||
trace!("dirent_from_path: opening {}", path.to_string_lossy());
|
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(
|
pub(crate) fn fd_readdir(
|
||||||
fd: &File,
|
fd: &File,
|
||||||
cookie: wasi::__wasi_dircookie_t,
|
cookie: wasi::__wasi_dircookie_t,
|
||||||
) -> Result<impl Iterator<Item = Result<Dirent>>> {
|
) -> WasiResult<impl Iterator<Item = WasiResult<Dirent>>> {
|
||||||
use winx::file::get_file_path;
|
use winx::file::get_file_path;
|
||||||
|
|
||||||
let cookie = cookie.try_into()?;
|
let cookie = cookie.try_into()?;
|
||||||
@@ -361,7 +365,7 @@ pub(crate) fn fd_readdir(
|
|||||||
Ok(iter.skip(cookie))
|
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;
|
use winx::file::get_file_path;
|
||||||
|
|
||||||
let path = resolved.concatenate()?;
|
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 dir_path = PathBuf::from(strip_extended_prefix(dir_path));
|
||||||
let target_path = target_path
|
let target_path = target_path
|
||||||
.strip_prefix(dir_path)
|
.strip_prefix(dir_path)
|
||||||
.map_err(|_| Error::ENOTCAPABLE)
|
.map_err(|_| WasiError::ENOTCAPABLE)
|
||||||
.and_then(|path| path.to_str().map(String::from).ok_or(Error::EILSEQ))?;
|
.and_then(|path| path.to_str().map(String::from).ok_or(WasiError::EILSEQ))?;
|
||||||
|
|
||||||
if buf.len() > 0 {
|
if buf.len() > 0 {
|
||||||
let mut chars = target_path.chars();
|
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('/') {
|
if resolved.path().ends_with('/') {
|
||||||
let suffix = resolved.path().trim_end_matches('/');
|
let suffix = resolved.path().trim_end_matches('/');
|
||||||
concatenate(&resolved.dirfd().as_os_handle(), Path::new(suffix)).map(Some)
|
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;
|
use std::fs;
|
||||||
|
|
||||||
let old_path = resolved_old.concatenate()?;
|
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
|
// [std::fs::rename]: https://doc.rust-lang.org/std/fs/fn.rename.html
|
||||||
if old_path.is_dir() && new_path.is_file() {
|
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
|
// Second sanity check: check we're not trying to rename a file into a path
|
||||||
// ending in a trailing slash.
|
// ending in a trailing slash.
|
||||||
if old_path.is_file() && resolved_new.path().ends_with('/') {
|
if old_path.is_file() && resolved_new.path().ends_with('/') {
|
||||||
return Err(Error::ENOTDIR);
|
return Err(WasiError::ENOTDIR);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO handle symlinks
|
// 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.
|
// So most likely dealing with new_path == dir.
|
||||||
// Eliminate case old_path == file first.
|
// Eliminate case old_path == file first.
|
||||||
if old_path.is_file() {
|
if old_path.is_file() {
|
||||||
return Err(Error::EISDIR);
|
return Err(WasiError::EISDIR);
|
||||||
} else {
|
} else {
|
||||||
// Ok, let's try removing an empty dir at new_path if it exists
|
// Ok, let's try removing an empty dir at new_path if it exists
|
||||||
// and is a nonempty dir.
|
// 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.
|
// a file instead of a dir, and if so, throw ENOTDIR.
|
||||||
if let Some(path) = strip_trailing_slashes_and_concatenate(&resolved_old)? {
|
if let Some(path) = strip_trailing_slashes_and_concatenate(&resolved_old)? {
|
||||||
if path.is_file() {
|
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 => {
|
None => {
|
||||||
log::debug!("Inconvertible OS error: {}", err);
|
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)
|
host_impl::filestat_from_win(file)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn path_filestat_get(
|
pub(crate) fn path_filestat_get(
|
||||||
resolved: PathGet,
|
resolved: PathGet,
|
||||||
dirflags: wasi::__wasi_lookupflags_t,
|
dirflags: wasi::__wasi_lookupflags_t,
|
||||||
) -> Result<wasi::__wasi_filestat_t> {
|
) -> WasiResult<wasi::__wasi_filestat_t> {
|
||||||
let path = resolved.concatenate()?;
|
let path = resolved.concatenate()?;
|
||||||
let file = File::open(path)?;
|
let file = File::open(path)?;
|
||||||
host_impl::filestat_from_win(&file)
|
host_impl::filestat_from_win(&file)
|
||||||
@@ -488,7 +492,7 @@ pub(crate) fn path_filestat_set_times(
|
|||||||
st_atim: wasi::__wasi_timestamp_t,
|
st_atim: wasi::__wasi_timestamp_t,
|
||||||
mut st_mtim: wasi::__wasi_timestamp_t,
|
mut st_mtim: wasi::__wasi_timestamp_t,
|
||||||
fst_flags: wasi::__wasi_fstflags_t,
|
fst_flags: wasi::__wasi_fstflags_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
use winx::file::AccessMode;
|
use winx::file::AccessMode;
|
||||||
let path = resolved.concatenate()?;
|
let path = resolved.concatenate()?;
|
||||||
let file = OpenOptions::new()
|
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)
|
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};
|
use std::os::windows::fs::{symlink_dir, symlink_file};
|
||||||
|
|
||||||
let old_path = concatenate(&resolved.dirfd().as_os_handle(), Path::new(old_path))?;
|
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 => {
|
winerror::ERROR_ACCESS_DENIED => {
|
||||||
// does the target exist?
|
// does the target exist?
|
||||||
if new_path.exists() {
|
if new_path.exists() {
|
||||||
return Err(Error::EEXIST);
|
return Err(WasiError::EEXIST);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
winerror::ERROR_INVALID_NAME => {
|
winerror::ERROR_INVALID_NAME => {
|
||||||
// does the target without trailing slashes exist?
|
// does the target without trailing slashes exist?
|
||||||
if let Some(path) = strip_trailing_slashes_and_concatenate(&resolved)? {
|
if let Some(path) = strip_trailing_slashes_and_concatenate(&resolved)? {
|
||||||
if path.exists() {
|
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 => {
|
None => {
|
||||||
log::debug!("Inconvertible OS error: {}", err);
|
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;
|
use std::fs;
|
||||||
|
|
||||||
let path = resolved.concatenate()?;
|
let path = resolved.concatenate()?;
|
||||||
@@ -573,19 +577,19 @@ pub(crate) fn path_unlink_file(resolved: PathGet) -> Result<()> {
|
|||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
log::debug!("Inconvertible OS error: {}", err);
|
log::debug!("Inconvertible OS error: {}", err);
|
||||||
Err(Error::EIO)
|
Err(WasiError::EIO)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if file_type.is_dir() {
|
} else if file_type.is_dir() {
|
||||||
Err(Error::EISDIR)
|
Err(WasiError::EISDIR)
|
||||||
} else if file_type.is_file() {
|
} else if file_type.is_file() {
|
||||||
fs::remove_file(path).map_err(Into::into)
|
fs::remove_file(path).map_err(Into::into)
|
||||||
} else {
|
} 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()?;
|
let path = resolved.concatenate()?;
|
||||||
std::fs::remove_dir(&path).map_err(Into::into)
|
std::fs::remove_dir(&path).map_err(Into::into)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#![allow(non_camel_case_types)]
|
#![allow(non_camel_case_types)]
|
||||||
use crate::fdentry::Descriptor;
|
use crate::fdentry::Descriptor;
|
||||||
use crate::hostcalls_impl::PathGet;
|
use crate::hostcalls_impl::PathGet;
|
||||||
use crate::{wasi, Error, Result};
|
use crate::wasi::{self, WasiError, WasiResult};
|
||||||
use std::ffi::{OsStr, OsString};
|
use std::ffi::{OsStr, OsString};
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::os::windows::ffi::{OsStrExt, OsStringExt};
|
use std::os::windows::ffi::{OsStrExt, OsStringExt};
|
||||||
@@ -9,11 +9,11 @@ use std::path::{Path, PathBuf};
|
|||||||
use winapi::shared::winerror;
|
use winapi::shared::winerror;
|
||||||
|
|
||||||
pub(crate) trait PathGetExt {
|
pub(crate) trait PathGetExt {
|
||||||
fn concatenate(&self) -> Result<PathBuf>;
|
fn concatenate(&self) -> WasiResult<PathBuf>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PathGetExt for PathGet {
|
impl PathGetExt for PathGet {
|
||||||
fn concatenate(&self) -> Result<PathBuf> {
|
fn concatenate(&self) -> WasiResult<PathBuf> {
|
||||||
match self.dirfd() {
|
match self.dirfd() {
|
||||||
Descriptor::OsHandle(file) => concatenate(file, Path::new(self.path())),
|
Descriptor::OsHandle(file) => concatenate(file, Path::new(self.path())),
|
||||||
Descriptor::VirtualFile(_virt) => {
|
Descriptor::VirtualFile(_virt) => {
|
||||||
@@ -55,7 +55,7 @@ pub(crate) fn path_open_rights(
|
|||||||
(needed_base, needed_inheriting)
|
(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::fs::OpenOptions;
|
||||||
use std::os::windows::fs::OpenOptionsExt;
|
use std::os::windows::fs::OpenOptionsExt;
|
||||||
use winx::file::Flags;
|
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() {
|
if let Some(code) = err.raw_os_error() {
|
||||||
log::debug!("openat error={:?}", code);
|
log::debug!("openat error={:?}", code);
|
||||||
if code as u32 == winerror::ERROR_INVALID_NAME {
|
if code as u32 == winerror::ERROR_INVALID_NAME {
|
||||||
return Err(Error::ENOTDIR);
|
return Err(WasiError::ENOTDIR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(err.into())
|
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;
|
use winx::file::get_file_path;
|
||||||
|
|
||||||
let path = concatenate(dirfd, Path::new(s_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 dir_path = PathBuf::from(strip_extended_prefix(dir_path));
|
||||||
let target_path = target_path
|
let target_path = target_path
|
||||||
.strip_prefix(dir_path)
|
.strip_prefix(dir_path)
|
||||||
.map_err(|_| Error::ENOTCAPABLE)?;
|
.map_err(|_| WasiError::ENOTCAPABLE)?;
|
||||||
let target_path = target_path.to_str().ok_or(Error::EILSEQ)?;
|
let target_path = target_path.to_str().ok_or(WasiError::EILSEQ)?;
|
||||||
return Ok(target_path.to_owned());
|
return Ok(target_path.to_owned());
|
||||||
}
|
}
|
||||||
Err(e) => e,
|
Err(e) => e,
|
||||||
@@ -105,7 +105,7 @@ pub(crate) fn readlinkat(dirfd: &File, s_path: &str) -> Result<String> {
|
|||||||
// strip "/" and check if exists
|
// strip "/" and check if exists
|
||||||
let path = concatenate(dirfd, Path::new(s_path.trim_end_matches('/')))?;
|
let path = concatenate(dirfd, Path::new(s_path.trim_end_matches('/')))?;
|
||||||
if path.exists() && !path.is_dir() {
|
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;
|
use winx::file::get_file_path;
|
||||||
|
|
||||||
// WASI is not able to deal with absolute paths
|
// WASI is not able to deal with absolute paths
|
||||||
// so error out if absolute
|
// so error out if absolute
|
||||||
if path.as_ref().is_absolute() {
|
if path.as_ref().is_absolute() {
|
||||||
return Err(Error::ENOTCAPABLE);
|
return Err(WasiError::ENOTCAPABLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
let dir_path = get_file_path(file)?;
|
let dir_path = get_file_path(file)?;
|
||||||
|
|||||||
@@ -5,7 +5,8 @@ use crate::fdentry::Descriptor;
|
|||||||
use crate::hostcalls_impl::{ClockEventData, FdEventData};
|
use crate::hostcalls_impl::{ClockEventData, FdEventData};
|
||||||
use crate::memory::*;
|
use crate::memory::*;
|
||||||
use crate::sys::host_impl;
|
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 cpu_time::{ProcessTime, ThreadTime};
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use log::{debug, error, trace, warn};
|
use log::{debug, error, trace, warn};
|
||||||
@@ -24,9 +25,9 @@ struct StdinPoll {
|
|||||||
|
|
||||||
enum PollState {
|
enum PollState {
|
||||||
Ready,
|
Ready,
|
||||||
NotReady, // it's not ready, but we didn't wait
|
NotReady, // it's not ready, but we didn't wait
|
||||||
TimedOut, // it's not ready and a timeout has occurred
|
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 {
|
enum WaitMode {
|
||||||
@@ -82,7 +83,7 @@ impl StdinPoll {
|
|||||||
// Linux returns `POLLIN` in both cases, and we imitate this behavior.
|
// Linux returns `POLLIN` in both cases, and we imitate this behavior.
|
||||||
let resp = match std::io::stdin().lock().fill_buf() {
|
let resp = match std::io::stdin().lock().fill_buf() {
|
||||||
Ok(_) => PollState::Ready,
|
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,
|
// 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
|
// Timer resolution on Windows is really hard. We may consider exposing the resolution of the respective
|
||||||
// timers as an associated function in the future.
|
// 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 {
|
Ok(match clock_id {
|
||||||
// This is the best that we can do with std::time::SystemTime.
|
// This is the best that we can do with std::time::SystemTime.
|
||||||
// Rust uses GetSystemTimeAsFileTime, which is said to have the resolution of
|
// 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.
|
// 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
|
// https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-getthreadtimes
|
||||||
wasi::__WASI_CLOCKID_THREAD_CPUTIME_ID => 100,
|
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 {
|
let duration = match clock_id {
|
||||||
wasi::__WASI_CLOCKID_REALTIME => get_monotonic_time(),
|
wasi::__WASI_CLOCKID_REALTIME => get_monotonic_time(),
|
||||||
wasi::__WASI_CLOCKID_MONOTONIC => get_realtime_time()?,
|
wasi::__WASI_CLOCKID_MONOTONIC => get_realtime_time()?,
|
||||||
wasi::__WASI_CLOCKID_PROCESS_CPUTIME_ID => get_proc_cputime()?,
|
wasi::__WASI_CLOCKID_PROCESS_CPUTIME_ID => get_proc_cputime()?,
|
||||||
wasi::__WASI_CLOCKID_THREAD_CPUTIME_ID => get_thread_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)
|
duration.as_nanos().try_into().map_err(Into::into)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_rw_event(event: &FdEventData, nbytes: Result<u64>) -> wasi::__wasi_event_t {
|
fn make_rw_event(event: &FdEventData, nbytes: WasiResult<u64>) -> wasi::__wasi_event_t {
|
||||||
use crate::error::AsWasiError;
|
let (nbytes, error) = match nbytes {
|
||||||
let error = nbytes.as_wasi_error();
|
Ok(nbytes) => (nbytes, WasiError::ESUCCESS),
|
||||||
let nbytes = nbytes.unwrap_or_default();
|
Err(e) => (u64::default(), e),
|
||||||
|
};
|
||||||
wasi::__wasi_event_t {
|
wasi::__wasi_event_t {
|
||||||
userdata: event.userdata,
|
userdata: event.userdata,
|
||||||
r#type: event.r#type,
|
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(
|
fn handle_error_event(
|
||||||
event: FdEventData,
|
event: FdEventData,
|
||||||
error: Error,
|
error: WasiError,
|
||||||
out_events: &mut Vec<wasi::__wasi_event_t>,
|
out_events: &mut Vec<wasi::__wasi_event_t>,
|
||||||
) {
|
) {
|
||||||
let new_event = make_rw_event(&event, Err(error));
|
let new_event = make_rw_event(&event, Err(error));
|
||||||
@@ -244,7 +250,7 @@ pub(crate) fn poll_oneoff(
|
|||||||
timeout: Option<ClockEventData>,
|
timeout: Option<ClockEventData>,
|
||||||
fd_events: Vec<FdEventData>,
|
fd_events: Vec<FdEventData>,
|
||||||
events: &mut Vec<wasi::__wasi_event_t>,
|
events: &mut Vec<wasi::__wasi_event_t>,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
use std::fs::Metadata;
|
use std::fs::Metadata;
|
||||||
use std::thread;
|
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()) }?;
|
let ftype = unsafe { winx::file::get_file_type(os_handle.as_raw_handle()) }?;
|
||||||
if ftype.is_unknown() || ftype.is_char() {
|
if ftype.is_unknown() || ftype.is_char() {
|
||||||
debug!("poll_oneoff: unsupported file type: {:?}", ftype);
|
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() {
|
} else if ftype.is_disk() {
|
||||||
immediate_events.push(event);
|
immediate_events.push(event);
|
||||||
} else if ftype.is_pipe() {
|
} else if ftype.is_pipe() {
|
||||||
@@ -349,7 +355,7 @@ pub(crate) fn poll_oneoff(
|
|||||||
PollState::Ready => handle_rw_event(event, events),
|
PollState::Ready => handle_rw_event(event, events),
|
||||||
PollState::NotReady => {} // not immediately available, so just ignore
|
PollState::NotReady => {} // not immediately available, so just ignore
|
||||||
PollState::TimedOut => handle_timeout_event(timeout.unwrap().0, events),
|
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 => {
|
None => {
|
||||||
error!("Polling only pipes with no timeout not supported on Windows.");
|
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()
|
START_MONOTONIC.elapsed()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_realtime_time() -> Result<Duration> {
|
fn get_realtime_time() -> WasiResult<Duration> {
|
||||||
SystemTime::now()
|
SystemTime::now()
|
||||||
.duration_since(UNIX_EPOCH)
|
.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())
|
Ok(ProcessTime::try_now()?.as_duration())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_thread_cputime() -> Result<Duration> {
|
fn get_thread_cputime() -> WasiResult<Duration> {
|
||||||
Ok(ThreadTime::try_now()?.as_duration())
|
Ok(ThreadTime::try_now()?.as_duration())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,16 +2,12 @@ pub(crate) mod fdentry_impl;
|
|||||||
pub(crate) mod host_impl;
|
pub(crate) mod host_impl;
|
||||||
pub(crate) mod hostcalls_impl;
|
pub(crate) mod hostcalls_impl;
|
||||||
|
|
||||||
use crate::Result;
|
|
||||||
use std::fs::{File, OpenOptions};
|
use std::fs::{File, OpenOptions};
|
||||||
|
use std::io::Result;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
pub(crate) fn dev_null() -> Result<File> {
|
pub(crate) fn dev_null() -> Result<File> {
|
||||||
OpenOptions::new()
|
OpenOptions::new().read(true).write(true).open("NUL")
|
||||||
.read(true)
|
|
||||||
.write(true)
|
|
||||||
.open("NUL")
|
|
||||||
.map_err(Into::into)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn preopen_dir<P: AsRef<Path>>(path: P) -> Result<File> {
|
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)
|
.read(true)
|
||||||
.attributes(FILE_FLAG_BACKUP_SEMANTICS)
|
.attributes(FILE_FLAG_BACKUP_SEMANTICS)
|
||||||
.open(path)
|
.open(path)
|
||||||
.map_err(Into::into)
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
use crate::host::Dirent;
|
use crate::host::Dirent;
|
||||||
use crate::host::FileType;
|
use crate::host::FileType;
|
||||||
use crate::{wasi, wasi32, Error, Result};
|
use crate::wasi::{self, WasiError, WasiResult};
|
||||||
|
use crate::wasi32;
|
||||||
use filetime::FileTime;
|
use filetime::FileTime;
|
||||||
use log::trace;
|
use log::trace;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
@@ -44,8 +45,8 @@ pub(crate) trait VirtualFile: MovableFile {
|
|||||||
|
|
||||||
fn try_clone(&self) -> io::Result<Box<dyn VirtualFile>>;
|
fn try_clone(&self) -> io::Result<Box<dyn VirtualFile>>;
|
||||||
|
|
||||||
fn readlinkat(&self, _path: &Path) -> Result<String> {
|
fn readlinkat(&self, _path: &Path) -> WasiResult<String> {
|
||||||
Err(Error::EACCES)
|
Err(WasiError::EACCES)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn openat(
|
fn openat(
|
||||||
@@ -55,51 +56,51 @@ pub(crate) trait VirtualFile: MovableFile {
|
|||||||
_write: bool,
|
_write: bool,
|
||||||
_oflags: wasi::__wasi_oflags_t,
|
_oflags: wasi::__wasi_oflags_t,
|
||||||
_fd_flags: wasi::__wasi_fdflags_t,
|
_fd_flags: wasi::__wasi_fdflags_t,
|
||||||
) -> Result<Box<dyn VirtualFile>> {
|
) -> WasiResult<Box<dyn VirtualFile>> {
|
||||||
Err(Error::EACCES)
|
Err(WasiError::EACCES)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn remove_directory(&self, _path: &str) -> Result<()> {
|
fn remove_directory(&self, _path: &str) -> WasiResult<()> {
|
||||||
Err(Error::EACCES)
|
Err(WasiError::EACCES)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn unlink_file(&self, _path: &str) -> Result<()> {
|
fn unlink_file(&self, _path: &str) -> WasiResult<()> {
|
||||||
Err(Error::EACCES)
|
Err(WasiError::EACCES)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn datasync(&self) -> Result<()> {
|
fn datasync(&self) -> WasiResult<()> {
|
||||||
Err(Error::EINVAL)
|
Err(WasiError::EINVAL)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sync(&self) -> Result<()> {
|
fn sync(&self) -> WasiResult<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_directory(&self, _path: &Path) -> Result<()> {
|
fn create_directory(&self, _path: &Path) -> WasiResult<()> {
|
||||||
Err(Error::EACCES)
|
Err(WasiError::EACCES)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn readdir(
|
fn readdir(
|
||||||
&self,
|
&self,
|
||||||
_cookie: wasi::__wasi_dircookie_t,
|
_cookie: wasi::__wasi_dircookie_t,
|
||||||
) -> Result<Box<dyn Iterator<Item = Result<Dirent>>>> {
|
) -> WasiResult<Box<dyn Iterator<Item = WasiResult<Dirent>>>> {
|
||||||
Err(Error::EBADF)
|
Err(WasiError::EBADF)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_vectored(&mut self, _iovs: &[io::IoSlice]) -> Result<usize> {
|
fn write_vectored(&mut self, _iovs: &[io::IoSlice]) -> WasiResult<usize> {
|
||||||
Err(Error::EBADF)
|
Err(WasiError::EBADF)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pread(&self, _buf: &mut [u8], _offset: u64) -> Result<usize> {
|
fn pread(&self, _buf: &mut [u8], _offset: u64) -> WasiResult<usize> {
|
||||||
Err(Error::EBADF)
|
Err(WasiError::EBADF)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pwrite(&self, _buf: &mut [u8], _offset: u64) -> Result<usize> {
|
fn pwrite(&self, _buf: &mut [u8], _offset: u64) -> WasiResult<usize> {
|
||||||
Err(Error::EBADF)
|
Err(WasiError::EBADF)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn seek(&mut self, _offset: SeekFrom) -> Result<u64> {
|
fn seek(&mut self, _offset: SeekFrom) -> WasiResult<u64> {
|
||||||
Err(Error::EBADF)
|
Err(WasiError::EBADF)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn advise(
|
fn advise(
|
||||||
@@ -107,36 +108,40 @@ pub(crate) trait VirtualFile: MovableFile {
|
|||||||
_advice: wasi::__wasi_advice_t,
|
_advice: wasi::__wasi_advice_t,
|
||||||
_offset: wasi::__wasi_filesize_t,
|
_offset: wasi::__wasi_filesize_t,
|
||||||
_len: wasi::__wasi_filesize_t,
|
_len: wasi::__wasi_filesize_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
Err(Error::EBADF)
|
Err(WasiError::EBADF)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn allocate(
|
fn allocate(
|
||||||
&self,
|
&self,
|
||||||
_offset: wasi::__wasi_filesize_t,
|
_offset: wasi::__wasi_filesize_t,
|
||||||
_len: wasi::__wasi_filesize_t,
|
_len: wasi::__wasi_filesize_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
Err(Error::EBADF)
|
Err(WasiError::EBADF)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn filestat_get(&self) -> Result<wasi::__wasi_filestat_t> {
|
fn filestat_get(&self) -> WasiResult<wasi::__wasi_filestat_t> {
|
||||||
Err(Error::EBADF)
|
Err(WasiError::EBADF)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn filestat_set_times(&self, _atim: Option<FileTime>, _mtim: Option<FileTime>) -> Result<()> {
|
fn filestat_set_times(
|
||||||
Err(Error::EBADF)
|
&self,
|
||||||
|
_atim: Option<FileTime>,
|
||||||
|
_mtim: Option<FileTime>,
|
||||||
|
) -> WasiResult<()> {
|
||||||
|
Err(WasiError::EBADF)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn filestat_set_size(&self, _st_size: wasi::__wasi_filesize_t) -> Result<()> {
|
fn filestat_set_size(&self, _st_size: wasi::__wasi_filesize_t) -> WasiResult<()> {
|
||||||
Err(Error::EBADF)
|
Err(WasiError::EBADF)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fdstat_set_flags(&mut self, _fdflags: wasi::__wasi_fdflags_t) -> Result<()> {
|
fn fdstat_set_flags(&mut self, _fdflags: wasi::__wasi_fdflags_t) -> WasiResult<()> {
|
||||||
Err(Error::EBADF)
|
Err(WasiError::EBADF)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_vectored(&mut self, _iovs: &mut [io::IoSliceMut]) -> Result<usize> {
|
fn read_vectored(&mut self, _iovs: &mut [io::IoSliceMut]) -> WasiResult<usize> {
|
||||||
Err(Error::EBADF)
|
Err(WasiError::EBADF)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_file_type(&self) -> wasi::__wasi_filetype_t;
|
fn get_file_type(&self) -> wasi::__wasi_filetype_t;
|
||||||
@@ -157,23 +162,30 @@ pub trait FileContents {
|
|||||||
/// The current number of bytes this `FileContents` describes.
|
/// The current number of bytes this `FileContents` describes.
|
||||||
fn size(&self) -> wasi::__wasi_filesize_t;
|
fn size(&self) -> wasi::__wasi_filesize_t;
|
||||||
/// Resize to hold `new_size` number of bytes, or error if this is not possible.
|
/// 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`
|
/// 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
|
/// is guaranteed to not exceed `max_size`. Implementations must not indicate more bytes have
|
||||||
/// been written than can be held by `iovs`.
|
/// 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
|
/// 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
|
/// be more than the capactiy of `iovs`, and must not exceed the limit reported by
|
||||||
/// `self.max_size()`.
|
/// `self.max_size()`.
|
||||||
fn preadv(&self, iovs: &mut [io::IoSliceMut], offset: wasi::__wasi_filesize_t)
|
fn preadv(
|
||||||
-> Result<usize>;
|
&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
|
/// 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
|
/// `buf` is guaranteed to not exceed `max_size`. Implementations must not indicate more bytes
|
||||||
/// have been written than the size of `buf`.
|
/// 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
|
/// 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()`.
|
/// 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 {
|
impl FileContents for VecFileContents {
|
||||||
@@ -185,8 +197,8 @@ impl FileContents for VecFileContents {
|
|||||||
self.content.len() as wasi::__wasi_filesize_t
|
self.content.len() as wasi::__wasi_filesize_t
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resize(&mut self, new_size: wasi::__wasi_filesize_t) -> Result<()> {
|
fn resize(&mut self, new_size: wasi::__wasi_filesize_t) -> WasiResult<()> {
|
||||||
let new_size: usize = new_size.try_into().map_err(|_| Error::EINVAL)?;
|
let new_size: usize = new_size.try_into().map_err(|_| WasiError::EINVAL)?;
|
||||||
self.content.resize(new_size, 0);
|
self.content.resize(new_size, 0);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -195,7 +207,7 @@ impl FileContents for VecFileContents {
|
|||||||
&self,
|
&self,
|
||||||
iovs: &mut [io::IoSliceMut],
|
iovs: &mut [io::IoSliceMut],
|
||||||
offset: wasi::__wasi_filesize_t,
|
offset: wasi::__wasi_filesize_t,
|
||||||
) -> Result<usize> {
|
) -> WasiResult<usize> {
|
||||||
let mut read_total = 0usize;
|
let mut read_total = 0usize;
|
||||||
for iov in iovs.iter_mut() {
|
for iov in iovs.iter_mut() {
|
||||||
let read = self.pread(iov, offset)?;
|
let read = self.pread(iov, offset)?;
|
||||||
@@ -204,7 +216,11 @@ impl FileContents for VecFileContents {
|
|||||||
Ok(read_total)
|
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;
|
let mut write_total = 0usize;
|
||||||
for iov in iovs.iter() {
|
for iov in iovs.iter() {
|
||||||
let written = self.pwrite(iov, offset)?;
|
let written = self.pwrite(iov, offset)?;
|
||||||
@@ -213,9 +229,9 @@ impl FileContents for VecFileContents {
|
|||||||
Ok(write_total)
|
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);
|
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);
|
let data_remaining = self.content.len().saturating_sub(offset);
|
||||||
|
|
||||||
@@ -228,10 +244,10 @@ impl FileContents for VecFileContents {
|
|||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
|
||||||
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> {
|
||||||
let offset: usize = offset.try_into().map_err(|_| Error::EINVAL)?;
|
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() {
|
if write_end > self.content.len() {
|
||||||
self.content.resize(write_end, 0);
|
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.
|
// no symlink support, so always say it's invalid.
|
||||||
Err(Error::ENOTDIR)
|
Err(WasiError::ENOTDIR)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn openat(
|
fn openat(
|
||||||
@@ -317,7 +333,7 @@ impl VirtualFile for InMemoryFile {
|
|||||||
write: bool,
|
write: bool,
|
||||||
oflags: wasi::__wasi_oflags_t,
|
oflags: wasi::__wasi_oflags_t,
|
||||||
fd_flags: wasi::__wasi_fdflags_t,
|
fd_flags: wasi::__wasi_fdflags_t,
|
||||||
) -> Result<Box<dyn VirtualFile>> {
|
) -> WasiResult<Box<dyn VirtualFile>> {
|
||||||
log::trace!(
|
log::trace!(
|
||||||
"InMemoryFile::openat(path={:?}, read={:?}, write={:?}, oflags={:?}, fd_flags={:?}",
|
"InMemoryFile::openat(path={:?}, read={:?}, write={:?}, oflags={:?}, fd_flags={:?}",
|
||||||
path,
|
path,
|
||||||
@@ -333,7 +349,7 @@ impl VirtualFile for InMemoryFile {
|
|||||||
path
|
path
|
||||||
);
|
);
|
||||||
log::trace!(" return ENOTDIR");
|
log::trace!(" return ENOTDIR");
|
||||||
return Err(Error::ENOTDIR);
|
return Err(WasiError::ENOTDIR);
|
||||||
}
|
}
|
||||||
|
|
||||||
if path == Path::new(".") {
|
if path == Path::new(".") {
|
||||||
@@ -344,24 +360,24 @@ impl VirtualFile for InMemoryFile {
|
|||||||
None => self.try_clone().map_err(Into::into),
|
None => self.try_clone().map_err(Into::into),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Err(Error::EACCES)
|
Err(WasiError::EACCES)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn remove_directory(&self, _path: &str) -> Result<()> {
|
fn remove_directory(&self, _path: &str) -> WasiResult<()> {
|
||||||
Err(Error::ENOTDIR)
|
Err(WasiError::ENOTDIR)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn unlink_file(&self, _path: &str) -> Result<()> {
|
fn unlink_file(&self, _path: &str) -> WasiResult<()> {
|
||||||
Err(Error::ENOTDIR)
|
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;
|
self.fd_flags = fdflags;
|
||||||
Ok(())
|
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);
|
trace!("write_vectored(iovs={:?})", iovs);
|
||||||
let mut data = self.data.borrow_mut();
|
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 let Some(end) = write_start.checked_add(max_size as wasi::__wasi_filesize_t) {
|
||||||
if end > data.max_size() {
|
if end > data.max_size() {
|
||||||
return Err(Error::EFBIG);
|
return Err(WasiError::EFBIG);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return Err(Error::EFBIG);
|
return Err(WasiError::EFBIG);
|
||||||
}
|
}
|
||||||
|
|
||||||
trace!(" | *write_start={:?}", write_start);
|
trace!(" | *write_start={:?}", write_start);
|
||||||
@@ -407,43 +423,43 @@ impl VirtualFile for InMemoryFile {
|
|||||||
Ok(written)
|
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_vectored(iovs={:?})", iovs);
|
||||||
trace!(" | *read_start={:?}", self.cursor);
|
trace!(" | *read_start={:?}", self.cursor);
|
||||||
self.data.borrow_mut().preadv(iovs, 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)
|
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)
|
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();
|
let content_len = self.data.borrow().size();
|
||||||
match offset {
|
match offset {
|
||||||
SeekFrom::Current(offset) => {
|
SeekFrom::Current(offset) => {
|
||||||
let new_cursor = if offset < 0 {
|
let new_cursor = if offset < 0 {
|
||||||
self.cursor
|
self.cursor
|
||||||
.checked_sub(offset.wrapping_neg() as u64)
|
.checked_sub(offset.wrapping_neg() as u64)
|
||||||
.ok_or(Error::EINVAL)?
|
.ok_or(WasiError::EINVAL)?
|
||||||
} else {
|
} else {
|
||||||
self.cursor
|
self.cursor
|
||||||
.checked_add(offset as u64)
|
.checked_add(offset as u64)
|
||||||
.ok_or(Error::EINVAL)?
|
.ok_or(WasiError::EINVAL)?
|
||||||
};
|
};
|
||||||
self.cursor = std::cmp::min(content_len, new_cursor);
|
self.cursor = std::cmp::min(content_len, new_cursor);
|
||||||
}
|
}
|
||||||
SeekFrom::End(offset) => {
|
SeekFrom::End(offset) => {
|
||||||
// A negative offset from the end would be past the end of the file,
|
// 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);
|
self.cursor = content_len.saturating_sub(offset);
|
||||||
}
|
}
|
||||||
SeekFrom::Start(offset) => {
|
SeekFrom::Start(offset) => {
|
||||||
// A negative offset from the end would be before the start of the file.
|
// 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);
|
self.cursor = std::cmp::min(content_len, offset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -456,7 +472,7 @@ impl VirtualFile for InMemoryFile {
|
|||||||
advice: wasi::__wasi_advice_t,
|
advice: wasi::__wasi_advice_t,
|
||||||
_offset: wasi::__wasi_filesize_t,
|
_offset: wasi::__wasi_filesize_t,
|
||||||
_len: wasi::__wasi_filesize_t,
|
_len: wasi::__wasi_filesize_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
// we'll just ignore advice for now, unless it's totally invalid
|
// we'll just ignore advice for now, unless it's totally invalid
|
||||||
match advice {
|
match advice {
|
||||||
wasi::__WASI_ADVICE_DONTNEED
|
wasi::__WASI_ADVICE_DONTNEED
|
||||||
@@ -465,7 +481,7 @@ impl VirtualFile for InMemoryFile {
|
|||||||
| wasi::__WASI_ADVICE_NOREUSE
|
| wasi::__WASI_ADVICE_NOREUSE
|
||||||
| wasi::__WASI_ADVICE_RANDOM
|
| wasi::__WASI_ADVICE_RANDOM
|
||||||
| wasi::__WASI_ADVICE_NORMAL => Ok(()),
|
| wasi::__WASI_ADVICE_NORMAL => Ok(()),
|
||||||
_ => Err(Error::EINVAL),
|
_ => Err(WasiError::EINVAL),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -473,12 +489,12 @@ impl VirtualFile for InMemoryFile {
|
|||||||
&self,
|
&self,
|
||||||
offset: wasi::__wasi_filesize_t,
|
offset: wasi::__wasi_filesize_t,
|
||||||
len: wasi::__wasi_filesize_t,
|
len: wasi::__wasi_filesize_t,
|
||||||
) -> Result<()> {
|
) -> WasiResult<()> {
|
||||||
let new_limit = offset.checked_add(len).ok_or(Error::EFBIG)?;
|
let new_limit = offset.checked_add(len).ok_or(WasiError::EFBIG)?;
|
||||||
let mut data = self.data.borrow_mut();
|
let mut data = self.data.borrow_mut();
|
||||||
|
|
||||||
if new_limit > data.max_size() {
|
if new_limit > data.max_size() {
|
||||||
return Err(Error::EFBIG);
|
return Err(WasiError::EFBIG);
|
||||||
}
|
}
|
||||||
|
|
||||||
if new_limit > data.size() {
|
if new_limit > data.size() {
|
||||||
@@ -488,15 +504,15 @@ impl VirtualFile for InMemoryFile {
|
|||||||
Ok(())
|
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();
|
let mut data = self.data.borrow_mut();
|
||||||
if st_size > data.max_size() {
|
if st_size > data.max_size() {
|
||||||
return Err(Error::EFBIG);
|
return Err(WasiError::EFBIG);
|
||||||
}
|
}
|
||||||
data.resize(st_size)
|
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 {
|
let stat = wasi::__wasi_filestat_t {
|
||||||
dev: 0,
|
dev: 0,
|
||||||
ino: 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.
|
// Files are not symbolic links or directories, faithfully report ENOTDIR.
|
||||||
Err(Error::ENOTDIR)
|
Err(WasiError::ENOTDIR)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn openat(
|
fn openat(
|
||||||
@@ -606,7 +622,7 @@ impl VirtualFile for VirtualDir {
|
|||||||
write: bool,
|
write: bool,
|
||||||
oflags: wasi::__wasi_oflags_t,
|
oflags: wasi::__wasi_oflags_t,
|
||||||
fd_flags: wasi::__wasi_fdflags_t,
|
fd_flags: wasi::__wasi_fdflags_t,
|
||||||
) -> Result<Box<dyn VirtualFile>> {
|
) -> WasiResult<Box<dyn VirtualFile>> {
|
||||||
log::trace!(
|
log::trace!(
|
||||||
"VirtualDir::openat(path={:?}, read={:?}, write={:?}, oflags={:?}, fd_flags={:?}",
|
"VirtualDir::openat(path={:?}, read={:?}, write={:?}, oflags={:?}, fd_flags={:?}",
|
||||||
path,
|
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
|
// openat may have been passed a path with a trailing slash, but files are mapped to paths
|
||||||
// with trailing slashes normalized out.
|
// 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 mut entries = self.entries.borrow_mut();
|
||||||
let entry_count = entries.len();
|
let entry_count = entries.len();
|
||||||
match entries.entry(Path::new(file_name).to_path_buf()) {
|
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 {
|
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!("VirtualDir::openat was passed oflags CREAT|EXCL, but the file {:?} exists.", file_name);
|
||||||
log::trace!(" return EEXIST");
|
log::trace!(" return EEXIST");
|
||||||
return Err(Error::EEXIST);
|
return Err(WasiError::EEXIST);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (oflags & wasi::__WASI_OFLAGS_DIRECTORY) != 0
|
if (oflags & wasi::__WASI_OFLAGS_DIRECTORY) != 0
|
||||||
@@ -651,7 +667,7 @@ impl VirtualFile for VirtualDir {
|
|||||||
file_name
|
file_name
|
||||||
);
|
);
|
||||||
log::trace!(" return ENOTDIR");
|
log::trace!(" return ENOTDIR");
|
||||||
return Err(Error::ENOTDIR);
|
return Err(WasiError::ENOTDIR);
|
||||||
}
|
}
|
||||||
|
|
||||||
e.get().try_clone().map_err(Into::into)
|
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
|
// would have with `usize`. The limit is the full `u32` range minus two so we
|
||||||
// can reserve "self" and "parent" cookie values.
|
// can reserve "self" and "parent" cookie values.
|
||||||
if entry_count >= (std::u32::MAX - RESERVED_ENTRY_COUNT) as usize {
|
if entry_count >= (std::u32::MAX - RESERVED_ENTRY_COUNT) as usize {
|
||||||
return Err(Error::ENOSPC);
|
return Err(WasiError::ENOSPC);
|
||||||
}
|
}
|
||||||
|
|
||||||
log::trace!(
|
log::trace!(
|
||||||
@@ -676,26 +692,26 @@ impl VirtualFile for VirtualDir {
|
|||||||
file.set_parent(Some(self.try_clone().expect("can clone self")));
|
file.set_parent(Some(self.try_clone().expect("can clone self")));
|
||||||
v.insert(file).try_clone().map_err(Into::into)
|
v.insert(file).try_clone().map_err(Into::into)
|
||||||
} else {
|
} 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 trimmed_path = path.trim_end_matches('/');
|
||||||
let mut entries = self.entries.borrow_mut();
|
let mut entries = self.entries.borrow_mut();
|
||||||
match entries.entry(Path::new(trimmed_path).to_path_buf()) {
|
match entries.entry(Path::new(trimmed_path).to_path_buf()) {
|
||||||
Entry::Occupied(e) => {
|
Entry::Occupied(e) => {
|
||||||
// first, does this name a directory?
|
// first, does this name a directory?
|
||||||
if e.get().get_file_type() != wasi::__WASI_FILETYPE_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?
|
// Okay, but is the directory empty?
|
||||||
let iter = e.get().readdir(wasi::__WASI_DIRCOOKIE_START)?;
|
let iter = e.get().readdir(wasi::__WASI_DIRCOOKIE_START)?;
|
||||||
if iter.skip(RESERVED_ENTRY_COUNT as usize).next().is_some() {
|
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.
|
// 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",
|
"VirtualDir::remove_directory failed to remove {}, no such entry",
|
||||||
trimmed_path
|
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('/');
|
let trimmed_path = path.trim_end_matches('/');
|
||||||
|
|
||||||
// Special case: we may be unlinking this directory itself if path is `"."`. In that case,
|
// 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 `".."`,
|
// 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.
|
// which is bound the same way, as this is by definition contained in a directory.
|
||||||
if trimmed_path == "." || trimmed_path == ".." {
|
if trimmed_path == "." || trimmed_path == ".." {
|
||||||
return Err(Error::EISDIR);
|
return Err(WasiError::EISDIR);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut entries = self.entries.borrow_mut();
|
let mut entries = self.entries.borrow_mut();
|
||||||
@@ -731,7 +747,7 @@ impl VirtualFile for VirtualDir {
|
|||||||
Entry::Occupied(e) => {
|
Entry::Occupied(e) => {
|
||||||
// Directories must be removed through `remove_directory`, not `unlink_file`.
|
// Directories must be removed through `remove_directory`, not `unlink_file`.
|
||||||
if e.get().get_file_type() == wasi::__WASI_FILETYPE_DIRECTORY {
|
if e.get().get_file_type() == wasi::__WASI_FILETYPE_DIRECTORY {
|
||||||
return Err(Error::EISDIR);
|
return Err(WasiError::EISDIR);
|
||||||
}
|
}
|
||||||
|
|
||||||
let removed = e.remove_entry();
|
let removed = e.remove_entry();
|
||||||
@@ -746,15 +762,15 @@ impl VirtualFile for VirtualDir {
|
|||||||
"VirtualDir::unlink_file failed to remove {}, no such entry",
|
"VirtualDir::unlink_file failed to remove {}, no such entry",
|
||||||
trimmed_path
|
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();
|
let mut entries = self.entries.borrow_mut();
|
||||||
match entries.entry(path.to_owned()) {
|
match entries.entry(path.to_owned()) {
|
||||||
Entry::Occupied(_) => Err(Error::EEXIST),
|
Entry::Occupied(_) => Err(WasiError::EEXIST),
|
||||||
Entry::Vacant(v) => {
|
Entry::Vacant(v) => {
|
||||||
if self.writable {
|
if self.writable {
|
||||||
let new_dir = Box::new(VirtualDir::new(true));
|
let new_dir = Box::new(VirtualDir::new(true));
|
||||||
@@ -762,26 +778,26 @@ impl VirtualFile for VirtualDir {
|
|||||||
v.insert(new_dir);
|
v.insert(new_dir);
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
Err(Error::EACCES)
|
Err(WasiError::EACCES)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_vectored(&mut self, _iovs: &[io::IoSlice]) -> Result<usize> {
|
fn write_vectored(&mut self, _iovs: &[io::IoSlice]) -> WasiResult<usize> {
|
||||||
Err(Error::EBADF)
|
Err(WasiError::EBADF)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn readdir(
|
fn readdir(
|
||||||
&self,
|
&self,
|
||||||
cookie: wasi::__wasi_dircookie_t,
|
cookie: wasi::__wasi_dircookie_t,
|
||||||
) -> Result<Box<dyn Iterator<Item = Result<Dirent>>>> {
|
) -> WasiResult<Box<dyn Iterator<Item = WasiResult<Dirent>>>> {
|
||||||
struct VirtualDirIter {
|
struct VirtualDirIter {
|
||||||
start: u32,
|
start: u32,
|
||||||
entries: Rc<RefCell<HashMap<PathBuf, Box<dyn VirtualFile>>>>,
|
entries: Rc<RefCell<HashMap<PathBuf, Box<dyn VirtualFile>>>>,
|
||||||
}
|
}
|
||||||
impl Iterator for VirtualDirIter {
|
impl Iterator for VirtualDirIter {
|
||||||
type Item = Result<Dirent>;
|
type Item = WasiResult<Dirent>;
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
log::trace!("VirtualDirIter::next continuing from {}", self.start);
|
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 {
|
let stat = wasi::__wasi_filestat_t {
|
||||||
dev: 0,
|
dev: 0,
|
||||||
ino: 0,
|
ino: 0,
|
||||||
|
|||||||
@@ -10,6 +10,115 @@ use wig::witx_wasi_types;
|
|||||||
|
|
||||||
witx_wasi_types!("snapshot" "wasi_snapshot_preview1");
|
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
|
pub(crate) const RIGHTS_ALL: __wasi_rights_t = __WASI_RIGHTS_FD_DATASYNC
|
||||||
| __WASI_RIGHTS_FD_READ
|
| __WASI_RIGHTS_FD_READ
|
||||||
| __WASI_RIGHTS_FD_SEEK
|
| __WASI_RIGHTS_FD_SEEK
|
||||||
|
|||||||
@@ -92,8 +92,7 @@ fn generate_wrappers(func: &witx::InterfaceFunc, old: bool) -> TokenStream {
|
|||||||
quote! {
|
quote! {
|
||||||
let ret = #call
|
let ret = #call
|
||||||
.err()
|
.err()
|
||||||
.unwrap_or(super::Error::ESUCCESS)
|
.unwrap_or(super::wasi::WasiError::ESUCCESS);
|
||||||
.as_wasi_error();
|
|
||||||
log::trace!(" | errno={}", ret);
|
log::trace!(" | errno={}", ret);
|
||||||
ret.as_raw_errno()
|
ret.as_raw_errno()
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user