wasmer_wasix/syscalls/wasi/
path_filestat_set_times.rs1use super::*;
2use crate::syscalls::*;
3
4#[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}