* 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
97 lines
3.2 KiB
Rust
97 lines
3.2 KiB
Rust
//! WASI host types. These are types that contain raw pointers and `usize`
|
|
//! values, and so are platform-specific.
|
|
|
|
#![allow(non_camel_case_types)]
|
|
#![allow(non_snake_case)]
|
|
|
|
use crate::wasi::*;
|
|
use std::{convert::TryInto, io, mem, slice};
|
|
use wig::witx_host_types;
|
|
|
|
witx_host_types!("snapshot" "wasi_snapshot_preview1");
|
|
|
|
pub(crate) unsafe fn ciovec_to_host(ciovec: &__wasi_ciovec_t) -> io::IoSlice {
|
|
let slice = slice::from_raw_parts(ciovec.buf as *const u8, ciovec.buf_len);
|
|
io::IoSlice::new(slice)
|
|
}
|
|
|
|
pub(crate) unsafe fn iovec_to_host_mut(iovec: &mut __wasi_iovec_t) -> io::IoSliceMut {
|
|
let slice = slice::from_raw_parts_mut(iovec.buf as *mut u8, iovec.buf_len);
|
|
io::IoSliceMut::new(slice)
|
|
}
|
|
|
|
#[allow(dead_code)] // trouble with sockets
|
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
|
#[repr(u8)]
|
|
pub enum FileType {
|
|
Unknown = __WASI_FILETYPE_UNKNOWN,
|
|
BlockDevice = __WASI_FILETYPE_BLOCK_DEVICE,
|
|
CharacterDevice = __WASI_FILETYPE_CHARACTER_DEVICE,
|
|
Directory = __WASI_FILETYPE_DIRECTORY,
|
|
RegularFile = __WASI_FILETYPE_REGULAR_FILE,
|
|
SocketDgram = __WASI_FILETYPE_SOCKET_DGRAM,
|
|
SocketStream = __WASI_FILETYPE_SOCKET_STREAM,
|
|
Symlink = __WASI_FILETYPE_SYMBOLIC_LINK,
|
|
}
|
|
|
|
impl FileType {
|
|
pub(crate) fn to_wasi(&self) -> __wasi_filetype_t {
|
|
*self as __wasi_filetype_t
|
|
}
|
|
|
|
pub(crate) fn from_wasi(wasi_filetype: u8) -> Option<Self> {
|
|
use FileType::*;
|
|
match wasi_filetype {
|
|
__WASI_FILETYPE_UNKNOWN => Some(Unknown),
|
|
__WASI_FILETYPE_BLOCK_DEVICE => Some(BlockDevice),
|
|
__WASI_FILETYPE_CHARACTER_DEVICE => Some(CharacterDevice),
|
|
__WASI_FILETYPE_DIRECTORY => Some(Directory),
|
|
__WASI_FILETYPE_REGULAR_FILE => Some(RegularFile),
|
|
__WASI_FILETYPE_SOCKET_DGRAM => Some(SocketDgram),
|
|
__WASI_FILETYPE_SOCKET_STREAM => Some(SocketStream),
|
|
__WASI_FILETYPE_SYMBOLIC_LINK => Some(Symlink),
|
|
_ => None,
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Clone)]
|
|
pub struct Dirent {
|
|
pub name: String,
|
|
pub ftype: FileType,
|
|
pub ino: u64,
|
|
pub cookie: __wasi_dircookie_t,
|
|
}
|
|
|
|
impl Dirent {
|
|
/// Serialize the directory entry to the format define by `__wasi_fd_readdir`,
|
|
/// so that the serialized entries can be concatenated by the implementation.
|
|
pub fn to_wasi_raw(&self) -> WasiResult<Vec<u8>> {
|
|
let name = self.name.as_bytes();
|
|
let namlen = name.len();
|
|
let dirent_size = mem::size_of::<__wasi_dirent_t>();
|
|
let offset = dirent_size
|
|
.checked_add(namlen)
|
|
.ok_or(WasiError::EOVERFLOW)?;
|
|
|
|
let mut raw = Vec::<u8>::with_capacity(offset);
|
|
raw.resize(offset, 0);
|
|
|
|
let sys_dirent = raw.as_mut_ptr() as *mut __wasi_dirent_t;
|
|
unsafe {
|
|
sys_dirent.write_unaligned(__wasi_dirent_t {
|
|
d_namlen: namlen.try_into()?,
|
|
d_ino: self.ino,
|
|
d_next: self.cookie,
|
|
d_type: self.ftype.to_wasi(),
|
|
});
|
|
}
|
|
|
|
let sys_name = unsafe { sys_dirent.offset(1) as *mut u8 };
|
|
let sys_name = unsafe { slice::from_raw_parts_mut(sys_name, namlen) };
|
|
sys_name.copy_from_slice(&name);
|
|
|
|
Ok(raw)
|
|
}
|
|
}
|