sketchy implementation of readdir

This commit is contained in:
Pat Hickey
2020-12-10 17:31:21 -08:00
parent 03c92de5aa
commit 47f3a6bcb9
3 changed files with 113 additions and 12 deletions

View File

@@ -20,6 +20,11 @@ pub trait WasiDir {
path: &str, path: &str,
create: bool, create: bool,
) -> Result<Box<dyn WasiDir>, Error>; ) -> Result<Box<dyn WasiDir>, Error>;
fn readdir(
&self,
cursor: ReaddirCursor,
) -> Result<Box<dyn Iterator<Item = Result<(ReaddirEntity, String), Error>>>, Error>;
} }
pub(crate) struct DirEntry { pub(crate) struct DirEntry {
@@ -84,3 +89,89 @@ impl TableDirExt for crate::table::Table {
} }
} }
} }
pub enum DirEntityType {
File(crate::file::Filetype),
Directory,
SymbolicLink,
Unknown,
}
pub struct ReaddirEntity {
next: ReaddirCursor,
inode: u64,
namelen: u64,
direnttype: DirEntityType,
}
pub struct ReaddirCursor(u64);
impl From<u64> for ReaddirCursor {
fn from(c: u64) -> ReaddirCursor {
ReaddirCursor(c)
}
}
impl From<ReaddirCursor> for u64 {
fn from(c: ReaddirCursor) -> u64 {
c.0
}
}
impl WasiDir for cap_std::fs::Dir {
fn open_file(
&self,
symlink_follow: bool,
path: &str,
oflags: file::OFlags,
fdflags: file::FdFlags,
) -> Result<Box<dyn WasiFile>, Error> {
todo!()
}
fn open_dir(
&self,
symlink_follow: bool,
path: &str,
create: bool,
) -> Result<Box<dyn WasiDir>, Error> {
todo!()
}
fn readdir(
&self,
cursor: ReaddirCursor,
) -> Result<Box<dyn Iterator<Item = Result<(ReaddirEntity, String), Error>>>, Error> {
let rd = self
.read_dir(PathBuf::new())?
.enumerate()
.skip(u64::from(cursor) as usize);
Ok(Box::new(rd.map(|(ix, entry)| {
let entry = entry?;
let file_type = entry.file_type()?;
let direnttype = if file_type.is_dir() {
DirEntityType::Directory
} else if file_type.is_file() {
DirEntityType::File(crate::file::Filetype::RegularFile) // XXX unify this with conversion in `impl WasiFile for cap_std::fs::File { get_filetype }`
} else if file_type.is_symlink() {
DirEntityType::SymbolicLink
} else {
DirEntityType::Unknown
};
let name = entry.file_name().into_string().map_err(|_| {
Error::Utf8(todo!(
// XXX
"idk how to make utf8 error out of osstring conversion"
))
})?;
let namelen = name.as_bytes().len() as u64;
// XXX need the metadata casing to be reusable here
let inode = todo!();
let entity = ReaddirEntity {
next: ReaddirCursor::from(ix as u64 + 1),
direnttype,
inode,
namelen,
};
Ok((entity, name))
})))
}
}

View File

@@ -15,6 +15,10 @@ pub trait WasiFile: FileIoExt + SetTimes {
fn set_filestat_size(&self, _size: u64) -> Result<(), Error>; fn set_filestat_size(&self, _size: u64) -> Result<(), Error>;
} }
// XXX missing:
// Unknown
// Directory
// SymbolicLink
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
pub enum Filetype { pub enum Filetype {
BlockDevice, BlockDevice,

View File

@@ -1,5 +1,5 @@
#![allow(unused_variables)] #![allow(unused_variables)]
use crate::dir::{DirCaps, DirEntry, TableDirExt}; use crate::dir::{DirCaps, DirEntry, ReaddirCursor, TableDirExt};
use crate::file::{FdFlags, FdStat, FileCaps, FileEntry, Filestat, Filetype, OFlags}; use crate::file::{FdFlags, FdStat, FileCaps, FileEntry, Filestat, Filetype, OFlags};
use crate::{Error, WasiCtx}; use crate::{Error, WasiCtx};
use fs_set_times::SystemTimeSpec; use fs_set_times::SystemTimeSpec;
@@ -427,17 +427,6 @@ impl<'a> wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
Err(Error::Notsup) Err(Error::Notsup)
} }
} }
fn fd_readdir(
&self,
fd: types::Fd,
buf: &GuestPtr<u8>,
buf_len: types::Size,
cookie: types::Dircookie,
) -> Result<types::Size, Error> {
todo!("fd_readdir is very complicated")
}
fn fd_renumber(&self, from: types::Fd, to: types::Fd) -> Result<(), Error> { fn fd_renumber(&self, from: types::Fd, to: types::Fd) -> Result<(), Error> {
let mut table = self.table(); let mut table = self.table();
let from = u32::from(from); let from = u32::from(from);
@@ -499,6 +488,23 @@ impl<'a> wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
Ok(offset) Ok(offset)
} }
fn fd_readdir(
&self,
dirfd: types::Fd,
buf: &GuestPtr<u8>,
buf_len: types::Size,
cookie: types::Dircookie,
) -> Result<types::Size, Error> {
let table = self.table();
let dir_entry: RefMut<DirEntry> = table.get(u32::from(dirfd))?;
let d = dir_entry.get_cap(DirCaps::READDIR)?;
for pair in d.readdir(ReaddirCursor::from(cookie))? {
let (entity, name) = pair?;
todo!()
}
todo!()
}
fn path_create_directory( fn path_create_directory(
&self, &self,
dirfd: types::Fd, dirfd: types::Fd,