From 27ddbda829795daa22057608304a66c99f2b8dfd Mon Sep 17 00:00:00 2001 From: Pat Hickey Date: Wed, 16 Dec 2020 15:15:48 -0800 Subject: [PATCH] preopens with Caps::all, implement create, remove dir, remove file --- crates/wasi-c2/src/ctx.rs | 2 +- crates/wasi-c2/src/dir.rs | 51 ++++++++++++++++++++--- crates/wasi-c2/src/error.rs | 4 +- crates/wasi-c2/src/file.rs | 21 +++++++--- crates/wasi-c2/src/snapshots/preview_1.rs | 22 +++++++--- 5 files changed, 80 insertions(+), 20 deletions(-) diff --git a/crates/wasi-c2/src/ctx.rs b/crates/wasi-c2/src/ctx.rs index 7295382dfa..a8b6108496 100644 --- a/crates/wasi-c2/src/ctx.rs +++ b/crates/wasi-c2/src/ctx.rs @@ -100,7 +100,7 @@ impl WasiCtxBuilder { dir: Box, path: impl AsRef, ) -> Result<&mut Self, Error> { - let caps = DirCaps::OPEN | DirCaps::CREATE_FILE; // XXX more base caps + let caps = DirCaps::all(); let file_caps = FileCaps::READ | FileCaps::WRITE; // XXX more base caps self.0.table().push(Box::new(DirEntry::new( caps, diff --git a/crates/wasi-c2/src/dir.rs b/crates/wasi-c2/src/dir.rs index 93334bc390..1d5e8d36d6 100644 --- a/crates/wasi-c2/src/dir.rs +++ b/crates/wasi-c2/src/dir.rs @@ -16,10 +16,16 @@ pub trait WasiDir { fn open_dir(&self, symlink_follow: bool, path: &str) -> Result, Error>; + fn create_dir(&self, path: &str) -> Result<(), Error>; + fn readdir( &self, cursor: ReaddirCursor, ) -> Result>>, Error>; + + fn remove_dir(&self, path: &str) -> Result<(), Error>; + + fn unlink_file(&self, path: &str) -> Result<(), Error>; } pub(crate) struct DirEntry { @@ -112,6 +118,31 @@ impl DirCaps { pub const SYMLINK: Self = DirCaps { flags: 512 }; pub const REMOVE_DIRECTORY: Self = DirCaps { flags: 1024 }; pub const UNLINK_FILE: Self = DirCaps { flags: 2048 }; + + // Missing that are in wasi-common directory_base: + // FD_FDSTAT_SET_FLAGS + // FD_SYNC + // FD_ADVISE + // PATH_FILESTAT_GET + // PATH_FILESTAT_SET_SIZE + // PATH_FILESTAT_SET_TIMES + // FD_FILESTAT_GET + // FD_FILESTAT_SET_TIMES + + pub fn all() -> DirCaps { + Self::CREATE_DIRECTORY + | Self::CREATE_FILE + | Self::LINK_SOURCE + | Self::LINK_TARGET + | Self::OPEN + | Self::READDIR + | Self::READLINK + | Self::RENAME_SOURCE + | Self::RENAME_TARGET + | Self::SYMLINK + | Self::REMOVE_DIRECTORY + | Self::UNLINK_FILE + } } impl std::ops::BitOr for DirCaps { @@ -128,12 +159,6 @@ pub struct DirStat { pub dir_caps: DirCaps, } -impl std::fmt::Display for DirCaps { - fn fmt(&self, _f: &mut std::fmt::Formatter) -> std::fmt::Result { - todo!() - } -} - pub trait TableDirExt { fn is_preopen(&self, fd: u32) -> bool; } @@ -219,6 +244,10 @@ impl WasiDir for cap_std::fs::Dir { Ok(Box::new(d)) } + fn create_dir(&self, path: &str) -> Result<(), Error> { + self.create_dir(Path::new(path))?; + Ok(()) + } fn readdir( &self, cursor: ReaddirCursor, @@ -257,4 +286,14 @@ impl WasiDir for cap_std::fs::Dir { Ok((entity, name)) }))) } + + fn remove_dir(&self, path: &str) -> Result<(), Error> { + self.remove_dir(Path::new(path))?; + Ok(()) + } + + fn unlink_file(&self, path: &str) -> Result<(), Error> { + self.remove_file(Path::new(path))?; + Ok(()) + } } diff --git a/crates/wasi-c2/src/error.rs b/crates/wasi-c2/src/error.rs index 8c278eb7ef..47920ce6b2 100644 --- a/crates/wasi-c2/src/error.rs +++ b/crates/wasi-c2/src/error.rs @@ -17,11 +17,11 @@ pub enum Error { GetRandom(#[from] getrandom::Error), /// Errno::Notcapable: Extension: Capabilities insufficient - #[error("File not capable: desired {desired}, has {has}")] + #[error("File not capable: desired {desired:?}, has {has:?}")] FileNotCapable { desired: FileCaps, has: FileCaps }, /// Errno::Notcapable: Extension: Capabilities insufficient - #[error("Directory not capable: desired {desired}, has {has}")] + #[error("Directory not capable: desired {desired:?}, has {has:?}")] DirNotCapable { desired: DirCaps, has: DirCaps }, /// Idk what the deal with this guy is yet diff --git a/crates/wasi-c2/src/file.rs b/crates/wasi-c2/src/file.rs index 9674650630..c7530d3d9e 100644 --- a/crates/wasi-c2/src/file.rs +++ b/crates/wasi-c2/src/file.rs @@ -170,6 +170,21 @@ impl FileCaps { pub const FILESTAT_GET: Self = FileCaps { flags: 512 }; pub const FILESTAT_SET_SIZE: Self = FileCaps { flags: 1024 }; pub const FILESTAT_SET_TIMES: Self = FileCaps { flags: 2048 }; + + pub fn all() -> FileCaps { + Self::DATASYNC + | Self::READ + | Self::SEEK + | Self::FDSTAT_SET_FLAGS + | Self::SYNC + | Self::TELL + | Self::WRITE + | Self::ADVISE + | Self::ALLOCATE + | Self::FILESTAT_GET + | Self::FILESTAT_SET_SIZE + | Self::FILESTAT_SET_TIMES + } } impl std::ops::BitOr for FileCaps { @@ -181,12 +196,6 @@ impl std::ops::BitOr for FileCaps { } } -impl std::fmt::Display for FileCaps { - fn fmt(&self, _f: &mut std::fmt::Formatter) -> std::fmt::Result { - todo!() - } -} - pub struct FdStat { pub filetype: Filetype, pub caps: FileCaps, diff --git a/crates/wasi-c2/src/snapshots/preview_1.rs b/crates/wasi-c2/src/snapshots/preview_1.rs index fd50c5061b..624956bb6f 100644 --- a/crates/wasi-c2/src/snapshots/preview_1.rs +++ b/crates/wasi-c2/src/snapshots/preview_1.rs @@ -92,8 +92,8 @@ impl From for types::Errno { PtrBorrowed { .. } => Self::Fault, InvalidUtf8 { .. } => Self::Ilseq, TryFromIntError { .. } => Self::Overflow, - InFunc { .. } => Self::Inval, - InDataField { .. } => Self::Inval, + InFunc { err, .. } => types::Errno::from(*err), + InDataField { err, .. } => types::Errno::from(*err), SliceLengthsDiffer { .. } => Self::Fault, BorrowCheckerOutOfHandles { .. } => Self::Fault, } @@ -527,7 +527,11 @@ impl<'a> wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx { dirfd: types::Fd, path: &GuestPtr<'_, str>, ) -> Result<(), Error> { - unimplemented!() + let table = self.table(); + let dir_entry: RefMut = table.get(u32::from(dirfd))?; + let dir = dir_entry.get_cap(DirCaps::CREATE_DIRECTORY)?; + let path = path.as_str()?; + dir.create_dir(path.deref()) } fn path_filestat_get( @@ -628,7 +632,11 @@ impl<'a> wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx { dirfd: types::Fd, path: &GuestPtr<'_, str>, ) -> Result<(), Error> { - unimplemented!() + let table = self.table(); + let dir_entry: RefMut = table.get(u32::from(dirfd))?; + let dir = dir_entry.get_cap(DirCaps::REMOVE_DIRECTORY)?; + let path = path.as_str()?; + dir.remove_dir(path.deref()) } fn path_rename( @@ -651,7 +659,11 @@ impl<'a> wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx { } fn path_unlink_file(&self, dirfd: types::Fd, path: &GuestPtr<'_, str>) -> Result<(), Error> { - unimplemented!() + let table = self.table(); + let dir_entry: RefMut = table.get(u32::from(dirfd))?; + let dir = dir_entry.get_cap(DirCaps::UNLINK_FILE)?; + let path = path.as_str()?; + dir.unlink_file(path.deref()) } fn poll_oneoff(