Skip to content

Commit

Permalink
fix wasi-fyi tests (#4708)
Browse files Browse the repository at this point in the history
  • Loading branch information
maminrayej authored May 17, 2024
2 parents 58a98d0 + 6dbd4c2 commit cca7b0a
Show file tree
Hide file tree
Showing 26 changed files with 254 additions and 9 deletions.
4 changes: 4 additions & 0 deletions lib/virtual-fs/src/arc_fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ impl ArcFileSystem {
}

impl FileSystem for ArcFileSystem {
fn readlink(&self, path: &Path) -> Result<PathBuf> {
self.fs.readlink(path)
}

fn read_dir(&self, path: &Path) -> Result<ReadDir> {
self.fs.read_dir(path)
}
Expand Down
4 changes: 4 additions & 0 deletions lib/virtual-fs/src/empty_fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ pub struct EmptyFileSystem {}

#[allow(unused_variables)]
impl FileSystem for EmptyFileSystem {
fn readlink(&self, path: &Path) -> Result<PathBuf> {
Err(FsError::EntryNotFound)
}

fn read_dir(&self, path: &Path) -> Result<ReadDir> {
// Special-case the root path by returning an empty iterator.
// An empty file system should still be readable, just not contain
Expand Down
10 changes: 10 additions & 0 deletions lib/virtual-fs/src/host_fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ impl FileSystem {
}

impl crate::FileSystem for FileSystem {
fn readlink(&self, path: &Path) -> Result<PathBuf> {
fs::read_link(path).map_err(Into::into)
}

fn read_dir(&self, path: &Path) -> Result<ReadDir> {
let read_dir = fs::read_dir(path)?;
let mut data = read_dir
Expand Down Expand Up @@ -153,6 +157,12 @@ impl crate::FileSystem for FileSystem {
.and_then(TryInto::try_into)
.map_err(Into::into)
}

fn symlink_metadata(&self, path: &Path) -> Result<Metadata> {
fs::symlink_metadata(path)
.and_then(TryInto::try_into)
.map_err(Into::into)
}
}

impl TryInto<Metadata> for std::fs::Metadata {
Expand Down
13 changes: 10 additions & 3 deletions lib/virtual-fs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ pub trait ClonableVirtualFile: VirtualFile + Clone {}
pub use ops::{copy_reference, copy_reference_ext};

pub trait FileSystem: fmt::Debug + Send + Sync + 'static + Upcastable {
fn readlink(&self, path: &Path) -> Result<PathBuf>;
fn read_dir(&self, path: &Path) -> Result<ReadDir>;
fn create_dir(&self, path: &Path) -> Result<()>;
fn remove_dir(&self, path: &Path) -> Result<()>;
Expand All @@ -99,9 +100,7 @@ pub trait FileSystem: fmt::Debug + Send + Sync + 'static + Upcastable {
/// This method gets metadata without following symlinks in the path.
/// Currently identical to `metadata` because symlinks aren't implemented
/// yet.
fn symlink_metadata(&self, path: &Path) -> Result<Metadata> {
self.metadata(path)
}
fn symlink_metadata(&self, path: &Path) -> Result<Metadata>;
fn remove_file(&self, path: &Path) -> Result<()>;

fn new_open_options(&self) -> OpenOptions;
Expand All @@ -128,6 +127,10 @@ where
(**self).read_dir(path)
}

fn readlink(&self, path: &Path) -> Result<PathBuf> {
(**self).readlink(path)
}

fn create_dir(&self, path: &Path) -> Result<()> {
(**self).create_dir(path)
}
Expand All @@ -144,6 +147,10 @@ where
(**self).metadata(path)
}

fn symlink_metadata(&self, path: &Path) -> Result<Metadata> {
(**self).symlink_metadata(path)
}

fn remove_file(&self, path: &Path) -> Result<()> {
(**self).remove_file(path)
}
Expand Down
29 changes: 29 additions & 0 deletions lib/virtual-fs/src/mem_fs/filesystem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,18 @@ impl FileSystem {
}

impl crate::FileSystem for FileSystem {
fn readlink(&self, path: &Path) -> Result<PathBuf> {
// Read lock.
let guard = self.inner.read().map_err(|_| FsError::Lock)?;

// Canonicalize the path.
let (_, inode_of_directory) = guard.canonicalize(path)?;
match inode_of_directory {
InodeResolution::Found(_) => Err(FsError::InvalidInput),
InodeResolution::Redirect(fs, path) => fs.readlink(path.as_path()),
}
}

fn read_dir(&self, path: &Path) -> Result<ReadDir> {
// Read lock.
let guard = self.inner.read().map_err(|_| FsError::Lock)?;
Expand Down Expand Up @@ -591,6 +603,23 @@ impl crate::FileSystem for FileSystem {
}
}

fn symlink_metadata(&self, path: &Path) -> Result<Metadata> {
// Read lock.
let guard = self.inner.read().map_err(|_| FsError::Lock)?;
match guard.inode_of(path)? {
InodeResolution::Found(inode) => Ok(guard
.storage
.get(inode)
.ok_or(FsError::UnknownError)?
.metadata()
.clone()),
InodeResolution::Redirect(fs, path) => {
drop(guard);
fs.symlink_metadata(path.as_path())
}
}
}

fn remove_file(&self, path: &Path) -> Result<()> {
let (inode_of_parent, position, inode_of_file) = {
// Read lock.
Expand Down
58 changes: 58 additions & 0 deletions lib/virtual-fs/src/overlay_fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,35 @@ where
S: for<'a> FileSystems<'a> + Send + Sync + 'static,
for<'a> <<S as FileSystems<'a>>::Iter as IntoIterator>::IntoIter: Send,
{
fn readlink(&self, path: &Path) -> crate::Result<PathBuf> {
// Whiteout files can not be read, they are just markers
if ops::is_white_out(path).is_some() {
return Err(FsError::EntryNotFound);
}

// Check if the file is in the primary
match self.primary.readlink(path) {
Ok(meta) => return Ok(meta),
Err(e) if should_continue(e) => {}
Err(e) => return Err(e),
}

// There might be a whiteout, search for this
if ops::has_white_out(&self.primary, path) {
return Err(FsError::EntryNotFound);
}

// Otherwise scan the secondaries
for fs in self.secondaries.filesystems() {
match fs.readlink(path) {
Err(e) if should_continue(e) => continue,
other => return other,
}
}

Err(FsError::EntryNotFound)
}

fn read_dir(&self, path: &Path) -> Result<ReadDir, FsError> {
let mut entries = Vec::new();
let mut had_at_least_one_success = false;
Expand Down Expand Up @@ -328,6 +357,35 @@ where
Err(FsError::EntryNotFound)
}

fn symlink_metadata(&self, path: &Path) -> crate::Result<Metadata> {
// Whiteout files can not be read, they are just markers
if ops::is_white_out(path).is_some() {
return Err(FsError::EntryNotFound);
}

// Check if the file is in the primary
match self.primary.symlink_metadata(path) {
Ok(meta) => return Ok(meta),
Err(e) if should_continue(e) => {}
Err(e) => return Err(e),
}

// There might be a whiteout, search for this
if ops::has_white_out(&self.primary, path) {
return Err(FsError::EntryNotFound);
}

// Otherwise scan the secondaries
for fs in self.secondaries.filesystems() {
match fs.symlink_metadata(path) {
Err(e) if should_continue(e) => continue,
other => return other,
}
}

Err(FsError::EntryNotFound)
}

fn remove_file(&self, path: &Path) -> Result<(), FsError> {
// It is not possible to delete whiteout files directly, instead
// one must delete the original file
Expand Down
4 changes: 4 additions & 0 deletions lib/virtual-fs/src/passthru_fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ impl PassthruFileSystem {
}

impl FileSystem for PassthruFileSystem {
fn readlink(&self, path: &Path) -> Result<PathBuf> {
self.fs.readlink(path)
}

fn read_dir(&self, path: &Path) -> Result<ReadDir> {
self.fs.read_dir(path)
}
Expand Down
10 changes: 10 additions & 0 deletions lib/virtual-fs/src/scoped_directory_fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,11 @@ impl ScopedDirectoryFileSystem {
}

impl FileSystem for ScopedDirectoryFileSystem {
fn readlink(&self, path: &Path) -> crate::Result<PathBuf> {
let path = self.prepare_path(path);
self.inner.readlink(&path)
}

fn read_dir(&self, path: &Path) -> Result<ReadDir, FsError> {
let path = self.prepare_path(path);

Expand Down Expand Up @@ -94,6 +99,11 @@ impl FileSystem for ScopedDirectoryFileSystem {
self.inner.metadata(&path)
}

fn symlink_metadata(&self, path: &Path) -> crate::Result<Metadata> {
let path = self.prepare_path(path);
self.inner.symlink_metadata(&path)
}

fn remove_file(&self, path: &Path) -> Result<(), FsError> {
let path = self.prepare_path(path);
self.inner.remove_file(&path)
Expand Down
14 changes: 14 additions & 0 deletions lib/virtual-fs/src/static_fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,20 @@ fn transform_into_read_dir(path: &Path, fs_entries: &[FsEntry<'_>]) -> crate::Re
}

impl FileSystem for StaticFileSystem {
fn readlink(&self, path: &Path) -> crate::Result<PathBuf> {
let path = normalizes_path(path);
if self
.volumes
.values()
.find_map(|v| v.get_file_entry(&path).ok())
.is_some()
{
Err(FsError::InvalidInput)
} else {
self.memory.readlink(Path::new(&path))
}
}

fn read_dir(&self, path: &Path) -> Result<ReadDir, FsError> {
let path = normalizes_path(path);
for volume in self.volumes.values() {
Expand Down
4 changes: 4 additions & 0 deletions lib/virtual-fs/src/tmp_fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@ impl TmpFileSystem {
}

impl FileSystem for TmpFileSystem {
fn readlink(&self, path: &Path) -> Result<PathBuf> {
self.fs.readlink(path)
}

fn read_dir(&self, path: &Path) -> Result<ReadDir> {
self.fs.read_dir(path)
}
Expand Down
10 changes: 10 additions & 0 deletions lib/virtual-fs/src/trace_fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@ impl<F> FileSystem for TraceFileSystem<F>
where
F: FileSystem,
{
#[tracing::instrument(level = "trace", skip(self), err)]
fn readlink(&self, path: &std::path::Path) -> crate::Result<PathBuf> {
self.0.readlink(path)
}

#[tracing::instrument(level = "trace", skip(self), err)]
fn read_dir(&self, path: &std::path::Path) -> crate::Result<crate::ReadDir> {
self.0.read_dir(path)
Expand Down Expand Up @@ -68,6 +73,11 @@ where
self.0.metadata(path)
}

#[tracing::instrument(level = "trace", skip(self), err)]
fn symlink_metadata(&self, path: &std::path::Path) -> crate::Result<crate::Metadata> {
self.0.symlink_metadata(path)
}

#[tracing::instrument(level = "trace", skip(self), err)]
fn remove_file(&self, path: &std::path::Path) -> crate::Result<()> {
self.0.remove_file(path)
Expand Down
26 changes: 26 additions & 0 deletions lib/virtual-fs/src/union_fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,32 @@ impl UnionFileSystem {
}

impl FileSystem for UnionFileSystem {
fn readlink(&self, path: &Path) -> Result<PathBuf> {
debug!("readlink: path={}", path.display());
let mut ret_error = FsError::EntryNotFound;
let path = path.to_string_lossy();
for (path_inner, mount) in filter_mounts(&self.mounts, path.as_ref()) {
match mount.fs.readlink(Path::new(path_inner.as_str())) {
Ok(ret) => {
return Ok(ret);
}
Err(err) => {
// This fixes a bug when attempting to create the directory /usr when it does not exist
// on the x86 version of memfs
// TODO: patch virtual-fs and remove
if let FsError::NotAFile = &err {
ret_error = FsError::EntryNotFound;
} else {
debug!("readlink failed: (path={}) - {}", path, err);
ret_error = err;
}
}
}
}
debug!("readlink: failed={}", ret_error);
Err(ret_error)
}

fn read_dir(&self, path: &Path) -> Result<ReadDir> {
debug!("read_dir: path={}", path.display());
self.read_dir_internal(path)
Expand Down
4 changes: 4 additions & 0 deletions lib/virtual-fs/src/webc_fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,10 @@ where
T: std::fmt::Debug + Send + Sync + 'static,
T: Deref<Target = WebC<'static>>,
{
fn readlink(&self, _path: &Path) -> crate::Result<PathBuf> {
Err(FsError::InvalidInput)
}

fn read_dir(&self, path: &Path) -> Result<ReadDir, FsError> {
let path = normalizes_path(path);
let read_dir_result = self
Expand Down
8 changes: 8 additions & 0 deletions lib/virtual-fs/src/webc_volume_fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ impl WebcVolumeFileSystem {
}

impl FileSystem for WebcVolumeFileSystem {
fn readlink(&self, _path: &Path) -> crate::Result<PathBuf> {
Err(FsError::InvalidInput)
}

fn read_dir(&self, path: &Path) -> Result<crate::ReadDir, FsError> {
let meta = self.metadata(path)?;

Expand Down Expand Up @@ -134,6 +138,10 @@ impl FileSystem for WebcVolumeFileSystem {
.ok_or(FsError::EntryNotFound)
}

fn symlink_metadata(&self, path: &Path) -> crate::Result<Metadata> {
self.metadata(path)
}

fn remove_file(&self, path: &Path) -> Result<(), FsError> {
let meta = self.metadata(path)?;

Expand Down
13 changes: 12 additions & 1 deletion lib/wasix/src/fs/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,13 @@ impl WasiFsRoot {
}

impl FileSystem for WasiFsRoot {
fn readlink(&self, path: &Path) -> virtual_fs::Result<PathBuf> {
match self {
WasiFsRoot::Sandbox(fs) => fs.readlink(path),
WasiFsRoot::Backing(fs) => fs.readlink(path),
}
}

fn read_dir(&self, path: &Path) -> virtual_fs::Result<virtual_fs::ReadDir> {
match self {
WasiFsRoot::Sandbox(fs) => fs.read_dir(path),
Expand Down Expand Up @@ -992,7 +999,8 @@ impl WasiFs {
}
} else if file_type.is_symlink() {
should_insert = false;
let link_value = file.read_link().map_err(map_io_err)?;
let link_value =
self.root_fs.readlink(&file).ok().ok_or(Errno::Noent)?;
debug!("attempting to decompose path {:?}", link_value);

let (pre_open_dir_fd, relative_path) = if link_value.is_relative() {
Expand Down Expand Up @@ -2026,6 +2034,9 @@ impl FallbackFileSystem {
}

impl FileSystem for FallbackFileSystem {
fn readlink(&self, _path: &Path) -> virtual_fs::Result<PathBuf> {
Self::fail()
}
fn read_dir(&self, _path: &Path) -> Result<virtual_fs::ReadDir, FsError> {
Self::fail();
}
Expand Down
Loading

0 comments on commit cca7b0a

Please sign in to comment.