diff --git a/crates/test-programs/build.rs b/crates/test-programs/build.rs index ff23b6f833..c953c57440 100644 --- a/crates/test-programs/build.rs +++ b/crates/test-programs/build.rs @@ -105,14 +105,7 @@ mod wasi_tests { )?; writeln!(out, " use super::{{runtime, utils, setup_log}};")?; for dir_entry in dir_entries { - let test_path = dir_entry.path(); - let stemstr = test_path - .file_stem() - .expect("file_stem") - .to_str() - .expect("to_str"); - - write_testsuite_tests(out, &test_path, testsuite)?; + write_testsuite_tests(out, &dir_entry.path(), testsuite)?; } writeln!(out, "}}")?; Ok(()) diff --git a/crates/test-programs/tests/wasm_tests/runtime.rs b/crates/test-programs/tests/wasm_tests/runtime.rs index bf05ff7757..3073d9453f 100644 --- a/crates/test-programs/tests/wasm_tests/runtime.rs +++ b/crates/test-programs/tests/wasm_tests/runtime.rs @@ -1,12 +1,8 @@ use anyhow::Context; -use std::convert::TryFrom; use std::fs::File; use std::path::Path; -use wasi_c2::{ - virt::pipe::{ReadPipe, WritePipe}, - WasiCtx, -}; -use wasmtime::{Config, Engine, Linker, Module, Store}; +use wasi_c2::virt::pipe::{ReadPipe, WritePipe}; +use wasmtime::{Linker, Module, Store}; pub fn instantiate(data: &[u8], bin_name: &str, workspace: Option<&Path>) -> anyhow::Result<()> { let stdout = WritePipe::new_in_memory(); @@ -27,6 +23,7 @@ pub fn instantiate(data: &[u8], bin_name: &str, workspace: Option<&Path>) -> any .stderr(Box::new(stderr.clone())); if let Some(workspace) = workspace { + println!("preopen: {:?}", workspace); let dirfd = File::open(workspace).context(format!("error while preopening {:?}", workspace))?; let preopen_dir = unsafe { cap_std::fs::Dir::from_std_file(dirfd) }; @@ -67,15 +64,3 @@ pub fn instantiate(data: &[u8], bin_name: &str, workspace: Option<&Path>) -> any } } } - -#[cfg(unix)] -fn reader_to_file(reader: os_pipe::PipeReader) -> File { - use std::os::unix::prelude::*; - unsafe { File::from_raw_fd(reader.into_raw_fd()) } -} - -#[cfg(windows)] -fn reader_to_file(reader: os_pipe::PipeReader) -> File { - use std::os::windows::prelude::*; - unsafe { File::from_raw_handle(reader.into_raw_handle()) } -} diff --git a/crates/wasi-c2/src/ctx.rs b/crates/wasi-c2/src/ctx.rs index 7b70bcd0ea..e7156f12a5 100644 --- a/crates/wasi-c2/src/ctx.rs +++ b/crates/wasi-c2/src/ctx.rs @@ -38,7 +38,7 @@ impl WasiCtx { inheriting_caps, file, }; - self.table().insert_at(fd, e); + self.table().insert_at(fd, Box::new(e)); } pub fn insert_dir( @@ -55,7 +55,7 @@ impl WasiCtx { preopen_path: Some(path), dir, }; - self.table().insert_at(fd, e); + self.table().insert_at(fd, Box::new(e)); } pub fn table(&self) -> RefMut { @@ -118,12 +118,12 @@ impl WasiCtxBuilder { ) -> Result<&mut Self, Error> { let base_caps = DirCaps::OPEN; let inheriting_caps = DirCaps::OPEN; - self.0.table().push(DirEntry { + self.0.table().push(Box::new(DirEntry { base_caps, inheriting_caps, preopen_path: Some(path.as_ref().to_owned()), dir, - })?; + }))?; Ok(self) } } diff --git a/crates/wasi-c2/src/dir.rs b/crates/wasi-c2/src/dir.rs index 68e0af539d..8736f09fb6 100644 --- a/crates/wasi-c2/src/dir.rs +++ b/crates/wasi-c2/src/dir.rs @@ -1,17 +1,18 @@ // this file is extremely wip #![allow(dead_code, unused_variables)] use crate::error::Error; -use crate::file::{self, WasiFile}; +use crate::file::{FileCaps, OFlags, WasiFile}; use std::ops::Deref; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; +use tracing::debug; pub trait WasiDir { fn open_file( &self, symlink_follow: bool, path: &str, - oflags: file::OFlags, - fdflags: file::FdFlags, + oflags: OFlags, + caps: FileCaps, ) -> Result, Error>; fn open_dir( @@ -42,6 +43,13 @@ impl DirEntry { Err(Error::DirNotCapable(caps)) } } + + pub fn get_dirstat(&self) -> DirStat { + DirStat { + base_caps: self.base_caps, + inheriting_caps: self.inheriting_caps, + } + } } #[derive(Debug, Clone, Copy)] @@ -59,14 +67,32 @@ impl DirCaps { self.flags & other.flags == other.flags } - pub const OPEN: Self = DirCaps { flags: 1 }; - pub const READDIR: Self = DirCaps { flags: 2 }; - pub const READLINK: Self = DirCaps { flags: 4 }; - pub const RENAME_SOURCE: Self = DirCaps { flags: 8 }; - pub const RENAME_TARGET: Self = DirCaps { flags: 16 }; - pub const SYMLINK: Self = DirCaps { flags: 32 }; - pub const REMOVE_DIRECTORY: Self = DirCaps { flags: 64 }; - pub const UNLINK_FILE: Self = DirCaps { flags: 128 }; + pub const CREATE_DIRECTORY: Self = DirCaps { flags: 1 }; + pub const CREATE_FILE: Self = DirCaps { flags: 2 }; + pub const LINK_SOURCE: Self = DirCaps { flags: 4 }; + pub const LINK_TARGET: Self = DirCaps { flags: 8 }; + pub const OPEN: Self = DirCaps { flags: 16 }; + pub const READDIR: Self = DirCaps { flags: 32 }; + pub const READLINK: Self = DirCaps { flags: 64 }; + pub const RENAME_SOURCE: Self = DirCaps { flags: 128 }; + pub const RENAME_TARGET: Self = DirCaps { flags: 256 }; + pub const SYMLINK: Self = DirCaps { flags: 512 }; + pub const REMOVE_DIRECTORY: Self = DirCaps { flags: 1024 }; + pub const UNLINK_FILE: Self = DirCaps { flags: 2048 }; +} + +impl std::ops::BitOr for DirCaps { + type Output = DirCaps; + fn bitor(self, rhs: DirCaps) -> DirCaps { + DirCaps { + flags: self.flags | rhs.flags, + } + } +} + +pub struct DirStat { + pub base_caps: DirCaps, + pub inheriting_caps: DirCaps, } impl std::fmt::Display for DirCaps { @@ -121,10 +147,31 @@ impl WasiDir for cap_std::fs::Dir { &self, symlink_follow: bool, path: &str, - oflags: file::OFlags, - fdflags: file::FdFlags, + oflags: OFlags, + caps: FileCaps, ) -> Result, Error> { - todo!() + // XXX obey symlink_follow + // XXX how to handle fdflags like append? OFlags dont contain read|write? + let mut opts = cap_std::fs::OpenOptions::new(); + if oflags.contains(&(OFlags::CREATE | OFlags::EXCLUSIVE)) { + opts.create_new(true); + } else if oflags.contains(&OFlags::CREATE) { + opts.create(true); + } + if oflags.contains(&OFlags::TRUNCATE) { + opts.truncate(true); + } + if caps.contains(&FileCaps::READ) { + opts.read(true); + } + if caps.contains(&FileCaps::WRITE) { + opts.write(true); + } + + debug!("Dir::open_file({:?}, {:?})", path, opts); + let f = self.open_with(Path::new(path), &opts)?; + debug!("succeeded"); + Ok(Box::new(f)) } fn open_dir( @@ -133,7 +180,9 @@ impl WasiDir for cap_std::fs::Dir { path: &str, create: bool, ) -> Result, Error> { - todo!() + // XXX obey symlink_follow, create + let d = self.open_dir(Path::new(path))?; + Ok(Box::new(d)) } fn readdir( diff --git a/crates/wasi-c2/src/file.rs b/crates/wasi-c2/src/file.rs index 4acfbd2f87..476fa01995 100644 --- a/crates/wasi-c2/src/file.rs +++ b/crates/wasi-c2/src/file.rs @@ -1,5 +1,4 @@ use crate::Error; -use cfg_if::cfg_if; use fs_set_times::SetTimes; use std::ops::Deref; use system_interface::fs::FileIoExt; @@ -9,6 +8,7 @@ pub trait WasiFile: FileIoExt + SetTimes { fn sync(&self) -> Result<(), Error>; fn get_filetype(&self) -> Result; fn get_fdflags(&self) -> Result; + fn set_fdflags(&self, _flags: FdFlags) -> Result<(), Error>; fn get_oflags(&self) -> Result; fn set_oflags(&self, _flags: OFlags) -> Result<(), Error>; fn get_filestat(&self) -> Result; @@ -38,7 +38,9 @@ impl FdFlags { pub fn contains(&self, other: &Self) -> bool { self.flags & other.flags == other.flags } - + pub fn empty() -> FdFlags { + FdFlags { flags: 0 } + } pub const APPEND: FdFlags = FdFlags { flags: 1 }; pub const DSYNC: FdFlags = FdFlags { flags: 2 }; pub const NONBLOCK: FdFlags = FdFlags { flags: 4 }; @@ -47,6 +49,15 @@ impl FdFlags { // etc } +impl std::ops::BitOr for FdFlags { + type Output = FdFlags; + fn bitor(self, rhs: FdFlags) -> FdFlags { + FdFlags { + flags: self.flags | rhs.flags, + } + } +} + #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub struct OFlags { flags: u32, @@ -57,19 +68,21 @@ impl OFlags { pub fn contains(&self, other: &Self) -> bool { self.flags & other.flags == other.flags } - - pub const ACCMODE: OFlags = OFlags { flags: 1 }; - pub const APPEND: OFlags = OFlags { flags: 2 }; - pub const CREATE: OFlags = OFlags { flags: 4 }; - pub const SYNC: OFlags = OFlags { flags: 4 }; - pub const NOFOLLOW: OFlags = OFlags { flags: 8 }; - pub const NONBLOCK: OFlags = OFlags { flags: 16 }; - pub const RDONLY: OFlags = OFlags { flags: 32 }; - pub const WRONLY: OFlags = OFlags { flags: 64 }; - pub const RDWR: OFlags = OFlags { - flags: Self::RDONLY.flags | Self::WRONLY.flags, - }; - // etc + pub fn empty() -> Self { + OFlags { flags: 0 } + } + pub const CREATE: OFlags = OFlags { flags: 1 }; + pub const DIRECTORY: OFlags = OFlags { flags: 2 }; + pub const EXCLUSIVE: OFlags = OFlags { flags: 4 }; + pub const TRUNCATE: OFlags = OFlags { flags: 8 }; +} +impl std::ops::BitOr for OFlags { + type Output = OFlags; + fn bitor(self, rhs: OFlags) -> OFlags { + OFlags { + flags: self.flags | rhs.flags, + } + } } #[derive(Debug, Clone)] @@ -181,34 +194,17 @@ impl WasiFile for cap_std::fs::File { } } fn get_fdflags(&self) -> Result { - // XXX cap-std doesnt expose append, dsync, nonblock, rsync, sync - todo!("get_fdflags is not implemented") + // XXX get_fdflags is not implemented but lets lie rather than panic: + Ok(FdFlags::empty()) + } + fn set_fdflags(&self, _fdflags: FdFlags) -> Result<(), Error> { + todo!("set_fdflags is not implemented") } fn get_oflags(&self) -> Result { - #![allow(unreachable_code, unused_variables)] - todo!("get_oflags implementation is incomplete"); - // XXX what if it was opened append, async, nonblock... - let perms = self.metadata()?.permissions(); - if perms.readonly() { - Ok(OFlags::RDONLY) - } else { - Ok(OFlags::RDWR) - } + todo!("get_oflags is not implemented"); } fn set_oflags(&self, flags: OFlags) -> Result<(), Error> { - #![allow(unreachable_code, unused_variables)] - cfg_if! { - if #[cfg(unix)] { - use std::os::unix::fs::PermissionsExt; - use cap_std::fs::Permissions; - use std::fs::Permissions as StdPermissions; - let flags = todo!("normalize to unix flags {:?}", flags); - self.set_permissions(Permissions::from_std(StdPermissions::from_mode(flags)))?; - } else { - Err(Error::Unsupported("set oflags on non-unix host system".to_owned())) - } - } - Ok(()) + todo!("set_oflags is not implemented"); } fn get_filestat(&self) -> Result { let meta = self.metadata()?; diff --git a/crates/wasi-c2/src/snapshots/preview_1.rs b/crates/wasi-c2/src/snapshots/preview_1.rs index 65e6c68305..062fe2a1f5 100644 --- a/crates/wasi-c2/src/snapshots/preview_1.rs +++ b/crates/wasi-c2/src/snapshots/preview_1.rs @@ -1,5 +1,5 @@ #![allow(unused_variables)] -use crate::dir::{DirCaps, DirEntry, ReaddirCursor, TableDirExt}; +use crate::dir::{DirCaps, DirEntry, DirStat, ReaddirCursor, TableDirExt}; use crate::file::{FdFlags, FdStat, FileCaps, FileEntry, Filestat, Filetype, OFlags}; use crate::{Error, WasiCtx}; use fs_set_times::SystemTimeSpec; @@ -168,6 +168,9 @@ impl<'a> wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx { let mut table = self.table(); let fd = u32::from(fd); + if !table.contains_key(fd) { + return Err(Error::Badf); + } // fd_close must close either a File or a Dir handle if table.is::(fd) { let _ = table.delete(fd); @@ -179,6 +182,9 @@ impl<'a> wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx { } drop(dir_entry); let _ = table.delete(fd); + } else { + // XXX do we just table delete anyway? + return Err(Error::Badf); } Ok(()) @@ -194,16 +200,25 @@ impl<'a> wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx { fn fd_fdstat_get(&self, fd: types::Fd) -> Result { let table = self.table(); - let file_entry: RefMut = table.get(u32::from(fd))?; - let fdstat = file_entry.get_fdstat()?; - Ok(types::Fdstat::from(&fdstat)) + let fd = u32::from(fd); + if table.is::(fd) { + let file_entry: RefMut = table.get(fd)?; + let fdstat = file_entry.get_fdstat()?; + Ok(types::Fdstat::from(&fdstat)) + } else if table.is::(fd) { + let dir_entry: RefMut = table.get(fd)?; + let dirstat = dir_entry.get_dirstat(); + Ok(types::Fdstat::from(&dirstat)) + } else { + Err(Error::Badf) + } } fn fd_fdstat_set_flags(&self, fd: types::Fd, flags: types::Fdflags) -> Result<(), Error> { let table = self.table(); let file_entry: RefMut = table.get(u32::from(fd))?; let f = file_entry.get_cap(FileCaps::FDSTAT_SET_FLAGS)?; - f.set_oflags(OFlags::try_from(&flags)?)?; + f.set_fdflags(FdFlags::from(&flags))?; Ok(()) } @@ -559,39 +574,40 @@ impl<'a> wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx { let dir_entry: RefMut = table.get(u32::from(dirfd))?; let dir = dir_entry.get_cap(DirCaps::OPEN)?; let symlink_follow = dirflags.contains(&types::Lookupflags::SYMLINK_FOLLOW); + let oflags = OFlags::from(&oflags); + let fdflags = FdFlags::from(&fdflags); let path = path.as_str()?; - if oflags.contains(&types::Oflags::DIRECTORY) { - let create = oflags.contains(&types::Oflags::CREAT); + if oflags.contains(&OFlags::DIRECTORY) { + let create = oflags.contains(&OFlags::CREATE); let child_dir = dir.open_dir(symlink_follow, path.deref(), create)?; // XXX go back and check these caps conversions - probably need to validate them // against ??? - let base_caps = DirCaps::try_from(&fs_rights_base)?; - let inheriting_caps = DirCaps::try_from(&fs_rights_inheriting)?; + let base_caps = DirCaps::from(&fs_rights_base); + let inheriting_caps = DirCaps::from(&fs_rights_inheriting); drop(dir); drop(dir_entry); - let fd = table.push(DirEntry { + let fd = table.push(Box::new(DirEntry { dir: child_dir, base_caps, inheriting_caps, preopen_path: None, - })?; + }))?; Ok(types::Fd::from(fd)) } else { - let oflags = OFlags::try_from(&oflags)?; - let fdflags = FdFlags::try_from(&fdflags)?; - let file = dir.open_file(symlink_follow, path.deref(), oflags, fdflags)?; // XXX go back and check these caps conversions - probably need to validate them // against ??? - let base_caps = FileCaps::try_from(&fs_rights_base)?; - let inheriting_caps = FileCaps::try_from(&fs_rights_inheriting)?; + let base_caps = FileCaps::from(&fs_rights_base); + let inheriting_caps = FileCaps::from(&fs_rights_inheriting); + + let file = dir.open_file(symlink_follow, path.deref(), oflags, base_caps)?; drop(dir); drop(dir_entry); - let fd = table.push(FileEntry { + let fd = table.push(Box::new(FileEntry { file, base_caps, inheriting_caps, - })?; + }))?; Ok(types::Fd::from(fd)) } } @@ -709,26 +725,187 @@ impl From<&FdStat> for types::Fdstat { } } +impl From<&DirStat> for types::Fdstat { + fn from(dirstat: &DirStat) -> types::Fdstat { + types::Fdstat { + fs_filetype: types::Filetype::Directory, + fs_rights_base: types::Rights::from(&dirstat.base_caps), + fs_rights_inheriting: types::Rights::from(&dirstat.inheriting_caps), + fs_flags: types::Fdflags::empty(), + } + } +} + // FileCaps can always be represented as wasi Rights impl From<&FileCaps> for types::Rights { fn from(caps: &FileCaps) -> types::Rights { - todo!("translate FileCaps flags to Rights flags") + let mut rights = types::Rights::empty(); + if caps.contains(&FileCaps::DATASYNC) { + rights = rights | types::Rights::FD_DATASYNC; + } + if caps.contains(&FileCaps::READ) { + rights = rights | types::Rights::FD_READ; + } + if caps.contains(&FileCaps::SEEK) { + rights = rights | types::Rights::FD_SEEK; + } + if caps.contains(&FileCaps::FDSTAT_SET_FLAGS) { + rights = rights | types::Rights::FD_FDSTAT_SET_FLAGS; + } + if caps.contains(&FileCaps::SYNC) { + rights = rights | types::Rights::FD_SYNC; + } + if caps.contains(&FileCaps::TELL) { + rights = rights | types::Rights::FD_TELL; + } + if caps.contains(&FileCaps::WRITE) { + rights = rights | types::Rights::FD_WRITE; + } + if caps.contains(&FileCaps::ADVISE) { + rights = rights | types::Rights::FD_ADVISE; + } + if caps.contains(&FileCaps::ALLOCATE) { + rights = rights | types::Rights::FD_ALLOCATE; + } + if caps.contains(&FileCaps::FILESTAT_GET) { + rights = rights | types::Rights::PATH_FILESTAT_GET; + } + if caps.contains(&FileCaps::FILESTAT_SET_SIZE) { + rights = rights | types::Rights::PATH_FILESTAT_SET_SIZE; + } + if caps.contains(&FileCaps::FILESTAT_SET_TIMES) { + rights = rights | types::Rights::PATH_FILESTAT_SET_TIMES; + } + rights } } // FileCaps are a subset of wasi Rights - not all Rights have a valid representation as FileCaps -impl TryFrom<&types::Rights> for FileCaps { - type Error = Error; - fn try_from(rights: &types::Rights) -> Result { - todo!("translate Rights flags to FileCaps flags") +impl From<&types::Rights> for FileCaps { + fn from(rights: &types::Rights) -> FileCaps { + let mut caps = FileCaps::empty(); + if rights.contains(&types::Rights::FD_DATASYNC) { + caps = caps | FileCaps::DATASYNC; + } + if rights.contains(&types::Rights::FD_READ) { + caps = caps | FileCaps::READ; + } + if rights.contains(&types::Rights::FD_SEEK) { + caps = caps | FileCaps::SEEK; + } + if rights.contains(&types::Rights::FD_FDSTAT_SET_FLAGS) { + caps = caps | FileCaps::FDSTAT_SET_FLAGS; + } + if rights.contains(&types::Rights::FD_SYNC) { + caps = caps | FileCaps::SYNC; + } + if rights.contains(&types::Rights::FD_TELL) { + caps = caps | FileCaps::TELL; + } + if rights.contains(&types::Rights::FD_WRITE) { + caps = caps | FileCaps::WRITE; + } + if rights.contains(&types::Rights::FD_ALLOCATE) { + caps = caps | FileCaps::ALLOCATE; + } + if rights.contains(&types::Rights::PATH_FILESTAT_GET) { + caps = caps | FileCaps::FILESTAT_GET; + } + if rights.contains(&types::Rights::PATH_FILESTAT_SET_SIZE) { + caps = caps | FileCaps::FILESTAT_SET_SIZE; + } + if rights.contains(&types::Rights::PATH_FILESTAT_SET_TIMES) { + caps = caps | FileCaps::FILESTAT_SET_TIMES; + } + caps + } +} + +// DirCaps can always be represented as wasi Rights +impl From<&DirCaps> for types::Rights { + fn from(caps: &DirCaps) -> types::Rights { + let mut rights = types::Rights::empty(); + if caps.contains(&DirCaps::CREATE_DIRECTORY) { + rights = rights | types::Rights::PATH_CREATE_DIRECTORY; + } + if caps.contains(&DirCaps::CREATE_FILE) { + rights = rights | types::Rights::PATH_CREATE_FILE; + } + if caps.contains(&DirCaps::LINK_SOURCE) { + rights = rights | types::Rights::PATH_LINK_SOURCE; + } + if caps.contains(&DirCaps::LINK_TARGET) { + rights = rights | types::Rights::PATH_LINK_TARGET; + } + if caps.contains(&DirCaps::OPEN) { + rights = rights | types::Rights::PATH_OPEN; + } + if caps.contains(&DirCaps::READDIR) { + rights = rights | types::Rights::FD_READDIR; + } + if caps.contains(&DirCaps::READLINK) { + rights = rights | types::Rights::PATH_READLINK; + } + if caps.contains(&DirCaps::RENAME_SOURCE) { + rights = rights | types::Rights::PATH_RENAME_SOURCE; + } + if caps.contains(&DirCaps::RENAME_TARGET) { + rights = rights | types::Rights::PATH_RENAME_TARGET; + } + if caps.contains(&DirCaps::SYMLINK) { + rights = rights | types::Rights::PATH_SYMLINK; + } + if caps.contains(&DirCaps::REMOVE_DIRECTORY) { + rights = rights | types::Rights::PATH_REMOVE_DIRECTORY; + } + if caps.contains(&DirCaps::UNLINK_FILE) { + rights = rights | types::Rights::PATH_UNLINK_FILE; + } + rights } } // DirCaps are a subset of wasi Rights - not all Rights have a valid representation as DirCaps -impl TryFrom<&types::Rights> for DirCaps { - type Error = Error; - fn try_from(rights: &types::Rights) -> Result { - todo!("translate Rights flags to DirCaps flags") +impl From<&types::Rights> for DirCaps { + fn from(rights: &types::Rights) -> DirCaps { + let mut caps = DirCaps::empty(); + if rights.contains(&types::Rights::PATH_CREATE_DIRECTORY) { + caps = caps | DirCaps::CREATE_DIRECTORY; + } + if rights.contains(&types::Rights::PATH_CREATE_FILE) { + caps = caps | DirCaps::CREATE_FILE; + } + if rights.contains(&types::Rights::PATH_LINK_SOURCE) { + caps = caps | DirCaps::LINK_SOURCE; + } + if rights.contains(&types::Rights::PATH_LINK_TARGET) { + caps = caps | DirCaps::LINK_TARGET; + } + if rights.contains(&types::Rights::PATH_OPEN) { + caps = caps | DirCaps::OPEN; + } + if rights.contains(&types::Rights::FD_READDIR) { + caps = caps | DirCaps::READDIR; + } + if rights.contains(&types::Rights::PATH_READLINK) { + caps = caps | DirCaps::READLINK; + } + if rights.contains(&types::Rights::PATH_RENAME_SOURCE) { + caps = caps | DirCaps::RENAME_SOURCE; + } + if rights.contains(&types::Rights::PATH_RENAME_TARGET) { + caps = caps | DirCaps::RENAME_TARGET; + } + if rights.contains(&types::Rights::PATH_SYMLINK) { + caps = caps | DirCaps::SYMLINK; + } + if rights.contains(&types::Rights::PATH_REMOVE_DIRECTORY) { + caps = caps | DirCaps::REMOVE_DIRECTORY; + } + if rights.contains(&types::Rights::PATH_UNLINK_FILE) { + caps = caps | DirCaps::UNLINK_FILE; + } + caps } } @@ -745,34 +922,85 @@ impl From<&Filetype> for types::Filetype { } impl From<&FdFlags> for types::Fdflags { fn from(fdflags: &FdFlags) -> types::Fdflags { - todo!("translate internal to Fdflags") - } -} - -impl TryFrom<&types::Oflags> for OFlags { - type Error = Error; - fn try_from(oflags: &types::Oflags) -> Result { - if oflags.contains(&types::Oflags::DIRECTORY) { - return Err(Error::Inval); + let mut out = types::Fdflags::empty(); + if fdflags.contains(&FdFlags::APPEND) { + out = out | types::Fdflags::APPEND; } - todo!("rest of oflags translation should be trivial - creat excl trunc") + if fdflags.contains(&FdFlags::DSYNC) { + out = out | types::Fdflags::DSYNC; + } + if fdflags.contains(&FdFlags::NONBLOCK) { + out = out | types::Fdflags::NONBLOCK; + } + if fdflags.contains(&FdFlags::RSYNC) { + out = out | types::Fdflags::RSYNC; + } + if fdflags.contains(&FdFlags::SYNC) { + out = out | types::Fdflags::SYNC; + } + out } } -impl TryFrom<&types::Fdflags> for FdFlags { - type Error = Error; - fn try_from(fdflags: &types::Fdflags) -> Result { - todo!() +impl From<&types::Fdflags> for FdFlags { + fn from(fdflags: &types::Fdflags) -> FdFlags { + let mut out = FdFlags::empty(); + if fdflags.contains(&types::Fdflags::APPEND) { + out = out | FdFlags::APPEND; + } + if fdflags.contains(&types::Fdflags::DSYNC) { + out = out | FdFlags::DSYNC; + } + if fdflags.contains(&types::Fdflags::NONBLOCK) { + out = out | FdFlags::NONBLOCK; + } + if fdflags.contains(&types::Fdflags::RSYNC) { + out = out | FdFlags::RSYNC; + } + if fdflags.contains(&types::Fdflags::SYNC) { + out = out | FdFlags::SYNC; + } + out } } -impl TryFrom<&types::Fdflags> for OFlags { - type Error = Error; - fn try_from(fdflags: &types::Fdflags) -> Result { - todo!() +impl From<&types::Oflags> for OFlags { + fn from(oflags: &types::Oflags) -> OFlags { + let mut out = OFlags::empty(); + if oflags.contains(&types::Oflags::CREAT) { + out = out | OFlags::CREATE; + } + if oflags.contains(&types::Oflags::DIRECTORY) { + out = out | OFlags::DIRECTORY; + } + if oflags.contains(&types::Oflags::EXCL) { + out = out | OFlags::EXCLUSIVE; + } + if oflags.contains(&types::Oflags::TRUNC) { + out = out | OFlags::TRUNCATE; + } + out } } +impl From<&OFlags> for types::Oflags { + fn from(oflags: &OFlags) -> types::Oflags { + let mut out = types::Oflags::empty(); + if oflags.contains(&OFlags::CREATE) { + out = out | types::Oflags::CREAT; + } + if oflags.contains(&OFlags::DIRECTORY) { + out = out | types::Oflags::DIRECTORY; + } + if oflags.contains(&OFlags::EXCLUSIVE) { + out = out | types::Oflags::EXCL; + } + if oflags.contains(&OFlags::TRUNCATE) { + out = out | types::Oflags::TRUNC; + } + out + } +} impl From for types::Filestat { fn from(stat: Filestat) -> types::Filestat { todo!() diff --git a/crates/wasi-c2/src/stdio.rs b/crates/wasi-c2/src/stdio.rs index a53c56596f..c4dd69cb5c 100644 --- a/crates/wasi-c2/src/stdio.rs +++ b/crates/wasi-c2/src/stdio.rs @@ -29,6 +29,9 @@ impl WasiFile for Stdin { fn get_fdflags(&self) -> Result { todo!() } + fn set_fdflags(&self, _fdflags: FdFlags) -> Result<(), Error> { + todo!() + } fn get_oflags(&self) -> Result { todo!() } @@ -69,6 +72,9 @@ impl WasiFile for Stdout { fn get_fdflags(&self) -> Result { todo!() } + fn set_fdflags(&self, _fdflags: FdFlags) -> Result<(), Error> { + todo!() + } fn get_oflags(&self) -> Result { todo!() } @@ -109,6 +115,9 @@ impl WasiFile for Stderr { fn get_fdflags(&self) -> Result { todo!() } + fn set_fdflags(&self, _fdflags: FdFlags) -> Result<(), Error> { + todo!() + } fn get_oflags(&self) -> Result { todo!() } diff --git a/crates/wasi-c2/src/table.rs b/crates/wasi-c2/src/table.rs index 0f13d20893..d94cc020b1 100644 --- a/crates/wasi-c2/src/table.rs +++ b/crates/wasi-c2/src/table.rs @@ -16,11 +16,11 @@ impl Table { } } - pub fn insert_at(&mut self, key: u32, a: impl Any + Sized) { - self.map.insert(key, RefCell::new(Box::new(a))); + pub fn insert_at(&mut self, key: u32, a: Box) { + self.map.insert(key, RefCell::new(a)); } - pub fn push(&mut self, a: impl Any + Sized) -> Result { + pub fn push(&mut self, a: Box) -> Result { loop { let key = self.next_key; // XXX this is not correct. The table may still have empty entries, but our @@ -29,7 +29,7 @@ impl Table { if self.map.contains_key(&key) { continue; } - self.map.insert(key, RefCell::new(Box::new(a))); + self.map.insert(key, RefCell::new(a)); return Ok(key); } } diff --git a/crates/wasi-c2/src/virt/pipe.rs b/crates/wasi-c2/src/virt/pipe.rs index cda5383dc5..2ae7edaedc 100644 --- a/crates/wasi-c2/src/virt/pipe.rs +++ b/crates/wasi-c2/src/virt/pipe.rs @@ -180,6 +180,9 @@ impl WasiFile for ReadPipe { fn get_fdflags(&self) -> Result { todo!() // do later } + fn set_fdflags(&self, _fdflags: FdFlags) -> Result<(), Error> { + todo!() + } fn get_oflags(&self) -> Result { todo!() // do later } @@ -334,6 +337,9 @@ impl WasiFile for WritePipe { fn get_fdflags(&self) -> Result { todo!() } + fn set_fdflags(&self, _fdflags: FdFlags) -> Result<(), Error> { + todo!() + } fn get_oflags(&self) -> Result { todo!() }