Skip to content

Commit

Permalink
On Windows, ignore files for which full_metadata fails.
Browse files Browse the repository at this point in the history
On Windows, `metadata` computes only partial metadata results, which don't
include what WASI needs for the `inode` field in `readdir` results. cap-std
has a `full_metadata` function which is able to include this extra
information, however it has more strict access requirements, so it sometimes
fails even when plain `metadata` would succeed.

Make WASI's `readdir` silently skip over files that can't be accessed by
`full_metadata`. These files wouldn't be openable in any other way by
WASI programs, so the only benefit of listing them would be to
let applications know that they exist. This allows it to avoid failing
and avoid returning bogus results.

This is part of a fix for bytecodealliance/cap-std#169.
  • Loading branch information
sunfishcode committed May 7, 2021
1 parent 002b074 commit ec5d801
Showing 1 changed file with 23 additions and 4 deletions.
27 changes: 23 additions & 4 deletions crates/wasi-common/cap-std-sync/src/dir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,9 +116,9 @@ impl WasiDir for Dir {
},
]
.into_iter()
.chain(
.chain({
// Now process the `DirEntry`s:
self.0.entries()?.map(|entry| {
let entries = self.0.entries()?.map(|entry| {
let entry = entry?;
let meta = entry.full_metadata()?;
let inode = meta.ino();
Expand All @@ -128,8 +128,27 @@ impl WasiDir for Dir {
.into_string()
.map_err(|_| Error::illegal_byte_sequence().context("filename"))?;
Ok((filetype, inode, name))
}),
)
});

// On Windows, filter out files like `C:\DumpStack.log.tmp` which we
// can't get a full metadata for.
#[cfg(windows)]
let entries = entries.filter(|entry: &Result<_, wasi_common::Error>| {
use winapi::shared::winerror::{ERROR_ACCESS_DENIED, ERROR_SHARING_VIOLATION};
if let Err(err) = entry {
if let Some(err) = err.downcast_ref::<std::io::Error>() {
if err.raw_os_error() == Some(ERROR_SHARING_VIOLATION as i32)
|| err.raw_os_error() == Some(ERROR_ACCESS_DENIED as i32)
{
return false;
}
}
}
true
});

entries
})
// Enumeration of the iterator makes it possible to define the ReaddirCursor
.enumerate()
.map(|(ix, r)| match r {
Expand Down

0 comments on commit ec5d801

Please sign in to comment.