Rollup merge of #152083 - chenyukang:yukang-fix-set-times-nofollow-on-windows, r=ChrisDenton

Fix set_times_nofollow for directory on windows

Fix issue from:
https://github.com/rust-lang/rust/issues/147455#issuecomment-3841311858

old code `opts.write(true)` on Windows requests `GENERIC_WRITE` access, replace with `opts.access_mode(c::FILE_WRITE_ATTRIBUTES)` to get minimal permission.

r? @joshtriplett
This commit is contained in:
Jonathan Brouwer 2026-02-04 14:39:28 +01:00 committed by GitHub
commit 3184d55536
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 53 additions and 2 deletions

View file

@ -2301,6 +2301,57 @@ fn test_fs_set_times() {
}
}
#[test]
fn test_fs_set_times_on_dir() {
#[cfg(target_vendor = "apple")]
use crate::os::darwin::fs::FileTimesExt;
#[cfg(windows)]
use crate::os::windows::fs::FileTimesExt;
let tmp = tmpdir();
let dir_path = tmp.join("testdir");
fs::create_dir(&dir_path).unwrap();
let mut times = FileTimes::new();
let accessed = SystemTime::UNIX_EPOCH + Duration::from_secs(12345);
let modified = SystemTime::UNIX_EPOCH + Duration::from_secs(54321);
times = times.set_accessed(accessed).set_modified(modified);
#[cfg(any(windows, target_vendor = "apple"))]
let created = SystemTime::UNIX_EPOCH + Duration::from_secs(32123);
#[cfg(any(windows, target_vendor = "apple"))]
{
times = times.set_created(created);
}
match fs::set_times(&dir_path, times) {
// Allow unsupported errors on platforms which don't support setting times.
#[cfg(not(any(
windows,
all(
unix,
not(any(
target_os = "android",
target_os = "redox",
target_os = "espidf",
target_os = "horizon"
))
)
)))]
Err(e) if e.kind() == ErrorKind::Unsupported => return,
Err(e) => panic!("error setting directory times: {e:?}"),
Ok(_) => {}
}
let metadata = fs::metadata(&dir_path).unwrap();
assert_eq!(metadata.accessed().unwrap(), accessed);
assert_eq!(metadata.modified().unwrap(), modified);
#[cfg(any(windows, target_vendor = "apple"))]
{
assert_eq!(metadata.created().unwrap(), created);
}
}
#[test]
fn test_fs_set_times_follows_symlink() {
#[cfg(target_vendor = "apple")]

View file

@ -1556,7 +1556,7 @@ pub fn set_perm(p: &WCStr, perm: FilePermissions) -> io::Result<()> {
pub fn set_times(p: &WCStr, times: FileTimes) -> io::Result<()> {
let mut opts = OpenOptions::new();
opts.write(true);
opts.access_mode(c::FILE_WRITE_ATTRIBUTES);
opts.custom_flags(c::FILE_FLAG_BACKUP_SEMANTICS);
let file = File::open_native(p, &opts)?;
file.set_times(times)
@ -1564,7 +1564,7 @@ pub fn set_times(p: &WCStr, times: FileTimes) -> io::Result<()> {
pub fn set_times_nofollow(p: &WCStr, times: FileTimes) -> io::Result<()> {
let mut opts = OpenOptions::new();
opts.write(true);
opts.access_mode(c::FILE_WRITE_ATTRIBUTES);
// `FILE_FLAG_OPEN_REPARSE_POINT` for no_follow behavior
opts.custom_flags(c::FILE_FLAG_BACKUP_SEMANTICS | c::FILE_FLAG_OPEN_REPARSE_POINT);
let file = File::open_native(p, &opts)?;