1 #![deny(unsafe_op_in_unsafe_fn)]
2 #![allow(dead_code)]
3 
4 use super::err2io;
5 use crate::io::{self, IoSlice, IoSliceMut, SeekFrom};
6 use crate::mem;
7 use crate::net::Shutdown;
8 use crate::os::wasi::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd};
9 use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};
10 
11 #[derive(Debug)]
12 pub struct WasiFd {
13     fd: OwnedFd,
14 }
15 
iovec<'a>(a: &'a mut [IoSliceMut<'_>]) -> &'a [wasi::Iovec]16 fn iovec<'a>(a: &'a mut [IoSliceMut<'_>]) -> &'a [wasi::Iovec] {
17     assert_eq!(mem::size_of::<IoSliceMut<'_>>(), mem::size_of::<wasi::Iovec>());
18     assert_eq!(mem::align_of::<IoSliceMut<'_>>(), mem::align_of::<wasi::Iovec>());
19     // SAFETY: `IoSliceMut` and `IoVec` have exactly the same memory layout
20     unsafe { mem::transmute(a) }
21 }
22 
ciovec<'a>(a: &'a [IoSlice<'_>]) -> &'a [wasi::Ciovec]23 fn ciovec<'a>(a: &'a [IoSlice<'_>]) -> &'a [wasi::Ciovec] {
24     assert_eq!(mem::size_of::<IoSlice<'_>>(), mem::size_of::<wasi::Ciovec>());
25     assert_eq!(mem::align_of::<IoSlice<'_>>(), mem::align_of::<wasi::Ciovec>());
26     // SAFETY: `IoSlice` and `CIoVec` have exactly the same memory layout
27     unsafe { mem::transmute(a) }
28 }
29 
30 impl WasiFd {
datasync(&self) -> io::Result<()>31     pub fn datasync(&self) -> io::Result<()> {
32         unsafe { wasi::fd_datasync(self.as_raw_fd() as wasi::Fd).map_err(err2io) }
33     }
34 
pread(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize>35     pub fn pread(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize> {
36         unsafe { wasi::fd_pread(self.as_raw_fd() as wasi::Fd, iovec(bufs), offset).map_err(err2io) }
37     }
38 
pwrite(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result<usize>39     pub fn pwrite(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result<usize> {
40         unsafe {
41             wasi::fd_pwrite(self.as_raw_fd() as wasi::Fd, ciovec(bufs), offset).map_err(err2io)
42         }
43     }
44 
read(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize>45     pub fn read(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
46         unsafe { wasi::fd_read(self.as_raw_fd() as wasi::Fd, iovec(bufs)).map_err(err2io) }
47     }
48 
write(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize>49     pub fn write(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
50         unsafe { wasi::fd_write(self.as_raw_fd() as wasi::Fd, ciovec(bufs)).map_err(err2io) }
51     }
52 
seek(&self, pos: SeekFrom) -> io::Result<u64>53     pub fn seek(&self, pos: SeekFrom) -> io::Result<u64> {
54         let (whence, offset) = match pos {
55             SeekFrom::Start(pos) => (wasi::WHENCE_SET, pos as i64),
56             SeekFrom::End(pos) => (wasi::WHENCE_END, pos),
57             SeekFrom::Current(pos) => (wasi::WHENCE_CUR, pos),
58         };
59         unsafe { wasi::fd_seek(self.as_raw_fd() as wasi::Fd, offset, whence).map_err(err2io) }
60     }
61 
tell(&self) -> io::Result<u64>62     pub fn tell(&self) -> io::Result<u64> {
63         unsafe { wasi::fd_tell(self.as_raw_fd() as wasi::Fd).map_err(err2io) }
64     }
65 
66     // FIXME: __wasi_fd_fdstat_get
67 
set_flags(&self, flags: wasi::Fdflags) -> io::Result<()>68     pub fn set_flags(&self, flags: wasi::Fdflags) -> io::Result<()> {
69         unsafe { wasi::fd_fdstat_set_flags(self.as_raw_fd() as wasi::Fd, flags).map_err(err2io) }
70     }
71 
set_rights(&self, base: wasi::Rights, inheriting: wasi::Rights) -> io::Result<()>72     pub fn set_rights(&self, base: wasi::Rights, inheriting: wasi::Rights) -> io::Result<()> {
73         unsafe {
74             wasi::fd_fdstat_set_rights(self.as_raw_fd() as wasi::Fd, base, inheriting)
75                 .map_err(err2io)
76         }
77     }
78 
sync(&self) -> io::Result<()>79     pub fn sync(&self) -> io::Result<()> {
80         unsafe { wasi::fd_sync(self.as_raw_fd() as wasi::Fd).map_err(err2io) }
81     }
82 
advise(&self, offset: u64, len: u64, advice: wasi::Advice) -> io::Result<()>83     pub fn advise(&self, offset: u64, len: u64, advice: wasi::Advice) -> io::Result<()> {
84         unsafe {
85             wasi::fd_advise(self.as_raw_fd() as wasi::Fd, offset, len, advice).map_err(err2io)
86         }
87     }
88 
allocate(&self, offset: u64, len: u64) -> io::Result<()>89     pub fn allocate(&self, offset: u64, len: u64) -> io::Result<()> {
90         unsafe { wasi::fd_allocate(self.as_raw_fd() as wasi::Fd, offset, len).map_err(err2io) }
91     }
92 
create_directory(&self, path: &str) -> io::Result<()>93     pub fn create_directory(&self, path: &str) -> io::Result<()> {
94         unsafe { wasi::path_create_directory(self.as_raw_fd() as wasi::Fd, path).map_err(err2io) }
95     }
96 
link( &self, old_flags: wasi::Lookupflags, old_path: &str, new_fd: &WasiFd, new_path: &str, ) -> io::Result<()>97     pub fn link(
98         &self,
99         old_flags: wasi::Lookupflags,
100         old_path: &str,
101         new_fd: &WasiFd,
102         new_path: &str,
103     ) -> io::Result<()> {
104         unsafe {
105             wasi::path_link(
106                 self.as_raw_fd() as wasi::Fd,
107                 old_flags,
108                 old_path,
109                 new_fd.as_raw_fd() as wasi::Fd,
110                 new_path,
111             )
112             .map_err(err2io)
113         }
114     }
115 
open( &self, dirflags: wasi::Lookupflags, path: &str, oflags: wasi::Oflags, fs_rights_base: wasi::Rights, fs_rights_inheriting: wasi::Rights, fs_flags: wasi::Fdflags, ) -> io::Result<WasiFd>116     pub fn open(
117         &self,
118         dirflags: wasi::Lookupflags,
119         path: &str,
120         oflags: wasi::Oflags,
121         fs_rights_base: wasi::Rights,
122         fs_rights_inheriting: wasi::Rights,
123         fs_flags: wasi::Fdflags,
124     ) -> io::Result<WasiFd> {
125         unsafe {
126             wasi::path_open(
127                 self.as_raw_fd() as wasi::Fd,
128                 dirflags,
129                 path,
130                 oflags,
131                 fs_rights_base,
132                 fs_rights_inheriting,
133                 fs_flags,
134             )
135             .map(|fd| WasiFd::from_raw_fd(fd as RawFd))
136             .map_err(err2io)
137         }
138     }
139 
readdir(&self, buf: &mut [u8], cookie: wasi::Dircookie) -> io::Result<usize>140     pub fn readdir(&self, buf: &mut [u8], cookie: wasi::Dircookie) -> io::Result<usize> {
141         unsafe {
142             wasi::fd_readdir(self.as_raw_fd() as wasi::Fd, buf.as_mut_ptr(), buf.len(), cookie)
143                 .map_err(err2io)
144         }
145     }
146 
readlink(&self, path: &str, buf: &mut [u8]) -> io::Result<usize>147     pub fn readlink(&self, path: &str, buf: &mut [u8]) -> io::Result<usize> {
148         unsafe {
149             wasi::path_readlink(self.as_raw_fd() as wasi::Fd, path, buf.as_mut_ptr(), buf.len())
150                 .map_err(err2io)
151         }
152     }
153 
rename(&self, old_path: &str, new_fd: &WasiFd, new_path: &str) -> io::Result<()>154     pub fn rename(&self, old_path: &str, new_fd: &WasiFd, new_path: &str) -> io::Result<()> {
155         unsafe {
156             wasi::path_rename(
157                 self.as_raw_fd() as wasi::Fd,
158                 old_path,
159                 new_fd.as_raw_fd() as wasi::Fd,
160                 new_path,
161             )
162             .map_err(err2io)
163         }
164     }
165 
filestat_get(&self) -> io::Result<wasi::Filestat>166     pub fn filestat_get(&self) -> io::Result<wasi::Filestat> {
167         unsafe { wasi::fd_filestat_get(self.as_raw_fd() as wasi::Fd).map_err(err2io) }
168     }
169 
filestat_set_times( &self, atim: wasi::Timestamp, mtim: wasi::Timestamp, fstflags: wasi::Fstflags, ) -> io::Result<()>170     pub fn filestat_set_times(
171         &self,
172         atim: wasi::Timestamp,
173         mtim: wasi::Timestamp,
174         fstflags: wasi::Fstflags,
175     ) -> io::Result<()> {
176         unsafe {
177             wasi::fd_filestat_set_times(self.as_raw_fd() as wasi::Fd, atim, mtim, fstflags)
178                 .map_err(err2io)
179         }
180     }
181 
filestat_set_size(&self, size: u64) -> io::Result<()>182     pub fn filestat_set_size(&self, size: u64) -> io::Result<()> {
183         unsafe { wasi::fd_filestat_set_size(self.as_raw_fd() as wasi::Fd, size).map_err(err2io) }
184     }
185 
path_filestat_get( &self, flags: wasi::Lookupflags, path: &str, ) -> io::Result<wasi::Filestat>186     pub fn path_filestat_get(
187         &self,
188         flags: wasi::Lookupflags,
189         path: &str,
190     ) -> io::Result<wasi::Filestat> {
191         unsafe {
192             wasi::path_filestat_get(self.as_raw_fd() as wasi::Fd, flags, path).map_err(err2io)
193         }
194     }
195 
path_filestat_set_times( &self, flags: wasi::Lookupflags, path: &str, atim: wasi::Timestamp, mtim: wasi::Timestamp, fstflags: wasi::Fstflags, ) -> io::Result<()>196     pub fn path_filestat_set_times(
197         &self,
198         flags: wasi::Lookupflags,
199         path: &str,
200         atim: wasi::Timestamp,
201         mtim: wasi::Timestamp,
202         fstflags: wasi::Fstflags,
203     ) -> io::Result<()> {
204         unsafe {
205             wasi::path_filestat_set_times(
206                 self.as_raw_fd() as wasi::Fd,
207                 flags,
208                 path,
209                 atim,
210                 mtim,
211                 fstflags,
212             )
213             .map_err(err2io)
214         }
215     }
216 
symlink(&self, old_path: &str, new_path: &str) -> io::Result<()>217     pub fn symlink(&self, old_path: &str, new_path: &str) -> io::Result<()> {
218         unsafe {
219             wasi::path_symlink(old_path, self.as_raw_fd() as wasi::Fd, new_path).map_err(err2io)
220         }
221     }
222 
unlink_file(&self, path: &str) -> io::Result<()>223     pub fn unlink_file(&self, path: &str) -> io::Result<()> {
224         unsafe { wasi::path_unlink_file(self.as_raw_fd() as wasi::Fd, path).map_err(err2io) }
225     }
226 
remove_directory(&self, path: &str) -> io::Result<()>227     pub fn remove_directory(&self, path: &str) -> io::Result<()> {
228         unsafe { wasi::path_remove_directory(self.as_raw_fd() as wasi::Fd, path).map_err(err2io) }
229     }
230 
sock_recv( &self, ri_data: &mut [IoSliceMut<'_>], ri_flags: wasi::Riflags, ) -> io::Result<(usize, wasi::Roflags)>231     pub fn sock_recv(
232         &self,
233         ri_data: &mut [IoSliceMut<'_>],
234         ri_flags: wasi::Riflags,
235     ) -> io::Result<(usize, wasi::Roflags)> {
236         unsafe {
237             wasi::sock_recv(self.as_raw_fd() as wasi::Fd, iovec(ri_data), ri_flags).map_err(err2io)
238         }
239     }
240 
sock_send(&self, si_data: &[IoSlice<'_>], si_flags: wasi::Siflags) -> io::Result<usize>241     pub fn sock_send(&self, si_data: &[IoSlice<'_>], si_flags: wasi::Siflags) -> io::Result<usize> {
242         unsafe {
243             wasi::sock_send(self.as_raw_fd() as wasi::Fd, ciovec(si_data), si_flags).map_err(err2io)
244         }
245     }
246 
sock_shutdown(&self, how: Shutdown) -> io::Result<()>247     pub fn sock_shutdown(&self, how: Shutdown) -> io::Result<()> {
248         let how = match how {
249             Shutdown::Read => wasi::SDFLAGS_RD,
250             Shutdown::Write => wasi::SDFLAGS_WR,
251             Shutdown::Both => wasi::SDFLAGS_WR | wasi::SDFLAGS_RD,
252         };
253         unsafe { wasi::sock_shutdown(self.as_raw_fd() as wasi::Fd, how).map_err(err2io) }
254     }
255 }
256 
257 impl AsInner<OwnedFd> for WasiFd {
as_inner(&self) -> &OwnedFd258     fn as_inner(&self) -> &OwnedFd {
259         &self.fd
260     }
261 }
262 
263 impl AsInnerMut<OwnedFd> for WasiFd {
as_inner_mut(&mut self) -> &mut OwnedFd264     fn as_inner_mut(&mut self) -> &mut OwnedFd {
265         &mut self.fd
266     }
267 }
268 
269 impl IntoInner<OwnedFd> for WasiFd {
into_inner(self) -> OwnedFd270     fn into_inner(self) -> OwnedFd {
271         self.fd
272     }
273 }
274 
275 impl FromInner<OwnedFd> for WasiFd {
from_inner(owned_fd: OwnedFd) -> Self276     fn from_inner(owned_fd: OwnedFd) -> Self {
277         Self { fd: owned_fd }
278     }
279 }
280 
281 impl AsFd for WasiFd {
as_fd(&self) -> BorrowedFd<'_>282     fn as_fd(&self) -> BorrowedFd<'_> {
283         self.fd.as_fd()
284     }
285 }
286 
287 impl AsRawFd for WasiFd {
as_raw_fd(&self) -> RawFd288     fn as_raw_fd(&self) -> RawFd {
289         self.fd.as_raw_fd()
290     }
291 }
292 
293 impl IntoRawFd for WasiFd {
into_raw_fd(self) -> RawFd294     fn into_raw_fd(self) -> RawFd {
295         self.fd.into_raw_fd()
296     }
297 }
298 
299 impl FromRawFd for WasiFd {
from_raw_fd(raw_fd: RawFd) -> Self300     unsafe fn from_raw_fd(raw_fd: RawFd) -> Self {
301         unsafe { Self { fd: FromRawFd::from_raw_fd(raw_fd) } }
302     }
303 }
304