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!()
}