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