]> git.lizzy.rs Git - rust.git/blob - library/std/src/sys/wasi/fd.rs
Auto merge of #75971 - Amjad50:libstd-deny-unsafe_op_in_unsafe_fn, r=Mark-Simulacrum
[rust.git] / library / std / src / sys / wasi / fd.rs
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
9 #[derive(Debug)]
10 pub struct WasiFd {
11     fd: wasi::Fd,
12 }
13
14 fn iovec<'a>(a: &'a mut [IoSliceMut<'_>]) -> &'a [wasi::Iovec] {
15     assert_eq!(mem::size_of::<IoSliceMut<'_>>(), mem::size_of::<wasi::Iovec>());
16     assert_eq!(mem::align_of::<IoSliceMut<'_>>(), mem::align_of::<wasi::Iovec>());
17     // SAFETY: `IoSliceMut` and `IoVec` have exactly the same memory layout
18     unsafe { mem::transmute(a) }
19 }
20
21 fn ciovec<'a>(a: &'a [IoSlice<'_>]) -> &'a [wasi::Ciovec] {
22     assert_eq!(mem::size_of::<IoSlice<'_>>(), mem::size_of::<wasi::Ciovec>());
23     assert_eq!(mem::align_of::<IoSlice<'_>>(), mem::align_of::<wasi::Ciovec>());
24     // SAFETY: `IoSlice` and `CIoVec` have exactly the same memory layout
25     unsafe { mem::transmute(a) }
26 }
27
28 impl WasiFd {
29     pub unsafe fn from_raw(fd: wasi::Fd) -> WasiFd {
30         WasiFd { fd }
31     }
32
33     pub fn into_raw(self) -> wasi::Fd {
34         let ret = self.fd;
35         mem::forget(self);
36         ret
37     }
38
39     pub fn as_raw(&self) -> wasi::Fd {
40         self.fd
41     }
42
43     pub fn datasync(&self) -> io::Result<()> {
44         unsafe { wasi::fd_datasync(self.fd).map_err(err2io) }
45     }
46
47     pub fn pread(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize> {
48         unsafe { wasi::fd_pread(self.fd, iovec(bufs), offset).map_err(err2io) }
49     }
50
51     pub fn pwrite(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result<usize> {
52         unsafe { wasi::fd_pwrite(self.fd, ciovec(bufs), offset).map_err(err2io) }
53     }
54
55     pub fn read(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
56         unsafe { wasi::fd_read(self.fd, iovec(bufs)).map_err(err2io) }
57     }
58
59     pub fn write(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
60         unsafe { wasi::fd_write(self.fd, ciovec(bufs)).map_err(err2io) }
61     }
62
63     pub fn seek(&self, pos: SeekFrom) -> io::Result<u64> {
64         let (whence, offset) = match pos {
65             SeekFrom::Start(pos) => (wasi::WHENCE_SET, pos as i64),
66             SeekFrom::End(pos) => (wasi::WHENCE_END, pos),
67             SeekFrom::Current(pos) => (wasi::WHENCE_CUR, pos),
68         };
69         unsafe { wasi::fd_seek(self.fd, offset, whence).map_err(err2io) }
70     }
71
72     pub fn tell(&self) -> io::Result<u64> {
73         unsafe { wasi::fd_tell(self.fd).map_err(err2io) }
74     }
75
76     // FIXME: __wasi_fd_fdstat_get
77
78     pub fn set_flags(&self, flags: wasi::Fdflags) -> io::Result<()> {
79         unsafe { wasi::fd_fdstat_set_flags(self.fd, flags).map_err(err2io) }
80     }
81
82     pub fn set_rights(&self, base: wasi::Rights, inheriting: wasi::Rights) -> io::Result<()> {
83         unsafe { wasi::fd_fdstat_set_rights(self.fd, base, inheriting).map_err(err2io) }
84     }
85
86     pub fn sync(&self) -> io::Result<()> {
87         unsafe { wasi::fd_sync(self.fd).map_err(err2io) }
88     }
89
90     pub fn advise(&self, offset: u64, len: u64, advice: wasi::Advice) -> io::Result<()> {
91         unsafe { wasi::fd_advise(self.fd, offset, len, advice).map_err(err2io) }
92     }
93
94     pub fn allocate(&self, offset: u64, len: u64) -> io::Result<()> {
95         unsafe { wasi::fd_allocate(self.fd, offset, len).map_err(err2io) }
96     }
97
98     pub fn create_directory(&self, path: &str) -> io::Result<()> {
99         unsafe { wasi::path_create_directory(self.fd, path).map_err(err2io) }
100     }
101
102     pub fn link(
103         &self,
104         old_flags: wasi::Lookupflags,
105         old_path: &str,
106         new_fd: &WasiFd,
107         new_path: &str,
108     ) -> io::Result<()> {
109         unsafe {
110             wasi::path_link(self.fd, old_flags, old_path, new_fd.fd, new_path).map_err(err2io)
111         }
112     }
113
114     pub fn open(
115         &self,
116         dirflags: wasi::Lookupflags,
117         path: &str,
118         oflags: wasi::Oflags,
119         fs_rights_base: wasi::Rights,
120         fs_rights_inheriting: wasi::Rights,
121         fs_flags: wasi::Fdflags,
122     ) -> io::Result<WasiFd> {
123         unsafe {
124             wasi::path_open(
125                 self.fd,
126                 dirflags,
127                 path,
128                 oflags,
129                 fs_rights_base,
130                 fs_rights_inheriting,
131                 fs_flags,
132             )
133             .map(|fd| WasiFd::from_raw(fd))
134             .map_err(err2io)
135         }
136     }
137
138     pub fn readdir(&self, buf: &mut [u8], cookie: wasi::Dircookie) -> io::Result<usize> {
139         unsafe { wasi::fd_readdir(self.fd, buf.as_mut_ptr(), buf.len(), cookie).map_err(err2io) }
140     }
141
142     pub fn readlink(&self, path: &str, buf: &mut [u8]) -> io::Result<usize> {
143         unsafe { wasi::path_readlink(self.fd, path, buf.as_mut_ptr(), buf.len()).map_err(err2io) }
144     }
145
146     pub fn rename(&self, old_path: &str, new_fd: &WasiFd, new_path: &str) -> io::Result<()> {
147         unsafe { wasi::path_rename(self.fd, old_path, new_fd.fd, new_path).map_err(err2io) }
148     }
149
150     pub fn filestat_get(&self) -> io::Result<wasi::Filestat> {
151         unsafe { wasi::fd_filestat_get(self.fd).map_err(err2io) }
152     }
153
154     pub fn filestat_set_times(
155         &self,
156         atim: wasi::Timestamp,
157         mtim: wasi::Timestamp,
158         fstflags: wasi::Fstflags,
159     ) -> io::Result<()> {
160         unsafe { wasi::fd_filestat_set_times(self.fd, atim, mtim, fstflags).map_err(err2io) }
161     }
162
163     pub fn filestat_set_size(&self, size: u64) -> io::Result<()> {
164         unsafe { wasi::fd_filestat_set_size(self.fd, size).map_err(err2io) }
165     }
166
167     pub fn path_filestat_get(
168         &self,
169         flags: wasi::Lookupflags,
170         path: &str,
171     ) -> io::Result<wasi::Filestat> {
172         unsafe { wasi::path_filestat_get(self.fd, flags, path).map_err(err2io) }
173     }
174
175     pub fn path_filestat_set_times(
176         &self,
177         flags: wasi::Lookupflags,
178         path: &str,
179         atim: wasi::Timestamp,
180         mtim: wasi::Timestamp,
181         fstflags: wasi::Fstflags,
182     ) -> io::Result<()> {
183         unsafe {
184             wasi::path_filestat_set_times(self.fd, flags, path, atim, mtim, fstflags)
185                 .map_err(err2io)
186         }
187     }
188
189     pub fn symlink(&self, old_path: &str, new_path: &str) -> io::Result<()> {
190         unsafe { wasi::path_symlink(old_path, self.fd, new_path).map_err(err2io) }
191     }
192
193     pub fn unlink_file(&self, path: &str) -> io::Result<()> {
194         unsafe { wasi::path_unlink_file(self.fd, path).map_err(err2io) }
195     }
196
197     pub fn remove_directory(&self, path: &str) -> io::Result<()> {
198         unsafe { wasi::path_remove_directory(self.fd, path).map_err(err2io) }
199     }
200
201     pub fn sock_recv(
202         &self,
203         ri_data: &mut [IoSliceMut<'_>],
204         ri_flags: wasi::Riflags,
205     ) -> io::Result<(usize, wasi::Roflags)> {
206         unsafe { wasi::sock_recv(self.fd, iovec(ri_data), ri_flags).map_err(err2io) }
207     }
208
209     pub fn sock_send(&self, si_data: &[IoSlice<'_>], si_flags: wasi::Siflags) -> io::Result<usize> {
210         unsafe { wasi::sock_send(self.fd, ciovec(si_data), si_flags).map_err(err2io) }
211     }
212
213     pub fn sock_shutdown(&self, how: Shutdown) -> io::Result<()> {
214         let how = match how {
215             Shutdown::Read => wasi::SDFLAGS_RD,
216             Shutdown::Write => wasi::SDFLAGS_WR,
217             Shutdown::Both => wasi::SDFLAGS_WR | wasi::SDFLAGS_RD,
218         };
219         unsafe { wasi::sock_shutdown(self.fd, how).map_err(err2io) }
220     }
221 }
222
223 impl Drop for WasiFd {
224     fn drop(&mut self) {
225         // FIXME: can we handle the return code here even though we can't on
226         // unix?
227         let _ = unsafe { wasi::fd_close(self.fd) };
228     }
229 }