add freeze file times on Windows

This commit is contained in:
Tristan Guichaoua 2026-01-11 12:05:49 +01:00
parent da2544bfbe
commit d772c3d99d
2 changed files with 44 additions and 0 deletions

View file

@ -305,6 +305,18 @@ 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`.
#[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;
}
#[stable(feature = "open_options_ext", since = "1.10.0")]
@ -333,6 +345,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`].

View file

@ -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)]
@ -204,6 +206,8 @@ impl OpenOptions {
attributes: 0,
security_qos_flags: 0,
inherit_handle: false,
freeze_last_access_time: false,
freeze_last_write_time: false,
}
}
@ -246,6 +250,12 @@ impl OpenOptions {
pub fn inherit_handle(&mut self, inherit: bool) {
self.inherit_handle = inherit;
}
pub fn freeze_last_access_time(&mut self, freeze: bool) {
self.freeze_last_access_time = freeze;
}
pub fn freeze_last_write_time(&mut self, freeze: bool) {
self.freeze_last_write_time = freeze;
}
fn get_access_mode(&self) -> io::Result<u32> {
match (self.read, self.write, self.append, self.access_mode) {
@ -343,6 +353,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