From 7228a248c13e7a702db9a80c1432df4375220ae0 Mon Sep 17 00:00:00 2001 From: Jakub Konka Date: Tue, 17 Mar 2020 22:58:49 +0100 Subject: [PATCH] [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::Hash` is quite a powerful assumption here!), and a custom method ```rust Fd::next(&self) -> Option; ``` 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.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`. --- crates/wasi-common/src/ctx.rs | 175 ++++++++---------- .../wasi-common/src/{fdentry.rs => entry.rs} | 10 +- crates/wasi-common/src/fdpool.rs | 133 +++++++++++++ crates/wasi-common/src/hostcalls_impl/fs.rs | 84 ++++----- .../src/hostcalls_impl/fs_helpers.rs | 6 +- crates/wasi-common/src/hostcalls_impl/misc.rs | 6 +- crates/wasi-common/src/lib.rs | 3 +- crates/wasi-common/src/old/snapshot_0/ctx.rs | 156 +++++++--------- .../old/snapshot_0/{fdentry.rs => entry.rs} | 6 +- .../src/old/snapshot_0/hostcalls_impl/fs.rs | 92 +++++---- .../snapshot_0/hostcalls_impl/fs_helpers.rs | 4 +- .../src/old/snapshot_0/hostcalls_impl/misc.rs | 6 +- crates/wasi-common/src/old/snapshot_0/mod.rs | 2 +- .../snapshot_0/sys/unix/bsd/hostcalls_impl.rs | 2 +- .../unix/{fdentry_impl.rs => entry_impl.rs} | 2 +- .../snapshot_0/sys/unix/hostcalls_impl/fs.rs | 2 +- .../sys/unix/linux/hostcalls_impl.rs | 2 +- .../src/old/snapshot_0/sys/unix/mod.rs | 2 +- .../{fdentry_impl.rs => entry_impl.rs} | 2 +- .../sys/windows/hostcalls_impl/fs.rs | 4 +- .../src/old/snapshot_0/sys/windows/mod.rs | 2 +- .../src/sys/unix/bsd/hostcalls_impl.rs | 2 +- .../unix/{fdentry_impl.rs => entry_impl.rs} | 2 +- .../src/sys/unix/hostcalls_impl/fs.rs | 4 +- .../src/sys/unix/hostcalls_impl/misc.rs | 2 +- .../src/sys/unix/linux/hostcalls_impl.rs | 4 +- crates/wasi-common/src/sys/unix/mod.rs | 2 +- .../{fdentry_impl.rs => entry_impl.rs} | 2 +- .../src/sys/windows/hostcalls_impl/fs.rs | 4 +- .../sys/windows/hostcalls_impl/fs_helpers.rs | 2 +- .../src/sys/windows/hostcalls_impl/misc.rs | 2 +- crates/wasi-common/src/sys/windows/mod.rs | 2 +- crates/wasi-common/src/wasi.rs | 9 + 33 files changed, 419 insertions(+), 319 deletions(-) rename crates/wasi-common/src/{fdentry.rs => entry.rs} (97%) create mode 100644 crates/wasi-common/src/fdpool.rs rename crates/wasi-common/src/old/snapshot_0/{fdentry.rs => entry.rs} (98%) rename crates/wasi-common/src/old/snapshot_0/sys/unix/{fdentry_impl.rs => entry_impl.rs} (98%) rename crates/wasi-common/src/old/snapshot_0/sys/windows/{fdentry_impl.rs => entry_impl.rs} (98%) rename crates/wasi-common/src/sys/unix/{fdentry_impl.rs => entry_impl.rs} (99%) rename crates/wasi-common/src/sys/windows/{fdentry_impl.rs => entry_impl.rs} (99%) diff --git a/crates/wasi-common/src/ctx.rs b/crates/wasi-common/src/ctx.rs index 899e272c0f..18b9467cb1 100644 --- a/crates/wasi-common/src/ctx.rs +++ b/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 = std::result::Result; -enum PendingFdEntry { - Thunk(fn() -> io::Result), +enum PendingEntry { + Thunk(fn() -> io::Result), 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 + f as *const fn() -> io::Result ), 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>, + stdin: Option, + stdout: Option, + stderr: Option, preopens: Option>, args: Option>, env: Option>, @@ -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::>>()?; - let mut fds: HashMap = 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 = 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, + fd_pool: FdPool, + entries: HashMap, pub(crate) args: Vec, pub(crate) env: Vec, } @@ -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 { - // 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 { + 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 { - self.fds.insert(fd, fe) + pub(crate) fn insert_entry_at(&mut self, fd: wasi::__wasi_fd_t, fe: Entry) -> Option { + 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 { - 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 { + // 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) } } diff --git a/crates/wasi-common/src/fdentry.rs b/crates/wasi-common/src/entry.rs similarity index 97% rename from crates/wasi-common/src/fdentry.rs rename to crates/wasi-common/src/entry.rs index 56ab57e5e7..5b07667d13 100644 --- a/crates/wasi-common/src/fdentry.rs +++ b/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 { match file { Descriptor::OsHandle(handle) => unsafe { determine_type_and_access_rights(&handle) } diff --git a/crates/wasi-common/src/fdpool.rs b/crates/wasi-common/src/fdpool.rs new file mode 100644 index 0000000000..8043abe01c --- /dev/null +++ b/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, + available: Vec, +} + +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(&mut self) -> Option { + 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(&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::().is_none()); + } +} diff --git a/crates/wasi-common/src/hostcalls_impl/fs.rs b/crates/wasi-common/src/hostcalls_impl/fs.rs index a9706d741b..ecedc67b71 100644 --- a/crates/wasi-common/src/hostcalls_impl/fs.rs +++ b/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 = 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)?; diff --git a/crates/wasi-common/src/hostcalls_impl/fs_helpers.rs b/crates/wasi-common/src/hostcalls_impl/fs_helpers.rs index b1a8e555a2..9869f83a24 100644 --- a/crates/wasi-common/src/hostcalls_impl/fs_helpers.rs +++ b/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, diff --git a/crates/wasi-common/src/hostcalls_impl/misc.rs b/crates/wasi-common/src/hostcalls_impl/misc.rs index 456beca24c..9dc99db609 100644 --- a/crates/wasi-common/src/hostcalls_impl/misc.rs +++ b/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 { diff --git a/crates/wasi-common/src/lib.rs b/crates/wasi-common/src/lib.rs index b20066b1cd..3228dd8bf4 100644 --- a/crates/wasi-common/src/lib.rs +++ b/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; diff --git a/crates/wasi-common/src/old/snapshot_0/ctx.rs b/crates/wasi-common/src/old/snapshot_0/ctx.rs index e9979bb46e..5b74ede010 100644 --- a/crates/wasi-common/src/old/snapshot_0/ctx.rs +++ b/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 = std::result::Result; -enum PendingFdEntry { - Thunk(fn() -> io::Result), +enum PendingEntry { + Thunk(fn() -> io::Result), 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 + "PendingEntry::Thunk({:p})", + f as *const fn() -> io::Result ), - 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, + stdin: PendingEntry, + stdout: PendingEntry, + stderr: PendingEntry, preopens: Vec<(PathBuf, File)>, args: Vec, env: HashMap, @@ -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::>>()?; - let mut fds: HashMap = HashMap::new(); + let mut fd_pool = FdPool::new(); + let mut entries: HashMap = 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, + fd_pool: FdPool, + entries: HashMap, pub(crate) args: Vec, pub(crate) env: Vec, } @@ -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 { - // 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 { + 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 { - self.fds.insert(fd, fe) + pub(crate) fn insert_entry_at(&mut self, fd: wasi::__wasi_fd_t, fe: Entry) -> Option { + 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 { - 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 { + // 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) } } diff --git a/crates/wasi-common/src/old/snapshot_0/fdentry.rs b/crates/wasi-common/src/old/snapshot_0/entry.rs similarity index 98% rename from crates/wasi-common/src/old/snapshot_0/fdentry.rs rename to crates/wasi-common/src/old/snapshot_0/entry.rs index cf248277f1..84892a1167 100644 --- a/crates/wasi-common/src/old/snapshot_0/fdentry.rs +++ b/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. diff --git a/crates/wasi-common/src/old/snapshot_0/hostcalls_impl/fs.rs b/crates/wasi-common/src/old/snapshot_0/hostcalls_impl/fs.rs index a038ad4bf8..8d71856682 100644 --- a/crates/wasi-common/src/old/snapshot_0/hostcalls_impl/fs.rs +++ b/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 = 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)?; diff --git a/crates/wasi-common/src/old/snapshot_0/hostcalls_impl/fs_helpers.rs b/crates/wasi-common/src/old/snapshot_0/hostcalls_impl/fs_helpers.rs index c646cc895e..aabdb29da2 100644 --- a/crates/wasi-common/src/old/snapshot_0/hostcalls_impl/fs_helpers.rs +++ b/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, diff --git a/crates/wasi-common/src/old/snapshot_0/hostcalls_impl/misc.rs b/crates/wasi-common/src/old/snapshot_0/hostcalls_impl/misc.rs index d577533bce..922d8b304c 100644 --- a/crates/wasi-common/src/old/snapshot_0/hostcalls_impl/misc.rs +++ b/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 { diff --git a/crates/wasi-common/src/old/snapshot_0/mod.rs b/crates/wasi-common/src/old/snapshot_0/mod.rs index d17e3035ce..b7418497dd 100644 --- a/crates/wasi-common/src/old/snapshot_0/mod.rs +++ b/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; diff --git a/crates/wasi-common/src/old/snapshot_0/sys/unix/bsd/hostcalls_impl.rs b/crates/wasi-common/src/old/snapshot_0/sys/unix/bsd/hostcalls_impl.rs index 8923114c8f..15ab4bc319 100644 --- a/crates/wasi-common/src/old/snapshot_0/sys/unix/bsd/hostcalls_impl.rs +++ b/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; diff --git a/crates/wasi-common/src/old/snapshot_0/sys/unix/fdentry_impl.rs b/crates/wasi-common/src/old/snapshot_0/sys/unix/entry_impl.rs similarity index 98% rename from crates/wasi-common/src/old/snapshot_0/sys/unix/fdentry_impl.rs rename to crates/wasi-common/src/old/snapshot_0/sys/unix/entry_impl.rs index a9bee8eeb9..aa0135470e 100644 --- a/crates/wasi-common/src/old/snapshot_0/sys/unix/fdentry_impl.rs +++ b/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; diff --git a/crates/wasi-common/src/old/snapshot_0/sys/unix/hostcalls_impl/fs.rs b/crates/wasi-common/src/old/snapshot_0/sys/unix/hostcalls_impl/fs.rs index 2766838fa1..3d106a4397 100644 --- a/crates/wasi-common/src/old/snapshot_0/sys/unix/hostcalls_impl/fs.rs +++ b/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; diff --git a/crates/wasi-common/src/old/snapshot_0/sys/unix/linux/hostcalls_impl.rs b/crates/wasi-common/src/old/snapshot_0/sys/unix/linux/hostcalls_impl.rs index efcff139a9..b0815e6814 100644 --- a/crates/wasi-common/src/old/snapshot_0/sys/unix/linux/hostcalls_impl.rs +++ b/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; diff --git a/crates/wasi-common/src/old/snapshot_0/sys/unix/mod.rs b/crates/wasi-common/src/old/snapshot_0/sys/unix/mod.rs index c5382556ab..959545e370 100644 --- a/crates/wasi-common/src/old/snapshot_0/sys/unix/mod.rs +++ b/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; diff --git a/crates/wasi-common/src/old/snapshot_0/sys/windows/fdentry_impl.rs b/crates/wasi-common/src/old/snapshot_0/sys/windows/entry_impl.rs similarity index 98% rename from crates/wasi-common/src/old/snapshot_0/sys/windows/fdentry_impl.rs rename to crates/wasi-common/src/old/snapshot_0/sys/windows/entry_impl.rs index b5a35833d6..9e2251b5ba 100644 --- a/crates/wasi-common/src/old/snapshot_0/sys/windows/fdentry_impl.rs +++ b/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; diff --git a/crates/wasi-common/src/old/snapshot_0/sys/windows/hostcalls_impl/fs.rs b/crates/wasi-common/src/old/snapshot_0/sys/windows/hostcalls_impl/fs.rs index f0f7453c7e..1fb0796b1c 100644 --- a/crates/wasi-common/src/old/snapshot_0/sys/windows/hostcalls_impl/fs.rs +++ b/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}; diff --git a/crates/wasi-common/src/old/snapshot_0/sys/windows/mod.rs b/crates/wasi-common/src/old/snapshot_0/sys/windows/mod.rs index 7783272946..5fd95f92c8 100644 --- a/crates/wasi-common/src/old/snapshot_0/sys/windows/mod.rs +++ b/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; diff --git a/crates/wasi-common/src/sys/unix/bsd/hostcalls_impl.rs b/crates/wasi-common/src/sys/unix/bsd/hostcalls_impl.rs index 9b56bb76a0..74b02773cf 100644 --- a/crates/wasi-common/src/sys/unix/bsd/hostcalls_impl.rs +++ b/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; diff --git a/crates/wasi-common/src/sys/unix/fdentry_impl.rs b/crates/wasi-common/src/sys/unix/entry_impl.rs similarity index 99% rename from crates/wasi-common/src/sys/unix/fdentry_impl.rs rename to crates/wasi-common/src/sys/unix/entry_impl.rs index 7a45e28c13..d6bc582235 100644 --- a/crates/wasi-common/src/sys/unix/fdentry_impl.rs +++ b/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; diff --git a/crates/wasi-common/src/sys/unix/hostcalls_impl/fs.rs b/crates/wasi-common/src/sys/unix/hostcalls_impl/fs.rs index abba915480..63eb64fdc0 100644 --- a/crates/wasi-common/src/sys/unix/hostcalls_impl/fs.rs +++ b/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; diff --git a/crates/wasi-common/src/sys/unix/hostcalls_impl/misc.rs b/crates/wasi-common/src/sys/unix/hostcalls_impl/misc.rs index 9456d2a69f..c710923a02 100644 --- a/crates/wasi-common/src/sys/unix/hostcalls_impl/misc.rs +++ b/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, yanix::poll::PollFd)>, events: &mut Vec, ) -> WasiResult<()> { - use crate::fdentry::Descriptor; + use crate::entry::Descriptor; use std::{convert::TryInto, os::unix::prelude::AsRawFd}; use yanix::{file::fionread, poll::PollFlags}; diff --git a/crates/wasi-common/src/sys/unix/linux/hostcalls_impl.rs b/crates/wasi-common/src/sys/unix/linux/hostcalls_impl.rs index 42ea5c8b92..9d36e9993a 100644 --- a/crates/wasi-common/src/sys/unix/linux/hostcalls_impl.rs +++ b/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; diff --git a/crates/wasi-common/src/sys/unix/mod.rs b/crates/wasi-common/src/sys/unix/mod.rs index abd5160114..84badddc25 100644 --- a/crates/wasi-common/src/sys/unix/mod.rs +++ b/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; diff --git a/crates/wasi-common/src/sys/windows/fdentry_impl.rs b/crates/wasi-common/src/sys/windows/entry_impl.rs similarity index 99% rename from crates/wasi-common/src/sys/windows/fdentry_impl.rs rename to crates/wasi-common/src/sys/windows/entry_impl.rs index 8776111673..182475fc38 100644 --- a/crates/wasi-common/src/sys/windows/fdentry_impl.rs +++ b/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; diff --git a/crates/wasi-common/src/sys/windows/hostcalls_impl/fs.rs b/crates/wasi-common/src/sys/windows/hostcalls_impl/fs.rs index 6d7030cfb3..1f91e6f9a9 100644 --- a/crates/wasi-common/src/sys/windows/hostcalls_impl/fs.rs +++ b/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}; diff --git a/crates/wasi-common/src/sys/windows/hostcalls_impl/fs_helpers.rs b/crates/wasi-common/src/sys/windows/hostcalls_impl/fs_helpers.rs index 7d35a4d95f..41ea9bbacf 100644 --- a/crates/wasi-common/src/sys/windows/hostcalls_impl/fs_helpers.rs +++ b/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}; diff --git a/crates/wasi-common/src/sys/windows/hostcalls_impl/misc.rs b/crates/wasi-common/src/sys/windows/hostcalls_impl/misc.rs index cb27e3690f..51539bf7ae 100644 --- a/crates/wasi-common/src/sys/windows/hostcalls_impl/misc.rs +++ b/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; diff --git a/crates/wasi-common/src/sys/windows/mod.rs b/crates/wasi-common/src/sys/windows/mod.rs index b9e51e25f8..7bece1e056 100644 --- a/crates/wasi-common/src/sys/windows/mod.rs +++ b/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; diff --git a/crates/wasi-common/src/wasi.rs b/crates/wasi-common/src/wasi.rs index 385541a0cf..deb579e24d 100644 --- a/crates/wasi-common/src/wasi.rs +++ b/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 + } +}