wasmer_wasix/syscalls/wasi/
path_filestat_get.rs

1use super::*;
2use crate::syscalls::*;
3use crate::types::wasi::Snapshot0Filestat;
4
5/// ### `path_filestat_get()`
6/// Access metadata about a file or directory
7/// Inputs:
8/// - `Fd fd`
9///     The directory that `path` is relative to
10/// - `LookupFlags flags`
11///     Flags to control how `path` is understood
12/// - `const char *path`
13///     String containing the file path
14/// - `u32 path_len`
15///     The length of the `path` string
16/// Output:
17/// - `__wasi_file_stat_t *buf`
18///     The location where the metadata will be stored
19#[instrument(level = "trace", skip_all, fields(%fd, path = field::Empty), ret)]
20pub fn path_filestat_get<M: MemorySize>(
21    ctx: FunctionEnvMut<'_, WasiEnv>,
22    fd: WasiFd,
23    flags: LookupFlags,
24    path: WasmPtr<u8, M>,
25    path_len: M::Offset,
26    buf: WasmPtr<Filestat, M>,
27) -> Errno {
28    let env = ctx.data();
29    let (memory, mut state, inodes) = unsafe { env.get_memory_and_wasi_state_and_inodes(&ctx, 0) };
30
31    let mut path_string = unsafe { get_input_str!(&memory, path, path_len) };
32
33    // Convert relative paths into absolute paths
34    // let path_str = if path_string == "." {
35    //     &"/"
36    // } else if path_string.starts_with("./") {
37    //     &path_string[1..]
38    // } else {
39    //     &path_string
40    // };
41    // if path_string.starts_with("./") || path_string == "." {
42    //     path_string = ctx.data().state.fs.relative_path_to_absolute(path_string);
43    // }
44    tracing::trace!(path = path_string.as_str());
45
46    let stat = wasi_try!(path_filestat_get_internal(
47        &memory,
48        state,
49        inodes,
50        fd,
51        flags,
52        &path_string
53    ));
54
55    wasi_try_mem!(buf.deref(&memory).write(stat));
56
57    Errno::Success
58}
59
60/// ### `path_filestat_get_internal()`
61/// return a Filstat or Errno
62pub(crate) fn path_filestat_get_internal(
63    memory: &MemoryView,
64    state: &WasiState,
65    inodes: &crate::WasiInodes,
66    fd: WasiFd,
67    flags: LookupFlags,
68    path_string: &str,
69) -> Result<Filestat, Errno> {
70    let root_dir = state.fs.get_fd(fd)?;
71
72    if !root_dir.inner.rights.contains(Rights::PATH_FILESTAT_GET) {
73        return Err(Errno::Access);
74    }
75    let file_inode = state.fs.get_inode_at_path(
76        inodes,
77        fd,
78        path_string,
79        flags & __WASI_LOOKUP_SYMLINK_FOLLOW != 0,
80    )?;
81
82    let st_ino = file_inode.ino().as_u64();
83    let mut stat = if file_inode.is_preopened {
84        *file_inode.stat.read().unwrap().deref()
85    } else {
86        let guard = file_inode.read();
87        state.fs.get_stat_for_kind(guard.deref())?
88    };
89    stat.st_ino = st_ino;
90    Ok(stat)
91}
92
93/// ### `path_filestat_get_old()`
94/// Access metadata about a file or directory
95/// Inputs:
96/// - `Fd fd`
97///     The directory that `path` is relative to
98/// - `LookupFlags flags`
99///     Flags to control how `path` is understood
100/// - `const char *path`
101///     String containing the file path
102/// - `u32 path_len`
103///     The length of the `path` string
104/// Output:
105/// - `__wasi_file_stat_t *buf`
106///     The location where the metadata will be stored
107#[instrument(level = "trace", skip_all, fields(%fd, path = field::Empty), ret)]
108pub fn path_filestat_get_old<M: MemorySize>(
109    ctx: FunctionEnvMut<'_, WasiEnv>,
110    fd: WasiFd,
111    flags: LookupFlags,
112    path: WasmPtr<u8, M>,
113    path_len: M::Offset,
114    buf: WasmPtr<Snapshot0Filestat, M>,
115) -> Errno {
116    let env = ctx.data();
117    let (memory, mut state, inodes) = unsafe { env.get_memory_and_wasi_state_and_inodes(&ctx, 0) };
118
119    let path_string = unsafe { get_input_str!(&memory, path, path_len) };
120    Span::current().record("path", path_string.as_str());
121
122    let stat = wasi_try!(path_filestat_get_internal(
123        &memory,
124        state,
125        inodes,
126        fd,
127        flags,
128        &path_string
129    ));
130
131    let old_stat = Snapshot0Filestat {
132        st_dev: stat.st_dev,
133        st_ino: stat.st_ino,
134        st_filetype: stat.st_filetype,
135        st_nlink: stat.st_nlink as u32,
136        st_size: stat.st_size,
137        st_atim: stat.st_atim,
138        st_mtim: stat.st_mtim,
139        st_ctim: stat.st_ctim,
140    };
141    wasi_try_mem!(buf.deref(&memory).write(old_stat));
142
143    Errno::Success
144}