diff --git a/lib/virtual-fs/src/arc_box_file.rs b/lib/virtual-fs/src/arc_box_file.rs index d518c7069ec..b55a8b415e6 100644 --- a/lib/virtual-fs/src/arc_box_file.rs +++ b/lib/virtual-fs/src/arc_box_file.rs @@ -102,6 +102,10 @@ impl VirtualFile for ArcBoxFile { let inner = self.inner.lock().unwrap(); inner.created_time() } + fn set_times(&mut self, atime: Option, mtime: Option) -> crate::Result<()> { + let mut inner = self.inner.lock().unwrap(); + inner.set_times(atime, mtime) + } fn size(&self) -> u64 { let inner = self.inner.lock().unwrap(); inner.size() diff --git a/lib/virtual-fs/src/arc_file.rs b/lib/virtual-fs/src/arc_file.rs index 4e980e02033..088f6e5ce02 100644 --- a/lib/virtual-fs/src/arc_file.rs +++ b/lib/virtual-fs/src/arc_file.rs @@ -118,6 +118,10 @@ where let inner = self.inner.lock().unwrap(); inner.created_time() } + fn set_times(&mut self, atime: Option, mtime: Option) -> crate::Result<()> { + let mut inner = self.inner.lock().unwrap(); + inner.set_times(atime, mtime) + } fn size(&self) -> u64 { let inner = self.inner.lock().unwrap(); inner.size() diff --git a/lib/virtual-fs/src/combine_file.rs b/lib/virtual-fs/src/combine_file.rs index f3db42ca58c..951de2e5a2f 100644 --- a/lib/virtual-fs/src/combine_file.rs +++ b/lib/virtual-fs/src/combine_file.rs @@ -33,6 +33,10 @@ impl VirtualFile for CombineFile { self.tx.created_time() } + fn set_times(&mut self, atime: Option, mtime: Option) -> crate::Result<()> { + self.tx.set_times(atime, mtime) + } + fn size(&self) -> u64 { self.rx.size() } diff --git a/lib/virtual-fs/src/cow_file.rs b/lib/virtual-fs/src/cow_file.rs index 4030981854e..643dc2a0554 100644 --- a/lib/virtual-fs/src/cow_file.rs +++ b/lib/virtual-fs/src/cow_file.rs @@ -195,6 +195,16 @@ impl VirtualFile for CopyOnWriteFile { fn created_time(&self) -> u64 { self.created_time } + fn set_times(&mut self, atime: Option, mtime: Option) -> crate::Result<()> { + if let Some(atime) = atime { + self.last_accessed = atime; + } + if let Some(mtime) = mtime { + self.last_modified = mtime; + } + + Ok(()) + } fn size(&self) -> u64 { match self.state.as_ref() { Some(inner) => inner.size(), diff --git a/lib/virtual-fs/src/dual_write_file.rs b/lib/virtual-fs/src/dual_write_file.rs index ef27a3f89d1..bf71ad41e86 100644 --- a/lib/virtual-fs/src/dual_write_file.rs +++ b/lib/virtual-fs/src/dual_write_file.rs @@ -41,6 +41,10 @@ impl VirtualFile for DualWriteFile { self.inner.created_time() } + fn set_times(&mut self, atime: Option, mtime: Option) -> crate::Result<()> { + self.inner.set_times(atime, mtime) + } + fn size(&self) -> u64 { self.inner.size() } diff --git a/lib/virtual-fs/src/host_fs.rs b/lib/virtual-fs/src/host_fs.rs index bac84f944b0..43048b2dc21 100644 --- a/lib/virtual-fs/src/host_fs.rs +++ b/lib/virtual-fs/src/host_fs.rs @@ -434,6 +434,14 @@ impl VirtualFile for File { .unwrap_or(0) } + fn set_times(&mut self, atime: Option, mtime: Option) -> crate::Result<()> { + let atime = atime.map(|t| filetime::FileTime::from_unix_time(t as i64, 0)); + let mtime = mtime.map(|t| filetime::FileTime::from_unix_time(t as i64, 0)); + + filetime::set_file_handle_times(&self.inner_std, atime, mtime) + .map_err(|_| crate::FsError::IOError) + } + fn size(&self) -> u64 { self.metadata().len() } diff --git a/lib/virtual-fs/src/lib.rs b/lib/virtual-fs/src/lib.rs index 7fb2343490a..f3a4f66d2a0 100644 --- a/lib/virtual-fs/src/lib.rs +++ b/lib/virtual-fs/src/lib.rs @@ -336,6 +336,12 @@ pub trait VirtualFile: /// the time at which the file was created in nanoseconds as a UNIX timestamp fn created_time(&self) -> u64; + #[allow(unused_variables)] + /// sets accessed and modified time + fn set_times(&mut self, atime: Option, mtime: Option) -> crate::Result<()> { + Ok(()) + } + /// the size of the file in bytes fn size(&self) -> u64; diff --git a/lib/virtual-fs/src/mem_fs/file.rs b/lib/virtual-fs/src/mem_fs/file.rs index 1a4336553f8..77a9dedf8c9 100644 --- a/lib/virtual-fs/src/mem_fs/file.rs +++ b/lib/virtual-fs/src/mem_fs/file.rs @@ -144,6 +144,27 @@ impl VirtualFile for FileHandle { node.metadata().created } + fn set_times(&mut self, atime: Option, mtime: Option) -> crate::Result<()> { + let mut fs = match self.filesystem.inner.write() { + Ok(fs) => fs, + _ => return Err(crate::FsError::Lock), + }; + + let inode = fs.storage.get_mut(self.inode); + if let Some(node) = inode { + if let Some(atime) = atime { + node.metadata_mut().accessed = atime; + } + if let Some(mtime) = mtime { + node.metadata_mut().modified = mtime; + } + + return Ok(()); + } + + Err(crate::FsError::UnknownError) + } + fn size(&self) -> u64 { let fs = match self.filesystem.inner.read() { Ok(fs) => fs, diff --git a/lib/virtual-fs/src/trace_fs.rs b/lib/virtual-fs/src/trace_fs.rs index 461b1cbf4fe..86abc0687bd 100644 --- a/lib/virtual-fs/src/trace_fs.rs +++ b/lib/virtual-fs/src/trace_fs.rs @@ -119,6 +119,11 @@ impl VirtualFile for TraceFile { self.file.created_time() } + #[tracing::instrument(level = "trace", skip(self), fields(path=%self.path.display()))] + fn set_times(&mut self, atime: Option, mtime: Option) -> crate::Result<()> { + self.file.set_times(atime, mtime) + } + #[tracing::instrument(level = "trace", skip(self), fields(path=%self.path.display()))] fn size(&self) -> u64 { self.file.size() diff --git a/lib/wasix/src/fs/inode_guard.rs b/lib/wasix/src/fs/inode_guard.rs index c944b9d0700..aca0e161c24 100644 --- a/lib/wasix/src/fs/inode_guard.rs +++ b/lib/wasix/src/fs/inode_guard.rs @@ -510,6 +510,19 @@ impl VirtualFile for WasiStateFileGuard { } } + fn set_times( + &mut self, + atime: Option, + mtime: Option, + ) -> Result<(), virtual_fs::FsError> { + let mut guard = self.lock_write(); + if let Some(file) = guard.as_mut() { + file.set_times(atime, mtime) + } else { + Err(crate::FsError::Lock) + } + } + fn size(&self) -> u64 { let guard = self.lock_read(); if let Some(file) = guard.as_ref() { diff --git a/lib/wasix/src/syscalls/wasi/fd_filestat_set_times.rs b/lib/wasix/src/syscalls/wasi/fd_filestat_set_times.rs index df7db200bc1..9add80b56d3 100644 --- a/lib/wasix/src/syscalls/wasi/fd_filestat_set_times.rs +++ b/lib/wasix/src/syscalls/wasi/fd_filestat_set_times.rs @@ -1,3 +1,5 @@ +use std::borrow::BorrowMut; + use super::*; use crate::syscalls::*; @@ -59,6 +61,9 @@ pub(crate) fn fd_filestat_set_times_internal( let inode = fd_entry.inode; + let mut atime = None; + let mut mtime = None; + if fst_flags.contains(Fstflags::SET_ATIM) || fst_flags.contains(Fstflags::SET_ATIM_NOW) { let time_to_set = if fst_flags.contains(Fstflags::SET_ATIM) { st_atim @@ -66,6 +71,7 @@ pub(crate) fn fd_filestat_set_times_internal( get_current_time_in_nanos()? }; inode.stat.write().unwrap().st_atim = time_to_set; + atime = Some(time_to_set); } if fst_flags.contains(Fstflags::SET_MTIM) || fst_flags.contains(Fstflags::SET_MTIM_NOW) { @@ -75,6 +81,17 @@ pub(crate) fn fd_filestat_set_times_internal( get_current_time_in_nanos()? }; inode.stat.write().unwrap().st_mtim = time_to_set; + mtime = Some(time_to_set); + } + + if let Kind::File { + handle: Some(handle), + .. + } = inode.kind.write().unwrap().deref() + { + let mut handle = handle.write().unwrap(); + + handle.set_times(atime, mtime); } Ok(())