From b66f92f6d55d4d6603fd5593c85498b59f2b8dac Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Fri, 23 Dec 2022 20:00:07 -0800 Subject: [PATCH] Implement host file flags and type functions. (#42) This gets us another step closer to running the Wasmtime tests. --- host/src/filesystem.rs | 91 ++++++++++++++++++++++------- wasi-common/cap-std-sync/src/dir.rs | 7 ++- wasi-common/src/dir.rs | 4 ++ 3 files changed, 81 insertions(+), 21 deletions(-) diff --git a/host/src/filesystem.rs b/host/src/filesystem.rs index bb8fce05..ae50e6de 100644 --- a/host/src/filesystem.rs +++ b/host/src/filesystem.rs @@ -9,7 +9,7 @@ use std::{ }; use wasi_common::{ dir::TableDirExt, - file::{FileStream, TableFileExt}, + file::{FdFlags, FileStream, TableFileExt}, WasiDir, WasiFile, }; @@ -101,44 +101,63 @@ fn convert(error: wasi_common::Error) -> wasmtime::component::Error for wasi_filesystem::OFlags { - fn into(self) -> wasi_common::file::OFlags { +impl From for wasi_common::file::OFlags { + fn from(oflags: wasi_filesystem::OFlags) -> Self { let mut flags = wasi_common::file::OFlags::empty(); - if contains(self, wasi_filesystem::OFlags::CREATE) { + if contains(oflags, wasi_filesystem::OFlags::CREATE) { flags |= wasi_common::file::OFlags::CREATE; } - if contains(self, wasi_filesystem::OFlags::DIRECTORY) { + if contains(oflags, wasi_filesystem::OFlags::DIRECTORY) { flags |= wasi_common::file::OFlags::DIRECTORY; } - if contains(self, wasi_filesystem::OFlags::EXCL) { + if contains(oflags, wasi_filesystem::OFlags::EXCL) { flags |= wasi_common::file::OFlags::EXCLUSIVE; } - if contains(self, wasi_filesystem::OFlags::TRUNC) { + if contains(oflags, wasi_filesystem::OFlags::TRUNC) { flags |= wasi_common::file::OFlags::TRUNCATE; } flags } } -impl Into for wasi_filesystem::DescriptorFlags { - fn into(self) -> wasi_common::file::FdFlags { - let mut flags = wasi_common::file::FdFlags::empty(); - if contains(self, wasi_filesystem::DescriptorFlags::DSYNC) { - flags |= wasi_common::file::FdFlags::DSYNC; +impl From for wasi_filesystem::DescriptorFlags { + fn from(fdflags: FdFlags) -> Self { + let mut flags = wasi_filesystem::DescriptorFlags::empty(); + if contains(fdflags, FdFlags::DSYNC) { + flags |= wasi_filesystem::DescriptorFlags::DSYNC; } - if contains(self, wasi_filesystem::DescriptorFlags::NONBLOCK) { - flags |= wasi_common::file::FdFlags::NONBLOCK; + if contains(fdflags, FdFlags::NONBLOCK) { + flags |= wasi_filesystem::DescriptorFlags::NONBLOCK; } - if contains(self, wasi_filesystem::DescriptorFlags::RSYNC) { - flags |= wasi_common::file::FdFlags::RSYNC; + if contains(fdflags, FdFlags::RSYNC) { + flags |= wasi_filesystem::DescriptorFlags::RSYNC; } - if contains(self, wasi_filesystem::DescriptorFlags::SYNC) { - flags |= wasi_common::file::FdFlags::SYNC; + if contains(fdflags, FdFlags::SYNC) { + flags |= wasi_filesystem::DescriptorFlags::SYNC; } flags } } +impl From for FdFlags { + fn from(flags: wasi_filesystem::DescriptorFlags) -> FdFlags { + let mut fdflags = FdFlags::empty(); + if contains(flags, wasi_filesystem::DescriptorFlags::DSYNC) { + fdflags |= FdFlags::DSYNC; + } + if contains(flags, wasi_filesystem::DescriptorFlags::NONBLOCK) { + fdflags |= FdFlags::NONBLOCK; + } + if contains(flags, wasi_filesystem::DescriptorFlags::RSYNC) { + fdflags |= FdFlags::RSYNC; + } + if contains(flags, wasi_filesystem::DescriptorFlags::SYNC) { + fdflags |= FdFlags::SYNC; + } + fdflags + } +} + impl From for wasi_filesystem::DescriptorType { fn from(type_: wasi_common::file::FileType) -> Self { match type_ { @@ -204,14 +223,46 @@ impl wasi_filesystem::WasiFilesystem for WasiCtx { &mut self, fd: wasi_filesystem::Descriptor, ) -> HostResult { - todo!() + let table = self.table(); + if table.is::>(fd) { + Ok(table + .get_file(fd) + .map_err(convert)? + .get_fdflags() + .await + .map_err(convert)? + .into()) + } else if table.is::>(fd) { + Ok(table + .get_dir(fd) + .map_err(convert)? + .get_fdflags() + .await + .map_err(convert)? + .into()) + } else { + Err(wasi_filesystem::Errno::Badf.into()) + } } async fn todo_type( &mut self, fd: wasi_filesystem::Descriptor, ) -> HostResult { - todo!() + let table = self.table(); + if table.is::>(fd) { + Ok(table + .get_file(fd) + .map_err(convert)? + .get_filetype() + .await + .map_err(convert)? + .into()) + } else if table.is::>(fd) { + Ok(wasi_filesystem::DescriptorType::Directory) + } else { + Err(wasi_filesystem::Errno::Badf.into()) + } } async fn set_flags( diff --git a/wasi-common/cap-std-sync/src/dir.rs b/wasi-common/cap-std-sync/src/dir.rs index 750bd378..93e4e114 100644 --- a/wasi-common/cap-std-sync/src/dir.rs +++ b/wasi-common/cap-std-sync/src/dir.rs @@ -1,4 +1,4 @@ -use crate::file::{filetype_from, File}; +use crate::file::{filetype_from, get_fd_flags, File}; use cap_fs_ext::{DirEntryExt, DirExt, MetadataExt, SystemTimeSpec}; use std::any::Any; use std::path::{Path, PathBuf}; @@ -80,6 +80,11 @@ impl Dir { Ok(File::from_cap_std(f)) } + pub fn get_fdflags(&self) -> Result { + let fdflags = get_fd_flags(&self.0)?; + Ok(fdflags) + } + pub fn open_dir_(&self, symlink_follow: bool, path: &str) -> Result { let d = if symlink_follow { self.0.open_dir(Path::new(path))? diff --git a/wasi-common/src/dir.rs b/wasi-common/src/dir.rs index b254f9ef..d355265a 100644 --- a/wasi-common/src/dir.rs +++ b/wasi-common/src/dir.rs @@ -27,6 +27,10 @@ pub trait WasiDir: Send + Sync { Err(Error::not_supported()) } + async fn get_fdflags(&self) -> Result { + Ok(FdFlags::empty()) + } + async fn create_dir(&self, _path: &str) -> Result<(), Error> { Err(Error::not_supported()) }