Browse Source

[wasi-common] add custom FdPool container for managing fd allocs/deallocs (#1329)

* Rename FdEntry to Entry

* Add custom FdSet container for managing fd allocs/deallocs

This commit adds a custom `FdSet` container which is intended
for use in `wasi-common` to track WASI fd allocs/deallocs. The
main aim for this container is to abstract away the current
approach of spawning new handles

```rust
fd = fd.checked_add(1).ok_or(...)?;
```

and to make it possible to reuse unused/reclaimed handles
which currently is not done.

The struct offers 3 methods to manage its functionality:
* `FdSet::new` initialises the internal data structures,
  and most notably, it preallocates an `FdSet::BATCH_SIZE`
  worth of handles in such a way that we always start popping
  from the "smallest" handle (think of it as of reversed stack,
  I guess; it's not a binary heap since we don't really care
  whether internally the handles are sorted in some way, just that
  the "largets" handle is at the bottom. Why will become clear
  when describing `allocate` method.)
* `FdSet::allocate` pops the next available handle if one is available.
  The tricky bit here is that, if we run out of handles, we preallocate
  the next `FdSet::BATCH_SIZE` worth of handles starting from the
  latest popped handle (i.e., the "largest" handle). This
  works only because we make sure to only ever pop and push already
  existing handles from the back, and push _new_ handles (from the
  preallocation step) from the front. When we ultimately run out
  of _all_ available handles, we then return `None` for the client
  to handle in some way (e.g., throwing an error such as `WasiError::EMFILE`
  or whatnot).
* `FdSet::deallocate` returns the already allocated handle back to
  the pool for further reuse.

When figuring out the internals, I've tried to optimise for both
alloc and dealloc performance, and I believe we've got an amortised
`O(1)~*` performance for both (if my maths is right, and it may very
well not be, so please verify!).

In order to keep `FdSet` fairly generic, I've made sure not to hard-code
it for the current type system generated by `wig` (i.e., `wasi::__wasi_fd_t`
representing WASI handle), but rather, any type which wants to be managed
by `FdSet` needs to conform to `Fd` trait. This trait is quite simple as
it only requires a couple of rudimentary traits (although `std:#️⃣:Hash`
is quite a powerful assumption here!), and a custom method

```rust
Fd::next(&self) -> Option<Self>;
```

which is there to encapsulate creating another handle from the given one.
In the current state of the code, that'd be simply `u32::checked_add(1)`.
When `wiggle` makes it way into the `wasi-common`, I'd imagine it being
similar to

```rust
fn next(&self) -> Option<Self> {
    self.0.checked_add(1).map(Self::from)
}
```

Anyhow, I'd be happy to learn your thoughts about this design!

* Fix compilation on other targets

* Rename FdSet to FdPool

* Fix FdPool unit tests

* Skip preallocation step in FdPool

* Replace 'replace' calls with direct assignment

* Reuse FdPool from snapshot1 in snapshot0

* Refactor FdPool::allocate

* Remove entry before deallocating the fd

* Refactor the design to accommodate `u32` as underlying type

This commit refactors the design by ensuring that the underlying
type in `FdPool` which we use to track and represent raw file
descriptors is `u32`. As a result, the structure of `FdPool` is
simplified massively as we no longer need to track the claimed
descriptors; in a way, we trust the caller to return the handle
after it's done with it. In case the caller decides to be clever
and return a handle which was not yet legally allocated, we panic.
This should never be a problem in `wasi-common` unless we hit a
bug.

To make all of this work, `Fd` trait is modified to require two
methods: `as_raw(&self) -> u32` and `from_raw(raw_fd: u32) -> Self`
both of which are used to convert to and from the `FdPool`'s underlying
type `u32`.
pull/1349/head
Jakub Konka 5 years ago
committed by GitHub
parent
commit
7228a248c1
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 175
      crates/wasi-common/src/ctx.rs
  2. 10
      crates/wasi-common/src/entry.rs
  3. 133
      crates/wasi-common/src/fdpool.rs
  4. 84
      crates/wasi-common/src/hostcalls_impl/fs.rs
  5. 6
      crates/wasi-common/src/hostcalls_impl/fs_helpers.rs
  6. 6
      crates/wasi-common/src/hostcalls_impl/misc.rs
  7. 3
      crates/wasi-common/src/lib.rs
  8. 156
      crates/wasi-common/src/old/snapshot_0/ctx.rs
  9. 6
      crates/wasi-common/src/old/snapshot_0/entry.rs
  10. 92
      crates/wasi-common/src/old/snapshot_0/hostcalls_impl/fs.rs
  11. 4
      crates/wasi-common/src/old/snapshot_0/hostcalls_impl/fs_helpers.rs
  12. 6
      crates/wasi-common/src/old/snapshot_0/hostcalls_impl/misc.rs
  13. 2
      crates/wasi-common/src/old/snapshot_0/mod.rs
  14. 2
      crates/wasi-common/src/old/snapshot_0/sys/unix/bsd/hostcalls_impl.rs
  15. 2
      crates/wasi-common/src/old/snapshot_0/sys/unix/entry_impl.rs
  16. 2
      crates/wasi-common/src/old/snapshot_0/sys/unix/hostcalls_impl/fs.rs
  17. 2
      crates/wasi-common/src/old/snapshot_0/sys/unix/linux/hostcalls_impl.rs
  18. 2
      crates/wasi-common/src/old/snapshot_0/sys/unix/mod.rs
  19. 2
      crates/wasi-common/src/old/snapshot_0/sys/windows/entry_impl.rs
  20. 4
      crates/wasi-common/src/old/snapshot_0/sys/windows/hostcalls_impl/fs.rs
  21. 2
      crates/wasi-common/src/old/snapshot_0/sys/windows/mod.rs
  22. 2
      crates/wasi-common/src/sys/unix/bsd/hostcalls_impl.rs
  23. 2
      crates/wasi-common/src/sys/unix/entry_impl.rs
  24. 4
      crates/wasi-common/src/sys/unix/hostcalls_impl/fs.rs
  25. 2
      crates/wasi-common/src/sys/unix/hostcalls_impl/misc.rs
  26. 4
      crates/wasi-common/src/sys/unix/linux/hostcalls_impl.rs
  27. 2
      crates/wasi-common/src/sys/unix/mod.rs
  28. 2
      crates/wasi-common/src/sys/windows/entry_impl.rs
  29. 4
      crates/wasi-common/src/sys/windows/hostcalls_impl/fs.rs
  30. 2
      crates/wasi-common/src/sys/windows/hostcalls_impl/fs_helpers.rs
  31. 2
      crates/wasi-common/src/sys/windows/hostcalls_impl/misc.rs
  32. 2
      crates/wasi-common/src/sys/windows/mod.rs
  33. 9
      crates/wasi-common/src/wasi.rs

175
crates/wasi-common/src/ctx.rs

@ -1,5 +1,6 @@
use crate::fdentry::{Descriptor, FdEntry};
use crate::sys::fdentry_impl::OsHandle;
use crate::entry::{Descriptor, Entry};
use crate::fdpool::FdPool;
use crate::sys::entry_impl::OsHandle;
use crate::virtfs::{VirtualDir, VirtualDirEntry};
use crate::wasi::{self, WasiError, WasiResult};
use std::borrow::Borrow;
@ -37,18 +38,18 @@ pub enum WasiCtxBuilderError {
type WasiCtxBuilderResult<T> = std::result::Result<T, WasiCtxBuilderError>;
enum PendingFdEntry {
Thunk(fn() -> io::Result<FdEntry>),
enum PendingEntry {
Thunk(fn() -> io::Result<Entry>),
File(File),
}
impl std::fmt::Debug for PendingFdEntry {
impl std::fmt::Debug for PendingEntry {
fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Thunk(f) => write!(
fmt,
"PendingFdEntry::Thunk({:p})",
f as *const fn() -> io::Result<FdEntry>
f as *const fn() -> io::Result<Entry>
),
Self::File(f) => write!(fmt, "PendingFdEntry::File({:?})", f),
}
@ -102,7 +103,9 @@ impl PendingCString {
/// A builder allowing customizable construction of `WasiCtx` instances.
pub struct WasiCtxBuilder {
fds: Option<HashMap<wasi::__wasi_fd_t, PendingFdEntry>>,
stdin: Option<PendingEntry>,
stdout: Option<PendingEntry>,
stderr: Option<PendingEntry>,
preopens: Option<Vec<(PathBuf, Descriptor)>>,
args: Option<Vec<PendingCString>>,
env: Option<HashMap<PendingCString, PendingCString>>,
@ -111,14 +114,14 @@ pub struct WasiCtxBuilder {
impl WasiCtxBuilder {
/// Builder for a new `WasiCtx`.
pub fn new() -> Self {
let mut fds = HashMap::new();
fds.insert(0, PendingFdEntry::Thunk(FdEntry::null));
fds.insert(1, PendingFdEntry::Thunk(FdEntry::null));
fds.insert(2, PendingFdEntry::Thunk(FdEntry::null));
let stdin = Some(PendingEntry::Thunk(Entry::null));
let stdout = Some(PendingEntry::Thunk(Entry::null));
let stderr = Some(PendingEntry::Thunk(Entry::null));
Self {
fds: Some(fds),
stdin,
stdout,
stderr,
preopens: Some(Vec::new()),
args: Some(Vec::new()),
env: Some(HashMap::new()),
@ -160,37 +163,27 @@ impl WasiCtxBuilder {
/// Inherit stdin from the host process.
pub fn inherit_stdin(&mut self) -> &mut Self {
self.fds
.as_mut()
.unwrap()
.insert(0, PendingFdEntry::Thunk(FdEntry::duplicate_stdin));
self.stdin = Some(PendingEntry::Thunk(Entry::duplicate_stdin));
self
}
/// Inherit stdout from the host process.
pub fn inherit_stdout(&mut self) -> &mut Self {
self.fds
.as_mut()
.unwrap()
.insert(1, PendingFdEntry::Thunk(FdEntry::duplicate_stdout));
self.stdout = Some(PendingEntry::Thunk(Entry::duplicate_stdout));
self
}
/// Inherit stdout from the host process.
pub fn inherit_stderr(&mut self) -> &mut Self {
self.fds
.as_mut()
.unwrap()
.insert(2, PendingFdEntry::Thunk(FdEntry::duplicate_stderr));
self.stderr = Some(PendingEntry::Thunk(Entry::duplicate_stderr));
self
}
/// Inherit the stdin, stdout, and stderr streams from the host process.
pub fn inherit_stdio(&mut self) -> &mut Self {
let fds = self.fds.as_mut().unwrap();
fds.insert(0, PendingFdEntry::Thunk(FdEntry::duplicate_stdin));
fds.insert(1, PendingFdEntry::Thunk(FdEntry::duplicate_stdout));
fds.insert(2, PendingFdEntry::Thunk(FdEntry::duplicate_stderr));
self.stdin = Some(PendingEntry::Thunk(Entry::duplicate_stdin));
self.stdout = Some(PendingEntry::Thunk(Entry::duplicate_stdout));
self.stderr = Some(PendingEntry::Thunk(Entry::duplicate_stderr));
self
}
@ -234,28 +227,19 @@ impl WasiCtxBuilder {
/// Provide a File to use as stdin
pub fn stdin(&mut self, file: File) -> &mut Self {
self.fds
.as_mut()
.unwrap()
.insert(0, PendingFdEntry::File(file));
self.stdin = Some(PendingEntry::File(file));
self
}
/// Provide a File to use as stdout
pub fn stdout(&mut self, file: File) -> &mut Self {
self.fds
.as_mut()
.unwrap()
.insert(1, PendingFdEntry::File(file));
self.stdout = Some(PendingEntry::File(file));
self
}
/// Provide a File to use as stderr
pub fn stderr(&mut self, file: File) -> &mut Self {
self.fds
.as_mut()
.unwrap()
.insert(2, PendingFdEntry::File(file));
self.stderr = Some(PendingEntry::File(file));
self
}
@ -338,28 +322,33 @@ impl WasiCtxBuilder {
})
.collect::<WasiCtxBuilderResult<Vec<CString>>>()?;
let mut fds: HashMap<wasi::__wasi_fd_t, FdEntry> = HashMap::new();
// Populate the non-preopen fds.
for (fd, pending) in self.fds.take().unwrap() {
let mut fd_pool = FdPool::new();
let mut entries: HashMap<wasi::__wasi_fd_t, Entry> = HashMap::new();
// Populate the non-preopen entries.
for pending in vec![
self.stdin.take().unwrap(),
self.stdout.take().unwrap(),
self.stderr.take().unwrap(),
] {
let fd = fd_pool
.allocate()
.ok_or(WasiCtxBuilderError::TooManyFilesOpen)?;
log::debug!("WasiCtx inserting ({:?}, {:?})", fd, pending);
match pending {
PendingFdEntry::Thunk(f) => {
fds.insert(fd, f()?);
PendingEntry::Thunk(f) => {
entries.insert(fd, f()?);
}
PendingFdEntry::File(f) => {
fds.insert(fd, FdEntry::from(Descriptor::OsHandle(OsHandle::from(f)))?);
PendingEntry::File(f) => {
entries.insert(fd, Entry::from(Descriptor::OsHandle(OsHandle::from(f)))?);
}
}
}
// Then add the preopen fds. Startup code in the guest starts looking at fd 3 for preopens,
// so we start from there. This variable is initially 2, though, because the loop
// immediately does the increment and check for overflow.
let mut preopen_fd: wasi::__wasi_fd_t = 2;
// Then add the preopen entries.
for (guest_path, dir) in self.preopens.take().unwrap() {
// We do the increment at the beginning of the loop body, so that we don't overflow
// unnecessarily if we have exactly the maximum number of file descriptors.
preopen_fd = preopen_fd
.checked_add(1)
let preopen_fd = fd_pool
.allocate()
.ok_or(WasiCtxBuilderError::TooManyFilesOpen)?;
match &dir {
@ -378,27 +367,26 @@ impl WasiCtxBuilder {
}
}
// We don't currently allow setting file descriptors other than 0-2, but this will avoid
// collisions if we restore that functionality in the future.
while fds.contains_key(&preopen_fd) {
preopen_fd = preopen_fd
.checked_add(1)
.ok_or(WasiCtxBuilderError::TooManyFilesOpen)?;
}
let mut fe = FdEntry::from(dir)?;
let mut fe = Entry::from(dir)?;
fe.preopen_path = Some(guest_path);
log::debug!("WasiCtx inserting ({:?}, {:?})", preopen_fd, fe);
fds.insert(preopen_fd, fe);
log::debug!("WasiCtx fds = {:?}", fds);
entries.insert(preopen_fd, fe);
log::debug!("WasiCtx entries = {:?}", entries);
}
Ok(WasiCtx { args, env, fds })
Ok(WasiCtx {
args,
env,
entries,
fd_pool,
})
}
}
#[derive(Debug)]
pub struct WasiCtx {
fds: HashMap<wasi::__wasi_fd_t, FdEntry>,
fd_pool: FdPool,
entries: HashMap<wasi::__wasi_fd_t, Entry>,
pub(crate) args: Vec<CString>,
pub(crate) env: Vec<CString>,
}
@ -420,53 +408,42 @@ impl WasiCtx {
}
/// Check if `WasiCtx` contains the specified raw WASI `fd`.
pub(crate) unsafe fn contains_fd_entry(&self, fd: wasi::__wasi_fd_t) -> bool {
self.fds.contains_key(&fd)
pub(crate) unsafe fn contains_entry(&self, fd: wasi::__wasi_fd_t) -> bool {
self.entries.contains_key(&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) -> WasiResult<&FdEntry> {
self.fds.get(&fd).ok_or(WasiError::EBADF)
/// Get an immutable `Entry` corresponding to the specified raw WASI `fd`.
pub(crate) unsafe fn get_entry(&self, fd: wasi::__wasi_fd_t) -> WasiResult<&Entry> {
self.entries.get(&fd).ok_or(WasiError::EBADF)
}
/// Get a mutable `FdEntry` corresponding to the specified raw WASI `fd`.
pub(crate) unsafe fn get_fd_entry_mut(
&mut self,
fd: wasi::__wasi_fd_t,
) -> WasiResult<&mut FdEntry> {
self.fds.get_mut(&fd).ok_or(WasiError::EBADF)
/// Get a mutable `Entry` corresponding to the specified raw WASI `fd`.
pub(crate) unsafe fn get_entry_mut(&mut self, fd: wasi::__wasi_fd_t) -> WasiResult<&mut Entry> {
self.entries.get_mut(&fd).ok_or(WasiError::EBADF)
}
/// Insert the specified `FdEntry` into the `WasiCtx` object.
/// Insert the specified `Entry` into the `WasiCtx` object.
///
/// The `FdEntry` will automatically get another free raw WASI `fd` assigned. Note that
/// the two subsequent free raw WASI `fd`s do not have to be stored contiguously.
pub(crate) fn insert_fd_entry(&mut self, fe: FdEntry) -> WasiResult<wasi::__wasi_fd_t> {
// Never insert where stdio handles are expected to be.
let mut fd = 3;
while self.fds.contains_key(&fd) {
if let Some(next_fd) = fd.checked_add(1) {
fd = next_fd;
} else {
return Err(WasiError::EMFILE);
}
}
self.fds.insert(fd, fe);
pub(crate) fn insert_entry(&mut self, fe: Entry) -> WasiResult<wasi::__wasi_fd_t> {
let fd = self.fd_pool.allocate().ok_or(WasiError::EMFILE)?;
self.entries.insert(fd, fe);
Ok(fd)
}
/// Insert the specified `FdEntry` with the specified raw WASI `fd` key into the `WasiCtx`
/// Insert the specified `Entry` with the specified raw WASI `fd` key into the `WasiCtx`
/// object.
pub(crate) fn insert_fd_entry_at(
&mut self,
fd: wasi::__wasi_fd_t,
fe: FdEntry,
) -> Option<FdEntry> {
self.fds.insert(fd, fe)
pub(crate) fn insert_entry_at(&mut self, fd: wasi::__wasi_fd_t, fe: Entry) -> Option<Entry> {
self.entries.insert(fd, fe)
}
/// 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) -> WasiResult<FdEntry> {
self.fds.remove(&fd).ok_or(WasiError::EBADF)
/// Remove `Entry` corresponding to the specified raw WASI `fd` from the `WasiCtx` object.
pub(crate) fn remove_entry(&mut self, fd: wasi::__wasi_fd_t) -> WasiResult<Entry> {
// Remove the `fd` from valid entries.
let entry = self.entries.remove(&fd).ok_or(WasiError::EBADF)?;
// Next, deallocate the `fd`.
self.fd_pool.deallocate(fd);
Ok(entry)
}
}

10
crates/wasi-common/src/fdentry.rs → crates/wasi-common/src/entry.rs

@ -1,7 +1,5 @@
use crate::sys::dev_null;
use crate::sys::fdentry_impl::{
descriptor_as_oshandle, determine_type_and_access_rights, OsHandle,
};
use crate::sys::entry_impl::{descriptor_as_oshandle, determine_type_and_access_rights, OsHandle};
use crate::virtfs::VirtualFile;
use crate::wasi::{self, WasiError, WasiResult};
use std::marker::PhantomData;
@ -87,10 +85,10 @@ impl Descriptor {
///
/// Here, the `descriptor` field stores the host `Descriptor` object (such as a file descriptor, or
/// stdin handle), and accessing it can only be done via the provided `FdEntry::as_descriptor` and
/// `FdEntry::as_descriptor_mut` methods which require a set of base and inheriting rights to be
/// `Entry::as_descriptor_mut` methods which require a set of base and inheriting rights to be
/// specified, verifying whether the stored `Descriptor` object is valid for the rights specified.
#[derive(Debug)]
pub(crate) struct FdEntry {
pub(crate) struct Entry {
pub(crate) file_type: wasi::__wasi_filetype_t,
descriptor: Descriptor,
pub(crate) rights_base: wasi::__wasi_rights_t,
@ -99,7 +97,7 @@ pub(crate) struct FdEntry {
// TODO: directories
}
impl FdEntry {
impl Entry {
pub(crate) fn from(file: Descriptor) -> io::Result<Self> {
match file {
Descriptor::OsHandle(handle) => unsafe { determine_type_and_access_rights(&handle) }

133
crates/wasi-common/src/fdpool.rs

@ -0,0 +1,133 @@
//! Contains mechanism for managing the WASI file descriptor
//! pool. It's intended to be mainly used within the `WasiCtx`
//! object(s).
/// Any type wishing to be treated as a valid WASI file descriptor
/// should implement this trait.
///
/// This trait is required as internally we use `u32` to represent
/// and manage raw file descriptors.
pub(crate) trait Fd {
/// Convert to `u32`.
fn as_raw(&self) -> u32;
/// Convert from `u32`.
fn from_raw(raw_fd: u32) -> Self;
}
/// This container tracks and manages all file descriptors that
/// were already allocated.
/// Internally, we use `u32` to represent the file descriptors;
/// however, the caller may supply any type `T` such that it
/// implements the `Fd` trait when requesting a new descriptor
/// via the `allocate` method, or when returning one back via
/// the `deallocate` method.
#[derive(Debug)]
pub(crate) struct FdPool {
next_alloc: Option<u32>,
available: Vec<u32>,
}
impl FdPool {
pub fn new() -> Self {
Self {
next_alloc: Some(0),
available: Vec::new(),
}
}
/// Obtain another valid WASI file descriptor.
///
/// If we've handed out the maximum possible amount of file
/// descriptors (which would be equal to `2^32 + 1` accounting for `0`),
/// then this method will return `None` to signal that case.
/// Otherwise, a new file descriptor is return as `Some(fd)`.
pub fn allocate<T: Fd>(&mut self) -> Option<T> {
if let Some(fd) = self.available.pop() {
// Since we've had free, unclaimed handle in the pool,
// simply claim it and return.
return Some(T::from_raw(fd));
}
// There are no free handles available in the pool, so try
// allocating an additional one into the pool. If we've
// reached our max number of handles, we will fail with None
// instead.
let fd = self.next_alloc.take()?;
// It's OK to not unpack the result of `fd.checked_add()` here which
// can fail since we check for `None` in the snippet above.
self.next_alloc = fd.checked_add(1);
Some(T::from_raw(fd))
}
/// Return a file descriptor back to the pool.
///
/// If the caller tries to return a file descriptor that was
/// not yet allocated (via spoofing, etc.), this method
/// will panic.
pub fn deallocate<T: Fd>(&mut self, fd: T) {
let fd = fd.as_raw();
if let Some(next_alloc) = self.next_alloc {
assert!(fd < next_alloc);
}
debug_assert!(!self.available.contains(&fd));
self.available.push(fd);
}
}
#[cfg(test)]
mod test {
use super::FdPool;
use std::ops::Deref;
#[derive(Debug)]
struct Fd(u32);
impl super::Fd for Fd {
fn as_raw(&self) -> u32 {
self.0
}
fn from_raw(raw_fd: u32) -> Self {
Self(raw_fd)
}
}
impl Deref for Fd {
type Target = u32;
fn deref(&self) -> &Self::Target {
&self.0
}
}
#[test]
fn basics() {
let mut fd_pool = FdPool::new();
let mut fd: Fd = fd_pool.allocate().expect("success allocating 0");
assert_eq!(*fd, 0);
fd = fd_pool.allocate().expect("success allocating 1");
assert_eq!(*fd, 1);
fd = fd_pool.allocate().expect("success allocating 2");
assert_eq!(*fd, 2);
fd_pool.deallocate(1u32);
fd_pool.deallocate(0u32);
fd = fd_pool.allocate().expect("success reallocating 0");
assert_eq!(*fd, 0);
fd = fd_pool.allocate().expect("success reallocating 1");
assert_eq!(*fd, 1);
fd = fd_pool.allocate().expect("success allocating 3");
assert_eq!(*fd, 3);
}
#[test]
#[should_panic]
fn deallocate_nonexistent() {
let mut fd_pool = FdPool::new();
fd_pool.deallocate(0u32);
}
#[test]
fn max_allocation() {
let mut fd_pool = FdPool::new();
// Spoof reaching the limit of allocs.
fd_pool.next_alloc = None;
assert!(fd_pool.allocate::<Fd>().is_none());
}
}

84
crates/wasi-common/src/hostcalls_impl/fs.rs

@ -1,7 +1,7 @@
#![allow(non_camel_case_types)]
use super::fs_helpers::path_get;
use crate::ctx::WasiCtx;
use crate::fdentry::{Descriptor, FdEntry};
use crate::entry::{Descriptor, Entry};
use crate::helpers::*;
use crate::host::Dirent;
use crate::memory::*;
@ -24,14 +24,14 @@ pub(crate) unsafe fn fd_close(
) -> WasiResult<()> {
trace!("fd_close(fd={:?})", fd);
if let Ok(fe) = wasi_ctx.get_fd_entry(fd) {
if let Ok(fe) = wasi_ctx.get_entry(fd) {
// can't close preopened files
if fe.preopen_path.is_some() {
return Err(WasiError::ENOTSUP);
}
}
wasi_ctx.remove_fd_entry(fd)?;
wasi_ctx.remove_entry(fd)?;
Ok(())
}
@ -43,7 +43,7 @@ pub(crate) unsafe fn fd_datasync(
trace!("fd_datasync(fd={:?})", fd);
let file = wasi_ctx
.get_fd_entry(fd)?
.get_entry(fd)?
.as_descriptor(wasi::__WASI_RIGHTS_FD_DATASYNC, 0)?;
match file {
@ -72,7 +72,7 @@ pub(crate) unsafe fn fd_pread(
);
let file = wasi_ctx
.get_fd_entry(fd)?
.get_entry(fd)?
.as_descriptor(wasi::__WASI_RIGHTS_FD_READ | wasi::__WASI_RIGHTS_FD_SEEK, 0)?
.as_file()?;
@ -140,7 +140,7 @@ pub(crate) unsafe fn fd_pwrite(
);
let file = wasi_ctx
.get_fd_entry(fd)?
.get_entry(fd)?
.as_descriptor(
wasi::__WASI_RIGHTS_FD_WRITE | wasi::__WASI_RIGHTS_FD_SEEK,
0,
@ -207,7 +207,7 @@ pub(crate) unsafe fn fd_read(
.collect();
let maybe_host_nread = match wasi_ctx
.get_fd_entry_mut(fd)?
.get_entry_mut(fd)?
.as_descriptor_mut(wasi::__WASI_RIGHTS_FD_READ, 0)?
{
Descriptor::OsHandle(file) => file.read_vectored(&mut iovs).map_err(Into::into),
@ -231,25 +231,25 @@ pub(crate) unsafe fn fd_renumber(
) -> WasiResult<()> {
trace!("fd_renumber(from={:?}, to={:?})", from, to);
if !wasi_ctx.contains_fd_entry(from) {
if !wasi_ctx.contains_entry(from) {
return Err(WasiError::EBADF);
}
// Don't allow renumbering over a pre-opened resource.
// TODO: Eventually, we do want to permit this, once libpreopen in
// 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_entry(from)?;
if from_fe.preopen_path.is_some() {
return Err(WasiError::ENOTSUP);
}
if let Ok(to_fe) = wasi_ctx.get_fd_entry(to) {
if let Ok(to_fe) = wasi_ctx.get_entry(to) {
if to_fe.preopen_path.is_some() {
return Err(WasiError::ENOTSUP);
}
}
let fe = wasi_ctx.remove_fd_entry(from)?;
wasi_ctx.insert_fd_entry_at(to, fe);
let fe = wasi_ctx.remove_entry(from)?;
wasi_ctx.insert_entry_at(to, fe);
Ok(())
}
@ -276,7 +276,7 @@ pub(crate) unsafe fn fd_seek(
wasi::__WASI_RIGHTS_FD_SEEK | wasi::__WASI_RIGHTS_FD_TELL
};
let file = wasi_ctx
.get_fd_entry_mut(fd)?
.get_entry_mut(fd)?
.as_descriptor_mut(rights, 0)?
.as_file_mut()?;
@ -310,7 +310,7 @@ pub(crate) unsafe fn fd_tell(
trace!("fd_tell(fd={:?}, newoffset={:#x?})", fd, newoffset);
let file = wasi_ctx
.get_fd_entry_mut(fd)?
.get_entry_mut(fd)?
.as_descriptor_mut(wasi::__WASI_RIGHTS_FD_TELL, 0)?
.as_file_mut()?;
@ -338,7 +338,7 @@ pub(crate) unsafe fn fd_fdstat_get(
trace!("fd_fdstat_get(fd={:?}, fdstat_ptr={:#x?})", fd, fdstat_ptr);
let mut fdstat = dec_fdstat_byref(memory, fdstat_ptr)?;
let wasi_file = wasi_ctx.get_fd_entry(fd)?.as_descriptor(0, 0)?;
let wasi_file = wasi_ctx.get_entry(fd)?.as_descriptor(0, 0)?;
let fs_flags = match wasi_file {
Descriptor::OsHandle(wasi_fd) => hostcalls_impl::fd_fdstat_get(&wasi_fd)?,
@ -346,7 +346,7 @@ pub(crate) unsafe fn fd_fdstat_get(
other => hostcalls_impl::fd_fdstat_get(&other.as_os_handle())?,
};
let fe = wasi_ctx.get_fd_entry(fd)?;
let fe = wasi_ctx.get_entry(fd)?;
fdstat.fs_filetype = fe.file_type;
fdstat.fs_rights_base = fe.rights_base;
fdstat.fs_rights_inheriting = fe.rights_inheriting;
@ -366,7 +366,7 @@ pub(crate) unsafe fn fd_fdstat_set_flags(
trace!("fd_fdstat_set_flags(fd={:?}, fdflags={:#x?})", fd, fdflags);
let descriptor = wasi_ctx
.get_fd_entry_mut(fd)?
.get_entry_mut(fd)?
.as_descriptor_mut(wasi::__WASI_RIGHTS_FD_FDSTAT_SET_FLAGS, 0)?;
match descriptor {
@ -409,7 +409,7 @@ pub(crate) unsafe fn fd_fdstat_set_rights(
fs_rights_inheriting
);
let fe = wasi_ctx.get_fd_entry_mut(fd)?;
let fe = wasi_ctx.get_entry_mut(fd)?;
if fe.rights_base & fs_rights_base != fs_rights_base
|| fe.rights_inheriting & fs_rights_inheriting != fs_rights_inheriting
{
@ -429,7 +429,7 @@ pub(crate) unsafe fn fd_sync(
trace!("fd_sync(fd={:?})", fd);
let file = wasi_ctx
.get_fd_entry(fd)?
.get_entry(fd)?
.as_descriptor(wasi::__WASI_RIGHTS_FD_SYNC, 0)?
.as_file()?;
match file {
@ -463,7 +463,7 @@ pub(crate) unsafe fn fd_write(
let iovs: Vec<io::IoSlice> = iovs.iter().map(|vec| host::ciovec_to_host(vec)).collect();
// perform unbuffered writes
let entry = wasi_ctx.get_fd_entry_mut(fd)?;
let entry = wasi_ctx.get_entry_mut(fd)?;
let isatty = entry.isatty();
let desc = entry.as_descriptor_mut(wasi::__WASI_RIGHTS_FD_WRITE, 0)?;
let host_nwritten = match desc {
@ -523,7 +523,7 @@ pub(crate) unsafe fn fd_advise(
);
let file = wasi_ctx
.get_fd_entry_mut(fd)?
.get_entry_mut(fd)?
.as_descriptor_mut(wasi::__WASI_RIGHTS_FD_ADVISE, 0)?
.as_file_mut()?;
@ -548,7 +548,7 @@ pub(crate) unsafe fn fd_allocate(
trace!("fd_allocate(fd={:?}, offset={}, len={})", fd, offset, len);
let file = wasi_ctx
.get_fd_entry(fd)?
.get_entry(fd)?
.as_descriptor(wasi::__WASI_RIGHTS_FD_ALLOCATE, 0)?
.as_file()?;
@ -597,7 +597,7 @@ pub(crate) unsafe fn path_create_directory(
trace!(" | (path_ptr,path_len)='{}'", path);
let rights = wasi::__WASI_RIGHTS_PATH_OPEN | wasi::__WASI_RIGHTS_PATH_CREATE_DIRECTORY;
let fe = wasi_ctx.get_fd_entry(dirfd)?;
let fe = wasi_ctx.get_entry(dirfd)?;
let resolved = path_get(fe, rights, 0, 0, path, false)?;
resolved.path_create_directory()
@ -631,8 +631,8 @@ pub(crate) unsafe fn path_link(
trace!(" | (old_path_ptr,old_path_len)='{}'", old_path);
trace!(" | (new_path_ptr,new_path_len)='{}'", new_path);
let old_fe = wasi_ctx.get_fd_entry(old_dirfd)?;
let new_fe = wasi_ctx.get_fd_entry(new_dirfd)?;
let old_fe = wasi_ctx.get_entry(old_dirfd)?;
let new_fe = wasi_ctx.get_entry(new_dirfd)?;
let resolved_old = path_get(
old_fe,
wasi::__WASI_RIGHTS_PATH_LINK_SOURCE,
@ -693,7 +693,7 @@ pub(crate) unsafe fn path_open(
needed_base,
needed_inheriting
);
let fe = wasi_ctx.get_fd_entry(dirfd)?;
let fe = wasi_ctx.get_entry(dirfd)?;
let resolved = path_get(
fe,
needed_base,
@ -719,12 +719,12 @@ pub(crate) unsafe fn path_open(
);
let fd = resolved.open_with(read, write, oflags, fs_flags)?;
let mut fe = FdEntry::from(fd)?;
let mut fe = Entry::from(fd)?;
// We need to manually deny the rights which are not explicitly requested
// because FdEntry::from will assign maximal consistent rights.
fe.rights_base &= fs_rights_base;
fe.rights_inheriting &= fs_rights_inheriting;
let guest_fd = wasi_ctx.insert_fd_entry(fe)?;
let guest_fd = wasi_ctx.insert_entry(fe)?;
trace!(" | *fd={:?}", guest_fd);
@ -757,7 +757,7 @@ pub(crate) unsafe fn path_readlink(
trace!(" | (path_ptr,path_len)='{}'", &path);
let fe = wasi_ctx.get_fd_entry(dirfd)?;
let fe = wasi_ctx.get_entry(dirfd)?;
let resolved = path_get(fe, wasi::__WASI_RIGHTS_PATH_READLINK, 0, 0, &path, false)?;
let mut buf = dec_slice_of_mut_u8(memory, buf_ptr, buf_len)?;
@ -801,8 +801,8 @@ pub(crate) unsafe fn path_rename(
trace!(" | (old_path_ptr,old_path_len)='{}'", old_path);
trace!(" | (new_path_ptr,new_path_len)='{}'", new_path);
let old_fe = wasi_ctx.get_fd_entry(old_dirfd)?;
let new_fe = wasi_ctx.get_fd_entry(new_dirfd)?;
let old_fe = wasi_ctx.get_entry(old_dirfd)?;
let new_fe = wasi_ctx.get_entry(new_dirfd)?;
let resolved_old = path_get(
old_fe,
wasi::__WASI_RIGHTS_PATH_RENAME_SOURCE,
@ -847,7 +847,7 @@ pub(crate) unsafe fn fd_filestat_get(
);
let fd = wasi_ctx
.get_fd_entry(fd)?
.get_entry(fd)?
.as_descriptor(wasi::__WASI_RIGHTS_FD_FILESTAT_GET, 0)?
.as_file()?;
let host_filestat = match fd {
@ -882,7 +882,7 @@ pub(crate) unsafe fn fd_filestat_set_times(
);
let fd = wasi_ctx
.get_fd_entry(fd)?
.get_entry(fd)?
.as_descriptor(wasi::__WASI_RIGHTS_FD_FILESTAT_SET_TIMES, 0)?
.as_file()?;
@ -942,7 +942,7 @@ pub(crate) unsafe fn fd_filestat_set_size(
trace!("fd_filestat_set_size(fd={:?}, st_size={})", fd, st_size);
let file = wasi_ctx
.get_fd_entry(fd)?
.get_entry(fd)?
.as_descriptor(wasi::__WASI_RIGHTS_FD_FILESTAT_SET_SIZE, 0)?
.as_file()?;
@ -983,7 +983,7 @@ pub(crate) unsafe fn path_filestat_get(
trace!(" | (path_ptr,path_len)='{}'", path);
let fe = wasi_ctx.get_fd_entry(dirfd)?;
let fe = wasi_ctx.get_entry(dirfd)?;
let resolved = path_get(
fe,
wasi::__WASI_RIGHTS_PATH_FILESTAT_GET,
@ -1029,7 +1029,7 @@ pub(crate) unsafe fn path_filestat_set_times(
trace!(" | (path_ptr,path_len)='{}'", path);
let fe = wasi_ctx.get_fd_entry(dirfd)?;
let fe = wasi_ctx.get_entry(dirfd)?;
let resolved = path_get(
fe,
wasi::__WASI_RIGHTS_PATH_FILESTAT_SET_TIMES,
@ -1073,7 +1073,7 @@ pub(crate) unsafe fn path_symlink(
trace!(" | (old_path_ptr,old_path_len)='{}'", old_path);
trace!(" | (new_path_ptr,new_path_len)='{}'", new_path);
let fe = wasi_ctx.get_fd_entry(dirfd)?;
let fe = wasi_ctx.get_entry(dirfd)?;
let resolved_new = path_get(fe, wasi::__WASI_RIGHTS_PATH_SYMLINK, 0, 0, new_path, true)?;
match resolved_new.dirfd() {
@ -1102,7 +1102,7 @@ pub(crate) unsafe fn path_unlink_file(
trace!(" | (path_ptr,path_len)='{}'", path);
let fe = wasi_ctx.get_fd_entry(dirfd)?;
let fe = wasi_ctx.get_entry(dirfd)?;
let resolved = path_get(fe, wasi::__WASI_RIGHTS_PATH_UNLINK_FILE, 0, 0, path, false)?;
match resolved.dirfd() {
@ -1129,7 +1129,7 @@ pub(crate) unsafe fn path_remove_directory(
trace!(" | (path_ptr,path_len)='{}'", path);
let fe = wasi_ctx.get_fd_entry(dirfd)?;
let fe = wasi_ctx.get_entry(dirfd)?;
let resolved = path_get(
fe,
wasi::__WASI_RIGHTS_PATH_REMOVE_DIRECTORY,
@ -1160,7 +1160,7 @@ pub(crate) unsafe fn fd_prestat_get(
);
// TODO: should we validate any rights here?
let fe = wasi_ctx.get_fd_entry(fd)?;
let fe = wasi_ctx.get_entry(fd)?;
let po_path = fe.preopen_path.as_ref().ok_or(WasiError::ENOTSUP)?;
if fe.file_type != wasi::__WASI_FILETYPE_DIRECTORY {
return Err(WasiError::ENOTDIR);
@ -1197,7 +1197,7 @@ pub(crate) unsafe fn fd_prestat_dir_name(
);
// TODO: should we validate any rights here?
let fe = wasi_ctx.get_fd_entry(fd)?;
let fe = wasi_ctx.get_entry(fd)?;
let po_path = fe.preopen_path.as_ref().ok_or(WasiError::ENOTSUP)?;
if fe.file_type != wasi::__WASI_FILETYPE_DIRECTORY {
return Err(WasiError::ENOTDIR);
@ -1235,7 +1235,7 @@ pub(crate) unsafe fn fd_readdir(
enc_usize_byref(memory, buf_used, 0)?;
let file = wasi_ctx
.get_fd_entry_mut(fd)?
.get_entry_mut(fd)?
.as_descriptor_mut(wasi::__WASI_RIGHTS_FD_READDIR, 0)?
.as_file_mut()?;
let host_buf = dec_slice_of_mut_u8(memory, buf, buf_len)?;

6
crates/wasi-common/src/hostcalls_impl/fs_helpers.rs

@ -1,9 +1,9 @@
#![allow(non_camel_case_types)]
use crate::sys::fdentry_impl::OsHandle;
use crate::sys::entry_impl::OsHandle;
use crate::sys::host_impl;
use crate::sys::hostcalls_impl::fs_helpers::*;
use crate::wasi::{self, WasiError, WasiResult};
use crate::{fdentry::Descriptor, fdentry::FdEntry};
use crate::{entry::Descriptor, entry::Entry};
use std::path::{Component, Path};
#[derive(Debug)]
@ -102,7 +102,7 @@ impl<'a, 'b> PathRef<'a, 'b> {
///
/// This is a workaround for not having Capsicum support in the OS.
pub(crate) fn path_get(
fe: &FdEntry,
fe: &Entry,
rights_base: wasi::__wasi_rights_t,
rights_inheriting: wasi::__wasi_rights_t,
dirflags: wasi::__wasi_lookupflags_t,

6
crates/wasi-common/src/hostcalls_impl/misc.rs

@ -1,6 +1,6 @@
#![allow(non_camel_case_types)]
use crate::ctx::WasiCtx;
use crate::fdentry::Descriptor;
use crate::entry::Descriptor;
use crate::memory::*;
use crate::sys::hostcalls_impl;
use crate::wasi::{self, WasiError, WasiResult};
@ -250,7 +250,7 @@ pub(crate) fn poll_oneoff(
let rights = wasi::__WASI_RIGHTS_FD_READ | wasi::__WASI_RIGHTS_POLL_FD_READWRITE;
match unsafe {
wasi_ctx
.get_fd_entry(wasi_fd)
.get_entry(wasi_fd)
.and_then(|fe| fe.as_descriptor(rights, 0))
} {
Ok(descriptor) => fd_events.push(FdEventData {
@ -278,7 +278,7 @@ pub(crate) fn poll_oneoff(
let rights = wasi::__WASI_RIGHTS_FD_WRITE | wasi::__WASI_RIGHTS_POLL_FD_READWRITE;
match unsafe {
wasi_ctx
.get_fd_entry(wasi_fd)
.get_entry(wasi_fd)
.and_then(|fe| fe.as_descriptor(rights, 0))
} {
Ok(descriptor) => fd_events.push(FdEventData {

3
crates/wasi-common/src/lib.rs

@ -22,7 +22,8 @@
)]
mod ctx;
mod fdentry;
mod entry;
mod fdpool;
pub mod fs;
mod helpers;
mod host;

156
crates/wasi-common/src/old/snapshot_0/ctx.rs

@ -1,4 +1,5 @@
use crate::old::snapshot_0::fdentry::FdEntry;
use crate::fdpool::FdPool;
use crate::old::snapshot_0::entry::Entry;
use crate::old::snapshot_0::wasi::{self, WasiError, WasiResult};
use std::borrow::Borrow;
use std::collections::HashMap;
@ -35,20 +36,20 @@ pub enum WasiCtxBuilderError {
type WasiCtxBuilderResult<T> = std::result::Result<T, WasiCtxBuilderError>;
enum PendingFdEntry {
Thunk(fn() -> io::Result<FdEntry>),
enum PendingEntry {
Thunk(fn() -> io::Result<Entry>),
File(File),
}
impl std::fmt::Debug for PendingFdEntry {
impl std::fmt::Debug for PendingEntry {
fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Thunk(f) => write!(
fmt,
"PendingFdEntry::Thunk({:p})",
f as *const fn() -> io::Result<FdEntry>
"PendingEntry::Thunk({:p})",
f as *const fn() -> io::Result<Entry>
),
Self::File(f) => write!(fmt, "PendingFdEntry::File({:?})", f),
Self::File(f) => write!(fmt, "PendingEntry::File({:?})", f),
}
}
}
@ -100,7 +101,9 @@ impl PendingCString {
/// A builder allowing customizable construction of `WasiCtx` instances.
pub struct WasiCtxBuilder {
fds: HashMap<wasi::__wasi_fd_t, PendingFdEntry>,
stdin: PendingEntry,
stdout: PendingEntry,
stderr: PendingEntry,
preopens: Vec<(PathBuf, File)>,
args: Vec<PendingCString>,
env: HashMap<PendingCString, PendingCString>,
@ -109,18 +112,17 @@ pub struct WasiCtxBuilder {
impl WasiCtxBuilder {
/// Builder for a new `WasiCtx`.
pub fn new() -> Self {
let mut builder = Self {
fds: HashMap::new(),
let stdin = PendingEntry::Thunk(Entry::null);
let stdout = PendingEntry::Thunk(Entry::null);
let stderr = PendingEntry::Thunk(Entry::null);
Self {
stdin,
stdout,
stderr,
preopens: Vec::new(),
args: vec![],
env: HashMap::new(),
};
builder.fds.insert(0, PendingFdEntry::Thunk(FdEntry::null));
builder.fds.insert(1, PendingFdEntry::Thunk(FdEntry::null));
builder.fds.insert(2, PendingFdEntry::Thunk(FdEntry::null));
builder
}
}
/// Add arguments to the command-line arguments list.
@ -153,12 +155,9 @@ impl WasiCtxBuilder {
/// Inherit the stdin, stdout, and stderr streams from the host process.
pub fn inherit_stdio(mut self) -> Self {
self.fds
.insert(0, PendingFdEntry::Thunk(FdEntry::duplicate_stdin));
self.fds
.insert(1, PendingFdEntry::Thunk(FdEntry::duplicate_stdout));
self.fds
.insert(2, PendingFdEntry::Thunk(FdEntry::duplicate_stderr));
self.stdin = PendingEntry::Thunk(Entry::duplicate_stdin);
self.stdout = PendingEntry::Thunk(Entry::duplicate_stdout);
self.stderr = PendingEntry::Thunk(Entry::duplicate_stderr);
self
}
@ -203,19 +202,19 @@ impl WasiCtxBuilder {
/// Provide a File to use as stdin
pub fn stdin(mut self, file: File) -> Self {
self.fds.insert(0, PendingFdEntry::File(file));
self.stdin = PendingEntry::File(file);
self
}
/// Provide a File to use as stdout
pub fn stdout(mut self, file: File) -> Self {
self.fds.insert(1, PendingFdEntry::File(file));
self.stdout = PendingEntry::File(file);
self
}
/// Provide a File to use as stderr
pub fn stderr(mut self, file: File) -> Self {
self.fds.insert(2, PendingFdEntry::File(file));
self.stderr = PendingEntry::File(file);
self
}
@ -255,55 +254,55 @@ impl WasiCtxBuilder {
})
.collect::<WasiCtxBuilderResult<Vec<CString>>>()?;
let mut fds: HashMap<wasi::__wasi_fd_t, FdEntry> = HashMap::new();
let mut fd_pool = FdPool::new();
let mut entries: HashMap<wasi::__wasi_fd_t, Entry> = HashMap::new();
// Populate the non-preopen fds.
for (fd, pending) in self.fds {
for pending in vec![self.stdin, self.stdout, self.stderr] {
let fd = fd_pool
.allocate()
.ok_or(WasiCtxBuilderError::TooManyFilesOpen)?;
log::debug!("WasiCtx inserting ({:?}, {:?})", fd, pending);
match pending {
PendingFdEntry::Thunk(f) => {
fds.insert(fd, f()?);
PendingEntry::Thunk(f) => {
entries.insert(fd, f()?);
}
PendingFdEntry::File(f) => {
fds.insert(fd, FdEntry::from(f)?);
PendingEntry::File(f) => {
entries.insert(fd, Entry::from(f)?);
}
}
}
// Then add the preopen fds. Startup code in the guest starts looking at fd 3 for preopens,
// so we start from there. This variable is initially 2, though, because the loop
// immediately does the increment and check for overflow.
let mut preopen_fd: wasi::__wasi_fd_t = 2;
// Then add the preopen fds.
for (guest_path, dir) in self.preopens {
// We do the increment at the beginning of the loop body, so that we don't overflow
// unnecessarily if we have exactly the maximum number of file descriptors.
preopen_fd = preopen_fd
.checked_add(1)
let preopen_fd = fd_pool
.allocate()
.ok_or(WasiCtxBuilderError::TooManyFilesOpen)?;
if !dir.metadata()?.is_dir() {
return Err(WasiCtxBuilderError::NotADirectory(guest_path));
}
// We don't currently allow setting file descriptors other than 0-2, but this will avoid
// collisions if we restore that functionality in the future.
while fds.contains_key(&preopen_fd) {
preopen_fd = preopen_fd
.checked_add(1)
.ok_or(WasiCtxBuilderError::TooManyFilesOpen)?;
}
let mut fe = FdEntry::from(dir)?;
let mut fe = Entry::from(dir)?;
fe.preopen_path = Some(guest_path);
log::debug!("WasiCtx inserting ({:?}, {:?})", preopen_fd, fe);
fds.insert(preopen_fd, fe);
log::debug!("WasiCtx fds = {:?}", fds);
entries.insert(preopen_fd, fe);
log::debug!("WasiCtx entries = {:?}", entries);
}
Ok(WasiCtx { args, env, fds })
Ok(WasiCtx {
args,
env,
fd_pool,
entries,
})
}
}
#[derive(Debug)]
pub struct WasiCtx {
fds: HashMap<wasi::__wasi_fd_t, FdEntry>,
fd_pool: FdPool,
entries: HashMap<wasi::__wasi_fd_t, Entry>,
pub(crate) args: Vec<CString>,
pub(crate) env: Vec<CString>,
}
@ -325,53 +324,42 @@ impl WasiCtx {
}
/// Check if `WasiCtx` contains the specified raw WASI `fd`.
pub(crate) unsafe fn contains_fd_entry(&self, fd: wasi::__wasi_fd_t) -> bool {
self.fds.contains_key(&fd)
pub(crate) unsafe fn contains_entry(&self, fd: wasi::__wasi_fd_t) -> bool {
self.entries.contains_key(&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) -> WasiResult<&FdEntry> {
self.fds.get(&fd).ok_or(WasiError::EBADF)
/// Get an immutable `Entry` corresponding to the specified raw WASI `fd`.
pub(crate) unsafe fn get_entry(&self, fd: wasi::__wasi_fd_t) -> WasiResult<&Entry> {
self.entries.get(&fd).ok_or(WasiError::EBADF)
}
/// Get a mutable `FdEntry` corresponding to the specified raw WASI `fd`.
pub(crate) unsafe fn get_fd_entry_mut(
&mut self,
fd: wasi::__wasi_fd_t,
) -> WasiResult<&mut FdEntry> {
self.fds.get_mut(&fd).ok_or(WasiError::EBADF)
/// Get a mutable `Entry` corresponding to the specified raw WASI `fd`.
pub(crate) unsafe fn get_entry_mut(&mut self, fd: wasi::__wasi_fd_t) -> WasiResult<&mut Entry> {
self.entries.get_mut(&fd).ok_or(WasiError::EBADF)
}
/// Insert the specified `FdEntry` into the `WasiCtx` object.
/// Insert the specified `Entry` into the `WasiCtx` object.
///
/// The `FdEntry` will automatically get another free raw WASI `fd` assigned. Note that
/// The `Entry` will automatically get another free raw WASI `fd` assigned. Note that
/// the two subsequent free raw WASI `fd`s do not have to be stored contiguously.
pub(crate) fn insert_fd_entry(&mut self, fe: FdEntry) -> WasiResult<wasi::__wasi_fd_t> {
// Never insert where stdio handles are expected to be.
let mut fd = 3;
while self.fds.contains_key(&fd) {
if let Some(next_fd) = fd.checked_add(1) {
fd = next_fd;
} else {
return Err(WasiError::EMFILE);
}
}
self.fds.insert(fd, fe);
pub(crate) fn insert_entry(&mut self, fe: Entry) -> WasiResult<wasi::__wasi_fd_t> {
let fd = self.fd_pool.allocate().ok_or(WasiError::EMFILE)?;
self.entries.insert(fd, fe);
Ok(fd)
}
/// Insert the specified `FdEntry` with the specified raw WASI `fd` key into the `WasiCtx`
/// Insert the specified `Entry` with the specified raw WASI `fd` key into the `WasiCtx`
/// object.
pub(crate) fn insert_fd_entry_at(
&mut self,
fd: wasi::__wasi_fd_t,
fe: FdEntry,
) -> Option<FdEntry> {
self.fds.insert(fd, fe)
pub(crate) fn insert_entry_at(&mut self, fd: wasi::__wasi_fd_t, fe: Entry) -> Option<Entry> {
self.entries.insert(fd, fe)
}
/// 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) -> WasiResult<FdEntry> {
self.fds.remove(&fd).ok_or(WasiError::EBADF)
/// Remove `Entry` corresponding to the specified raw WASI `fd` from the `WasiCtx` object.
pub(crate) fn remove_entry(&mut self, fd: wasi::__wasi_fd_t) -> WasiResult<Entry> {
// Remove the `fd` from valid entries.
let entry = self.entries.remove(&fd).ok_or(WasiError::EBADF)?;
// Next, deallocate the `fd`.
self.fd_pool.deallocate(fd);
Ok(entry)
}
}

6
crates/wasi-common/src/old/snapshot_0/fdentry.rs → crates/wasi-common/src/old/snapshot_0/entry.rs

@ -1,5 +1,5 @@
use crate::old::snapshot_0::sys::dev_null;
use crate::old::snapshot_0::sys::fdentry_impl::{
use crate::old::snapshot_0::sys::entry_impl::{
descriptor_as_oshandle, determine_type_and_access_rights, OsHandle,
};
use crate::old::snapshot_0::wasi::{self, WasiError, WasiResult};
@ -51,7 +51,7 @@ impl Descriptor {
/// `FdEntry::as_descriptor_mut` methods which require a set of base and inheriting rights to be
/// specified, verifying whether the stored `Descriptor` object is valid for the rights specified.
#[derive(Debug)]
pub(crate) struct FdEntry {
pub(crate) struct Entry {
pub(crate) file_type: wasi::__wasi_filetype_t,
descriptor: Descriptor,
pub(crate) rights_base: wasi::__wasi_rights_t,
@ -60,7 +60,7 @@ pub(crate) struct FdEntry {
// TODO: directories
}
impl FdEntry {
impl Entry {
/// Create an FdEntry with *maximal* possible rights from a given `File`.
/// If this is not desired, the rights of the resulting `FdEntry` should
/// be manually restricted.

92
crates/wasi-common/src/old/snapshot_0/hostcalls_impl/fs.rs

@ -1,10 +1,10 @@
#![allow(non_camel_case_types)]
use super::fs_helpers::path_get;
use crate::old::snapshot_0::ctx::WasiCtx;
use crate::old::snapshot_0::fdentry::{Descriptor, FdEntry};
use crate::old::snapshot_0::entry::{Descriptor, Entry};
use crate::old::snapshot_0::helpers::*;
use crate::old::snapshot_0::memory::*;
use crate::old::snapshot_0::sys::fdentry_impl::determine_type_rights;
use crate::old::snapshot_0::sys::entry_impl::determine_type_rights;
use crate::old::snapshot_0::sys::hostcalls_impl::fs_helpers::path_open_rights;
use crate::old::snapshot_0::sys::{host_impl, hostcalls_impl};
use crate::old::snapshot_0::wasi::{self, WasiError, WasiResult};
@ -24,14 +24,14 @@ pub(crate) unsafe fn fd_close(
) -> WasiResult<()> {
trace!("fd_close(fd={:?})", fd);
if let Ok(fe) = wasi_ctx.get_fd_entry(fd) {
if let Ok(fe) = wasi_ctx.get_entry(fd) {
// can't close preopened files
if fe.preopen_path.is_some() {
return Err(WasiError::ENOTSUP);
}
}
wasi_ctx.remove_fd_entry(fd)?;
wasi_ctx.remove_entry(fd)?;
Ok(())
}
@ -43,7 +43,7 @@ pub(crate) unsafe fn fd_datasync(
trace!("fd_datasync(fd={:?})", fd);
let fd = wasi_ctx
.get_fd_entry(fd)?
.get_entry(fd)?
.as_descriptor(wasi::__WASI_RIGHTS_FD_DATASYNC, 0)?
.as_file()?;
@ -69,7 +69,7 @@ pub(crate) unsafe fn fd_pread(
);
let fd = wasi_ctx
.get_fd_entry(fd)?
.get_entry(fd)?
.as_descriptor(wasi::__WASI_RIGHTS_FD_READ | wasi::__WASI_RIGHTS_FD_SEEK, 0)?
.as_file()?;
@ -118,7 +118,7 @@ pub(crate) unsafe fn fd_pwrite(
);
let fd = wasi_ctx
.get_fd_entry(fd)?
.get_entry(fd)?
.as_descriptor(
wasi::__WASI_RIGHTS_FD_WRITE | wasi::__WASI_RIGHTS_FD_SEEK,
0,
@ -167,7 +167,7 @@ pub(crate) unsafe fn fd_read(
.collect();
let maybe_host_nread = match wasi_ctx
.get_fd_entry_mut(fd)?
.get_entry_mut(fd)?
.as_descriptor_mut(wasi::__WASI_RIGHTS_FD_READ, 0)?
{
Descriptor::OsHandle(file) => file.read_vectored(&mut iovs),
@ -190,25 +190,25 @@ pub(crate) unsafe fn fd_renumber(
) -> WasiResult<()> {
trace!("fd_renumber(from={:?}, to={:?})", from, to);
if !wasi_ctx.contains_fd_entry(from) {
if !wasi_ctx.contains_entry(from) {
return Err(WasiError::EBADF);
}
// Don't allow renumbering over a pre-opened resource.
// TODO: Eventually, we do want to permit this, once libpreopen in
// 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_entry(from)?;
if from_fe.preopen_path.is_some() {
return Err(WasiError::ENOTSUP);
}
if let Ok(to_fe) = wasi_ctx.get_fd_entry(to) {
if let Ok(to_fe) = wasi_ctx.get_entry(to) {
if to_fe.preopen_path.is_some() {
return Err(WasiError::ENOTSUP);
}
}
let fe = wasi_ctx.remove_fd_entry(from)?;
wasi_ctx.insert_fd_entry_at(to, fe);
let fe = wasi_ctx.remove_entry(from)?;
wasi_ctx.insert_entry_at(to, fe);
Ok(())
}
@ -235,7 +235,7 @@ pub(crate) unsafe fn fd_seek(
wasi::__WASI_RIGHTS_FD_SEEK | wasi::__WASI_RIGHTS_FD_TELL
};
let fd = wasi_ctx
.get_fd_entry_mut(fd)?
.get_entry_mut(fd)?
.as_descriptor_mut(rights, 0)?
.as_file_mut()?;
@ -261,7 +261,7 @@ pub(crate) unsafe fn fd_tell(
trace!("fd_tell(fd={:?}, newoffset={:#x?})", fd, newoffset);
let fd = wasi_ctx
.get_fd_entry_mut(fd)?
.get_entry_mut(fd)?
.as_descriptor_mut(wasi::__WASI_RIGHTS_FD_TELL, 0)?
.as_file_mut()?;
@ -281,14 +281,11 @@ pub(crate) unsafe fn fd_fdstat_get(
trace!("fd_fdstat_get(fd={:?}, fdstat_ptr={:#x?})", fd, fdstat_ptr);
let mut fdstat = dec_fdstat_byref(memory, fdstat_ptr)?;
let host_fd = wasi_ctx
.get_fd_entry(fd)?
.as_descriptor(0, 0)?
.as_os_handle();
let host_fd = wasi_ctx.get_entry(fd)?.as_descriptor(0, 0)?.as_os_handle();
let fs_flags = hostcalls_impl::fd_fdstat_get(&host_fd)?;
let fe = wasi_ctx.get_fd_entry(fd)?;
let fe = wasi_ctx.get_entry(fd)?;
fdstat.fs_filetype = fe.file_type;
fdstat.fs_rights_base = fe.rights_base;
fdstat.fs_rights_inheriting = fe.rights_inheriting;
@ -307,10 +304,7 @@ pub(crate) unsafe fn fd_fdstat_set_flags(
) -> WasiResult<()> {
trace!("fd_fdstat_set_flags(fd={:?}, fdflags={:#x?})", fd, fdflags);
let fd = wasi_ctx
.get_fd_entry(fd)?
.as_descriptor(0, 0)?
.as_os_handle();
let fd = wasi_ctx.get_entry(fd)?.as_descriptor(0, 0)?.as_os_handle();
hostcalls_impl::fd_fdstat_set_flags(&fd, fdflags)
}
@ -329,7 +323,7 @@ pub(crate) unsafe fn fd_fdstat_set_rights(
fs_rights_inheriting
);
let fe = wasi_ctx.get_fd_entry_mut(fd)?;
let fe = wasi_ctx.get_entry_mut(fd)?;
if fe.rights_base & fs_rights_base != fs_rights_base
|| fe.rights_inheriting & fs_rights_inheriting != fs_rights_inheriting
{
@ -349,7 +343,7 @@ pub(crate) unsafe fn fd_sync(
trace!("fd_sync(fd={:?})", fd);
let fd = wasi_ctx
.get_fd_entry(fd)?
.get_entry(fd)?
.as_descriptor(wasi::__WASI_RIGHTS_FD_SYNC, 0)?
.as_file()?;
fd.sync_all().map_err(Into::into)
@ -375,7 +369,7 @@ pub(crate) unsafe fn fd_write(
let iovs: Vec<io::IoSlice> = iovs.iter().map(|vec| host::ciovec_to_host(vec)).collect();
// perform unbuffered writes
let entry = wasi_ctx.get_fd_entry_mut(fd)?;
let entry = wasi_ctx.get_entry_mut(fd)?;
let isatty = entry.isatty();
let desc = entry.as_descriptor_mut(wasi::__WASI_RIGHTS_FD_WRITE, 0)?;
let host_nwritten = match desc {
@ -428,7 +422,7 @@ pub(crate) unsafe fn fd_advise(
);
let fd = wasi_ctx
.get_fd_entry(fd)?
.get_entry(fd)?
.as_descriptor(wasi::__WASI_RIGHTS_FD_ADVISE, 0)?
.as_file()?;
@ -445,7 +439,7 @@ pub(crate) unsafe fn fd_allocate(
trace!("fd_allocate(fd={:?}, offset={}, len={})", fd, offset, len);
let fd = wasi_ctx
.get_fd_entry(fd)?
.get_entry(fd)?
.as_descriptor(wasi::__WASI_RIGHTS_FD_ALLOCATE, 0)?
.as_file()?;
@ -484,7 +478,7 @@ pub(crate) unsafe fn path_create_directory(
trace!(" | (path_ptr,path_len)='{}'", path);
let rights = wasi::__WASI_RIGHTS_PATH_OPEN | wasi::__WASI_RIGHTS_PATH_CREATE_DIRECTORY;
let fe = wasi_ctx.get_fd_entry(dirfd)?;
let fe = wasi_ctx.get_entry(dirfd)?;
let resolved = path_get(fe, rights, 0, 0, path, false)?;
hostcalls_impl::path_create_directory(resolved)
@ -518,8 +512,8 @@ pub(crate) unsafe fn path_link(
trace!(" | (old_path_ptr,old_path_len)='{}'", old_path);
trace!(" | (new_path_ptr,new_path_len)='{}'", new_path);
let old_fe = wasi_ctx.get_fd_entry(old_dirfd)?;
let new_fe = wasi_ctx.get_fd_entry(new_dirfd)?;
let old_fe = wasi_ctx.get_entry(old_dirfd)?;
let new_fe = wasi_ctx.get_entry(new_dirfd)?;
let resolved_old = path_get(
old_fe,
wasi::__WASI_RIGHTS_PATH_LINK_SOURCE,
@ -575,7 +569,7 @@ pub(crate) unsafe fn path_open(
let (needed_base, needed_inheriting) =
path_open_rights(fs_rights_base, fs_rights_inheriting, oflags, fs_flags);
let fe = wasi_ctx.get_fd_entry(dirfd)?;
let fe = wasi_ctx.get_entry(dirfd)?;
let resolved = path_get(
fe,
needed_base,
@ -598,10 +592,10 @@ pub(crate) unsafe fn path_open(
// Determine the type of the new file descriptor and which rights contradict with this type
let (_ty, max_base, max_inheriting) = determine_type_rights(&fd)?;
let mut fe = FdEntry::from(fd)?;
let mut fe = Entry::from(fd)?;
fe.rights_base &= max_base;
fe.rights_inheriting &= max_inheriting;
let guest_fd = wasi_ctx.insert_fd_entry(fe)?;
let guest_fd = wasi_ctx.insert_entry(fe)?;
trace!(" | *fd={:?}", guest_fd);
@ -634,7 +628,7 @@ pub(crate) unsafe fn path_readlink(
trace!(" | (path_ptr,path_len)='{}'", &path);
let fe = wasi_ctx.get_fd_entry(dirfd)?;
let fe = wasi_ctx.get_entry(dirfd)?;
let resolved = path_get(fe, wasi::__WASI_RIGHTS_PATH_READLINK, 0, 0, &path, false)?;
let mut buf = dec_slice_of_mut_u8(memory, buf_ptr, buf_len)?;
@ -673,8 +667,8 @@ pub(crate) unsafe fn path_rename(
trace!(" | (old_path_ptr,old_path_len)='{}'", old_path);
trace!(" | (new_path_ptr,new_path_len)='{}'", new_path);
let old_fe = wasi_ctx.get_fd_entry(old_dirfd)?;
let new_fe = wasi_ctx.get_fd_entry(new_dirfd)?;
let old_fe = wasi_ctx.get_entry(old_dirfd)?;
let new_fe = wasi_ctx.get_entry(new_dirfd)?;
let resolved_old = path_get(
old_fe,
wasi::__WASI_RIGHTS_PATH_RENAME_SOURCE,
@ -710,7 +704,7 @@ pub(crate) unsafe fn fd_filestat_get(
filestat_ptr
);
let fd = wasi_ctx.get_fd_entry(fd)?.as_descriptor(0, 0)?.as_file()?;
let fd = wasi_ctx.get_entry(fd)?.as_descriptor(0, 0)?.as_file()?;
let host_filestat = hostcalls_impl::fd_filestat_get(fd)?;
trace!(" | *filestat_ptr={:?}", host_filestat);
@ -735,7 +729,7 @@ pub(crate) unsafe fn fd_filestat_set_times(
);
let fd = wasi_ctx
.get_fd_entry(fd)?
.get_entry(fd)?
.as_descriptor(wasi::__WASI_RIGHTS_FD_FILESTAT_SET_TIMES, 0)?
.as_file()?;
@ -787,7 +781,7 @@ pub(crate) unsafe fn fd_filestat_set_size(
trace!("fd_filestat_set_size(fd={:?}, st_size={})", fd, st_size);
let fd = wasi_ctx
.get_fd_entry(fd)?
.get_entry(fd)?
.as_descriptor(wasi::__WASI_RIGHTS_FD_FILESTAT_SET_SIZE, 0)?
.as_file()?;
@ -820,7 +814,7 @@ pub(crate) unsafe fn path_filestat_get(
trace!(" | (path_ptr,path_len)='{}'", path);
let fe = wasi_ctx.get_fd_entry(dirfd)?;
let fe = wasi_ctx.get_entry(dirfd)?;
let resolved = path_get(
fe,
wasi::__WASI_RIGHTS_PATH_FILESTAT_GET,
@ -861,7 +855,7 @@ pub(crate) unsafe fn path_filestat_set_times(
trace!(" | (path_ptr,path_len)='{}'", path);
let fe = wasi_ctx.get_fd_entry(dirfd)?;
let fe = wasi_ctx.get_entry(dirfd)?;
let resolved = path_get(
fe,
wasi::__WASI_RIGHTS_PATH_FILESTAT_SET_TIMES,
@ -898,7 +892,7 @@ pub(crate) unsafe fn path_symlink(
trace!(" | (old_path_ptr,old_path_len)='{}'", old_path);
trace!(" | (new_path_ptr,new_path_len)='{}'", new_path);
let fe = wasi_ctx.get_fd_entry(dirfd)?;
let fe = wasi_ctx.get_entry(dirfd)?;
let resolved_new = path_get(fe, wasi::__WASI_RIGHTS_PATH_SYMLINK, 0, 0, new_path, true)?;
hostcalls_impl::path_symlink(old_path, resolved_new)
@ -922,7 +916,7 @@ pub(crate) unsafe fn path_unlink_file(
trace!(" | (path_ptr,path_len)='{}'", path);
let fe = wasi_ctx.get_fd_entry(dirfd)?;
let fe = wasi_ctx.get_entry(dirfd)?;
let resolved = path_get(fe, wasi::__WASI_RIGHTS_PATH_UNLINK_FILE, 0, 0, path, false)?;
hostcalls_impl::path_unlink_file(resolved)
@ -946,7 +940,7 @@ pub(crate) unsafe fn path_remove_directory(
trace!(" | (path_ptr,path_len)='{}'", path);
let fe = wasi_ctx.get_fd_entry(dirfd)?;
let fe = wasi_ctx.get_entry(dirfd)?;
let resolved = path_get(
fe,
wasi::__WASI_RIGHTS_PATH_REMOVE_DIRECTORY,
@ -974,7 +968,7 @@ pub(crate) unsafe fn fd_prestat_get(
);
// TODO: should we validate any rights here?
let fe = wasi_ctx.get_fd_entry(fd)?;
let fe = wasi_ctx.get_entry(fd)?;
let po_path = fe.preopen_path.as_ref().ok_or(WasiError::ENOTSUP)?;
if fe.file_type != wasi::__WASI_FILETYPE_DIRECTORY {
return Err(WasiError::ENOTDIR);
@ -1011,7 +1005,7 @@ pub(crate) unsafe fn fd_prestat_dir_name(
);
// TODO: should we validate any rights here?
let fe = wasi_ctx.get_fd_entry(fd)?;
let fe = wasi_ctx.get_entry(fd)?;
let po_path = fe.preopen_path.as_ref().ok_or(WasiError::ENOTSUP)?;
if fe.file_type != wasi::__WASI_FILETYPE_DIRECTORY {
return Err(WasiError::ENOTDIR);
@ -1049,7 +1043,7 @@ pub(crate) unsafe fn fd_readdir(
enc_usize_byref(memory, buf_used, 0)?;
let file = wasi_ctx
.get_fd_entry_mut(fd)?
.get_entry_mut(fd)?
.as_descriptor_mut(wasi::__WASI_RIGHTS_FD_READDIR, 0)?
.as_file_mut()?;
let mut host_buf = dec_slice_of_mut_u8(memory, buf, buf_len)?;

4
crates/wasi-common/src/old/snapshot_0/hostcalls_impl/fs_helpers.rs

@ -1,5 +1,5 @@
#![allow(non_camel_case_types)]
use crate::old::snapshot_0::fdentry::FdEntry;
use crate::old::snapshot_0::entry::Entry;
use crate::old::snapshot_0::sys::host_impl;
use crate::old::snapshot_0::sys::hostcalls_impl::fs_helpers::*;
use crate::old::snapshot_0::wasi::{self, WasiError, WasiResult};
@ -26,7 +26,7 @@ impl PathGet {
///
/// This is a workaround for not having Capsicum support in the OS.
pub(crate) fn path_get(
fe: &FdEntry,
fe: &Entry,
rights_base: wasi::__wasi_rights_t,
rights_inheriting: wasi::__wasi_rights_t,
dirflags: wasi::__wasi_lookupflags_t,

6
crates/wasi-common/src/old/snapshot_0/hostcalls_impl/misc.rs

@ -1,6 +1,6 @@
#![allow(non_camel_case_types)]
use crate::old::snapshot_0::ctx::WasiCtx;
use crate::old::snapshot_0::fdentry::Descriptor;
use crate::old::snapshot_0::entry::Descriptor;
use crate::old::snapshot_0::memory::*;
use crate::old::snapshot_0::sys::hostcalls_impl;
use crate::old::snapshot_0::wasi::{self, WasiError, WasiResult};
@ -245,7 +245,7 @@ pub(crate) fn poll_oneoff(
let rights = wasi::__WASI_RIGHTS_FD_READ | wasi::__WASI_RIGHTS_POLL_FD_READWRITE;
match unsafe {
wasi_ctx
.get_fd_entry(wasi_fd)
.get_entry(wasi_fd)
.and_then(|fe| fe.as_descriptor(rights, 0))
} {
Ok(descriptor) => fd_events.push(FdEventData {
@ -273,7 +273,7 @@ pub(crate) fn poll_oneoff(
let rights = wasi::__WASI_RIGHTS_FD_WRITE | wasi::__WASI_RIGHTS_POLL_FD_READWRITE;
match unsafe {
wasi_ctx
.get_fd_entry(wasi_fd)
.get_entry(wasi_fd)
.and_then(|fe| fe.as_descriptor(rights, 0))
} {
Ok(descriptor) => fd_events.push(FdEventData {

2
crates/wasi-common/src/old/snapshot_0/mod.rs

@ -1,5 +1,5 @@
mod ctx;
mod fdentry;
mod entry;
mod helpers;
mod host;
mod hostcalls_impl;

2
crates/wasi-common/src/old/snapshot_0/sys/unix/bsd/hostcalls_impl.rs

@ -131,7 +131,7 @@ pub(crate) fn path_rename(resolved_old: PathGet, resolved_new: PathGet) -> WasiR
}
pub(crate) mod fd_readdir_impl {
use crate::old::snapshot_0::sys::fdentry_impl::OsHandle;
use crate::old::snapshot_0::sys::entry_impl::OsHandle;
use crate::old::snapshot_0::wasi::WasiResult;
use std::sync::{Mutex, MutexGuard};
use yanix::dir::Dir;

2
crates/wasi-common/src/old/snapshot_0/sys/unix/fdentry_impl.rs → crates/wasi-common/src/old/snapshot_0/sys/unix/entry_impl.rs

@ -1,4 +1,4 @@
use crate::old::snapshot_0::fdentry::{Descriptor, OsHandleRef};
use crate::old::snapshot_0::entry::{Descriptor, OsHandleRef};
use crate::old::snapshot_0::{sys::unix::sys_impl, wasi};
use std::fs::File;
use std::io;

2
crates/wasi-common/src/old/snapshot_0/sys/unix/hostcalls_impl/fs.rs

@ -2,7 +2,7 @@
#![allow(unused_unsafe)]
use crate::old::snapshot_0::host::Dirent;
use crate::old::snapshot_0::hostcalls_impl::PathGet;
use crate::old::snapshot_0::sys::{fdentry_impl::OsHandle, host_impl, unix::sys_impl};
use crate::old::snapshot_0::sys::{entry_impl::OsHandle, host_impl, unix::sys_impl};
use crate::old::snapshot_0::wasi::{self, WasiError, WasiResult};
use std::convert::TryInto;
use std::fs::File;

2
crates/wasi-common/src/old/snapshot_0/sys/unix/linux/hostcalls_impl.rs

@ -38,7 +38,7 @@ pub(crate) fn path_rename(resolved_old: PathGet, resolved_new: PathGet) -> WasiR
}
pub(crate) mod fd_readdir_impl {
use crate::old::snapshot_0::sys::fdentry_impl::OsHandle;
use crate::old::snapshot_0::sys::entry_impl::OsHandle;
use crate::old::snapshot_0::wasi::WasiResult;
use yanix::dir::Dir;

2
crates/wasi-common/src/old/snapshot_0/sys/unix/mod.rs

@ -1,4 +1,4 @@
pub(crate) mod fdentry_impl;
pub(crate) mod entry_impl;
pub(crate) mod host_impl;
pub(crate) mod hostcalls_impl;

2
crates/wasi-common/src/old/snapshot_0/sys/windows/fdentry_impl.rs → crates/wasi-common/src/old/snapshot_0/sys/windows/entry_impl.rs

@ -1,4 +1,4 @@
use crate::old::snapshot_0::fdentry::{Descriptor, OsHandleRef};
use crate::old::snapshot_0::entry::{Descriptor, OsHandleRef};
use crate::old::snapshot_0::wasi;
use std::fs::File;
use std::io;

4
crates/wasi-common/src/old/snapshot_0/sys/windows/hostcalls_impl/fs.rs

@ -2,10 +2,10 @@
#![allow(unused)]
use super::fs_helpers::*;
use crate::old::snapshot_0::ctx::WasiCtx;
use crate::old::snapshot_0::fdentry::FdEntry;
use crate::old::snapshot_0::entry::Entry;
use crate::old::snapshot_0::host::{Dirent, FileType};
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::entry_impl::determine_type_rights;
use crate::old::snapshot_0::sys::host_impl::{self, path_from_host};
use crate::old::snapshot_0::sys::hostcalls_impl::fs_helpers::PathGetExt;
use crate::old::snapshot_0::wasi::{self, WasiError, WasiResult};

2
crates/wasi-common/src/old/snapshot_0/sys/windows/mod.rs

@ -1,4 +1,4 @@
pub(crate) mod fdentry_impl;
pub(crate) mod entry_impl;
pub(crate) mod host_impl;
pub(crate) mod hostcalls_impl;

2
crates/wasi-common/src/sys/unix/bsd/hostcalls_impl.rs

@ -131,7 +131,7 @@ pub(crate) fn path_rename(resolved_old: PathGet, resolved_new: PathGet) -> WasiR
}
pub(crate) mod fd_readdir_impl {
use crate::sys::fdentry_impl::OsHandle;
use crate::sys::entry_impl::OsHandle;
use crate::wasi::WasiResult;
use std::sync::{Mutex, MutexGuard};
use yanix::dir::Dir;

2
crates/wasi-common/src/sys/unix/fdentry_impl.rs → crates/wasi-common/src/sys/unix/entry_impl.rs

@ -1,4 +1,4 @@
use crate::fdentry::{Descriptor, OsHandleRef};
use crate::entry::{Descriptor, OsHandleRef};
use crate::{sys::unix::sys_impl, wasi};
use std::fs::File;
use std::io;

4
crates/wasi-common/src/sys/unix/hostcalls_impl/fs.rs

@ -1,9 +1,9 @@
#![allow(non_camel_case_types)]
#![allow(unused_unsafe)]
use crate::fdentry::Descriptor;
use crate::entry::Descriptor;
use crate::host::Dirent;
use crate::hostcalls_impl::PathGet;
use crate::sys::fdentry_impl::OsHandle;
use crate::sys::entry_impl::OsHandle;
use crate::sys::{host_impl, unix::sys_impl};
use crate::wasi::{self, WasiError, WasiResult};
use std::convert::TryInto;

2
crates/wasi-common/src/sys/unix/hostcalls_impl/misc.rs

@ -127,7 +127,7 @@ fn poll_oneoff_handle_fd_event<'a>(
ready_events: impl Iterator<Item = (FdEventData<'a>, yanix::poll::PollFd)>,
events: &mut Vec<wasi::__wasi_event_t>,
) -> WasiResult<()> {
use crate::fdentry::Descriptor;
use crate::entry::Descriptor;
use std::{convert::TryInto, os::unix::prelude::AsRawFd};
use yanix::{file::fionread, poll::PollFlags};

4
crates/wasi-common/src/sys/unix/linux/hostcalls_impl.rs

@ -1,4 +1,4 @@
use crate::fdentry::Descriptor;
use crate::entry::Descriptor;
use crate::hostcalls_impl::PathGet;
use crate::wasi::WasiResult;
use std::os::unix::prelude::AsRawFd;
@ -46,7 +46,7 @@ pub(crate) fn path_rename(resolved_old: PathGet, resolved_new: PathGet) -> WasiR
}
pub(crate) mod fd_readdir_impl {
use crate::sys::fdentry_impl::OsHandle;
use crate::sys::entry_impl::OsHandle;
use crate::wasi::WasiResult;
use yanix::dir::Dir;

2
crates/wasi-common/src/sys/unix/mod.rs

@ -1,4 +1,4 @@
pub(crate) mod fdentry_impl;
pub(crate) mod entry_impl;
pub(crate) mod host_impl;
pub(crate) mod hostcalls_impl;

2
crates/wasi-common/src/sys/windows/fdentry_impl.rs → crates/wasi-common/src/sys/windows/entry_impl.rs

@ -1,4 +1,4 @@
use crate::fdentry::{Descriptor, OsHandleRef};
use crate::entry::{Descriptor, OsHandleRef};
use crate::wasi;
use std::fs::File;
use std::io;

4
crates/wasi-common/src/sys/windows/hostcalls_impl/fs.rs

@ -2,10 +2,10 @@
#![allow(unused)]
use super::fs_helpers::*;
use crate::ctx::WasiCtx;
use crate::fdentry::{Descriptor, FdEntry};
use crate::entry::{Descriptor, Entry};
use crate::host::{Dirent, FileType};
use crate::hostcalls_impl::{fd_filestat_set_times_impl, PathGet};
use crate::sys::fdentry_impl::{determine_type_rights, OsHandle};
use crate::sys::entry_impl::{determine_type_rights, OsHandle};
use crate::sys::host_impl::{self, path_from_host};
use crate::sys::hostcalls_impl::fs_helpers::PathGetExt;
use crate::wasi::{self, WasiError, WasiResult};

2
crates/wasi-common/src/sys/windows/hostcalls_impl/fs_helpers.rs

@ -1,5 +1,5 @@
#![allow(non_camel_case_types)]
use crate::fdentry::Descriptor;
use crate::entry::Descriptor;
use crate::hostcalls_impl::PathGet;
use crate::wasi::{self, WasiError, WasiResult};
use std::ffi::{OsStr, OsString};

2
crates/wasi-common/src/sys/windows/hostcalls_impl/misc.rs

@ -1,7 +1,7 @@
#![allow(non_camel_case_types)]
#![allow(unused_unsafe)]
#![allow(unused)]
use crate::fdentry::Descriptor;
use crate::entry::Descriptor;
use crate::hostcalls_impl::{ClockEventData, FdEventData};
use crate::memory::*;
use crate::sys::host_impl;

2
crates/wasi-common/src/sys/windows/mod.rs

@ -1,4 +1,4 @@
pub(crate) mod fdentry_impl;
pub(crate) mod entry_impl;
pub(crate) mod host_impl;
pub(crate) mod hostcalls_impl;

9
crates/wasi-common/src/wasi.rs

@ -226,3 +226,12 @@ pub fn whence_to_str(whence: __wasi_whence_t) -> &'static str {
}
pub const __WASI_DIRCOOKIE_START: __wasi_dircookie_t = 0;
impl crate::fdpool::Fd for __wasi_fd_t {
fn as_raw(&self) -> u32 {
*self
}
fn from_raw(raw_fd: u32) -> Self {
raw_fd
}
}

Loading…
Cancel
Save