wasmer_wasix/syscalls/wasi/
path_readlink.rs1use super::*;
2use crate::syscalls::*;
3
4#[instrument(level = "trace", skip_all, fields(%dir_fd, path = field::Empty), ret)]
21pub fn path_readlink<M: MemorySize>(
22 mut ctx: FunctionEnvMut<'_, WasiEnv>,
23 dir_fd: WasiFd,
24 path: WasmPtr<u8, M>,
25 path_len: M::Offset,
26 buf: WasmPtr<u8, M>,
27 buf_len: M::Offset,
28 buf_used: WasmPtr<M::Offset, M>,
29) -> Result<Errno, WasiError> {
30 WasiEnv::do_pending_operations(&mut ctx)?;
31
32 let env = ctx.data();
33 let (memory, mut state, inodes) = unsafe { env.get_memory_and_wasi_state_and_inodes(&ctx, 0) };
34
35 let base_dir = wasi_try_ok!(state.fs.get_fd(dir_fd));
36 if !base_dir.inner.rights.contains(Rights::PATH_READLINK) {
37 return Ok(Errno::Access);
38 }
39 let mut path_str = unsafe { get_input_str_ok!(&memory, path, path_len) };
40 Span::current().record("path", path_str.as_str());
41
42 let inode = wasi_try_ok!(state.fs.get_inode_at_path(inodes, dir_fd, &path_str, false));
43
44 {
45 let guard = inode.read();
46 if let Kind::Symlink { relative_path, .. } = guard.deref() {
47 let rel_path_str = relative_path.to_string_lossy();
48 let buf_len: u64 = buf_len.into();
49 let bytes = rel_path_str.bytes();
50 if bytes.len() as u64 >= buf_len {
51 return Ok(Errno::Overflow);
52 }
53 let bytes: Vec<_> = bytes.collect();
54
55 let out =
56 wasi_try_mem_ok!(buf.slice(&memory, wasi_try_ok!(to_offset::<M>(bytes.len()))));
57 wasi_try_mem_ok!(out.write_slice(&bytes));
58 let bytes_len: M::Offset =
61 wasi_try_ok!(bytes.len().try_into().map_err(|_| Errno::Overflow));
62 wasi_try_mem_ok!(buf_used.deref(&memory).write(bytes_len));
63 } else {
64 return Ok(Errno::Inval);
65 }
66 }
67
68 Ok(Errno::Success)
69}