1 use crate::{Error, ErrorExt, SystemTimeSpec};
2 use bitflags::bitflags;
3 use std::any::Any;
4 use std::sync::Arc;
5 
6 #[async_trait::async_trait]
7 pub trait WasiFile: Send + Sync {
as_any(&self) -> &dyn Any8     fn as_any(&self) -> &dyn Any;
get_filetype(&self) -> Result<FileType, Error>9     async fn get_filetype(&self) -> Result<FileType, Error>;
10 
11     #[cfg(unix)]
pollable(&self) -> Option<rustix::fd::BorrowedFd<'_>>12     fn pollable(&self) -> Option<rustix::fd::BorrowedFd<'_>> {
13         None
14     }
15 
16     #[cfg(windows)]
pollable(&self) -> Option<io_extras::os::windows::RawHandleOrSocket>17     fn pollable(&self) -> Option<io_extras::os::windows::RawHandleOrSocket> {
18         None
19     }
20 
isatty(&self) -> bool21     fn isatty(&self) -> bool {
22         false
23     }
24 
sock_accept(&self, _fdflags: FdFlags) -> Result<Box<dyn WasiFile>, Error>25     async fn sock_accept(&self, _fdflags: FdFlags) -> Result<Box<dyn WasiFile>, Error> {
26         Err(Error::badf())
27     }
28 
sock_recv<'a>( &self, _ri_data: &mut [std::io::IoSliceMut<'a>], _ri_flags: RiFlags, ) -> Result<(u64, RoFlags), Error>29     async fn sock_recv<'a>(
30         &self,
31         _ri_data: &mut [std::io::IoSliceMut<'a>],
32         _ri_flags: RiFlags,
33     ) -> Result<(u64, RoFlags), Error> {
34         Err(Error::badf())
35     }
36 
sock_send<'a>( &self, _si_data: &[std::io::IoSlice<'a>], _si_flags: SiFlags, ) -> Result<u64, Error>37     async fn sock_send<'a>(
38         &self,
39         _si_data: &[std::io::IoSlice<'a>],
40         _si_flags: SiFlags,
41     ) -> Result<u64, Error> {
42         Err(Error::badf())
43     }
44 
sock_shutdown(&self, _how: SdFlags) -> Result<(), Error>45     async fn sock_shutdown(&self, _how: SdFlags) -> Result<(), Error> {
46         Err(Error::badf())
47     }
48 
datasync(&self) -> Result<(), Error>49     async fn datasync(&self) -> Result<(), Error> {
50         Ok(())
51     }
52 
sync(&self) -> Result<(), Error>53     async fn sync(&self) -> Result<(), Error> {
54         Ok(())
55     }
56 
get_fdflags(&self) -> Result<FdFlags, Error>57     async fn get_fdflags(&self) -> Result<FdFlags, Error> {
58         Ok(FdFlags::empty())
59     }
60 
set_fdflags(&mut self, _flags: FdFlags) -> Result<(), Error>61     async fn set_fdflags(&mut self, _flags: FdFlags) -> Result<(), Error> {
62         Err(Error::badf())
63     }
64 
get_filestat(&self) -> Result<Filestat, Error>65     async fn get_filestat(&self) -> Result<Filestat, Error> {
66         Ok(Filestat {
67             device_id: 0,
68             inode: 0,
69             filetype: self.get_filetype().await?,
70             nlink: 0,
71             size: 0, // XXX no way to get a size out of a Read :(
72             atim: None,
73             mtim: None,
74             ctim: None,
75         })
76     }
77 
set_filestat_size(&self, _size: u64) -> Result<(), Error>78     async fn set_filestat_size(&self, _size: u64) -> Result<(), Error> {
79         Err(Error::badf())
80     }
81 
advise(&self, _offset: u64, _len: u64, _advice: Advice) -> Result<(), Error>82     async fn advise(&self, _offset: u64, _len: u64, _advice: Advice) -> Result<(), Error> {
83         Err(Error::badf())
84     }
85 
set_times( &self, _atime: Option<SystemTimeSpec>, _mtime: Option<SystemTimeSpec>, ) -> Result<(), Error>86     async fn set_times(
87         &self,
88         _atime: Option<SystemTimeSpec>,
89         _mtime: Option<SystemTimeSpec>,
90     ) -> Result<(), Error> {
91         Err(Error::badf())
92     }
93 
read_vectored<'a>(&self, _bufs: &mut [std::io::IoSliceMut<'a>]) -> Result<u64, Error>94     async fn read_vectored<'a>(&self, _bufs: &mut [std::io::IoSliceMut<'a>]) -> Result<u64, Error> {
95         Err(Error::badf())
96     }
97 
read_vectored_at<'a>( &self, _bufs: &mut [std::io::IoSliceMut<'a>], _offset: u64, ) -> Result<u64, Error>98     async fn read_vectored_at<'a>(
99         &self,
100         _bufs: &mut [std::io::IoSliceMut<'a>],
101         _offset: u64,
102     ) -> Result<u64, Error> {
103         Err(Error::badf())
104     }
105 
write_vectored<'a>(&self, _bufs: &[std::io::IoSlice<'a>]) -> Result<u64, Error>106     async fn write_vectored<'a>(&self, _bufs: &[std::io::IoSlice<'a>]) -> Result<u64, Error> {
107         Err(Error::badf())
108     }
109 
write_vectored_at<'a>( &self, _bufs: &[std::io::IoSlice<'a>], _offset: u64, ) -> Result<u64, Error>110     async fn write_vectored_at<'a>(
111         &self,
112         _bufs: &[std::io::IoSlice<'a>],
113         _offset: u64,
114     ) -> Result<u64, Error> {
115         Err(Error::badf())
116     }
117 
seek(&self, _pos: std::io::SeekFrom) -> Result<u64, Error>118     async fn seek(&self, _pos: std::io::SeekFrom) -> Result<u64, Error> {
119         Err(Error::badf())
120     }
121 
peek(&self, _buf: &mut [u8]) -> Result<u64, Error>122     async fn peek(&self, _buf: &mut [u8]) -> Result<u64, Error> {
123         Err(Error::badf())
124     }
125 
num_ready_bytes(&self) -> Result<u64, Error>126     fn num_ready_bytes(&self) -> Result<u64, Error> {
127         Ok(0)
128     }
129 
readable(&self) -> Result<(), Error>130     async fn readable(&self) -> Result<(), Error> {
131         Err(Error::badf())
132     }
133 
writable(&self) -> Result<(), Error>134     async fn writable(&self) -> Result<(), Error> {
135         Err(Error::badf())
136     }
137 }
138 
139 #[derive(Debug, Copy, Clone, PartialEq, Eq)]
140 pub enum FileType {
141     Unknown,
142     BlockDevice,
143     CharacterDevice,
144     Directory,
145     RegularFile,
146     SocketDgram,
147     SocketStream,
148     SymbolicLink,
149     Pipe,
150 }
151 
152 bitflags! {
153     #[derive(Copy, Clone, Debug, PartialEq, Eq)]
154     pub struct FdFlags: u32 {
155         const APPEND   = 0b1;
156         const DSYNC    = 0b10;
157         const NONBLOCK = 0b100;
158         const RSYNC    = 0b1000;
159         const SYNC     = 0b10000;
160     }
161 }
162 
163 bitflags! {
164     #[derive(Copy, Clone, Debug, PartialEq, Eq)]
165     pub struct SdFlags: u32 {
166         const RD = 0b1;
167         const WR = 0b10;
168     }
169 }
170 
171 bitflags! {
172     #[derive(Copy, Clone, Debug, PartialEq, Eq)]
173     pub struct SiFlags: u32 {
174     }
175 }
176 
177 bitflags! {
178     #[derive(Copy, Clone, Debug, PartialEq, Eq)]
179     pub struct RiFlags: u32 {
180         const RECV_PEEK    = 0b1;
181         const RECV_WAITALL = 0b10;
182     }
183 }
184 
185 bitflags! {
186     #[derive(Copy, Clone, Debug, PartialEq, Eq)]
187     pub struct RoFlags: u32 {
188         const RECV_DATA_TRUNCATED = 0b1;
189     }
190 }
191 
192 bitflags! {
193     #[derive(Copy, Clone, Debug, PartialEq, Eq)]
194     pub struct OFlags: u32 {
195         const CREATE    = 0b1;
196         const DIRECTORY = 0b10;
197         const EXCLUSIVE = 0b100;
198         const TRUNCATE  = 0b1000;
199     }
200 }
201 
202 #[derive(Debug, Clone, PartialEq, Eq)]
203 pub struct Filestat {
204     pub device_id: u64,
205     pub inode: u64,
206     pub filetype: FileType,
207     pub nlink: u64,
208     pub size: u64, // this is a read field, the rest are file fields
209     pub atim: Option<std::time::SystemTime>,
210     pub mtim: Option<std::time::SystemTime>,
211     pub ctim: Option<std::time::SystemTime>,
212 }
213 
214 pub(crate) trait TableFileExt {
get_file(&self, fd: u32) -> Result<Arc<FileEntry>, Error>215     fn get_file(&self, fd: u32) -> Result<Arc<FileEntry>, Error>;
get_file_mut(&mut self, fd: u32) -> Result<&mut FileEntry, Error>216     fn get_file_mut(&mut self, fd: u32) -> Result<&mut FileEntry, Error>;
217 }
218 impl TableFileExt for crate::table::Table {
get_file(&self, fd: u32) -> Result<Arc<FileEntry>, Error>219     fn get_file(&self, fd: u32) -> Result<Arc<FileEntry>, Error> {
220         self.get(fd)
221     }
get_file_mut(&mut self, fd: u32) -> Result<&mut FileEntry, Error>222     fn get_file_mut(&mut self, fd: u32) -> Result<&mut FileEntry, Error> {
223         self.get_mut(fd)
224     }
225 }
226 
227 pub(crate) struct FileEntry {
228     pub file: Box<dyn WasiFile>,
229     pub access_mode: FileAccessMode,
230 }
231 
232 bitflags! {
233     #[derive(Copy, Clone, Debug, PartialEq, Eq)]
234     pub struct FileAccessMode : u32 {
235         const READ = 0b1;
236         const WRITE= 0b10;
237     }
238 }
239 
240 impl FileEntry {
new(file: Box<dyn WasiFile>, access_mode: FileAccessMode) -> Self241     pub fn new(file: Box<dyn WasiFile>, access_mode: FileAccessMode) -> Self {
242         FileEntry { file, access_mode }
243     }
244 
get_fdstat(&self) -> Result<FdStat, Error>245     pub async fn get_fdstat(&self) -> Result<FdStat, Error> {
246         Ok(FdStat {
247             filetype: self.file.get_filetype().await?,
248             flags: self.file.get_fdflags().await?,
249             access_mode: self.access_mode,
250         })
251     }
252 }
253 
254 #[derive(Debug, Clone)]
255 pub struct FdStat {
256     pub filetype: FileType,
257     pub flags: FdFlags,
258     pub access_mode: FileAccessMode,
259 }
260 
261 #[derive(Debug, Clone)]
262 pub enum Advice {
263     Normal,
264     Sequential,
265     Random,
266     WillNeed,
267     DontNeed,
268     NoReuse,
269 }
270