async_wasi/snapshots/preview_1/
mod.rs

1use super::{
2    common::{
3        clock,
4        error::Errno,
5        memory::{Memory, WasmPtr},
6        types::*,
7    },
8    env::{
9        vfs::{self, FdFlags, WASIRights},
10        AsyncVM,
11    },
12    WasiCtx,
13};
14
15#[cfg(all(unix, feature = "async_tokio"))]
16pub mod async_poll;
17#[cfg(all(unix, feature = "async_tokio"))]
18pub mod async_socket;
19
20pub fn args_get<M: Memory>(
21    ctx: &WasiCtx,
22    mem: &mut M,
23    argv: WasmPtr<__wasi_size_t>,
24    argv_buf: WasmPtr<u8>,
25) -> Result<(), Errno> {
26    log::trace!("args_get");
27
28    let mut header_offset = 0;
29    for (argv_index, arg) in ctx.args.iter().enumerate() {
30        let arg_buf = mem.mut_data(argv + argv_index)?;
31        *arg_buf = ((argv_buf.0 + header_offset) as u32).to_le();
32
33        let arg_bytes = arg.as_bytes();
34        let arg_buf = mem.mut_slice(argv_buf + header_offset, arg.len())?;
35        arg_buf.copy_from_slice(arg_bytes);
36        let ptr = mem.mut_data::<u8>(argv_buf + header_offset + arg.len())?;
37        *ptr = 0u8;
38
39        header_offset += arg.len() + 1;
40    }
41    Ok(())
42}
43
44pub fn args_sizes_get<M: Memory>(
45    ctx: &WasiCtx,
46    mem: &mut M,
47    argc: WasmPtr<__wasi_size_t>,
48    argv_buf_size: WasmPtr<__wasi_size_t>,
49) -> Result<(), Errno> {
50    log::trace!("args_sizes_get");
51
52    let wasi_argc = ctx.args.len();
53    debug_assert!(wasi_argc < __wasi_size_t::MAX as usize);
54    let argc = mem.mut_data(argc)?;
55    *argc = (wasi_argc as u32).to_le();
56
57    let mut wasi_argv_buf_size = 0;
58    for argv in &ctx.args {
59        // add \0
60        wasi_argv_buf_size += argv.len() + 1;
61    }
62    let argv_buf_size = mem.mut_data(argv_buf_size)?;
63    *argv_buf_size = (wasi_argv_buf_size as u32).to_le();
64
65    Ok(())
66}
67
68pub fn environ_get<M: Memory>(
69    ctx: &WasiCtx,
70    mem: &mut M,
71    environ: WasmPtr<__wasi_size_t>,
72    environ_buf: WasmPtr<u8>,
73) -> Result<(), Errno> {
74    log::trace!("environ_get");
75
76    let mut header_offset = 0;
77
78    for (environ_index, env) in ctx.envs.iter().enumerate() {
79        let environ_ptr = mem.mut_data(environ + environ_index)?;
80        *environ_ptr = ((environ_buf.0 + header_offset) as u32).to_le();
81
82        let env_bytes = env.as_bytes();
83        let env_buf = mem.mut_slice(environ_buf + header_offset, env.len())?;
84        env_buf.copy_from_slice(env_bytes);
85        let ptr = mem.mut_data::<u8>(environ_buf + header_offset + env.len())?;
86        *ptr = 0u8;
87
88        header_offset += env.len() + 1;
89    }
90    Ok(())
91}
92
93pub fn environ_sizes_get<M: Memory>(
94    ctx: &WasiCtx,
95    mem: &mut M,
96    environ_count: WasmPtr<__wasi_size_t>,
97    environ_buf_size: WasmPtr<__wasi_size_t>,
98) -> Result<(), Errno> {
99    log::trace!("environ_sizes_get");
100
101    let wasi_envs_len = ctx.envs.len();
102    debug_assert!(
103        wasi_envs_len < __wasi_size_t::MAX as usize,
104        "wasi_envs_len({wasi_envs_len})"
105    );
106    let environ_count = mem.mut_data(environ_count)?;
107    *environ_count = (wasi_envs_len as u32).to_le();
108
109    let mut wasi_envs_buf_size = 0;
110    for env in &ctx.envs {
111        // add \0
112        wasi_envs_buf_size += env.len() + 1;
113    }
114    let environ_buf_size = mem.mut_data(environ_buf_size)?;
115    *environ_buf_size = (wasi_envs_buf_size as u32).to_le();
116
117    Ok(())
118}
119
120pub fn clock_res_get<M: Memory>(
121    _ctx: &mut WasiCtx,
122    mem: &mut M,
123    clock_id: __wasi_clockid_t::Type,
124    resolution_ptr: WasmPtr<__wasi_timestamp_t>,
125) -> Result<(), Errno> {
126    log::trace!("clock_res_get");
127
128    let resolution = clock::wasi_clock_res_get(clock_id)?;
129    let resolution_ptr = mem.mut_data(resolution_ptr)?;
130    *resolution_ptr = resolution.to_le();
131    Ok(())
132}
133
134pub fn clock_time_get<M: Memory>(
135    ctx: &WasiCtx,
136    mem: &mut M,
137    clock_id: __wasi_clockid_t::Type,
138    precision: __wasi_timestamp_t,
139    time_ptr: WasmPtr<__wasi_timestamp_t>,
140) -> Result<(), Errno> {
141    log::trace!("clock_time_get");
142
143    let time = clock::wasi_clock_time_get(ctx, clock_id, precision)?;
144    let time_ptr = mem.mut_data(time_ptr)?;
145    *time_ptr = time.to_le();
146    Ok(())
147}
148
149pub fn random_get<M: Memory>(
150    _ctx: &mut WasiCtx,
151    mem: &mut M,
152    buf: WasmPtr<u8>,
153    buf_len: __wasi_size_t,
154) -> Result<(), Errno> {
155    log::trace!("random_get");
156
157    let u8_buffer = mem.mut_slice(buf, buf_len as usize)?;
158    getrandom::getrandom(u8_buffer).map_err(|_| Errno(__wasi_errno_t::__WASI_ERRNO_IO))
159}
160
161pub fn fd_prestat_get<M: Memory>(
162    ctx: &mut WasiCtx,
163    mem: &mut M,
164    fd: __wasi_fd_t,
165    prestat_ptr: WasmPtr<__wasi_prestat_t>,
166) -> Result<(), Errno> {
167    log::trace!("fd_prestat_get({fd})");
168
169    let prestat = mem.mut_data(prestat_ptr)?;
170
171    let pr_name_len = ctx.vfs.fd_preopen_get(fd as usize)?.as_bytes().len() as u32;
172
173    prestat.tag = __wasi_preopentype_t::__WASI_PREOPENTYPE_DIR;
174    prestat.u = __wasi_prestat_u_t {
175        dir: __wasi_prestat_dir_t { pr_name_len },
176    };
177    Ok(())
178}
179
180pub fn fd_prestat_dir_name<M: Memory>(
181    ctx: &mut WasiCtx,
182    mem: &mut M,
183    fd: __wasi_fd_t,
184    path_buf_ptr: WasmPtr<u8>,
185    path_max_len: __wasi_size_t,
186) -> Result<(), Errno> {
187    log::trace!("fd_prestat_dir_name({fd})");
188
189    let path = ctx.vfs.fd_preopen_get(fd as usize)?;
190    let path_bytes = path.as_bytes();
191    let path_len = path_bytes.len();
192    if path_len > path_max_len as usize {
193        return Err(Errno::__WASI_ERRNO_NAMETOOLONG);
194    }
195    let path_buf = mem.mut_slice(path_buf_ptr, path_max_len as usize)?;
196    path_buf.clone_from_slice(&path_bytes[0..path_max_len as usize]);
197    Ok(())
198}
199
200pub fn fd_renumber<M: Memory>(
201    ctx: &mut WasiCtx,
202    _mem: &mut M,
203    from: __wasi_fd_t,
204    to: __wasi_fd_t,
205) -> Result<(), Errno> {
206    log::trace!("fd_renumber {from} {to}");
207
208    ctx.vfs.fd_renumber(from as usize, to as usize)
209}
210
211pub fn fd_advise<M: Memory>(
212    ctx: &mut WasiCtx,
213    _mem: &mut M,
214    fd: __wasi_fd_t,
215    offset: __wasi_filesize_t,
216    len: __wasi_filesize_t,
217    advice: __wasi_advice_t::Type,
218) -> Result<(), Errno> {
219    log::trace!("fd_advise {fd}");
220
221    ctx.vfs.fd_advise(fd as usize, offset, len, advice)
222}
223
224pub fn fd_allocate<M: Memory>(
225    ctx: &mut WasiCtx,
226    _mem: &mut M,
227    fd: __wasi_fd_t,
228    offset: __wasi_filesize_t,
229    len: __wasi_filesize_t,
230) -> Result<(), Errno> {
231    log::trace!("fd_allocate {fd}");
232
233    ctx.vfs.get_mut_file(fd as usize)?.fd_allocate(offset, len)
234}
235
236pub fn fd_close<M: Memory>(ctx: &mut WasiCtx, _mem: &mut M, fd: __wasi_fd_t) -> Result<(), Errno> {
237    log::trace!("fd_close {fd}");
238
239    ctx.vfs.fd_close(fd as usize)
240}
241
242pub fn fd_seek<M: Memory>(
243    ctx: &mut WasiCtx,
244    mem: &mut M,
245    fd: __wasi_fd_t,
246    offset: __wasi_filedelta_t,
247    whence: __wasi_whence_t::Type,
248    newoffset_ptr: WasmPtr<__wasi_filesize_t>,
249) -> Result<(), Errno> {
250    log::trace!("fd_seek {fd}");
251
252    let fs = ctx.vfs.get_mut_file(fd as usize)?;
253    let newoffset = mem.mut_data(newoffset_ptr)?;
254    *newoffset = fs.fd_seek(offset, whence)?.to_le();
255    Ok(())
256}
257
258pub fn fd_sync<M: Memory>(ctx: &mut WasiCtx, _mem: &mut M, fd: __wasi_fd_t) -> Result<(), Errno> {
259    log::trace!("fd_sync {fd}");
260
261    let fs = ctx.vfs.get_mut_file(fd as usize)?;
262    fs.fd_sync()
263}
264
265pub fn fd_datasync<M: Memory>(
266    ctx: &mut WasiCtx,
267    _mem: &mut M,
268    fd: __wasi_fd_t,
269) -> Result<(), Errno> {
270    log::trace!("fd_datasync {fd}");
271
272    let fs = ctx.vfs.get_mut_file(fd as usize)?;
273    fs.fd_datasync()
274}
275
276pub fn fd_tell<M: Memory>(
277    ctx: &mut WasiCtx,
278    mem: &mut M,
279    fd: __wasi_fd_t,
280    offset: WasmPtr<__wasi_filesize_t>,
281) -> Result<(), Errno> {
282    log::trace!("fd_tell {fd}");
283
284    let fs = ctx.vfs.get_mut_file(fd as usize)?;
285    mem.write_data(offset, fs.fd_tell()?)
286}
287
288pub fn fd_fdstat_get<M: Memory>(
289    ctx: &mut WasiCtx,
290    mem: &mut M,
291    fd: __wasi_fd_t,
292    buf_ptr: WasmPtr<__wasi_fdstat_t>,
293) -> Result<(), Errno> {
294    log::trace!("fd_fdstat_get {fd}");
295
296    let fd_stat;
297    #[cfg(all(unix, feature = "async_tokio"))]
298    {
299        if let Ok(s) = ctx.vfs.get_socket(fd as usize) {
300            fd_stat = s.fd_fdstat_get()?;
301        } else {
302            fd_stat = ctx.vfs.get_inode(fd as usize)?.fd_fdstat_get()?;
303        }
304    }
305    #[cfg(not(all(unix, feature = "async_tokio")))]
306    {
307        fd_stat = ctx.vfs.get_inode(fd as usize)?.fd_fdstat_get()?;
308    }
309
310    mem.write_data(buf_ptr, __wasi_fdstat_t::from(fd_stat))
311}
312
313pub fn fd_fdstat_set_flags<M: Memory>(
314    ctx: &mut WasiCtx,
315    _mem: &mut M,
316    fd: __wasi_fd_t,
317    flags: __wasi_fdflags_t::Type,
318) -> Result<(), Errno> {
319    log::trace!("fd_fdstat_set_flags {fd}");
320
321    let fdflags = FdFlags::from_bits_truncate(flags);
322
323    if let Ok(fs) = ctx.vfs.get_mut_file(fd as usize) {
324        fs.fd_fdstat_set_flags(fdflags)?;
325        return Ok(());
326    }
327    #[cfg(all(unix, feature = "async_tokio"))]
328    if let Ok(s) = ctx.vfs.get_mut_socket(fd as usize) {
329        s.set_nonblocking(fdflags.contains(FdFlags::NONBLOCK))?;
330        return Ok(());
331    }
332
333    Err(Errno::__WASI_ERRNO_BADF)
334}
335
336pub fn fd_fdstat_set_rights<M: Memory>(
337    ctx: &mut WasiCtx,
338    _mem: &mut M,
339    fd: __wasi_fd_t,
340    fs_rights_base: __wasi_rights_t::Type,
341    fs_rights_inheriting: __wasi_rights_t::Type,
342) -> Result<(), Errno> {
343    log::trace!("fd_fdstat_set_rights {fd}");
344
345    let fs_rights_base = WASIRights::from_bits_truncate(fs_rights_base);
346    let fs_rights_inheriting = WASIRights::from_bits_truncate(fs_rights_inheriting);
347    ctx.vfs
348        .get_mut_inode(fd as usize)?
349        .fd_fdstat_set_rights(fs_rights_base, fs_rights_inheriting)
350}
351
352pub fn fd_filestat_get<M: Memory>(
353    ctx: &mut WasiCtx,
354    mem: &mut M,
355    fd: __wasi_fd_t,
356    buf: WasmPtr<__wasi_filestat_t>,
357) -> Result<(), Errno> {
358    log::trace!("fd_filestat_get {fd}");
359
360    let filestat = ctx.vfs.get_inode(fd as usize)?.fd_filestat_get()?;
361    mem.write_data(buf, __wasi_filestat_t::from(filestat))
362}
363
364pub fn fd_filestat_set_size<M: Memory>(
365    ctx: &mut WasiCtx,
366    _mem: &mut M,
367    fd: __wasi_fd_t,
368    st_size: __wasi_filesize_t,
369) -> Result<(), Errno> {
370    log::trace!("fd_filestat_set_size {fd}");
371
372    let fs = ctx.vfs.get_mut_file(fd as usize)?;
373    fs.fd_filestat_set_size(st_size)
374}
375
376pub fn fd_filestat_set_times<M: Memory>(
377    ctx: &mut WasiCtx,
378    _mem: &mut M,
379    fd: __wasi_fd_t,
380    st_atim: __wasi_timestamp_t,
381    st_mtim: __wasi_timestamp_t,
382    fst_flags: __wasi_fstflags_t::Type,
383) -> Result<(), Errno> {
384    log::trace!("fd_filestat_set_times {fd}");
385
386    let inode = ctx.vfs.get_mut_inode(fd as usize)?;
387    inode.fd_filestat_set_times(st_atim, st_mtim, fst_flags)
388}
389
390pub fn fd_read<M: Memory>(
391    ctx: &mut WasiCtx,
392    mem: &mut M,
393    fd: __wasi_fd_t,
394    iovs: WasmPtr<__wasi_iovec_t>,
395    iovs_len: __wasi_size_t,
396    nread: WasmPtr<__wasi_size_t>,
397) -> Result<(), Errno> {
398    log::trace!("fd_read {fd}");
399
400    let fs = ctx.vfs.get_mut_file(fd as usize)?;
401    let mut bufs = mem.mut_iovec(iovs, iovs_len)?;
402    let n = fs.fd_read(&mut bufs)? as __wasi_size_t;
403    mem.write_data(nread, n.to_le())
404}
405
406pub fn fd_pread<M: Memory>(
407    ctx: &mut WasiCtx,
408    mem: &mut M,
409    fd: __wasi_fd_t,
410    iovs: WasmPtr<__wasi_iovec_t>,
411    iovs_len: __wasi_size_t,
412    offset: __wasi_filesize_t,
413    nread: WasmPtr<__wasi_size_t>,
414) -> Result<(), Errno> {
415    log::trace!("fd_pread {fd}");
416
417    let fs = ctx.vfs.get_mut_file(fd as usize)?;
418    let mut bufs = mem.mut_iovec(iovs, iovs_len)?;
419    let n = fs.fd_pread(&mut bufs, offset)? as __wasi_size_t;
420    mem.write_data(nread, n.to_le())
421}
422
423pub fn fd_write<M: Memory>(
424    ctx: &mut WasiCtx,
425    mem: &mut M,
426    fd: __wasi_fd_t,
427    iovs: WasmPtr<__wasi_ciovec_t>,
428    iovs_len: __wasi_size_t,
429    nwritten: WasmPtr<__wasi_size_t>,
430) -> Result<(), Errno> {
431    log::trace!("fd_write {fd}");
432
433    let fs = ctx.vfs.get_mut_file(fd as usize)?;
434    let bufs = mem.get_iovec(iovs, iovs_len)?;
435    let n = fs.fd_write(&bufs)? as __wasi_size_t;
436    mem.write_data(nwritten, n.to_le())
437}
438
439pub fn fd_pwrite<M: Memory>(
440    ctx: &mut WasiCtx,
441    mem: &mut M,
442    fd: __wasi_fd_t,
443    iovs: WasmPtr<__wasi_ciovec_t>,
444    iovs_len: __wasi_size_t,
445    offset: __wasi_filesize_t,
446    nwritten: WasmPtr<__wasi_size_t>,
447) -> Result<(), Errno> {
448    log::trace!("fd_pwrite {fd}");
449
450    let fs = ctx.vfs.get_mut_file(fd as usize)?;
451    let bufs = mem.get_iovec(iovs, iovs_len)?;
452    let n = fs.fd_pwrite(&bufs, offset)? as __wasi_size_t;
453    mem.write_data(nwritten, n.to_le())
454}
455
456pub fn fd_readdir<M: Memory>(
457    ctx: &mut WasiCtx,
458    mem: &mut M,
459    fd: __wasi_fd_t,
460    buf: WasmPtr<u8>,
461    buf_len: __wasi_size_t,
462    cookie: __wasi_dircookie_t,
463    bufused_ptr: WasmPtr<__wasi_size_t>,
464) -> Result<(), Errno> {
465    log::trace!("fd_readdir {fd}");
466
467    let dir = ctx.vfs.get_dir(fd as usize)?;
468    let buf = mem.mut_slice(buf, buf_len as usize)?;
469    let bufused = dir.fd_readdir(cookie as usize, buf)? as __wasi_size_t;
470    let bufused_ptr = mem.mut_data(bufused_ptr)?;
471    *bufused_ptr = bufused.to_le();
472    Ok(())
473}
474
475pub fn path_create_directory<M: Memory>(
476    ctx: &mut WasiCtx,
477    mem: &M,
478    dirfd: __wasi_fd_t,
479    path_ptr: WasmPtr<u8>,
480    path_len: __wasi_size_t,
481) -> Result<(), Errno> {
482    log::trace!("path_create_directory");
483
484    let path_buf = mem.get_slice(path_ptr, path_len as usize)?;
485    let path_str = std::str::from_utf8(path_buf).or(Err(Errno::__WASI_ERRNO_ILSEQ))?;
486
487    log::trace!("path_create_directory({dirfd} {path_str})");
488    ctx.vfs.path_create_directory(dirfd as usize, path_str)
489}
490
491pub fn path_filestat_get<M: Memory>(
492    ctx: &mut WasiCtx,
493    mem: &mut M,
494    dirfd: __wasi_fd_t,
495    flags: __wasi_lookupflags_t::Type,
496    path_ptr: WasmPtr<u8>,
497    path_len: __wasi_size_t,
498    file_stat_ptr: WasmPtr<__wasi_filestat_t>,
499) -> Result<(), Errno> {
500    let path_buf = mem.get_slice(path_ptr, path_len as usize)?;
501    let path_str = std::str::from_utf8(path_buf).or(Err(Errno::__WASI_ERRNO_ILSEQ))?;
502
503    log::trace!("path_filestat_get {dirfd} {path_str}");
504
505    let flags = flags & __wasi_lookupflags_t::__WASI_LOOKUPFLAGS_SYMLINK_FOLLOW > 0;
506    let file_stat = ctx.vfs.path_filestat_get(dirfd as usize, path_str, flags)?;
507    let stat = mem.mut_data(file_stat_ptr)?;
508    *stat = file_stat.into();
509    Ok(())
510}
511
512pub fn path_filestat_set_times<M: Memory>(
513    _ctx: &mut WasiCtx,
514    _mem: &mut M,
515    _dirfd: __wasi_fd_t,
516    _flags: __wasi_lookupflags_t::Type,
517    _path: WasmPtr<u8>,
518    _path_len: __wasi_size_t,
519    _st_atim: __wasi_timestamp_t,
520    _st_mtim: __wasi_timestamp_t,
521    _fst_flags: __wasi_fstflags_t::Type,
522) -> Result<(), Errno> {
523    Err(Errno::__WASI_ERRNO_NOSYS)
524}
525
526pub fn path_link<M: Memory>(
527    _ctx: &mut WasiCtx,
528    _mem: &mut M,
529    _old_fd: __wasi_fd_t,
530    _old_flags: __wasi_lookupflags_t::Type,
531    _old_path: WasmPtr<u8>,
532    _old_path_len: __wasi_size_t,
533    _new_fd: __wasi_fd_t,
534    _new_path: WasmPtr<u8>,
535    _new_path_len: __wasi_size_t,
536) -> Result<(), Errno> {
537    Err(Errno::__WASI_ERRNO_NOSYS)
538}
539
540pub fn path_open<M: Memory>(
541    ctx: &mut WasiCtx,
542    mem: &mut M,
543    dirfd: __wasi_fd_t,
544    _dirflags: __wasi_lookupflags_t::Type,
545    path: WasmPtr<u8>,
546    path_len: __wasi_size_t,
547    o_flags: __wasi_oflags_t::Type,
548    fs_rights_base: __wasi_rights_t::Type,
549    fs_rights_inheriting: __wasi_rights_t::Type,
550    fs_flags: __wasi_fdflags_t::Type,
551    fd_ptr: WasmPtr<__wasi_fd_t>,
552) -> Result<(), Errno> {
553    let path_buf = mem.get_slice(path, path_len as usize)?;
554    let path = std::str::from_utf8(path_buf).or(Err(Errno::__WASI_ERRNO_ILSEQ))?;
555
556    let oflags = vfs::OFlags::from_bits_truncate(o_flags);
557    let fdflags = vfs::FdFlags::from_bits_truncate(fs_flags);
558    let fs_rights_base = vfs::WASIRights::from_bits_truncate(fs_rights_base);
559    let fs_rights_inheriting = vfs::WASIRights::from_bits_truncate(fs_rights_inheriting);
560
561    let vfd = ctx.vfs.path_open(
562        dirfd as usize,
563        path,
564        oflags,
565        fs_rights_base,
566        fs_rights_inheriting,
567        fdflags,
568    )?;
569
570    mem.write_data(fd_ptr, vfd as i32)
571}
572
573pub fn path_readlink<M: Memory>(
574    _ctx: &mut WasiCtx,
575    _mem: &mut M,
576    _dir_fd: __wasi_fd_t,
577    _path: WasmPtr<u8>,
578    _path_len: __wasi_size_t,
579    _buf: WasmPtr<u8>,
580    _buf_len: __wasi_size_t,
581    _buf_used: WasmPtr<__wasi_size_t>,
582) -> Result<(), Errno> {
583    Err(Errno::__WASI_ERRNO_NOSYS)
584}
585
586pub fn path_remove_directory<M: Memory>(
587    ctx: &mut WasiCtx,
588    mem: &M,
589    dirfd: __wasi_fd_t,
590    path_ptr: WasmPtr<u8>,
591    path_len: __wasi_size_t,
592) -> Result<(), Errno> {
593    let path_buf = mem.get_slice(path_ptr, path_len as usize)?;
594    let path = std::str::from_utf8(path_buf).or(Err(Errno::__WASI_ERRNO_ILSEQ))?;
595    log::trace!("path_remove_directory {dirfd} {path}");
596    ctx.vfs.path_remove_directory(dirfd as usize, path)
597}
598
599pub fn path_rename<M: Memory>(
600    ctx: &mut WasiCtx,
601    mem: &M,
602    old_fd: __wasi_fd_t,
603    old_path: WasmPtr<u8>,
604    old_path_len: __wasi_size_t,
605    new_fd: __wasi_fd_t,
606    new_path: WasmPtr<u8>,
607    new_path_len: __wasi_size_t,
608) -> Result<(), Errno> {
609    let old_path = mem.get_slice(old_path, old_path_len as usize)?;
610    let old_path = std::str::from_utf8(old_path).or(Err(Errno::__WASI_ERRNO_ILSEQ))?;
611
612    let new_path = mem.get_slice(new_path, new_path_len as usize)?;
613    let new_path = std::str::from_utf8(new_path).or(Err(Errno::__WASI_ERRNO_ILSEQ))?;
614
615    log::trace!("path_rename {old_fd} {old_path} {new_fd} {new_path}");
616
617    ctx.vfs
618        .path_rename(old_fd as usize, old_path, new_fd as usize, new_path)
619}
620
621pub fn path_symlink<M: Memory>(
622    _ctx: &mut WasiCtx,
623    _mem: &mut M,
624    _old_path: WasmPtr<u8>,
625    _old_path_len: __wasi_size_t,
626    _fd: __wasi_fd_t,
627    _new_path: WasmPtr<u8>,
628    _new_path_len: __wasi_size_t,
629) -> Result<(), Errno> {
630    Err(Errno::__WASI_ERRNO_NOSYS)
631}
632
633pub fn path_unlink_file<M: Memory>(
634    ctx: &mut WasiCtx,
635    mem: &M,
636    dirfd: __wasi_fd_t,
637    path_ptr: WasmPtr<u8>,
638    path_len: __wasi_size_t,
639) -> Result<(), Errno> {
640    let path_buf = mem.get_slice(path_ptr, path_len as usize)?;
641    let path = std::str::from_utf8(path_buf).or(Err(Errno::__WASI_ERRNO_ILSEQ))?;
642
643    log::trace!("path_unlink_file {dirfd} {path}");
644    ctx.vfs.path_unlink_file(dirfd as usize, path)
645}
646
647pub fn proc_exit<M: Memory>(ctx: &mut WasiCtx, _mem: &mut M, code: __wasi_exitcode_t) {
648    ctx.exit_code = u32::from_le(code)
649}
650
651pub fn proc_raise<M: Memory>(
652    _ctx: &mut WasiCtx,
653    _mem: &mut M,
654    _sig: __wasi_signal_t::Type,
655) -> Result<(), Errno> {
656    Err(Errno::__WASI_ERRNO_NOSYS)
657}
658
659pub fn sched_yield<VM: AsyncVM>(_ctx: &mut WasiCtx, vm: &mut VM) -> Result<(), Errno> {
660    vm.yield_now()
661}