1use crate::{Error, ErrorExt, SystemTimeSpec};
2use bitflags::bitflags;
3use std::any::Any;
4use std::sync::Arc;
5
6#[wiggle::async_trait]
7pub trait WasiFile: Send + Sync {
8 fn as_any(&self) -> &dyn Any;
9 async fn get_filetype(&self) -> Result<FileType, Error>;
10
11 #[cfg(unix)]
12 fn pollable(&self) -> Option<rustix::fd::BorrowedFd> {
13 None
14 }
15
16 #[cfg(windows)]
17 fn pollable(&self) -> Option<io_extras::os::windows::RawHandleOrSocket> {
18 None
19 }
20
21 fn isatty(&self) -> bool {
22 false
23 }
24
25 async fn sock_accept(&self, _fdflags: FdFlags) -> Result<Box<dyn WasiFile>, Error> {
26 Err(Error::badf())
27 }
28
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
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
45 async fn sock_shutdown(&self, _how: SdFlags) -> Result<(), Error> {
46 Err(Error::badf())
47 }
48
49 async fn datasync(&self) -> Result<(), Error> {
50 Ok(())
51 }
52
53 async fn sync(&self) -> Result<(), Error> {
54 Ok(())
55 }
56
57 async fn get_fdflags(&self) -> Result<FdFlags, Error> {
58 Ok(FdFlags::empty())
59 }
60
61 async fn set_fdflags(&mut self, _flags: FdFlags) -> Result<(), Error> {
62 Err(Error::badf())
63 }
64
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, atim: None,
73 mtim: None,
74 ctim: None,
75 })
76 }
77
78 async fn set_filestat_size(&self, _size: u64) -> Result<(), Error> {
79 Err(Error::badf())
80 }
81
82 async fn advise(&self, _offset: u64, _len: u64, _advice: Advice) -> Result<(), Error> {
83 Err(Error::badf())
84 }
85
86 async fn set_times(
87 &self,
88 _atime: Option<SystemTimeSpec>,
89 _mtime: Option<SystemTimeSpec>,
90 ) -> Result<(), Error> {
91 Err(Error::badf())
92 }
93
94 async fn read_vectored<'a>(&self, _bufs: &mut [std::io::IoSliceMut<'a>]) -> Result<u64, Error> {
95 Err(Error::badf())
96 }
97
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
106 async fn write_vectored<'a>(&self, _bufs: &[std::io::IoSlice<'a>]) -> Result<u64, Error> {
107 Err(Error::badf())
108 }
109
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
118 async fn seek(&self, _pos: std::io::SeekFrom) -> Result<u64, Error> {
119 Err(Error::badf())
120 }
121
122 async fn peek(&self, _buf: &mut [u8]) -> Result<u64, Error> {
123 Err(Error::badf())
124 }
125
126 fn num_ready_bytes(&self) -> Result<u64, Error> {
127 Ok(0)
128 }
129
130 async fn readable(&self) -> Result<(), Error> {
131 Err(Error::badf())
132 }
133
134 async fn writable(&self) -> Result<(), Error> {
135 Err(Error::badf())
136 }
137}
138
139#[derive(Debug, Copy, Clone, PartialEq, Eq)]
140pub enum FileType {
141 Unknown,
142 BlockDevice,
143 CharacterDevice,
144 Directory,
145 RegularFile,
146 SocketDgram,
147 SocketStream,
148 SymbolicLink,
149 Pipe,
150}
151
152bitflags! {
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
163bitflags! {
164 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
165 pub struct SdFlags: u32 {
166 const RD = 0b1;
167 const WR = 0b10;
168 }
169}
170
171bitflags! {
172 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
173 pub struct SiFlags: u32 {
174 }
175}
176
177bitflags! {
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
185bitflags! {
186 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
187 pub struct RoFlags: u32 {
188 const RECV_DATA_TRUNCATED = 0b1;
189 }
190}
191
192bitflags! {
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)]
203pub struct Filestat {
204 pub device_id: u64,
205 pub inode: u64,
206 pub filetype: FileType,
207 pub nlink: u64,
208 pub size: u64, pub atim: Option<std::time::SystemTime>,
210 pub mtim: Option<std::time::SystemTime>,
211 pub ctim: Option<std::time::SystemTime>,
212}
213
214pub(crate) trait TableFileExt {
215 fn get_file(&self, fd: u32) -> Result<Arc<FileEntry>, Error>;
216 fn get_file_mut(&mut self, fd: u32) -> Result<&mut FileEntry, Error>;
217}
218impl TableFileExt for crate::table::Table {
219 fn get_file(&self, fd: u32) -> Result<Arc<FileEntry>, Error> {
220 self.get(fd)
221 }
222 fn get_file_mut(&mut self, fd: u32) -> Result<&mut FileEntry, Error> {
223 self.get_mut(fd)
224 }
225}
226
227pub(crate) struct FileEntry {
228 pub file: Box<dyn WasiFile>,
229 pub access_mode: FileAccessMode,
230}
231
232bitflags! {
233 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
234 pub struct FileAccessMode : u32 {
235 const READ = 0b1;
236 const WRITE= 0b10;
237 }
238}
239
240impl FileEntry {
241 pub fn new(file: Box<dyn WasiFile>, access_mode: FileAccessMode) -> Self {
242 FileEntry { file, access_mode }
243 }
244
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)]
255pub struct FdStat {
256 pub filetype: FileType,
257 pub flags: FdFlags,
258 pub access_mode: FileAccessMode,
259}
260
261#[derive(Debug, Clone)]
262pub enum Advice {
263 Normal,
264 Sequential,
265 Random,
266 WillNeed,
267 DontNeed,
268 NoReuse,
269}