wasmer_wasix/syscalls/wasi/
path_open.rs

1use super::*;
2use crate::syscalls::*;
3
4/// ### `path_open()`
5/// Open file located at the given path
6/// Inputs:
7/// - `Fd dirfd`
8///     The fd corresponding to the directory that the file is in
9/// - `LookupFlags dirflags`
10///     Flags specifying how the path will be resolved
11/// - `char *path`
12///     The path of the file or directory to open
13/// - `u32 path_len`
14///     The length of the `path` string
15/// - `Oflags o_flags`
16///     How the file will be opened
17/// - `Rights fs_rights_base`
18///     The rights of the created file descriptor
19/// - `Rights fs_rightsinheriting`
20///     The rights of file descriptors derived from the created file descriptor
21/// - `Fdflags fs_flags`
22///     The flags of the file descriptor
23/// Output:
24/// - `Fd* fd`
25///     The new file descriptor
26/// Possible Errors:
27/// - `Errno::Access`, `Errno::Badf`, `Errno::Fault`, `Errno::Fbig?`, `Errno::Inval`, `Errno::Io`, `Errno::Loop`, `Errno::Mfile`, `Errno::Nametoolong?`, `Errno::Nfile`, `Errno::Noent`, `Errno::Notdir`, `Errno::Rofs`, and `Errno::Notcapable`
28#[instrument(level = "trace", skip_all, fields(%dirfd, path = field::Empty, follow_symlinks = field::Empty, ret_fd = field::Empty), ret)]
29pub fn path_open<M: MemorySize>(
30    mut ctx: FunctionEnvMut<'_, WasiEnv>,
31    dirfd: WasiFd,
32    dirflags: LookupFlags,
33    path: WasmPtr<u8, M>,
34    path_len: M::Offset,
35    o_flags: Oflags,
36    fs_rights_base: Rights,
37    fs_rights_inheriting: Rights,
38    fs_flags: Fdflags,
39    fd: WasmPtr<WasiFd, M>,
40) -> Result<Errno, WasiError> {
41    WasiEnv::do_pending_operations(&mut ctx)?;
42
43    if dirflags & __WASI_LOOKUP_SYMLINK_FOLLOW != 0 {
44        Span::current().record("follow_symlinks", true);
45    }
46    let env = ctx.data();
47    let (memory, mut state, mut inodes) =
48        unsafe { env.get_memory_and_wasi_state_and_inodes(&ctx, 0) };
49    /* TODO: find actual upper bound on name size (also this is a path, not a name :think-fish:) */
50    let path_len64: u64 = path_len.into();
51    if path_len64 > 1024u64 * 1024u64 {
52        return Ok(Errno::Nametoolong);
53    }
54
55    if path_len64 == 0 {
56        return Ok(Errno::Noent);
57    }
58
59    // o_flags:
60    // - __WASI_O_CREAT (create if it does not exist)
61    // - __WASI_O_DIRECTORY (fail if not dir)
62    // - __WASI_O_EXCL (fail if file exists)
63    // - __WASI_O_TRUNC (truncate size to 0)
64
65    let path_string = unsafe { get_input_str_ok!(&memory, path, path_len) };
66    Span::current().record("path", path_string.as_str());
67
68    let out_fd = wasi_try_ok!(path_open_internal(
69        ctx.data(),
70        dirfd,
71        dirflags,
72        &path_string,
73        o_flags,
74        fs_rights_base,
75        fs_rights_inheriting,
76        fs_flags,
77        Fdflagsext::empty(),
78        None,
79    )?);
80    let env = ctx.data();
81
82    #[cfg(feature = "journal")]
83    if env.enable_journal {
84        JournalEffector::save_path_open(
85            &mut ctx,
86            out_fd,
87            dirfd,
88            dirflags,
89            path_string,
90            o_flags,
91            fs_rights_base,
92            fs_rights_inheriting,
93            fs_flags,
94            Fdflagsext::empty(),
95        )
96        .map_err(|err| {
97            tracing::error!("failed to save unlink event - {}", err);
98            WasiError::Exit(ExitCode::from(Errno::Fault))
99        })?;
100    }
101
102    let env = ctx.data();
103    let (memory, mut state, mut inodes) =
104        unsafe { env.get_memory_and_wasi_state_and_inodes(&ctx, 0) };
105
106    Span::current().record("ret_fd", out_fd);
107
108    let fd_ref = fd.deref(&memory);
109    wasi_try_mem_ok!(fd_ref.write(out_fd));
110
111    Ok(Errno::Success)
112}