wasmer_wasix/syscalls/wasi/
fd_filestat_set_times.rs1use std::borrow::BorrowMut;
2
3use super::*;
4use crate::syscalls::*;
5
6#[instrument(level = "trace", skip_all, fields(%fd, %st_atim, %st_mtim), ret)]
16pub fn fd_filestat_set_times(
17 mut ctx: FunctionEnvMut<'_, WasiEnv>,
18 fd: WasiFd,
19 st_atim: Timestamp,
20 st_mtim: Timestamp,
21 fst_flags: Fstflags,
22) -> Result<Errno, WasiError> {
23 WasiEnv::do_pending_operations(&mut ctx)?;
24
25 wasi_try_ok!(fd_filestat_set_times_internal(
26 &mut ctx, fd, st_atim, st_mtim, fst_flags
27 ));
28 let env = ctx.data();
29
30 #[cfg(feature = "journal")]
31 if env.enable_journal {
32 JournalEffector::save_fd_set_times(&mut ctx, fd, st_atim, st_mtim, fst_flags).map_err(
33 |err| {
34 tracing::error!("failed to save file set times event - {}", err);
35 WasiError::Exit(ExitCode::from(Errno::Fault))
36 },
37 )?;
38 }
39
40 Ok(Errno::Success)
41}
42
43pub(crate) fn fd_filestat_set_times_internal(
44 ctx: &mut FunctionEnvMut<'_, WasiEnv>,
45 fd: WasiFd,
46 st_atim: Timestamp,
47 st_mtim: Timestamp,
48 fst_flags: Fstflags,
49) -> Result<(), Errno> {
50 let env = ctx.data();
51 let (_, mut state) = unsafe { env.get_memory_and_wasi_state(&ctx, 0) };
52 let fd_entry = state.fs.get_fd(fd)?;
53
54 if !fd_entry
55 .inner
56 .rights
57 .contains(Rights::FD_FILESTAT_SET_TIMES)
58 {
59 return Err(Errno::Access);
60 }
61
62 if (fst_flags.contains(Fstflags::SET_ATIM) && fst_flags.contains(Fstflags::SET_ATIM_NOW))
63 || (fst_flags.contains(Fstflags::SET_MTIM) && fst_flags.contains(Fstflags::SET_MTIM_NOW))
64 {
65 return Err(Errno::Inval);
66 }
67
68 let inode = fd_entry.inode;
69
70 let mut atime = None;
71 let mut mtime = None;
72
73 if fst_flags.contains(Fstflags::SET_ATIM) || fst_flags.contains(Fstflags::SET_ATIM_NOW) {
74 let time_to_set = if fst_flags.contains(Fstflags::SET_ATIM) {
75 st_atim
76 } else {
77 get_current_time_in_nanos()?
78 };
79 inode.stat.write().unwrap().st_atim = time_to_set;
80 atime = Some(time_to_set);
81 }
82
83 if fst_flags.contains(Fstflags::SET_MTIM) || fst_flags.contains(Fstflags::SET_MTIM_NOW) {
84 let time_to_set = if fst_flags.contains(Fstflags::SET_MTIM) {
85 st_mtim
86 } else {
87 get_current_time_in_nanos()?
88 };
89 inode.stat.write().unwrap().st_mtim = time_to_set;
90 mtime = Some(time_to_set);
91 }
92
93 if let Kind::File {
94 handle: Some(handle),
95 ..
96 } = inode.kind.write().unwrap().deref()
97 {
98 let mut handle = handle.write().unwrap();
99
100 handle.set_times(atime, mtime);
101 }
102
103 Ok(())
104}