wasmer_wasix/syscalls/wasix/
getcwd.rs

1use super::*;
2use crate::syscalls::*;
3
4/// ### `getcwd()`
5/// Returns the current working directory
6/// If the path exceeds the size of the buffer then this function
7/// will return ERANGE
8#[instrument(level = "trace", skip_all, fields(path = field::Empty, max_path_len = field::Empty), ret)]
9pub fn getcwd<M: MemorySize>(
10    ctx: FunctionEnvMut<'_, WasiEnv>,
11    path: WasmPtr<u8, M>,
12    path_len: WasmPtr<M::Offset, M>,
13) -> Errno {
14    let env = ctx.data();
15    let (memory, mut state, inodes) = unsafe { env.get_memory_and_wasi_state_and_inodes(&ctx, 0) };
16
17    let (_, cur_dir) = wasi_try!(state.fs.get_current_dir(inodes, crate::VIRTUAL_ROOT_FD));
18    Span::current().record("path", cur_dir.as_str());
19
20    let max_path_len = wasi_try_mem!(path_len.read(&memory));
21    let max_path_len64: u64 = max_path_len.into();
22    let path_slice = match (path.is_null(), max_path_len64) {
23        (true, _) => None,
24        (_, 0) => None,
25        (_, _) => Some(wasi_try_mem!(path.slice(&memory, max_path_len))),
26    };
27    Span::current().record("max_path_len", max_path_len64);
28
29    let cur_dir = cur_dir.as_bytes();
30    wasi_try_mem!(path_len.write(&memory, wasi_try!(to_offset::<M>(cur_dir.len()))));
31    if cur_dir.len() as u64 > max_path_len64 {
32        return Errno::Range;
33    }
34
35    if let Some(path_slice) = path_slice {
36        let cur_dir = {
37            let mut u8_buffer = vec![0; max_path_len64 as usize];
38            let cur_dir_len = cur_dir.len();
39            if (cur_dir_len as u64) <= max_path_len64 {
40                u8_buffer[..cur_dir_len].clone_from_slice(cur_dir);
41            } else {
42                return Errno::Range;
43            }
44            u8_buffer
45        };
46
47        wasi_try_mem!(path_slice.write_slice(cur_dir.as_ref()));
48        Errno::Success
49    } else {
50        Errno::Inval
51    }
52}