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