wasmer_wasix/syscalls/wasi/
path_filestat_set_times.rs

1use super::*;
2use crate::syscalls::*;
3
4/// ### `path_filestat_set_times()`
5/// Update time metadata on a file or directory
6/// Inputs:
7/// - `Fd fd`
8///     The directory relative to which the path is resolved
9/// - `LookupFlags flags`
10///     Flags to control how the path is understood
11/// - `const char *path`
12///     String containing the file path
13/// - `u32 path_len`
14///     The length of the `path` string
15/// - `Timestamp st_atim`
16///     The timestamp that the last accessed time attribute is set to
17/// -  `Timestamp st_mtim`
18///     The timestamp that the last modified time attribute is set to
19/// - `Fstflags fst_flags`
20///     A bitmask controlling which attributes are set
21#[instrument(level = "trace", skip_all, fields(%fd, path = field::Empty, %st_atim, %st_mtim), ret)]
22pub fn path_filestat_set_times<M: MemorySize>(
23    mut ctx: FunctionEnvMut<'_, WasiEnv>,
24    fd: WasiFd,
25    flags: LookupFlags,
26    path: WasmPtr<u8, M>,
27    path_len: M::Offset,
28    st_atim: Timestamp,
29    st_mtim: Timestamp,
30    fst_flags: Fstflags,
31) -> Result<Errno, WasiError> {
32    WasiEnv::do_pending_operations(&mut ctx)?;
33
34    let env = ctx.data();
35    let (memory, mut state, inodes) = unsafe { env.get_memory_and_wasi_state_and_inodes(&ctx, 0) };
36
37    let path_string = unsafe { get_input_str_ok!(&memory, path, path_len) };
38    Span::current().record("path", path_string.as_str());
39
40    wasi_try_ok!(path_filestat_set_times_internal(
41        &mut ctx,
42        fd,
43        flags,
44        &path_string,
45        st_atim,
46        st_mtim,
47        fst_flags
48    ));
49    let env = ctx.data();
50
51    #[cfg(feature = "journal")]
52    if env.enable_journal {
53        JournalEffector::save_path_set_times(
54            &mut ctx,
55            fd,
56            flags,
57            path_string,
58            st_atim,
59            st_mtim,
60            fst_flags,
61        )
62        .map_err(|err| {
63            tracing::error!("failed to save file set times event - {}", err);
64            WasiError::Exit(ExitCode::from(Errno::Fault))
65        })?;
66    }
67
68    Ok(Errno::Success)
69}
70
71pub(crate) fn path_filestat_set_times_internal(
72    ctx: &mut FunctionEnvMut<'_, WasiEnv>,
73    fd: WasiFd,
74    flags: LookupFlags,
75    path: &str,
76    st_atim: Timestamp,
77    st_mtim: Timestamp,
78    fst_flags: Fstflags,
79) -> Result<(), Errno> {
80    let env = ctx.data();
81    let (memory, mut state, inodes) = unsafe { env.get_memory_and_wasi_state_and_inodes(&ctx, 0) };
82    let fd_entry = state.fs.get_fd(fd)?;
83    let fd_inode = fd_entry.inode;
84    if !fd_entry
85        .inner
86        .rights
87        .contains(Rights::PATH_FILESTAT_SET_TIMES)
88    {
89        return Err(Errno::Access);
90    }
91    if (fst_flags.contains(Fstflags::SET_ATIM) && fst_flags.contains(Fstflags::SET_ATIM_NOW))
92        || (fst_flags.contains(Fstflags::SET_MTIM) && fst_flags.contains(Fstflags::SET_MTIM_NOW))
93    {
94        return Err(Errno::Inval);
95    }
96
97    let file_inode =
98        state
99            .fs
100            .get_inode_at_path(inodes, fd, path, flags & __WASI_LOOKUP_SYMLINK_FOLLOW != 0)?;
101    let stat = {
102        let guard = file_inode.read();
103        state.fs.get_stat_for_kind(guard.deref())?
104    };
105
106    if fst_flags.contains(Fstflags::SET_ATIM) || fst_flags.contains(Fstflags::SET_ATIM_NOW) {
107        let time_to_set = if fst_flags.contains(Fstflags::SET_ATIM) {
108            st_atim
109        } else {
110            get_current_time_in_nanos()?
111        };
112        fd_inode.stat.write().unwrap().st_atim = time_to_set;
113    }
114    if fst_flags.contains(Fstflags::SET_MTIM) || fst_flags.contains(Fstflags::SET_MTIM_NOW) {
115        let time_to_set = if fst_flags.contains(Fstflags::SET_MTIM) {
116            st_mtim
117        } else {
118            get_current_time_in_nanos()?
119        };
120        fd_inode.stat.write().unwrap().st_mtim = time_to_set;
121    }
122
123    Ok(())
124}