From c12283979e28dcc6bf143333a70977fc2a981e22 Mon Sep 17 00:00:00 2001 From: Tristan Guichaoua Date: Sat, 6 Dec 2025 16:39:40 +0100 Subject: [PATCH 1/4] add freeze file times on Windows --- library/std/src/os/windows/fs.rs | 20 ++++++++++++++++++++ library/std/src/sys/fs/windows.rs | 20 ++++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/library/std/src/os/windows/fs.rs b/library/std/src/os/windows/fs.rs index b445f368aeb12..934df4101ae81 100644 --- a/library/std/src/os/windows/fs.rs +++ b/library/std/src/os/windows/fs.rs @@ -305,6 +305,16 @@ pub trait OpenOptionsExt { /// https://docs.microsoft.com/en-us/windows/win32/api/winnt/ne-winnt-security_impersonation_level #[stable(feature = "open_options_ext", since = "1.10.0")] fn security_qos_flags(&mut self, flags: u32) -> &mut Self; + + /// If set to `true`, prevent the "last access time" of the file from being changed. + /// + /// Default to `false`. + fn freeze_last_access_time(&mut self, freeze: bool) -> &mut Self; + + /// If set to `true`, prevent the "last write time" of the file from being changed. + /// + /// Default to `false`. + fn freeze_last_write_time(&mut self, freeze: bool) -> &mut Self; } #[stable(feature = "open_options_ext", since = "1.10.0")] @@ -333,6 +343,16 @@ impl OpenOptionsExt for OpenOptions { self.as_inner_mut().security_qos_flags(flags); self } + + fn freeze_last_access_time(&mut self, freeze: bool) -> &mut Self { + self.as_inner_mut().freeze_last_access_time(freeze); + self + } + + fn freeze_last_write_time(&mut self, freeze: bool) -> &mut Self { + self.as_inner_mut().freeze_last_write_time(freeze); + self + } } /// Windows-specific extensions to [`fs::Metadata`]. diff --git a/library/std/src/sys/fs/windows.rs b/library/std/src/sys/fs/windows.rs index f2d325da35c7d..d30e5a5e4ab02 100644 --- a/library/std/src/sys/fs/windows.rs +++ b/library/std/src/sys/fs/windows.rs @@ -81,6 +81,8 @@ pub struct OpenOptions { share_mode: u32, security_qos_flags: u32, inherit_handle: bool, + freeze_last_access_time: bool, + freeze_last_write_time: bool, } #[derive(Clone, PartialEq, Eq, Debug)] @@ -246,6 +248,12 @@ impl OpenOptions { pub fn inherit_handle(&mut self, inherit: bool) { self.inherit_handle = inherit; } + fn freeze_last_access_time(&mut self, freeze: bool) { + self.freeze_last_access_time = freeze; + } + fn freeze_last_write_time(&mut self, freeze: bool) { + self.freeze_last_write_time = freeze; + } fn get_access_mode(&self) -> io::Result { match (self.read, self.write, self.append, self.access_mode) { @@ -343,6 +351,18 @@ impl File { }; let handle = unsafe { HandleOrInvalid::from_raw_handle(handle) }; if let Ok(handle) = OwnedHandle::try_from(handle) { + if opts.freeze_last_access_time || opts.freeze_last_write_time { + let file_time = + c::FILETIME { dwLowDateTime: 0xFFFFFFFF, dwHighDateTime: 0xFFFFFFFF }; + cvt(unsafe { + c::SetFileTime( + handle.as_raw_handle(), + core::ptr::null(), + if opts.freeze_last_access_time { &file_time } else { core::ptr::null() }, + if opts.freeze_last_write_time { &file_time } else { core::ptr::null() }, + ) + })?; + } // Manual truncation. See #115745. if opts.truncate && creation == c::OPEN_ALWAYS From e06bc684c69e709f0f63880c87e524127a94d2de Mon Sep 17 00:00:00 2001 From: Tristan Guichaoua Date: Sat, 6 Dec 2025 16:46:17 +0100 Subject: [PATCH 2/4] add new fields to `OpenOptions::new` --- library/std/src/sys/fs/windows.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/library/std/src/sys/fs/windows.rs b/library/std/src/sys/fs/windows.rs index d30e5a5e4ab02..35ec3eb3bcd26 100644 --- a/library/std/src/sys/fs/windows.rs +++ b/library/std/src/sys/fs/windows.rs @@ -206,6 +206,8 @@ impl OpenOptions { attributes: 0, security_qos_flags: 0, inherit_handle: false, + freeze_last_access_time: false, + freeze_last_write_time: false, } } From c4d717c7aa84cdd9c2737a2e6a8faa3bbf868524 Mon Sep 17 00:00:00 2001 From: Tristan Guichaoua Date: Sat, 6 Dec 2025 17:07:54 +0100 Subject: [PATCH 3/4] fix visibility --- library/std/src/sys/fs/windows.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/std/src/sys/fs/windows.rs b/library/std/src/sys/fs/windows.rs index 35ec3eb3bcd26..e214284a03a74 100644 --- a/library/std/src/sys/fs/windows.rs +++ b/library/std/src/sys/fs/windows.rs @@ -250,10 +250,10 @@ impl OpenOptions { pub fn inherit_handle(&mut self, inherit: bool) { self.inherit_handle = inherit; } - fn freeze_last_access_time(&mut self, freeze: bool) { + pub fn freeze_last_access_time(&mut self, freeze: bool) { self.freeze_last_access_time = freeze; } - fn freeze_last_write_time(&mut self, freeze: bool) { + pub fn freeze_last_write_time(&mut self, freeze: bool) { self.freeze_last_write_time = freeze; } From c2b6a4c56fdbe76a5a1636fad4995c6e744ae091 Mon Sep 17 00:00:00 2001 From: Tristan Guichaoua Date: Sat, 6 Dec 2025 20:22:03 +0100 Subject: [PATCH 4/4] add stability attributes --- library/std/src/os/windows/fs.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/library/std/src/os/windows/fs.rs b/library/std/src/os/windows/fs.rs index 934df4101ae81..95a4ea53ce1e5 100644 --- a/library/std/src/os/windows/fs.rs +++ b/library/std/src/os/windows/fs.rs @@ -309,11 +309,13 @@ pub trait OpenOptionsExt { /// If set to `true`, prevent the "last access time" of the file from being changed. /// /// Default to `false`. + #[unstable(feature = "windows_freeze_file_times", issue = "149715")] fn freeze_last_access_time(&mut self, freeze: bool) -> &mut Self; /// If set to `true`, prevent the "last write time" of the file from being changed. /// /// Default to `false`. + #[unstable(feature = "windows_freeze_file_times", issue = "149715")] fn freeze_last_write_time(&mut self, freeze: bool) -> &mut Self; }