1 use crate::file::{FdFlags, FileType, Filestat, OFlags, WasiFile}; 2 use crate::{Error, ErrorExt, SystemTimeSpec}; 3 use std::any::Any; 4 use std::path::PathBuf; 5 use std::sync::Arc; 6 7 pub enum OpenResult { 8 File(Box<dyn WasiFile>), 9 Dir(Box<dyn WasiDir>), 10 } 11 12 #[async_trait::async_trait] 13 pub trait WasiDir: Send + Sync { as_any(&self) -> &dyn Any14 fn as_any(&self) -> &dyn Any; 15 open_file( &self, _symlink_follow: bool, _path: &str, _oflags: OFlags, _read: bool, _write: bool, _fdflags: FdFlags, ) -> Result<OpenResult, Error>16 async fn open_file( 17 &self, 18 _symlink_follow: bool, 19 _path: &str, 20 _oflags: OFlags, 21 _read: bool, 22 _write: bool, 23 _fdflags: FdFlags, 24 ) -> Result<OpenResult, Error> { 25 Err(Error::not_supported()) 26 } 27 create_dir(&self, _path: &str) -> Result<(), Error>28 async fn create_dir(&self, _path: &str) -> Result<(), Error> { 29 Err(Error::not_supported()) 30 } 31 32 // XXX the iterator here needs to be asyncified as well! readdir( &self, _cursor: ReaddirCursor, ) -> Result<Box<dyn Iterator<Item = Result<ReaddirEntity, Error>> + Send>, Error>33 async fn readdir( 34 &self, 35 _cursor: ReaddirCursor, 36 ) -> Result<Box<dyn Iterator<Item = Result<ReaddirEntity, Error>> + Send>, Error> { 37 Err(Error::not_supported()) 38 } 39 symlink(&self, _old_path: &str, _new_path: &str) -> Result<(), Error>40 async fn symlink(&self, _old_path: &str, _new_path: &str) -> Result<(), Error> { 41 Err(Error::not_supported()) 42 } 43 remove_dir(&self, _path: &str) -> Result<(), Error>44 async fn remove_dir(&self, _path: &str) -> Result<(), Error> { 45 Err(Error::not_supported()) 46 } 47 unlink_file(&self, _path: &str) -> Result<(), Error>48 async fn unlink_file(&self, _path: &str) -> Result<(), Error> { 49 Err(Error::not_supported()) 50 } 51 read_link(&self, _path: &str) -> Result<PathBuf, Error>52 async fn read_link(&self, _path: &str) -> Result<PathBuf, Error> { 53 Err(Error::not_supported()) 54 } 55 get_filestat(&self) -> Result<Filestat, Error>56 async fn get_filestat(&self) -> Result<Filestat, Error> { 57 Err(Error::not_supported()) 58 } 59 get_path_filestat( &self, _path: &str, _follow_symlinks: bool, ) -> Result<Filestat, Error>60 async fn get_path_filestat( 61 &self, 62 _path: &str, 63 _follow_symlinks: bool, 64 ) -> Result<Filestat, Error> { 65 Err(Error::not_supported()) 66 } 67 rename( &self, _path: &str, _dest_dir: &dyn WasiDir, _dest_path: &str, ) -> Result<(), Error>68 async fn rename( 69 &self, 70 _path: &str, 71 _dest_dir: &dyn WasiDir, 72 _dest_path: &str, 73 ) -> Result<(), Error> { 74 Err(Error::not_supported()) 75 } 76 hard_link( &self, _path: &str, _target_dir: &dyn WasiDir, _target_path: &str, ) -> Result<(), Error>77 async fn hard_link( 78 &self, 79 _path: &str, 80 _target_dir: &dyn WasiDir, 81 _target_path: &str, 82 ) -> Result<(), Error> { 83 Err(Error::not_supported()) 84 } 85 set_times( &self, _path: &str, _atime: Option<SystemTimeSpec>, _mtime: Option<SystemTimeSpec>, _follow_symlinks: bool, ) -> Result<(), Error>86 async fn set_times( 87 &self, 88 _path: &str, 89 _atime: Option<SystemTimeSpec>, 90 _mtime: Option<SystemTimeSpec>, 91 _follow_symlinks: bool, 92 ) -> Result<(), Error> { 93 Err(Error::not_supported()) 94 } 95 } 96 97 pub(crate) struct DirEntry { 98 preopen_path: Option<PathBuf>, // precondition: PathBuf is valid unicode 99 pub dir: Box<dyn WasiDir>, 100 } 101 102 impl DirEntry { new(preopen_path: Option<PathBuf>, dir: Box<dyn WasiDir>) -> Self103 pub fn new(preopen_path: Option<PathBuf>, dir: Box<dyn WasiDir>) -> Self { 104 DirEntry { preopen_path, dir } 105 } preopen_path(&self) -> &Option<PathBuf>106 pub fn preopen_path(&self) -> &Option<PathBuf> { 107 &self.preopen_path 108 } 109 } 110 111 pub(crate) trait TableDirExt { get_dir(&self, fd: u32) -> Result<Arc<DirEntry>, Error>112 fn get_dir(&self, fd: u32) -> Result<Arc<DirEntry>, Error>; 113 } 114 115 impl TableDirExt for crate::table::Table { get_dir(&self, fd: u32) -> Result<Arc<DirEntry>, Error>116 fn get_dir(&self, fd: u32) -> Result<Arc<DirEntry>, Error> { 117 self.get(fd) 118 } 119 } 120 121 #[derive(Debug, Clone)] 122 pub struct ReaddirEntity { 123 pub next: ReaddirCursor, 124 pub inode: u64, 125 pub name: String, 126 pub filetype: FileType, 127 } 128 129 #[derive(Debug, Copy, Clone)] 130 pub struct ReaddirCursor(u64); 131 impl From<u64> for ReaddirCursor { from(c: u64) -> ReaddirCursor132 fn from(c: u64) -> ReaddirCursor { 133 ReaddirCursor(c) 134 } 135 } 136 impl From<ReaddirCursor> for u64 { from(c: ReaddirCursor) -> u64137 fn from(c: ReaddirCursor) -> u64 { 138 c.0 139 } 140 } 141