this is indeed a nice way to do refs!

This commit is contained in:
Pat Hickey
2021-01-13 15:11:11 -08:00
parent 7beb52a2bc
commit ea94d6f79d
3 changed files with 169 additions and 128 deletions

View File

@@ -3,6 +3,7 @@ use crate::file::{FdFlags, FileCaps, FileType, Filestat, OFlags, WasiFile};
use bitflags::bitflags; use bitflags::bitflags;
use cap_fs_ext::SystemTimeSpec; use cap_fs_ext::SystemTimeSpec;
use std::any::Any; use std::any::Any;
use std::cell::Ref;
use std::convert::TryInto; use std::convert::TryInto;
use std::ops::Deref; use std::ops::Deref;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
@@ -66,9 +67,9 @@ impl DirEntry {
dir, dir,
} }
} }
pub fn get_cap(&self, caps: DirCaps) -> Result<&dyn WasiDir, Error> { pub fn capable_of_dir(&self, caps: DirCaps) -> Result<(), Error> {
if self.caps.contains(caps) { if self.caps.contains(caps) {
Ok(self.dir.deref()) Ok(())
} else { } else {
Err(Error::DirNotCapable { Err(Error::DirNotCapable {
desired: caps, desired: caps,
@@ -76,14 +77,22 @@ impl DirEntry {
}) })
} }
} }
pub fn capable_of_file(&self, caps: FileCaps) -> Result<(), Error> {
if self.file_caps.contains(caps) {
Ok(())
} else {
Err(Error::FileNotCapable {
desired: caps,
has: self.file_caps,
})
}
}
pub fn drop_caps_to(&mut self, caps: DirCaps, file_caps: FileCaps) -> Result<(), Error> { pub fn drop_caps_to(&mut self, caps: DirCaps, file_caps: FileCaps) -> Result<(), Error> {
if self.caps.contains(caps) && self.file_caps.contains(file_caps) { self.capable_of_dir(caps)?;
self.capable_of_file(file_caps)?;
self.caps = caps; self.caps = caps;
self.file_caps = file_caps; self.file_caps = file_caps;
Ok(()) Ok(())
} else {
Err(Error::NotCapable)
}
} }
pub fn child_dir_caps(&self, desired_caps: DirCaps) -> DirCaps { pub fn child_dir_caps(&self, desired_caps: DirCaps) -> DirCaps {
self.caps & desired_caps self.caps & desired_caps
@@ -102,6 +111,17 @@ impl DirEntry {
} }
} }
pub trait DirEntryExt<'a> {
fn get_cap(self, caps: DirCaps) -> Result<Ref<'a, dyn WasiDir>, Error>;
}
impl<'a> DirEntryExt<'a> for Ref<'a, DirEntry> {
fn get_cap(self, caps: DirCaps) -> Result<Ref<'a, dyn WasiDir>, Error> {
self.capable_of_dir(caps)?;
Ok(Ref::map(self, |r| r.dir.deref()))
}
}
bitflags! { bitflags! {
pub struct DirCaps: u32 { pub struct DirCaps: u32 {
const CREATE_DIRECTORY = 0b1; const CREATE_DIRECTORY = 0b1;
@@ -129,11 +149,15 @@ pub struct DirFdStat {
pub dir_caps: DirCaps, pub dir_caps: DirCaps,
} }
pub trait TableDirExt { pub(crate) trait TableDirExt {
fn get_dir(&self, fd: u32) -> Result<Ref<DirEntry>, Error>;
fn is_preopen(&self, fd: u32) -> bool; fn is_preopen(&self, fd: u32) -> bool;
} }
impl TableDirExt for crate::table::Table { impl TableDirExt for crate::table::Table {
fn get_dir(&self, fd: u32) -> Result<Ref<DirEntry>, Error> {
self.get(fd)
}
fn is_preopen(&self, fd: u32) -> bool { fn is_preopen(&self, fd: u32) -> bool {
if self.is::<DirEntry>(fd) { if self.is::<DirEntry>(fd) {
let dir_entry: std::cell::Ref<DirEntry> = self.get(fd).unwrap(); let dir_entry: std::cell::Ref<DirEntry> = self.get(fd).unwrap();

View File

@@ -83,6 +83,15 @@ pub struct Filestat {
pub ctim: Option<std::time::SystemTime>, pub ctim: Option<std::time::SystemTime>,
} }
pub(crate) trait TableFileExt {
fn get_file(&self, fd: u32) -> Result<Ref<FileEntry>, Error>;
}
impl TableFileExt for crate::table::Table {
fn get_file(&self, fd: u32) -> Result<Ref<FileEntry>, Error> {
self.get(fd)
}
}
pub(crate) struct FileEntry { pub(crate) struct FileEntry {
caps: FileCaps, caps: FileCaps,
file: Box<dyn WasiFile>, file: Box<dyn WasiFile>,

View File

@@ -1,6 +1,10 @@
#![allow(unused_variables)] #![allow(unused_variables)]
use crate::dir::{DirCaps, DirEntry, DirFdStat, ReaddirCursor, ReaddirEntity, TableDirExt}; use crate::dir::{
use crate::file::{FdFlags, FdStat, FileCaps, FileEntry, FileEntryExt, FileType, Filestat, OFlags}; DirCaps, DirEntry, DirEntryExt, DirFdStat, ReaddirCursor, ReaddirEntity, TableDirExt,
};
use crate::file::{
FdFlags, FdStat, FileCaps, FileEntry, FileEntryExt, FileType, Filestat, OFlags, TableFileExt,
};
use crate::sched::subscription::{RwEventFlags, SubscriptionResult}; use crate::sched::subscription::{RwEventFlags, SubscriptionResult};
use crate::sched::Poll; use crate::sched::Poll;
use crate::{Error, WasiCtx}; use crate::{Error, WasiCtx};
@@ -194,10 +198,10 @@ impl<'a> wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
len: types::Filesize, len: types::Filesize,
advice: types::Advice, advice: types::Advice,
) -> Result<(), Error> { ) -> Result<(), Error> {
let table = self.table(); self.table()
let file_entry: Ref<FileEntry> = table.get(u32::from(fd))?; .get_file(u32::from(fd))?
let f = file_entry.get_cap(FileCaps::ADVISE)?; .get_cap(FileCaps::ADVISE)?
f.advise(offset, len, advice.into())?; .advise(offset, len, advice.into())?;
Ok(()) Ok(())
} }
@@ -207,10 +211,10 @@ impl<'a> wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
offset: types::Filesize, offset: types::Filesize,
len: types::Filesize, len: types::Filesize,
) -> Result<(), Error> { ) -> Result<(), Error> {
let table = self.table(); self.table()
let file_entry: Ref<FileEntry> = table.get(u32::from(fd))?; .get_file(u32::from(fd))?
let f = file_entry.get_cap(FileCaps::ALLOCATE)?; .get_cap(FileCaps::ALLOCATE)?
f.allocate(offset, len)?; .allocate(offset, len)?;
Ok(()) Ok(())
} }
@@ -242,10 +246,10 @@ impl<'a> wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
} }
fn fd_datasync(&self, fd: types::Fd) -> Result<(), Error> { fn fd_datasync(&self, fd: types::Fd) -> Result<(), Error> {
let table = self.table(); self.table()
let file_entry: Ref<FileEntry> = table.get(u32::from(fd))?; .get_file(u32::from(fd))?
let f = file_entry.get_cap(FileCaps::DATASYNC)?; .get_cap(FileCaps::DATASYNC)?
f.datasync()?; .datasync()?;
Ok(()) Ok(())
} }
@@ -266,10 +270,10 @@ impl<'a> wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
} }
fn fd_fdstat_set_flags(&self, fd: types::Fd, flags: types::Fdflags) -> Result<(), Error> { fn fd_fdstat_set_flags(&self, fd: types::Fd, flags: types::Fdflags) -> Result<(), Error> {
let table = self.table(); self.table()
let file_entry: Ref<FileEntry> = table.get(u32::from(fd))?; .get_file(u32::from(fd))?
let f = file_entry.get_cap(FileCaps::FDSTAT_SET_FLAGS)?; .get_cap(FileCaps::FDSTAT_SET_FLAGS)?
f.set_fdflags(FdFlags::from(&flags))?; .set_fdflags(FdFlags::from(&flags))?;
Ok(()) Ok(())
} }
@@ -299,14 +303,16 @@ impl<'a> wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
let table = self.table(); let table = self.table();
let fd = u32::from(fd); let fd = u32::from(fd);
if table.is::<FileEntry>(fd) { if table.is::<FileEntry>(fd) {
let file_entry: Ref<FileEntry> = table.get(fd)?; let filestat = table
let f = file_entry.get_cap(FileCaps::FILESTAT_GET)?; .get_file(fd)?
let filestat = f.get_filestat()?; .get_cap(FileCaps::FILESTAT_GET)?
.get_filestat()?;
Ok(filestat.into()) Ok(filestat.into())
} else if table.is::<DirEntry>(fd) { } else if table.is::<DirEntry>(fd) {
let dir_entry: Ref<DirEntry> = table.get(fd)?; let filestat = table
let d = dir_entry.get_cap(DirCaps::FILESTAT_GET)?; .get_dir(fd)?
let filestat = d.get_filestat()?; .get_cap(DirCaps::FILESTAT_GET)?
.get_filestat()?;
Ok(filestat.into()) Ok(filestat.into())
} else { } else {
Err(Error::Badf) Err(Error::Badf)
@@ -314,10 +320,10 @@ impl<'a> wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
} }
fn fd_filestat_set_size(&self, fd: types::Fd, size: types::Filesize) -> Result<(), Error> { fn fd_filestat_set_size(&self, fd: types::Fd, size: types::Filesize) -> Result<(), Error> {
let table = self.table(); self.table()
let file_entry: Ref<FileEntry> = table.get(u32::from(fd))?; .get_file(u32::from(fd))?
let f = file_entry.get_cap(FileCaps::FILESTAT_SET_SIZE)?; .get_cap(FileCaps::FILESTAT_SET_SIZE)?
f.set_filestat_size(size)?; .set_filestat_size(size)?;
Ok(()) Ok(())
} }
@@ -359,14 +365,14 @@ impl<'a> wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
None None
}; };
let file_entry: Ref<FileEntry> = table.get(fd).unwrap(); table
let f = file_entry.get_cap(FileCaps::FILESTAT_SET_TIMES)?; .get_file(fd)
f.set_times(atim, mtim)?; .expect("checked that entry is file")
.get_cap(FileCaps::FILESTAT_SET_TIMES)?
.set_times(atim, mtim)?;
Ok(()) Ok(())
} else if table.is::<DirEntry>(fd) { } else if table.is::<DirEntry>(fd) {
use cap_std::time::{Duration, SystemClock}; use cap_std::time::{Duration, SystemClock};
let dir_entry: Ref<DirEntry> = table.get(fd).unwrap();
let d = dir_entry.get_cap(DirCaps::FILESTAT_SET_TIMES)?;
use cap_fs_ext::SystemTimeSpec; use cap_fs_ext::SystemTimeSpec;
let atim = if set_atim { let atim = if set_atim {
@@ -388,7 +394,12 @@ impl<'a> wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
None None
}; };
d.set_times(".", atim, mtim) table
.get_dir(fd)
.expect("checked that entry is dir")
.get_cap(DirCaps::FILESTAT_SET_TIMES)?
.set_times(".", atim, mtim)?;
Ok(())
} else { } else {
Err(Error::Badf) Err(Error::Badf)
} }
@@ -396,8 +407,7 @@ impl<'a> wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
fn fd_read(&self, fd: types::Fd, iovs: &types::IovecArray<'_>) -> Result<types::Size, Error> { fn fd_read(&self, fd: types::Fd, iovs: &types::IovecArray<'_>) -> Result<types::Size, Error> {
let table = self.table(); let table = self.table();
let file_entry: Ref<FileEntry> = table.get(u32::from(fd))?; let f = table.get_file(u32::from(fd))?.get_cap(FileCaps::READ)?;
let f = file_entry.get_cap(FileCaps::READ)?;
let mut guest_slices: Vec<wiggle::GuestSliceMut<u8>> = iovs let mut guest_slices: Vec<wiggle::GuestSliceMut<u8>> = iovs
.iter() .iter()
@@ -424,8 +434,9 @@ impl<'a> wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
offset: types::Filesize, offset: types::Filesize,
) -> Result<types::Size, Error> { ) -> Result<types::Size, Error> {
let table = self.table(); let table = self.table();
let file_entry: Ref<FileEntry> = table.get(u32::from(fd))?; let f = table
let f = file_entry.get_cap(FileCaps::READ | FileCaps::SEEK)?; .get_file(u32::from(fd))?
.get_cap(FileCaps::READ | FileCaps::SEEK)?;
let mut guest_slices: Vec<wiggle::GuestSliceMut<u8>> = iovs let mut guest_slices: Vec<wiggle::GuestSliceMut<u8>> = iovs
.iter() .iter()
@@ -451,8 +462,7 @@ impl<'a> wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
ciovs: &types::CiovecArray<'_>, ciovs: &types::CiovecArray<'_>,
) -> Result<types::Size, Error> { ) -> Result<types::Size, Error> {
let table = self.table(); let table = self.table();
let file_entry: Ref<FileEntry> = table.get(u32::from(fd))?; let f = table.get_file(u32::from(fd))?.get_cap(FileCaps::WRITE)?;
let f = file_entry.get_cap(FileCaps::WRITE)?;
let guest_slices: Vec<wiggle::GuestSlice<u8>> = ciovs let guest_slices: Vec<wiggle::GuestSlice<u8>> = ciovs
.iter() .iter()
@@ -479,8 +489,9 @@ impl<'a> wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
offset: types::Filesize, offset: types::Filesize,
) -> Result<types::Size, Error> { ) -> Result<types::Size, Error> {
let table = self.table(); let table = self.table();
let file_entry: Ref<FileEntry> = table.get(u32::from(fd))?; let f = table
let f = file_entry.get_cap(FileCaps::WRITE | FileCaps::SEEK)?; .get_file(u32::from(fd))?
.get_cap(FileCaps::WRITE | FileCaps::SEEK)?;
let guest_slices: Vec<wiggle::GuestSlice<u8>> = ciovs let guest_slices: Vec<wiggle::GuestSlice<u8>> = ciovs
.iter() .iter()
@@ -568,31 +579,33 @@ impl<'a> wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
FileCaps::TELL | FileCaps::SEEK FileCaps::TELL | FileCaps::SEEK
}; };
let table = self.table();
let file_entry: Ref<FileEntry> = table.get(u32::from(fd))?;
let f = file_entry.get_cap(required_caps)?;
let whence = match whence { let whence = match whence {
types::Whence::Cur => SeekFrom::Current(offset), types::Whence::Cur => SeekFrom::Current(offset),
types::Whence::End => SeekFrom::End(offset), types::Whence::End => SeekFrom::End(offset),
types::Whence::Set => SeekFrom::Start(offset as u64), types::Whence::Set => SeekFrom::Start(offset as u64),
}; };
let newoffset = f.seek(whence)?; let newoffset = self
.table()
.get_file(u32::from(fd))?
.get_cap(required_caps)?
.seek(whence)?;
Ok(newoffset) Ok(newoffset)
} }
fn fd_sync(&self, fd: types::Fd) -> Result<(), Error> { fn fd_sync(&self, fd: types::Fd) -> Result<(), Error> {
let table = self.table(); self.table()
let file_entry: Ref<FileEntry> = table.get(u32::from(fd))?; .get_file(u32::from(fd))?
let f = file_entry.get_cap(FileCaps::SYNC)?; .get_cap(FileCaps::SYNC)?
f.sync()?; .sync()?;
Ok(()) Ok(())
} }
fn fd_tell(&self, fd: types::Fd) -> Result<types::Filesize, Error> { fn fd_tell(&self, fd: types::Fd) -> Result<types::Filesize, Error> {
let table = self.table(); let offset = self
let file_entry: Ref<FileEntry> = table.get(u32::from(fd))?; .table()
let f = file_entry.get_cap(FileCaps::TELL)?; .get_file(u32::from(fd))?
let offset = f.seek(std::io::SeekFrom::Current(0))?; .get_cap(FileCaps::TELL)?
.seek(std::io::SeekFrom::Current(0))?;
Ok(offset) Ok(offset)
} }
@@ -603,19 +616,14 @@ impl<'a> wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
buf_len: types::Size, buf_len: types::Size,
cookie: types::Dircookie, cookie: types::Dircookie,
) -> Result<types::Size, Error> { ) -> Result<types::Size, Error> {
let table = self.table();
let fd = u32::from(fd);
debug!(
"fd_readdir {} is a DirEntry: {}",
fd,
table.is::<DirEntry>(fd)
);
let dir_entry: Ref<DirEntry> = table.get(fd)?;
let d = dir_entry.get_cap(DirCaps::READDIR)?;
let mut bufused = 0; let mut bufused = 0;
let mut buf = buf.clone(); let mut buf = buf.clone();
for pair in d.readdir(ReaddirCursor::from(cookie))? { for pair in self
.table()
.get_dir(u32::from(fd))?
.get_cap(DirCaps::READDIR)?
.readdir(ReaddirCursor::from(cookie))?
{
let (entity, name) = pair?; let (entity, name) = pair?;
let dirent_raw = dirent_bytes(types::Dirent::from(&entity)); let dirent_raw = dirent_bytes(types::Dirent::from(&entity));
let dirent_len: types::Size = dirent_raw.len().try_into()?; let dirent_len: types::Size = dirent_raw.len().try_into()?;
@@ -659,11 +667,10 @@ impl<'a> wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
dirfd: types::Fd, dirfd: types::Fd,
path: &GuestPtr<'_, str>, path: &GuestPtr<'_, str>,
) -> Result<(), Error> { ) -> Result<(), Error> {
let table = self.table(); self.table()
let dir_entry: Ref<DirEntry> = table.get(u32::from(dirfd))?; .get_dir(u32::from(dirfd))?
let dir = dir_entry.get_cap(DirCaps::CREATE_DIRECTORY)?; .get_cap(DirCaps::CREATE_DIRECTORY)?
let path = path.as_str()?; .create_dir(path.as_str()?.deref())
dir.create_dir(path.deref())
} }
fn path_filestat_get( fn path_filestat_get(
@@ -672,10 +679,11 @@ impl<'a> wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
flags: types::Lookupflags, flags: types::Lookupflags,
path: &GuestPtr<'_, str>, path: &GuestPtr<'_, str>,
) -> Result<types::Filestat, Error> { ) -> Result<types::Filestat, Error> {
let table = self.table(); let filestat = self
let dir_entry: Ref<DirEntry> = table.get(u32::from(dirfd))?; .table()
let dir = dir_entry.get_cap(DirCaps::PATH_FILESTAT_GET)?; .get_dir(u32::from(dirfd))?
let filestat = dir.get_path_filestat(path.as_str()?.deref())?; .get_cap(DirCaps::PATH_FILESTAT_GET)?
.get_path_filestat(path.as_str()?.deref())?;
Ok(types::Filestat::from(filestat)) Ok(types::Filestat::from(filestat))
} }
@@ -688,11 +696,6 @@ impl<'a> wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
mtim: types::Timestamp, mtim: types::Timestamp,
fst_flags: types::Fstflags, fst_flags: types::Fstflags,
) -> Result<(), Error> { ) -> Result<(), Error> {
let table = self.table();
let dir_entry: Ref<DirEntry> = table.get(u32::from(dirfd))?;
let dir = dir_entry.get_cap(DirCaps::PATH_FILESTAT_SET_TIMES)?;
let path = path.as_str()?;
// XXX DRY these are in fd_filestat_set_times twice! // XXX DRY these are in fd_filestat_set_times twice!
let set_atim = fst_flags.contains(types::Fstflags::ATIM); let set_atim = fst_flags.contains(types::Fstflags::ATIM);
let set_atim_now = fst_flags.contains(types::Fstflags::ATIM_NOW); let set_atim_now = fst_flags.contains(types::Fstflags::ATIM_NOW);
@@ -722,7 +725,10 @@ impl<'a> wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
None None
}; };
dir.set_times(path.deref(), atim, mtim) self.table()
.get_dir(u32::from(dirfd))?
.get_cap(DirCaps::PATH_FILESTAT_SET_TIMES)?
.set_times(path.as_str()?.deref(), atim, mtim)
} }
fn path_link( fn path_link(
@@ -734,10 +740,12 @@ impl<'a> wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
target_path: &GuestPtr<'_, str>, target_path: &GuestPtr<'_, str>,
) -> Result<(), Error> { ) -> Result<(), Error> {
let table = self.table(); let table = self.table();
let src_entry: Ref<DirEntry> = table.get(u32::from(src_fd))?; let src_dir = table
let src_dir = src_entry.get_cap(DirCaps::LINK_SOURCE)?; .get_dir(u32::from(src_fd))?
let target_entry: Ref<DirEntry> = table.get(u32::from(target_fd))?; .get_cap(DirCaps::LINK_SOURCE)?;
let target_dir = target_entry.get_cap(DirCaps::LINK_TARGET)?; let target_dir = table
.get_dir(u32::from(target_fd))?
.get_cap(DirCaps::LINK_TARGET)?;
let symlink_follow = src_flags.contains(types::Lookupflags::SYMLINK_FOLLOW); let symlink_follow = src_flags.contains(types::Lookupflags::SYMLINK_FOLLOW);
src_dir.hard_link( src_dir.hard_link(
@@ -763,7 +771,7 @@ impl<'a> wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
if table.is::<FileEntry>(dirfd) { if table.is::<FileEntry>(dirfd) {
return Err(Error::Notdir); return Err(Error::Notdir);
} }
let dir_entry: Ref<DirEntry> = table.get(dirfd)?; let dir_entry = table.get_dir(dirfd)?;
let symlink_follow = dirflags.contains(types::Lookupflags::SYMLINK_FOLLOW); let symlink_follow = dirflags.contains(types::Lookupflags::SYMLINK_FOLLOW);
@@ -777,12 +785,11 @@ impl<'a> wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
{ {
return Err(Error::Inval); return Err(Error::Inval);
} }
let dir = dir_entry.get_cap(DirCaps::OPEN)?;
let child_dir = dir.open_dir(symlink_follow, path.deref())?;
let dir_caps = dir_entry.child_dir_caps(DirCaps::from(&fs_rights_base)); let dir_caps = dir_entry.child_dir_caps(DirCaps::from(&fs_rights_base));
let file_caps = dir_entry.child_file_caps(FileCaps::from(&fs_rights_inheriting)); let file_caps = dir_entry.child_file_caps(FileCaps::from(&fs_rights_inheriting));
let dir = dir_entry.get_cap(DirCaps::OPEN)?;
let child_dir = dir.open_dir(symlink_follow, path.deref())?;
drop(dir); drop(dir);
drop(dir_entry);
let fd = table.push(Box::new(DirEntry::new( let fd = table.push(Box::new(DirEntry::new(
dir_caps, file_caps, None, child_dir, dir_caps, file_caps, None, child_dir,
)))?; )))?;
@@ -793,11 +800,10 @@ impl<'a> wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
required_caps = required_caps | DirCaps::CREATE_FILE; required_caps = required_caps | DirCaps::CREATE_FILE;
} }
let dir = dir_entry.get_cap(required_caps)?;
let file_caps = dir_entry.child_file_caps(FileCaps::from(&fs_rights_base)); let file_caps = dir_entry.child_file_caps(FileCaps::from(&fs_rights_base));
let dir = dir_entry.get_cap(required_caps)?;
let file = dir.open_file(symlink_follow, path.deref(), oflags, file_caps, fdflags)?; let file = dir.open_file(symlink_follow, path.deref(), oflags, file_caps, fdflags)?;
drop(dir); drop(dir);
drop(dir_entry);
let fd = table.push(Box::new(FileEntry::new(file_caps, file)))?; let fd = table.push(Box::new(FileEntry::new(file_caps, file)))?;
Ok(types::Fd::from(fd)) Ok(types::Fd::from(fd))
} }
@@ -810,12 +816,11 @@ impl<'a> wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
buf: &GuestPtr<u8>, buf: &GuestPtr<u8>,
buf_len: types::Size, buf_len: types::Size,
) -> Result<types::Size, Error> { ) -> Result<types::Size, Error> {
let table = self.table(); let link = self
let dir_entry: Ref<DirEntry> = table.get(u32::from(dirfd))?; .table()
let dir = dir_entry.get_cap(DirCaps::READLINK)?; .get_dir(u32::from(dirfd))?
let path = path.as_str()?; .get_cap(DirCaps::READLINK)?
let link = dir .read_link(path.as_str()?.deref())?
.read_link(path.deref())?
.into_os_string() .into_os_string()
.into_string() .into_string()
.map_err(|_| Error::Ilseq)?; .map_err(|_| Error::Ilseq)?;
@@ -834,11 +839,10 @@ impl<'a> wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
dirfd: types::Fd, dirfd: types::Fd,
path: &GuestPtr<'_, str>, path: &GuestPtr<'_, str>,
) -> Result<(), Error> { ) -> Result<(), Error> {
let table = self.table(); self.table()
let dir_entry: Ref<DirEntry> = table.get(u32::from(dirfd))?; .get_dir(u32::from(dirfd))?
let dir = dir_entry.get_cap(DirCaps::REMOVE_DIRECTORY)?; .get_cap(DirCaps::REMOVE_DIRECTORY)?
let path = path.as_str()?; .remove_dir(path.as_str()?.deref())
dir.remove_dir(path.deref())
} }
fn path_rename( fn path_rename(
@@ -849,10 +853,12 @@ impl<'a> wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
dest_path: &GuestPtr<'_, str>, dest_path: &GuestPtr<'_, str>,
) -> Result<(), Error> { ) -> Result<(), Error> {
let table = self.table(); let table = self.table();
let src_entry: Ref<DirEntry> = table.get(u32::from(src_fd))?; let src_dir = table
let src_dir = src_entry.get_cap(DirCaps::RENAME_SOURCE)?; .get_dir(u32::from(src_fd))?
let dest_entry: Ref<DirEntry> = table.get(u32::from(dest_fd))?; .get_cap(DirCaps::RENAME_SOURCE)?;
let dest_dir = dest_entry.get_cap(DirCaps::RENAME_TARGET)?; let dest_dir = table
.get_dir(u32::from(dest_fd))?
.get_cap(DirCaps::RENAME_TARGET)?;
src_dir.rename( src_dir.rename(
src_path.as_str()?.deref(), src_path.as_str()?.deref(),
dest_dir.deref(), dest_dir.deref(),
@@ -866,20 +872,17 @@ impl<'a> wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
dirfd: types::Fd, dirfd: types::Fd,
dest_path: &GuestPtr<'_, str>, dest_path: &GuestPtr<'_, str>,
) -> Result<(), Error> { ) -> Result<(), Error> {
let table = self.table(); self.table()
let dir_entry: Ref<DirEntry> = table.get(u32::from(dirfd))?; .get_dir(u32::from(dirfd))?
let dir = dir_entry.get_cap(DirCaps::SYMLINK)?; .get_cap(DirCaps::SYMLINK)?
let src_path = src_path.as_str()?; .symlink(src_path.as_str()?.deref(), dest_path.as_str()?.deref())
let dest_path = dest_path.as_str()?;
dir.symlink(src_path.deref(), dest_path.deref())
} }
fn path_unlink_file(&self, dirfd: types::Fd, path: &GuestPtr<'_, str>) -> Result<(), Error> { fn path_unlink_file(&self, dirfd: types::Fd, path: &GuestPtr<'_, str>) -> Result<(), Error> {
let table = self.table(); self.table()
let dir_entry: Ref<DirEntry> = table.get(u32::from(dirfd))?; .get_dir(u32::from(dirfd))?
let dir = dir_entry.get_cap(DirCaps::UNLINK_FILE)?; .get_cap(DirCaps::UNLINK_FILE)?
let path = path.as_str()?; .unlink_file(path.as_str()?.deref())
dir.unlink_file(path.deref())
} }
fn poll_oneoff( fn poll_oneoff(
@@ -921,12 +924,17 @@ impl<'a> wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
}, },
types::SubscriptionU::FdRead(readsub) => { types::SubscriptionU::FdRead(readsub) => {
let fd = readsub.file_descriptor; let fd = readsub.file_descriptor;
let file_entry: Ref<FileEntry> = table.get(u32::from(fd))?; let file = table
let f = file_entry.get_cap(FileCaps::POLL_READWRITE)?; .get_file(u32::from(fd))?
poll.subscribe_read(f, sub.userdata.into()); .get_cap(FileCaps::POLL_READWRITE)?;
poll.subscribe_read(file, sub.userdata.into());
} }
types::SubscriptionU::FdWrite(writesub) => { types::SubscriptionU::FdWrite(writesub) => {
todo!() let fd = writesub.file_descriptor;
let file = table
.get_file(u32::from(fd))?
.get_cap(FileCaps::POLL_READWRITE)?;
poll.subscribe_write(file, sub.userdata.into());
} }
} }
} }