diff --git a/crates/wasi-c2/src/dir.rs b/crates/wasi-c2/src/dir.rs index e6f7596c85..6f6d361148 100644 --- a/crates/wasi-c2/src/dir.rs +++ b/crates/wasi-c2/src/dir.rs @@ -1,7 +1,5 @@ -// this file is extremely wip -#![allow(dead_code, unused_variables)] use crate::error::Error; -use crate::file::{FileCaps, OFlags, WasiFile}; +use crate::file::{FileCaps, FileType, OFlags, WasiFile}; use std::ops::Deref; use std::path::{Path, PathBuf}; @@ -171,18 +169,11 @@ 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 next: ReaddirCursor, + pub inode: u64, + pub namelen: u64, + pub filetype: FileType, } pub struct ReaddirCursor(u64); @@ -262,29 +253,19 @@ impl WasiDir for cap_std::fs::Dir { .enumerate() .skip(u64::from(cursor) as usize); Ok(Box::new(rd.map(|(ix, entry)| { + use cap_fs_ext::MetadataExt; 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 meta = entry.metadata()?; + let inode = meta.ino(); + let filetype = FileType::from(&meta.file_type()); + let name = entry + .file_name() + .into_string() + .map_err(|_| Error::Utf8(todo!()))?; 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, + filetype, inode, namelen, }; diff --git a/crates/wasi-c2/src/file.rs b/crates/wasi-c2/src/file.rs index 38caf8d5de..847c6f87cb 100644 --- a/crates/wasi-c2/src/file.rs +++ b/crates/wasi-c2/src/file.rs @@ -6,7 +6,7 @@ use system_interface::fs::FileIoExt; pub trait WasiFile: FileIoExt + SetTimes { fn datasync(&self) -> Result<(), Error>; fn sync(&self) -> Result<(), Error>; - fn get_filetype(&self) -> Result; + fn get_filetype(&self) -> Result; fn get_fdflags(&self) -> Result; fn set_fdflags(&self, _flags: FdFlags) -> Result<(), Error>; fn get_oflags(&self) -> Result; @@ -15,17 +15,41 @@ pub trait WasiFile: FileIoExt + SetTimes { fn set_filestat_size(&self, _size: u64) -> Result<(), Error>; } -// XXX missing: -// Unknown -// Directory -// SymbolicLink #[derive(Debug, Copy, Clone)] -pub enum Filetype { +pub enum FileType { + Directory, BlockDevice, CharacterDevice, RegularFile, SocketDgram, SocketStream, + SymbolicLink, + Unknown, +} + +impl From<&cap_std::fs::FileType> for FileType { + fn from(ft: &cap_std::fs::FileType) -> FileType { + use cap_fs_ext::FileTypeExt; + if ft.is_dir() { + FileType::Directory + } else if ft.is_symlink() { + FileType::SymbolicLink + } else if ft.is_socket() { + if ft.is_block_device() { + FileType::SocketDgram + } else { + FileType::SocketStream + } + } else if ft.is_block_device() { + FileType::BlockDevice + } else if ft.is_char_device() { + FileType::CharacterDevice + } else if ft.is_file() { + FileType::RegularFile + } else { + FileType::Unknown + } + } } #[derive(Debug, Copy, Clone, PartialEq, Eq)] @@ -89,7 +113,7 @@ impl std::ops::BitOr for OFlags { pub struct Filestat { pub device_id: u64, pub inode: u64, - pub filetype: Filetype, + pub filetype: FileType, pub nlink: u64, pub size: u64, pub atim: Option, @@ -197,7 +221,7 @@ impl std::ops::BitOr for FileCaps { } pub struct FdStat { - pub filetype: Filetype, + pub filetype: FileType, pub caps: FileCaps, pub flags: FdFlags, } @@ -211,16 +235,9 @@ impl WasiFile for cap_std::fs::File { self.sync_all()?; Ok(()) } - fn get_filetype(&self) -> Result { + fn get_filetype(&self) -> Result { let meta = self.metadata()?; - // cap-std's Metadata/FileType only offers booleans indicating whether a file is a directory, - // symlink, or regular file. - // Directories should be excluded by the type system. - if meta.is_file() { - Ok(Filetype::RegularFile) - } else { - todo!("get_filetype doesnt know how to handle case when not a file"); - } + Ok(FileType::from(&meta.file_type())) } fn get_fdflags(&self) -> Result { // XXX get_fdflags is not implemented but lets lie rather than panic: @@ -241,7 +258,7 @@ impl WasiFile for cap_std::fs::File { Ok(Filestat { device_id: meta.dev(), inode: meta.ino(), - filetype: self.get_filetype()?, + filetype: FileType::from(&meta.file_type()), nlink: meta.nlink(), size: meta.len(), atim: meta.accessed().map(|t| Some(t.into_std())).unwrap_or(None), diff --git a/crates/wasi-c2/src/snapshots/preview_1.rs b/crates/wasi-c2/src/snapshots/preview_1.rs index cee8f4fa8e..c4f2f2b03a 100644 --- a/crates/wasi-c2/src/snapshots/preview_1.rs +++ b/crates/wasi-c2/src/snapshots/preview_1.rs @@ -1,6 +1,6 @@ #![allow(unused_variables)] use crate::dir::{DirCaps, DirEntry, DirStat, ReaddirCursor, TableDirExt}; -use crate::file::{FdFlags, FdStat, FileCaps, FileEntry, Filestat, Filetype, OFlags}; +use crate::file::{FdFlags, FdStat, FileCaps, FileEntry, FileType, Filestat, OFlags}; use crate::{Error, WasiCtx}; use fs_set_times::SystemTimeSpec; use std::cell::{Ref, RefMut}; @@ -970,14 +970,17 @@ impl From<&types::Rights> for DirCaps { } } -impl From<&Filetype> for types::Filetype { - fn from(ft: &Filetype) -> types::Filetype { +impl From<&FileType> for types::Filetype { + fn from(ft: &FileType) -> types::Filetype { match ft { - Filetype::BlockDevice => types::Filetype::BlockDevice, - Filetype::CharacterDevice => types::Filetype::CharacterDevice, - Filetype::RegularFile => types::Filetype::RegularFile, - Filetype::SocketDgram => types::Filetype::SocketDgram, - Filetype::SocketStream => types::Filetype::SocketStream, + FileType::Directory => types::Filetype::Directory, + FileType::BlockDevice => types::Filetype::BlockDevice, + FileType::CharacterDevice => types::Filetype::CharacterDevice, + FileType::RegularFile => types::Filetype::RegularFile, + FileType::SocketDgram => types::Filetype::SocketDgram, + FileType::SocketStream => types::Filetype::SocketStream, + FileType::SymbolicLink => types::Filetype::SymbolicLink, + FileType::Unknown => types::Filetype::Unknown, } } } diff --git a/crates/wasi-c2/src/stdio.rs b/crates/wasi-c2/src/stdio.rs index c4dd69cb5c..9e83217363 100644 --- a/crates/wasi-c2/src/stdio.rs +++ b/crates/wasi-c2/src/stdio.rs @@ -1,4 +1,4 @@ -use crate::file::{FdFlags, Filestat, Filetype, OFlags, WasiFile}; +use crate::file::{FdFlags, FileType, Filestat, OFlags, WasiFile}; use crate::Error; #[cfg(unix)] use std::os::unix::io::{AsRawFd, RawFd}; @@ -23,8 +23,8 @@ impl WasiFile for Stdin { fn sync(&self) -> Result<(), Error> { Ok(()) } - fn get_filetype(&self) -> Result { - Ok(Filetype::CharacterDevice) + fn get_filetype(&self) -> Result { + Ok(FileType::CharacterDevice) } fn get_fdflags(&self) -> Result { todo!() @@ -66,8 +66,8 @@ impl WasiFile for Stdout { fn sync(&self) -> Result<(), Error> { Ok(()) } - fn get_filetype(&self) -> Result { - Ok(Filetype::CharacterDevice) + fn get_filetype(&self) -> Result { + Ok(FileType::CharacterDevice) } fn get_fdflags(&self) -> Result { todo!() @@ -109,8 +109,8 @@ impl WasiFile for Stderr { fn sync(&self) -> Result<(), Error> { Ok(()) } - fn get_filetype(&self) -> Result { - Ok(Filetype::CharacterDevice) + fn get_filetype(&self) -> Result { + Ok(FileType::CharacterDevice) } fn get_fdflags(&self) -> Result { todo!() diff --git a/crates/wasi-c2/src/virt/pipe.rs b/crates/wasi-c2/src/virt/pipe.rs index d8b1b4f8d1..abf059601d 100644 --- a/crates/wasi-c2/src/virt/pipe.rs +++ b/crates/wasi-c2/src/virt/pipe.rs @@ -9,7 +9,7 @@ //! Some convenience constructors are included for common backing types like `Vec` and `String`, //! but the virtual pipes can be instantiated with any `Read` or `Write` type. //! -use crate::file::{FdFlags, Filestat, Filetype, OFlags, WasiFile}; +use crate::file::{FdFlags, FileType, Filestat, OFlags, WasiFile}; use crate::Error; use std::io::{self, Read, Write}; use std::sync::{Arc, RwLock}; @@ -174,8 +174,8 @@ impl WasiFile for ReadPipe { fn sync(&self) -> Result<(), Error> { Ok(()) // trivial } - fn get_filetype(&self) -> Result { - Ok(Filetype::CharacterDevice) // XXX wrong + fn get_filetype(&self) -> Result { + Ok(FileType::CharacterDevice) // XXX wrong } fn get_fdflags(&self) -> Result { Ok(FdFlags::empty()) @@ -340,8 +340,8 @@ impl WasiFile for WritePipe { fn sync(&self) -> Result<(), Error> { Ok(()) } - fn get_filetype(&self) -> Result { - Ok(Filetype::CharacterDevice) // XXX + fn get_filetype(&self) -> Result { + Ok(FileType::CharacterDevice) // XXX } fn get_fdflags(&self) -> Result { Ok(FdFlags::APPEND)