1 //! Bindings for WASIp0 aka Preview 0 aka `wasi_unstable`.
2 //!
3 //! This module is purely here for backwards compatibility in the Wasmtime CLI.
4 //! You probably want to use [`p1`](crate::p1) instead.
5
6 use crate::p0::types::Error;
7 use crate::p1::WasiP1Ctx;
8 use crate::p1::types as snapshot1_types;
9 use crate::p1::wasi_snapshot_preview1::WasiSnapshotPreview1 as Snapshot1;
10 use wiggle::{GuestError, GuestMemory, GuestPtr};
11
add_to_linker_async<T: Send + 'static>( linker: &mut wasmtime::Linker<T>, f: impl Fn(&mut T) -> &mut WasiP1Ctx + Copy + Send + Sync + 'static, ) -> wasmtime::Result<()>12 pub fn add_to_linker_async<T: Send + 'static>(
13 linker: &mut wasmtime::Linker<T>,
14 f: impl Fn(&mut T) -> &mut WasiP1Ctx + Copy + Send + Sync + 'static,
15 ) -> wasmtime::Result<()> {
16 wasi_unstable::add_to_linker(linker, f)
17 }
18
add_to_linker_sync<T: Send + 'static>( linker: &mut wasmtime::Linker<T>, f: impl Fn(&mut T) -> &mut WasiP1Ctx + Copy + Send + Sync + 'static, ) -> wasmtime::Result<()>19 pub fn add_to_linker_sync<T: Send + 'static>(
20 linker: &mut wasmtime::Linker<T>,
21 f: impl Fn(&mut T) -> &mut WasiP1Ctx + Copy + Send + Sync + 'static,
22 ) -> wasmtime::Result<()> {
23 sync::add_wasi_unstable_to_linker(linker, f)
24 }
25
26 wiggle::from_witx!({
27 witx: ["witx/p0/wasi_unstable.witx"],
28 async: {
29 wasi_unstable::{
30 fd_advise, fd_close, fd_datasync, fd_fdstat_get, fd_filestat_get, fd_filestat_set_size,
31 fd_filestat_set_times, fd_read, fd_pread, fd_seek, fd_sync, fd_readdir, fd_write,
32 fd_pwrite, poll_oneoff, path_create_directory, path_filestat_get,
33 path_filestat_set_times, path_link, path_open, path_readlink, path_remove_directory,
34 path_rename, path_symlink, path_unlink_file
35 }
36 },
37 errors: { errno => trappable Error },
38 });
39
40 mod sync {
41 use std::future::Future;
42 use wasmtime::Result;
43
44 wiggle::wasmtime_integration!({
45 witx: ["witx/p0/wasi_unstable.witx"],
46 target: super,
47 block_on[in_tokio]: {
48 wasi_unstable::{
49 fd_advise, fd_close, fd_datasync, fd_fdstat_get, fd_filestat_get, fd_filestat_set_size,
50 fd_filestat_set_times, fd_read, fd_pread, fd_seek, fd_sync, fd_readdir, fd_write,
51 fd_pwrite, poll_oneoff, path_create_directory, path_filestat_get,
52 path_filestat_set_times, path_link, path_open, path_readlink, path_remove_directory,
53 path_rename, path_symlink, path_unlink_file
54 }
55 },
56 errors: { errno => trappable Error },
57 });
58
59 // Small wrapper around `in_tokio` to add a `Result` layer which is always
60 // `Ok`
in_tokio<F: Future>(future: F) -> Result<F::Output>61 fn in_tokio<F: Future>(future: F) -> Result<F::Output> {
62 Ok(crate::runtime::in_tokio(future))
63 }
64 }
65
66 impl wiggle::GuestErrorType for types::Errno {
success() -> Self67 fn success() -> Self {
68 Self::Success
69 }
70 }
71
72 impl<T: Snapshot1 + Send> wasi_unstable::WasiUnstable for T {
set_hostcall_fuel(&mut self, fuel: usize)73 fn set_hostcall_fuel(&mut self, fuel: usize) {
74 Snapshot1::set_hostcall_fuel(self, fuel)
75 }
args_get( &mut self, memory: &mut GuestMemory<'_>, argv: GuestPtr<GuestPtr<u8>>, argv_buf: GuestPtr<u8>, ) -> Result<(), Error>76 fn args_get(
77 &mut self,
78 memory: &mut GuestMemory<'_>,
79 argv: GuestPtr<GuestPtr<u8>>,
80 argv_buf: GuestPtr<u8>,
81 ) -> Result<(), Error> {
82 Snapshot1::args_get(self, memory, argv, argv_buf)?;
83 Ok(())
84 }
85
args_sizes_get( &mut self, memory: &mut GuestMemory<'_>, ) -> Result<(types::Size, types::Size), Error>86 fn args_sizes_get(
87 &mut self,
88 memory: &mut GuestMemory<'_>,
89 ) -> Result<(types::Size, types::Size), Error> {
90 let s = Snapshot1::args_sizes_get(self, memory)?;
91 Ok(s)
92 }
93
environ_get( &mut self, memory: &mut GuestMemory<'_>, environ: GuestPtr<GuestPtr<u8>>, environ_buf: GuestPtr<u8>, ) -> Result<(), Error>94 fn environ_get(
95 &mut self,
96 memory: &mut GuestMemory<'_>,
97 environ: GuestPtr<GuestPtr<u8>>,
98 environ_buf: GuestPtr<u8>,
99 ) -> Result<(), Error> {
100 Snapshot1::environ_get(self, memory, environ, environ_buf)?;
101 Ok(())
102 }
103
environ_sizes_get( &mut self, memory: &mut GuestMemory<'_>, ) -> Result<(types::Size, types::Size), Error>104 fn environ_sizes_get(
105 &mut self,
106 memory: &mut GuestMemory<'_>,
107 ) -> Result<(types::Size, types::Size), Error> {
108 let s = Snapshot1::environ_sizes_get(self, memory)?;
109 Ok(s)
110 }
111
clock_res_get( &mut self, memory: &mut GuestMemory<'_>, id: types::Clockid, ) -> Result<types::Timestamp, Error>112 fn clock_res_get(
113 &mut self,
114 memory: &mut GuestMemory<'_>,
115 id: types::Clockid,
116 ) -> Result<types::Timestamp, Error> {
117 let t = Snapshot1::clock_res_get(self, memory, id.into())?;
118 Ok(t)
119 }
120
clock_time_get( &mut self, memory: &mut GuestMemory<'_>, id: types::Clockid, precision: types::Timestamp, ) -> Result<types::Timestamp, Error>121 fn clock_time_get(
122 &mut self,
123 memory: &mut GuestMemory<'_>,
124 id: types::Clockid,
125 precision: types::Timestamp,
126 ) -> Result<types::Timestamp, Error> {
127 let t = Snapshot1::clock_time_get(self, memory, id.into(), precision)?;
128 Ok(t)
129 }
130
fd_advise( &mut self, memory: &mut GuestMemory<'_>, fd: types::Fd, offset: types::Filesize, len: types::Filesize, advice: types::Advice, ) -> Result<(), Error>131 async fn fd_advise(
132 &mut self,
133 memory: &mut GuestMemory<'_>,
134 fd: types::Fd,
135 offset: types::Filesize,
136 len: types::Filesize,
137 advice: types::Advice,
138 ) -> Result<(), Error> {
139 Snapshot1::fd_advise(self, memory, fd.into(), offset, len, advice.into()).await?;
140 Ok(())
141 }
142
fd_allocate( &mut self, memory: &mut GuestMemory<'_>, fd: types::Fd, offset: types::Filesize, len: types::Filesize, ) -> Result<(), Error>143 fn fd_allocate(
144 &mut self,
145 memory: &mut GuestMemory<'_>,
146 fd: types::Fd,
147 offset: types::Filesize,
148 len: types::Filesize,
149 ) -> Result<(), Error> {
150 Snapshot1::fd_allocate(self, memory, fd.into(), offset, len)?;
151 Ok(())
152 }
153
fd_close(&mut self, memory: &mut GuestMemory<'_>, fd: types::Fd) -> Result<(), Error>154 async fn fd_close(&mut self, memory: &mut GuestMemory<'_>, fd: types::Fd) -> Result<(), Error> {
155 Snapshot1::fd_close(self, memory, fd.into()).await?;
156 Ok(())
157 }
158
fd_datasync( &mut self, memory: &mut GuestMemory<'_>, fd: types::Fd, ) -> Result<(), Error>159 async fn fd_datasync(
160 &mut self,
161 memory: &mut GuestMemory<'_>,
162 fd: types::Fd,
163 ) -> Result<(), Error> {
164 Snapshot1::fd_datasync(self, memory, fd.into()).await?;
165 Ok(())
166 }
167
fd_fdstat_get( &mut self, memory: &mut GuestMemory<'_>, fd: types::Fd, ) -> Result<types::Fdstat, Error>168 async fn fd_fdstat_get(
169 &mut self,
170 memory: &mut GuestMemory<'_>,
171 fd: types::Fd,
172 ) -> Result<types::Fdstat, Error> {
173 Ok(Snapshot1::fd_fdstat_get(self, memory, fd.into())
174 .await?
175 .into())
176 }
177
fd_fdstat_set_flags( &mut self, memory: &mut GuestMemory<'_>, fd: types::Fd, flags: types::Fdflags, ) -> Result<(), Error>178 fn fd_fdstat_set_flags(
179 &mut self,
180 memory: &mut GuestMemory<'_>,
181 fd: types::Fd,
182 flags: types::Fdflags,
183 ) -> Result<(), Error> {
184 Snapshot1::fd_fdstat_set_flags(self, memory, fd.into(), flags.into())?;
185 Ok(())
186 }
187
fd_fdstat_set_rights( &mut self, memory: &mut GuestMemory<'_>, fd: types::Fd, fs_rights_base: types::Rights, fs_rights_inheriting: types::Rights, ) -> Result<(), Error>188 fn fd_fdstat_set_rights(
189 &mut self,
190 memory: &mut GuestMemory<'_>,
191 fd: types::Fd,
192 fs_rights_base: types::Rights,
193 fs_rights_inheriting: types::Rights,
194 ) -> Result<(), Error> {
195 Snapshot1::fd_fdstat_set_rights(
196 self,
197 memory,
198 fd.into(),
199 fs_rights_base.into(),
200 fs_rights_inheriting.into(),
201 )?;
202 Ok(())
203 }
204
fd_filestat_get( &mut self, memory: &mut GuestMemory<'_>, fd: types::Fd, ) -> Result<types::Filestat, Error>205 async fn fd_filestat_get(
206 &mut self,
207 memory: &mut GuestMemory<'_>,
208 fd: types::Fd,
209 ) -> Result<types::Filestat, Error> {
210 Ok(Snapshot1::fd_filestat_get(self, memory, fd.into())
211 .await?
212 .into())
213 }
214
fd_filestat_set_size( &mut self, memory: &mut GuestMemory<'_>, fd: types::Fd, size: types::Filesize, ) -> Result<(), Error>215 async fn fd_filestat_set_size(
216 &mut self,
217 memory: &mut GuestMemory<'_>,
218 fd: types::Fd,
219 size: types::Filesize,
220 ) -> Result<(), Error> {
221 Snapshot1::fd_filestat_set_size(self, memory, fd.into(), size).await?;
222 Ok(())
223 }
224
fd_filestat_set_times( &mut self, memory: &mut GuestMemory<'_>, fd: types::Fd, atim: types::Timestamp, mtim: types::Timestamp, fst_flags: types::Fstflags, ) -> Result<(), Error>225 async fn fd_filestat_set_times(
226 &mut self,
227 memory: &mut GuestMemory<'_>,
228 fd: types::Fd,
229 atim: types::Timestamp,
230 mtim: types::Timestamp,
231 fst_flags: types::Fstflags,
232 ) -> Result<(), Error> {
233 Snapshot1::fd_filestat_set_times(self, memory, fd.into(), atim, mtim, fst_flags.into())
234 .await?;
235 Ok(())
236 }
237
fd_read( &mut self, memory: &mut GuestMemory<'_>, fd: types::Fd, iovs: types::IovecArray, ) -> Result<types::Size, Error>238 async fn fd_read(
239 &mut self,
240 memory: &mut GuestMemory<'_>,
241 fd: types::Fd,
242 iovs: types::IovecArray,
243 ) -> Result<types::Size, Error> {
244 assert_iovec_array_same();
245 let result = Snapshot1::fd_read(self, memory, fd.into(), iovs.cast()).await?;
246 Ok(result)
247 }
248
fd_pread( &mut self, memory: &mut GuestMemory<'_>, fd: types::Fd, iovs: types::IovecArray, offset: types::Filesize, ) -> Result<types::Size, Error>249 async fn fd_pread(
250 &mut self,
251 memory: &mut GuestMemory<'_>,
252 fd: types::Fd,
253 iovs: types::IovecArray,
254 offset: types::Filesize,
255 ) -> Result<types::Size, Error> {
256 assert_iovec_array_same();
257 let result = Snapshot1::fd_pread(self, memory, fd.into(), iovs.cast(), offset).await?;
258 Ok(result)
259 }
260
fd_write( &mut self, memory: &mut GuestMemory<'_>, fd: types::Fd, ciovs: types::CiovecArray, ) -> Result<types::Size, Error>261 async fn fd_write(
262 &mut self,
263 memory: &mut GuestMemory<'_>,
264 fd: types::Fd,
265 ciovs: types::CiovecArray,
266 ) -> Result<types::Size, Error> {
267 assert_ciovec_array_same();
268 let result = Snapshot1::fd_write(self, memory, fd.into(), ciovs.cast()).await?;
269 Ok(result)
270 }
271
fd_pwrite( &mut self, memory: &mut GuestMemory<'_>, fd: types::Fd, ciovs: types::CiovecArray, offset: types::Filesize, ) -> Result<types::Size, Error>272 async fn fd_pwrite(
273 &mut self,
274 memory: &mut GuestMemory<'_>,
275 fd: types::Fd,
276 ciovs: types::CiovecArray,
277 offset: types::Filesize,
278 ) -> Result<types::Size, Error> {
279 assert_ciovec_array_same();
280 let result = Snapshot1::fd_pwrite(self, memory, fd.into(), ciovs.cast(), offset).await?;
281 Ok(result)
282 }
283
fd_prestat_get( &mut self, memory: &mut GuestMemory<'_>, fd: types::Fd, ) -> Result<types::Prestat, Error>284 fn fd_prestat_get(
285 &mut self,
286 memory: &mut GuestMemory<'_>,
287 fd: types::Fd,
288 ) -> Result<types::Prestat, Error> {
289 Ok(Snapshot1::fd_prestat_get(self, memory, fd.into())?.into())
290 }
291
fd_prestat_dir_name( &mut self, memory: &mut GuestMemory<'_>, fd: types::Fd, path: GuestPtr<u8>, path_max_len: types::Size, ) -> Result<(), Error>292 fn fd_prestat_dir_name(
293 &mut self,
294 memory: &mut GuestMemory<'_>,
295 fd: types::Fd,
296 path: GuestPtr<u8>,
297 path_max_len: types::Size,
298 ) -> Result<(), Error> {
299 Snapshot1::fd_prestat_dir_name(self, memory, fd.into(), path, path_max_len)?;
300 Ok(())
301 }
302
fd_renumber( &mut self, memory: &mut GuestMemory<'_>, from: types::Fd, to: types::Fd, ) -> Result<(), Error>303 fn fd_renumber(
304 &mut self,
305 memory: &mut GuestMemory<'_>,
306 from: types::Fd,
307 to: types::Fd,
308 ) -> Result<(), Error> {
309 Snapshot1::fd_renumber(self, memory, from.into(), to.into())?;
310 Ok(())
311 }
312
fd_seek( &mut self, memory: &mut GuestMemory<'_>, fd: types::Fd, offset: types::Filedelta, whence: types::Whence, ) -> Result<types::Filesize, Error>313 async fn fd_seek(
314 &mut self,
315 memory: &mut GuestMemory<'_>,
316 fd: types::Fd,
317 offset: types::Filedelta,
318 whence: types::Whence,
319 ) -> Result<types::Filesize, Error> {
320 Ok(Snapshot1::fd_seek(self, memory, fd.into(), offset, whence.into()).await?)
321 }
322
fd_sync(&mut self, memory: &mut GuestMemory<'_>, fd: types::Fd) -> Result<(), Error>323 async fn fd_sync(&mut self, memory: &mut GuestMemory<'_>, fd: types::Fd) -> Result<(), Error> {
324 Snapshot1::fd_sync(self, memory, fd.into()).await?;
325 Ok(())
326 }
327
fd_tell( &mut self, memory: &mut GuestMemory<'_>, fd: types::Fd, ) -> Result<types::Filesize, Error>328 fn fd_tell(
329 &mut self,
330 memory: &mut GuestMemory<'_>,
331 fd: types::Fd,
332 ) -> Result<types::Filesize, Error> {
333 Ok(Snapshot1::fd_tell(self, memory, fd.into())?)
334 }
335
fd_readdir( &mut self, memory: &mut GuestMemory<'_>, fd: types::Fd, buf: GuestPtr<u8>, buf_len: types::Size, cookie: types::Dircookie, ) -> Result<types::Size, Error>336 async fn fd_readdir(
337 &mut self,
338 memory: &mut GuestMemory<'_>,
339 fd: types::Fd,
340 buf: GuestPtr<u8>,
341 buf_len: types::Size,
342 cookie: types::Dircookie,
343 ) -> Result<types::Size, Error> {
344 Ok(Snapshot1::fd_readdir(self, memory, fd.into(), buf, buf_len, cookie).await?)
345 }
346
path_create_directory( &mut self, memory: &mut GuestMemory<'_>, dirfd: types::Fd, path: GuestPtr<str>, ) -> Result<(), Error>347 async fn path_create_directory(
348 &mut self,
349 memory: &mut GuestMemory<'_>,
350 dirfd: types::Fd,
351 path: GuestPtr<str>,
352 ) -> Result<(), Error> {
353 Snapshot1::path_create_directory(self, memory, dirfd.into(), path).await?;
354 Ok(())
355 }
356
path_filestat_get( &mut self, memory: &mut GuestMemory<'_>, dirfd: types::Fd, flags: types::Lookupflags, path: GuestPtr<str>, ) -> Result<types::Filestat, Error>357 async fn path_filestat_get(
358 &mut self,
359 memory: &mut GuestMemory<'_>,
360 dirfd: types::Fd,
361 flags: types::Lookupflags,
362 path: GuestPtr<str>,
363 ) -> Result<types::Filestat, Error> {
364 Ok(
365 Snapshot1::path_filestat_get(self, memory, dirfd.into(), flags.into(), path)
366 .await?
367 .into(),
368 )
369 }
370
path_filestat_set_times( &mut self, memory: &mut GuestMemory<'_>, dirfd: types::Fd, flags: types::Lookupflags, path: GuestPtr<str>, atim: types::Timestamp, mtim: types::Timestamp, fst_flags: types::Fstflags, ) -> Result<(), Error>371 async fn path_filestat_set_times(
372 &mut self,
373 memory: &mut GuestMemory<'_>,
374 dirfd: types::Fd,
375 flags: types::Lookupflags,
376 path: GuestPtr<str>,
377 atim: types::Timestamp,
378 mtim: types::Timestamp,
379 fst_flags: types::Fstflags,
380 ) -> Result<(), Error> {
381 Snapshot1::path_filestat_set_times(
382 self,
383 memory,
384 dirfd.into(),
385 flags.into(),
386 path,
387 atim,
388 mtim,
389 fst_flags.into(),
390 )
391 .await?;
392 Ok(())
393 }
394
path_link( &mut self, memory: &mut GuestMemory<'_>, src_fd: types::Fd, src_flags: types::Lookupflags, src_path: GuestPtr<str>, target_fd: types::Fd, target_path: GuestPtr<str>, ) -> Result<(), Error>395 async fn path_link(
396 &mut self,
397 memory: &mut GuestMemory<'_>,
398 src_fd: types::Fd,
399 src_flags: types::Lookupflags,
400 src_path: GuestPtr<str>,
401 target_fd: types::Fd,
402 target_path: GuestPtr<str>,
403 ) -> Result<(), Error> {
404 Snapshot1::path_link(
405 self,
406 memory,
407 src_fd.into(),
408 src_flags.into(),
409 src_path,
410 target_fd.into(),
411 target_path,
412 )
413 .await?;
414 Ok(())
415 }
416
path_open( &mut self, memory: &mut GuestMemory<'_>, dirfd: types::Fd, dirflags: types::Lookupflags, path: GuestPtr<str>, oflags: types::Oflags, fs_rights_base: types::Rights, fs_rights_inheriting: types::Rights, fdflags: types::Fdflags, ) -> Result<types::Fd, Error>417 async fn path_open(
418 &mut self,
419 memory: &mut GuestMemory<'_>,
420 dirfd: types::Fd,
421 dirflags: types::Lookupflags,
422 path: GuestPtr<str>,
423 oflags: types::Oflags,
424 fs_rights_base: types::Rights,
425 fs_rights_inheriting: types::Rights,
426 fdflags: types::Fdflags,
427 ) -> Result<types::Fd, Error> {
428 Ok(Snapshot1::path_open(
429 self,
430 memory,
431 dirfd.into(),
432 dirflags.into(),
433 path,
434 oflags.into(),
435 fs_rights_base.into(),
436 fs_rights_inheriting.into(),
437 fdflags.into(),
438 )
439 .await?
440 .into())
441 }
442
path_readlink( &mut self, memory: &mut GuestMemory<'_>, dirfd: types::Fd, path: GuestPtr<str>, buf: GuestPtr<u8>, buf_len: types::Size, ) -> Result<types::Size, Error>443 async fn path_readlink(
444 &mut self,
445 memory: &mut GuestMemory<'_>,
446 dirfd: types::Fd,
447 path: GuestPtr<str>,
448 buf: GuestPtr<u8>,
449 buf_len: types::Size,
450 ) -> Result<types::Size, Error> {
451 Ok(Snapshot1::path_readlink(self, memory, dirfd.into(), path, buf, buf_len).await?)
452 }
453
path_remove_directory( &mut self, memory: &mut GuestMemory<'_>, dirfd: types::Fd, path: GuestPtr<str>, ) -> Result<(), Error>454 async fn path_remove_directory(
455 &mut self,
456 memory: &mut GuestMemory<'_>,
457 dirfd: types::Fd,
458 path: GuestPtr<str>,
459 ) -> Result<(), Error> {
460 Snapshot1::path_remove_directory(self, memory, dirfd.into(), path).await?;
461 Ok(())
462 }
463
path_rename( &mut self, memory: &mut GuestMemory<'_>, src_fd: types::Fd, src_path: GuestPtr<str>, dest_fd: types::Fd, dest_path: GuestPtr<str>, ) -> Result<(), Error>464 async fn path_rename(
465 &mut self,
466 memory: &mut GuestMemory<'_>,
467 src_fd: types::Fd,
468 src_path: GuestPtr<str>,
469 dest_fd: types::Fd,
470 dest_path: GuestPtr<str>,
471 ) -> Result<(), Error> {
472 Snapshot1::path_rename(
473 self,
474 memory,
475 src_fd.into(),
476 src_path,
477 dest_fd.into(),
478 dest_path,
479 )
480 .await?;
481 Ok(())
482 }
483
path_symlink( &mut self, memory: &mut GuestMemory<'_>, src_path: GuestPtr<str>, dirfd: types::Fd, dest_path: GuestPtr<str>, ) -> Result<(), Error>484 async fn path_symlink(
485 &mut self,
486 memory: &mut GuestMemory<'_>,
487 src_path: GuestPtr<str>,
488 dirfd: types::Fd,
489 dest_path: GuestPtr<str>,
490 ) -> Result<(), Error> {
491 Snapshot1::path_symlink(self, memory, src_path, dirfd.into(), dest_path).await?;
492 Ok(())
493 }
494
path_unlink_file( &mut self, memory: &mut GuestMemory<'_>, dirfd: types::Fd, path: GuestPtr<str>, ) -> Result<(), Error>495 async fn path_unlink_file(
496 &mut self,
497 memory: &mut GuestMemory<'_>,
498 dirfd: types::Fd,
499 path: GuestPtr<str>,
500 ) -> Result<(), Error> {
501 Snapshot1::path_unlink_file(self, memory, dirfd.into(), path).await?;
502 Ok(())
503 }
504
505 // The representation of `SubscriptionClock` is different in p0 and
506 // p1 so a bit of a hack is employed here. The change was to remove a
507 // field from `SubscriptionClock` so to implement this without copying too
508 // much the `subs` field is overwritten with p1-compatible structures
509 // and then the p1 implementation is used. Before returning though
510 // the old values are restored to pretend like we didn't overwrite them.
511 //
512 // Surely no one would pass overlapping pointers to this API right?
poll_oneoff( &mut self, memory: &mut GuestMemory<'_>, subs: GuestPtr<types::Subscription>, events: GuestPtr<types::Event>, nsubscriptions: types::Size, ) -> Result<types::Size, Error>513 async fn poll_oneoff(
514 &mut self,
515 memory: &mut GuestMemory<'_>,
516 subs: GuestPtr<types::Subscription>,
517 events: GuestPtr<types::Event>,
518 nsubscriptions: types::Size,
519 ) -> Result<types::Size, Error> {
520 let subs_array = subs.as_array(nsubscriptions);
521 let mut old_subs = Vec::new();
522 for slot in subs_array.iter() {
523 let slot = slot?;
524 let sub = memory.read(slot)?;
525 old_subs.push(sub.clone());
526 memory.write(
527 slot.cast(),
528 snapshot1_types::Subscription {
529 userdata: sub.userdata,
530 u: match sub.u {
531 types::SubscriptionU::Clock(c) => {
532 snapshot1_types::SubscriptionU::Clock(c.into())
533 }
534 types::SubscriptionU::FdRead(c) => {
535 snapshot1_types::SubscriptionU::FdRead(c.into())
536 }
537 types::SubscriptionU::FdWrite(c) => {
538 snapshot1_types::SubscriptionU::FdWrite(c.into())
539 }
540 },
541 },
542 )?;
543 }
544 let ret = Snapshot1::poll_oneoff(self, memory, subs.cast(), events.cast(), nsubscriptions)
545 .await?;
546 for (sub, slot) in old_subs.into_iter().zip(subs_array.iter()) {
547 memory.write(slot?, sub)?;
548 }
549 Ok(ret)
550 }
551
proc_exit( &mut self, memory: &mut GuestMemory<'_>, status: types::Exitcode, ) -> wasmtime::Error552 fn proc_exit(
553 &mut self,
554 memory: &mut GuestMemory<'_>,
555 status: types::Exitcode,
556 ) -> wasmtime::Error {
557 Snapshot1::proc_exit(self, memory, status)
558 }
559
proc_raise( &mut self, memory: &mut GuestMemory<'_>, sig: types::Signal, ) -> Result<(), Error>560 fn proc_raise(
561 &mut self,
562 memory: &mut GuestMemory<'_>,
563 sig: types::Signal,
564 ) -> Result<(), Error> {
565 Snapshot1::proc_raise(self, memory, sig.into())?;
566 Ok(())
567 }
568
sched_yield(&mut self, memory: &mut GuestMemory<'_>) -> Result<(), Error>569 fn sched_yield(&mut self, memory: &mut GuestMemory<'_>) -> Result<(), Error> {
570 Snapshot1::sched_yield(self, memory)?;
571 Ok(())
572 }
573
random_get( &mut self, memory: &mut GuestMemory<'_>, buf: GuestPtr<u8>, buf_len: types::Size, ) -> Result<(), Error>574 fn random_get(
575 &mut self,
576 memory: &mut GuestMemory<'_>,
577 buf: GuestPtr<u8>,
578 buf_len: types::Size,
579 ) -> Result<(), Error> {
580 Snapshot1::random_get(self, memory, buf, buf_len)?;
581 Ok(())
582 }
583
sock_recv( &mut self, _memory: &mut GuestMemory<'_>, _fd: types::Fd, _ri_data: types::IovecArray, _ri_flags: types::Riflags, ) -> Result<(types::Size, types::Roflags), Error>584 fn sock_recv(
585 &mut self,
586 _memory: &mut GuestMemory<'_>,
587 _fd: types::Fd,
588 _ri_data: types::IovecArray,
589 _ri_flags: types::Riflags,
590 ) -> Result<(types::Size, types::Roflags), Error> {
591 Err(Error::trap(wasmtime::Error::msg("sock_recv unsupported")))
592 }
593
sock_send( &mut self, _memory: &mut GuestMemory<'_>, _fd: types::Fd, _si_data: types::CiovecArray, _si_flags: types::Siflags, ) -> Result<types::Size, Error>594 fn sock_send(
595 &mut self,
596 _memory: &mut GuestMemory<'_>,
597 _fd: types::Fd,
598 _si_data: types::CiovecArray,
599 _si_flags: types::Siflags,
600 ) -> Result<types::Size, Error> {
601 Err(Error::trap(wasmtime::Error::msg("sock_send unsupported")))
602 }
603
sock_shutdown( &mut self, _memory: &mut GuestMemory<'_>, _fd: types::Fd, _how: types::Sdflags, ) -> Result<(), Error>604 fn sock_shutdown(
605 &mut self,
606 _memory: &mut GuestMemory<'_>,
607 _fd: types::Fd,
608 _how: types::Sdflags,
609 ) -> Result<(), Error> {
610 Err(Error::trap(wasmtime::Error::msg(
611 "sock_shutdown unsupported",
612 )))
613 }
614 }
615
assert_iovec_array_same()616 fn assert_iovec_array_same() {
617 // NB: this isn't enough to assert the types are the same, but it's
618 // something. Additionally p1 and p0 aren't changing any more
619 // and it's been manually verified that these two types are the same, so
620 // it's ok to cast between them.
621 assert_eq!(
622 std::mem::size_of::<types::IovecArray>(),
623 std::mem::size_of::<snapshot1_types::IovecArray>()
624 );
625 }
626
assert_ciovec_array_same()627 fn assert_ciovec_array_same() {
628 // NB: see above too
629 assert_eq!(
630 std::mem::size_of::<types::CiovecArray>(),
631 std::mem::size_of::<snapshot1_types::CiovecArray>()
632 );
633 }
634
635 impl From<snapshot1_types::Error> for Error {
from(error: snapshot1_types::Error) -> Error636 fn from(error: snapshot1_types::Error) -> Error {
637 match error.downcast() {
638 Ok(errno) => Error::from(types::Errno::from(errno)),
639 Err(trap) => Error::trap(trap),
640 }
641 }
642 }
643
644 /// Fd is a newtype wrapper around u32. Unwrap and wrap it.
645 impl From<types::Fd> for snapshot1_types::Fd {
from(fd: types::Fd) -> snapshot1_types::Fd646 fn from(fd: types::Fd) -> snapshot1_types::Fd {
647 u32::from(fd).into()
648 }
649 }
650
651 /// Fd is a newtype wrapper around u32. Unwrap and wrap it.
652 impl From<snapshot1_types::Fd> for types::Fd {
from(fd: snapshot1_types::Fd) -> types::Fd653 fn from(fd: snapshot1_types::Fd) -> types::Fd {
654 u32::from(fd).into()
655 }
656 }
657
658 /// Trivial conversion between two c-style enums that have the exact same set of variants.
659 /// Could we do something unsafe and not list all these variants out? Probably, but doing
660 /// it this way doesn't bother me much. I copy-pasted the list of variants out of the
661 /// rendered rustdocs.
662 /// LLVM ought to compile these From impls into no-ops, inshallah
663 macro_rules! convert_enum {
664 ($from:ty, $to:ty, $($var:ident),+) => {
665 impl From<$from> for $to {
666 fn from(e: $from) -> $to {
667 match e {
668 $( <$from>::$var => <$to>::$var, )+
669 }
670 }
671 }
672 }
673 }
674 convert_enum!(
675 snapshot1_types::Errno,
676 types::Errno,
677 Success,
678 TooBig,
679 Acces,
680 Addrinuse,
681 Addrnotavail,
682 Afnosupport,
683 Again,
684 Already,
685 Badf,
686 Badmsg,
687 Busy,
688 Canceled,
689 Child,
690 Connaborted,
691 Connrefused,
692 Connreset,
693 Deadlk,
694 Destaddrreq,
695 Dom,
696 Dquot,
697 Exist,
698 Fault,
699 Fbig,
700 Hostunreach,
701 Idrm,
702 Ilseq,
703 Inprogress,
704 Intr,
705 Inval,
706 Io,
707 Isconn,
708 Isdir,
709 Loop,
710 Mfile,
711 Mlink,
712 Msgsize,
713 Multihop,
714 Nametoolong,
715 Netdown,
716 Netreset,
717 Netunreach,
718 Nfile,
719 Nobufs,
720 Nodev,
721 Noent,
722 Noexec,
723 Nolck,
724 Nolink,
725 Nomem,
726 Nomsg,
727 Noprotoopt,
728 Nospc,
729 Nosys,
730 Notconn,
731 Notdir,
732 Notempty,
733 Notrecoverable,
734 Notsock,
735 Notsup,
736 Notty,
737 Nxio,
738 Overflow,
739 Ownerdead,
740 Perm,
741 Pipe,
742 Proto,
743 Protonosupport,
744 Prototype,
745 Range,
746 Rofs,
747 Spipe,
748 Srch,
749 Stale,
750 Timedout,
751 Txtbsy,
752 Xdev,
753 Notcapable
754 );
755 convert_enum!(
756 types::Clockid,
757 snapshot1_types::Clockid,
758 Realtime,
759 Monotonic,
760 ProcessCputimeId,
761 ThreadCputimeId
762 );
763
764 convert_enum!(
765 types::Advice,
766 snapshot1_types::Advice,
767 Normal,
768 Sequential,
769 Random,
770 Willneed,
771 Dontneed,
772 Noreuse
773 );
774 convert_enum!(
775 snapshot1_types::Filetype,
776 types::Filetype,
777 Directory,
778 BlockDevice,
779 CharacterDevice,
780 RegularFile,
781 SocketDgram,
782 SocketStream,
783 SymbolicLink,
784 Unknown
785 );
786 convert_enum!(types::Whence, snapshot1_types::Whence, Cur, End, Set);
787
788 convert_enum!(
789 types::Signal,
790 snapshot1_types::Signal,
791 None,
792 Hup,
793 Int,
794 Quit,
795 Ill,
796 Trap,
797 Abrt,
798 Bus,
799 Fpe,
800 Kill,
801 Usr1,
802 Segv,
803 Usr2,
804 Pipe,
805 Alrm,
806 Term,
807 Chld,
808 Cont,
809 Stop,
810 Tstp,
811 Ttin,
812 Ttou,
813 Urg,
814 Xcpu,
815 Xfsz,
816 Vtalrm,
817 Prof,
818 Winch,
819 Poll,
820 Pwr,
821 Sys
822 );
823
824 /// Prestat isn't a c-style enum, its a union where the variant has a payload. Its the only one of
825 /// those we need to convert, so write it by hand.
826 impl From<snapshot1_types::Prestat> for types::Prestat {
from(p: snapshot1_types::Prestat) -> types::Prestat827 fn from(p: snapshot1_types::Prestat) -> types::Prestat {
828 match p {
829 snapshot1_types::Prestat::Dir(d) => types::Prestat::Dir(d.into()),
830 }
831 }
832 }
833
834 /// Trivial conversion between two structs that have the exact same set of fields,
835 /// with recursive descent into the field types.
836 macro_rules! convert_struct {
837 ($from:ty, $to:path, $($field:ident),+) => {
838 impl From<$from> for $to {
839 fn from(e: $from) -> $to {
840 $to {
841 $( $field: e.$field.into(), )+
842 }
843 }
844 }
845 }
846 }
847
848 convert_struct!(snapshot1_types::PrestatDir, types::PrestatDir, pr_name_len);
849 convert_struct!(
850 snapshot1_types::Fdstat,
851 types::Fdstat,
852 fs_filetype,
853 fs_rights_base,
854 fs_rights_inheriting,
855 fs_flags
856 );
857 convert_struct!(
858 types::SubscriptionClock,
859 snapshot1_types::SubscriptionClock,
860 id,
861 timeout,
862 precision,
863 flags
864 );
865 convert_struct!(
866 types::SubscriptionFdReadwrite,
867 snapshot1_types::SubscriptionFdReadwrite,
868 file_descriptor
869 );
870
871 /// Snapshot1 Filestat is incompatible with Snapshot0 Filestat - the nlink
872 /// field is u32 on this Filestat, and u64 on theirs. If you've got more than
873 /// 2^32 links I don't know what to tell you
874 impl From<snapshot1_types::Filestat> for types::Filestat {
from(f: snapshot1_types::Filestat) -> types::Filestat875 fn from(f: snapshot1_types::Filestat) -> types::Filestat {
876 types::Filestat {
877 dev: f.dev,
878 ino: f.ino,
879 filetype: f.filetype.into(),
880 nlink: f.nlink.try_into().unwrap_or(u32::MAX),
881 size: f.size,
882 atim: f.atim,
883 mtim: f.mtim,
884 ctim: f.ctim,
885 }
886 }
887 }
888
889 /// Trivial conversion between two bitflags that have the exact same set of flags.
890 macro_rules! convert_flags {
891 ($from:ty, $to:ty, $($flag:ident),+) => {
892 impl From<$from> for $to {
893 fn from(f: $from) -> $to {
894 let mut out = <$to>::empty();
895 $(
896 if f.contains(<$from>::$flag) {
897 out |= <$to>::$flag;
898 }
899 )+
900 out
901 }
902 }
903 }
904 }
905
906 /// Need to convert in both directions? This saves listing out the flags twice
907 macro_rules! convert_flags_bidirectional {
908 ($from:ty, $to:ty, $($flag:tt)*) => {
909 convert_flags!($from, $to, $($flag)*);
910 convert_flags!($to, $from, $($flag)*);
911 }
912 }
913
914 convert_flags_bidirectional!(
915 snapshot1_types::Fdflags,
916 types::Fdflags,
917 APPEND,
918 DSYNC,
919 NONBLOCK,
920 RSYNC,
921 SYNC
922 );
923 convert_flags!(
924 types::Lookupflags,
925 snapshot1_types::Lookupflags,
926 SYMLINK_FOLLOW
927 );
928 convert_flags!(
929 types::Fstflags,
930 snapshot1_types::Fstflags,
931 ATIM,
932 ATIM_NOW,
933 MTIM,
934 MTIM_NOW
935 );
936 convert_flags!(
937 types::Oflags,
938 snapshot1_types::Oflags,
939 CREAT,
940 DIRECTORY,
941 EXCL,
942 TRUNC
943 );
944 convert_flags_bidirectional!(
945 types::Rights,
946 snapshot1_types::Rights,
947 FD_DATASYNC,
948 FD_READ,
949 FD_SEEK,
950 FD_FDSTAT_SET_FLAGS,
951 FD_SYNC,
952 FD_TELL,
953 FD_WRITE,
954 FD_ADVISE,
955 FD_ALLOCATE,
956 PATH_CREATE_DIRECTORY,
957 PATH_CREATE_FILE,
958 PATH_LINK_SOURCE,
959 PATH_LINK_TARGET,
960 PATH_OPEN,
961 FD_READDIR,
962 PATH_READLINK,
963 PATH_RENAME_SOURCE,
964 PATH_RENAME_TARGET,
965 PATH_FILESTAT_GET,
966 PATH_FILESTAT_SET_SIZE,
967 PATH_FILESTAT_SET_TIMES,
968 FD_FILESTAT_GET,
969 FD_FILESTAT_SET_SIZE,
970 FD_FILESTAT_SET_TIMES,
971 PATH_SYMLINK,
972 PATH_REMOVE_DIRECTORY,
973 PATH_UNLINK_FILE,
974 POLL_FD_READWRITE,
975 SOCK_SHUTDOWN
976 );
977 convert_flags!(
978 types::Subclockflags,
979 snapshot1_types::Subclockflags,
980 SUBSCRIPTION_CLOCK_ABSTIME
981 );
982
983 impl From<GuestError> for types::Error {
from(err: GuestError) -> Self984 fn from(err: GuestError) -> Self {
985 snapshot1_types::Error::from(err).into()
986 }
987 }
988