[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`.
This commit is contained in:
Jakub Konka
2020-03-17 22:58:49 +01:00
committed by GitHub
parent ba0dc40b2b
commit 7228a248c1
33 changed files with 419 additions and 319 deletions

View File

@@ -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)
}
}

View File

@@ -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.

View File

@@ -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)?;

View File

@@ -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,

View File

@@ -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 {

View File

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

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

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

View File

@@ -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;

View File

@@ -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};

View File

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