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