From 814b337d5ec9d47137ad654f2b9a6dab96d49de7 Mon Sep 17 00:00:00 2001 From: Ben Wiederhake Date: Sun, 24 Mar 2024 20:31:04 +0100 Subject: [PATCH] Properly handle set_file_{,handle_}times_now in unix/utimes.rs This is a POSIX-feature according to https://pubs.opengroup.org/onlinepubs/9699919799/ By changing mod.rs, I verified that this works on Linux 4.9 and Linux 6.6. --- src/unix/utimes.rs | 39 +++++++++++++++++++++++++++++++-------- 1 file changed, 31 insertions(+), 8 deletions(-) diff --git a/src/unix/utimes.rs b/src/unix/utimes.rs index 025ebac..285a531 100644 --- a/src/unix/utimes.rs +++ b/src/unix/utimes.rs @@ -4,6 +4,7 @@ use std::fs; use std::io; use std::os::unix::prelude::*; use std::path::Path; +use std::ptr; #[allow(dead_code)] pub fn set_file_times(p: &Path, atime: FileTime, mtime: FileTime) -> io::Result<()> { @@ -12,13 +13,19 @@ pub fn set_file_times(p: &Path, atime: FileTime, mtime: FileTime) -> io::Result< #[allow(dead_code)] pub fn set_file_times_now(p: &Path, follow_symlink: bool) -> io::Result<()> { - let time = FileTime::now(); - // TODO: Do the same trick as on Linux? - if follow_symlink { - set_file_times(p, time, time) + let p = CString::new(p.as_os_str().as_bytes())?; + let rc = unsafe { + if !follow_symlink { + libc::lutimes(p.as_ptr(), ptr::null::()) + } else { + libc::utimes(p.as_ptr(), ptr::null::()) + } + }; + return if rc == 0 { + Ok(()) } else { - set_symlink_file_times(p, time, time) - } + Err(io::Error::last_os_error()) + }; } #[allow(dead_code)] @@ -71,10 +78,26 @@ pub fn set_file_handle_times( }; } +#[cfg(not(target_env = "uclibc"))] +#[allow(dead_code)] +pub fn set_file_handle_times_now(f: &fs::File) -> io::Result<()> { + let rc = unsafe { libc::futimes(f.as_raw_fd(), ptr::null::()) }; + return if rc == 0 { + Ok(()) + } else { + Err(io::Error::last_os_error()) + }; +} + +#[cfg(target_env = "uclibc")] #[allow(dead_code)] pub fn set_file_handle_times_now(f: &fs::File) -> io::Result<()> { - let time = FileTime::now(); - set_file_handle_times(f, Some(time), Some(time)) // TODO: Do the same trick as on Linux? + let rc = unsafe { libc::futimens(f.as_raw_fd(), ptr::null::()) }; + return if rc == 0 { + Ok(()) + } else { + Err(io::Error::last_os_error()) + }; } fn get_times(