add . and .. to the readdir iterator

This commit is contained in:
Pat Hickey
2021-01-04 17:22:46 -08:00
parent 222a57868e
commit d51ffe8d4e
2 changed files with 53 additions and 23 deletions

View File

@@ -6,8 +6,6 @@ wasi_tests::directory_seek
impl of Caps to see about this
wasi_tests::fd_flags_set
- set_fdflags is not implemented. test wanted to clear O_APPEND mode
wasi_tests::fd_readdir
- test expects `..` and `.`, Dir::readdir doesnt provide them
wasi_tests::nofollow_errors
- nofollow not implemented for dirs
wasi_tests::path_filestat

View File

@@ -262,27 +262,59 @@ impl WasiDir for cap_std::fs::Dir {
&self,
cursor: ReaddirCursor,
) -> Result<Box<dyn Iterator<Item = Result<(ReaddirEntity, String), Error>>>, Error> {
let rd = self
.read_dir(Path::new("."))
.expect("always possible to readdir an open Dir") // XXX is this true?
.enumerate()
.skip(u64::from(cursor) as usize);
Ok(Box::new(rd.map(|(ix, entry)| {
use cap_fs_ext::MetadataExt;
// cap_std's read_dir does not include . and .., we should prepend these.
// Why closures? failure of any individual entry doesn't mean the whole method should
// fail.
// Why the tuple? We can't construct a cap_std::fs::DirEntry.
let rd = vec![
(|| {
let meta = self.dir_metadata()?;
let name = ".".to_owned();
let namelen = name.as_bytes().len().try_into()?;
Ok((FileType::Directory, meta.ino(), namelen, name))
})(),
(|| {
// XXX if parent dir is mounted it *might* be possible to give its inode, but we
// don't know that in this context.
let name = "..".to_owned();
let namelen = name.as_bytes().len().try_into()?;
Ok((FileType::Directory, 0, namelen, name))
})(),
]
.into_iter()
.chain(
// Now process the `DirEntry`s:
self.read_dir(Path::new("."))
.expect("always possible to readdir an open Dir") // XXX is this true?
.map(|entry| {
let entry = entry?;
let meta = entry.metadata()?;
let inode = meta.ino();
let filetype = FileType::from(&meta.file_type());
let name = entry.file_name().into_string().map_err(|_| Error::Ilseq)?;
let namelen = name.as_bytes().len().try_into()?;
let entity = ReaddirEntity {
Ok((filetype, inode, namelen, name))
}),
)
// Enumeration of the iterator makes it possible to define the ReaddirCursor
.enumerate()
.map(|(ix, r)| match r {
Ok((filetype, inode, namelen, name)) => Ok((
ReaddirEntity {
next: ReaddirCursor::from(ix as u64 + 1),
filetype,
inode,
namelen,
};
Ok((entity, name))
})))
},
name,
)),
Err(e) => Err(e),
})
.skip(u64::from(cursor) as usize);
Ok(Box::new(rd))
}
fn symlink(&self, src_path: &str, dest_path: &str) -> Result<(), Error> {