]> git.lizzy.rs Git - rust.git/blob - src/libstd/sys/wasi/fd.rs
libstd: deny(elided_lifetimes_in_paths), fixes in wasi
[rust.git] / src / libstd / sys / wasi / fd.rs
1 #![allow(dead_code)]
2
3 use crate::io::{self, IoVec, IoVecMut, SeekFrom};
4 use crate::mem;
5 use crate::net::Shutdown;
6 use crate::sys::cvt_wasi;
7 use libc::{self, c_char, c_void};
8
9 pub struct WasiFd {
10     fd: libc::__wasi_fd_t,
11 }
12
13 // FIXME: these should probably all be fancier structs, builders, enums, etc
14 pub type LookupFlags = u32;
15 pub type FdFlags = u16;
16 pub type Advice = u8;
17 pub type Rights = u64;
18 pub type Oflags = u16;
19 pub type DirCookie = u64;
20 pub type Timestamp = u64;
21 pub type FstFlags = u16;
22 pub type RiFlags = u16;
23 pub type RoFlags = u16;
24 pub type SiFlags = u16;
25
26 fn iovec(a: &mut [IoVecMut<'_>]) -> (*const libc::__wasi_iovec_t, usize) {
27     assert_eq!(
28         mem::size_of::<IoVecMut<'_>>(),
29         mem::size_of::<libc::__wasi_iovec_t>()
30     );
31     assert_eq!(
32         mem::align_of::<IoVecMut<'_>>(),
33         mem::align_of::<libc::__wasi_iovec_t>()
34     );
35     (a.as_ptr() as *const libc::__wasi_iovec_t, a.len())
36 }
37
38 fn ciovec(a: &[IoVec<'_>]) -> (*const libc::__wasi_ciovec_t, usize) {
39     assert_eq!(
40         mem::size_of::<IoVec<'_>>(),
41         mem::size_of::<libc::__wasi_ciovec_t>()
42     );
43     assert_eq!(
44         mem::align_of::<IoVec<'_>>(),
45         mem::align_of::<libc::__wasi_ciovec_t>()
46     );
47     (a.as_ptr() as *const libc::__wasi_ciovec_t, a.len())
48 }
49
50 impl WasiFd {
51     pub unsafe fn from_raw(fd: libc::__wasi_fd_t) -> WasiFd {
52         WasiFd { fd }
53     }
54
55     pub fn datasync(&self) -> io::Result<()> {
56         cvt_wasi(unsafe { libc::__wasi_fd_datasync(self.fd) })
57     }
58
59     pub fn pread(&self, bufs: &mut [IoVecMut<'_>], offset: u64) -> io::Result<usize> {
60         let mut read = 0;
61         let (ptr, len) = iovec(bufs);
62         cvt_wasi(unsafe { libc::__wasi_fd_pread(self.fd, ptr, len, offset, &mut read) })?;
63         Ok(read)
64     }
65
66     pub fn pwrite(&self, bufs: &[IoVec<'_>], offset: u64) -> io::Result<usize> {
67         let mut read = 0;
68         let (ptr, len) = ciovec(bufs);
69         cvt_wasi(unsafe { libc::__wasi_fd_pwrite(self.fd, ptr, len, offset, &mut read) })?;
70         Ok(read)
71     }
72
73     pub fn read(&self, bufs: &mut [IoVecMut<'_>]) -> io::Result<usize> {
74         let mut read = 0;
75         let (ptr, len) = iovec(bufs);
76         cvt_wasi(unsafe { libc::__wasi_fd_read(self.fd, ptr, len, &mut read) })?;
77         Ok(read)
78     }
79
80     pub fn write(&self, bufs: &[IoVec<'_>]) -> io::Result<usize> {
81         let mut read = 0;
82         let (ptr, len) = ciovec(bufs);
83         cvt_wasi(unsafe { libc::__wasi_fd_write(self.fd, ptr, len, &mut read) })?;
84         Ok(read)
85     }
86
87     pub fn seek(&self, pos: SeekFrom) -> io::Result<u64> {
88         let (whence, offset) = match pos {
89             SeekFrom::Start(pos) => (libc::__WASI_WHENCE_SET, pos as i64),
90             SeekFrom::End(pos) => (libc::__WASI_WHENCE_END, pos),
91             SeekFrom::Current(pos) => (libc::__WASI_WHENCE_CUR, pos),
92         };
93         let mut pos = 0;
94         cvt_wasi(unsafe { libc::__wasi_fd_seek(self.fd, offset, whence, &mut pos) })?;
95         Ok(pos)
96     }
97
98     pub fn tell(&self) -> io::Result<u64> {
99         let mut pos = 0;
100         cvt_wasi(unsafe { libc::__wasi_fd_tell(self.fd, &mut pos) })?;
101         Ok(pos)
102     }
103
104     // FIXME: __wasi_fd_fdstat_get
105
106     pub fn set_flags(&self, flags: FdFlags) -> io::Result<()> {
107         cvt_wasi(unsafe { libc::__wasi_fd_fdstat_set_flags(self.fd, flags) })
108     }
109
110     pub fn set_rights(&self, base: Rights, inheriting: Rights) -> io::Result<()> {
111         cvt_wasi(unsafe { libc::__wasi_fd_fdstat_set_rights(self.fd, base, inheriting) })
112     }
113
114     pub fn sync(&self) -> io::Result<()> {
115         cvt_wasi(unsafe { libc::__wasi_fd_sync(self.fd) })
116     }
117
118     pub fn advise(&self, offset: u64, len: u64, advice: Advice) -> io::Result<()> {
119         cvt_wasi(unsafe { libc::__wasi_fd_advise(self.fd, offset, len, advice as u8) })
120     }
121
122     pub fn allocate(&self, offset: u64, len: u64) -> io::Result<()> {
123         cvt_wasi(unsafe { libc::__wasi_fd_allocate(self.fd, offset, len) })
124     }
125
126     pub fn crate_directory(&self, path: &[u8]) -> io::Result<()> {
127         cvt_wasi(unsafe {
128             libc::__wasi_path_create_directory(self.fd, path.as_ptr() as *const c_char, path.len())
129         })
130     }
131
132     pub fn link(
133         &self,
134         old_flags: LookupFlags,
135         old_path: &[u8],
136         new_fd: &WasiFd,
137         new_path: &[u8],
138     ) -> io::Result<()> {
139         cvt_wasi(unsafe {
140             libc::__wasi_path_link(
141                 self.fd,
142                 old_flags,
143                 old_path.as_ptr() as *const c_char,
144                 old_path.len(),
145                 new_fd.fd,
146                 new_path.as_ptr() as *const c_char,
147                 new_path.len(),
148             )
149         })
150     }
151
152     pub fn open(
153         &self,
154         dirflags: LookupFlags,
155         path: &[u8],
156         oflags: Oflags,
157         fs_rights_base: Rights,
158         fs_rights_inheriting: Rights,
159         fs_flags: FdFlags,
160     ) -> io::Result<WasiFd> {
161         unsafe {
162             let mut fd = 0;
163             cvt_wasi(libc::__wasi_path_open(
164                 self.fd,
165                 dirflags,
166                 path.as_ptr() as *const c_char,
167                 path.len(),
168                 oflags,
169                 fs_rights_base,
170                 fs_rights_inheriting,
171                 fs_flags,
172                 &mut fd,
173             ))?;
174             Ok(WasiFd::from_raw(fd))
175         }
176     }
177
178     pub fn readdir(&self, buf: &mut [u8], cookie: DirCookie) -> io::Result<usize> {
179         let mut used = 0;
180         cvt_wasi(unsafe {
181             libc::__wasi_fd_readdir(
182                 self.fd,
183                 buf.as_mut_ptr() as *mut c_void,
184                 buf.len(),
185                 cookie,
186                 &mut used,
187             )
188         })?;
189         Ok(used)
190     }
191
192     pub fn readlink(&self, path: &[u8], buf: &mut [u8]) -> io::Result<usize> {
193         let mut used = 0;
194         cvt_wasi(unsafe {
195             libc::__wasi_path_readlink(
196                 self.fd,
197                 path.as_ptr() as *const c_char,
198                 path.len(),
199                 buf.as_mut_ptr() as *mut c_char,
200                 buf.len(),
201                 &mut used,
202             )
203         })?;
204         Ok(used)
205     }
206
207     pub fn rename(&self, old_path: &[u8], new_fd: &WasiFd, new_path: &[u8]) -> io::Result<()> {
208         cvt_wasi(unsafe {
209             libc::__wasi_path_rename(
210                 self.fd,
211                 old_path.as_ptr() as *const c_char,
212                 old_path.len(),
213                 new_fd.fd,
214                 new_path.as_ptr() as *const c_char,
215                 new_path.len(),
216             )
217         })
218     }
219
220     // FIXME: __wasi_fd_filestat_get
221
222     pub fn filestat_set_times(
223         &self,
224         atim: Timestamp,
225         mtim: Timestamp,
226         fstflags: FstFlags,
227     ) -> io::Result<()> {
228         cvt_wasi(unsafe { libc::__wasi_fd_filestat_set_times(self.fd, atim, mtim, fstflags) })
229     }
230
231     pub fn filestat_set_size(&self, size: u64) -> io::Result<()> {
232         cvt_wasi(unsafe { libc::__wasi_fd_filestat_set_size(self.fd, size) })
233     }
234
235     // FIXME: __wasi_path_filestat_get
236
237     pub fn path_filestat_set_times(
238         &self,
239         flags: LookupFlags,
240         path: &[u8],
241         atim: Timestamp,
242         mtim: Timestamp,
243         fstflags: FstFlags,
244     ) -> io::Result<()> {
245         cvt_wasi(unsafe {
246             libc::__wasi_path_filestat_set_times(
247                 self.fd,
248                 flags,
249                 path.as_ptr() as *const c_char,
250                 path.len(),
251                 atim,
252                 mtim,
253                 fstflags,
254             )
255         })
256     }
257
258     pub fn symlink(&self, old_path: &[u8], new_path: &[u8]) -> io::Result<()> {
259         cvt_wasi(unsafe {
260             libc::__wasi_path_symlink(
261                 old_path.as_ptr() as *const c_char,
262                 old_path.len(),
263                 self.fd,
264                 new_path.as_ptr() as *const c_char,
265                 new_path.len(),
266             )
267         })
268     }
269
270     pub fn unlink_file(&self, path: &[u8]) -> io::Result<()> {
271         cvt_wasi(unsafe {
272             libc::__wasi_path_unlink_file(self.fd, path.as_ptr() as *const c_char, path.len())
273         })
274     }
275
276     pub fn remove_directory(&self, path: &[u8]) -> io::Result<()> {
277         cvt_wasi(unsafe {
278             libc::__wasi_path_remove_directory(self.fd, path.as_ptr() as *const c_char, path.len())
279         })
280     }
281
282     pub fn sock_recv(
283         &self,
284         ri_data: &mut [IoVecMut<'_>],
285         ri_flags: RiFlags,
286     ) -> io::Result<(usize, RoFlags)> {
287         let mut ro_datalen = 0;
288         let mut ro_flags = 0;
289         let (ptr, len) = iovec(ri_data);
290         cvt_wasi(unsafe {
291             libc::__wasi_sock_recv(self.fd, ptr, len, ri_flags, &mut ro_datalen, &mut ro_flags)
292         })?;
293         Ok((ro_datalen, ro_flags))
294     }
295
296     pub fn sock_send(&self, si_data: &[IoVec<'_>], si_flags: SiFlags) -> io::Result<usize> {
297         let mut so_datalen = 0;
298         let (ptr, len) = ciovec(si_data);
299         cvt_wasi(unsafe { libc::__wasi_sock_send(self.fd, ptr, len, si_flags, &mut so_datalen) })?;
300         Ok(so_datalen)
301     }
302
303     pub fn sock_shutdown(&self, how: Shutdown) -> io::Result<()> {
304         let how = match how {
305             Shutdown::Read => libc::__WASI_SHUT_RD,
306             Shutdown::Write => libc::__WASI_SHUT_WR,
307             Shutdown::Both => libc::__WASI_SHUT_WR | libc::__WASI_SHUT_RD,
308         };
309         cvt_wasi(unsafe { libc::__wasi_sock_shutdown(self.fd, how) })?;
310         Ok(())
311     }
312 }
313
314 impl Drop for WasiFd {
315     fn drop(&mut self) {
316         unsafe {
317             // FIXME: can we handle the return code here even though we can't on
318             // unix?
319             libc::__wasi_fd_close(self.fd);
320         }
321     }
322 }