Skip to content

Commit

Permalink
feat: Add associated constants UTIME_OMIT UTIME_NOW to TimeSpec (
Browse files Browse the repository at this point in the history
…nix-rust#1879)

* feat: support UTIME_NOW & UTIME_OMIT

* fmt

* fmt

* linux x32 type cast

* fmt
  • Loading branch information
SteveLauC authored Dec 10, 2023
1 parent d518abd commit 1c189d9
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 1 deletion.
1 change: 1 addition & 0 deletions changelog/1879.added.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add associated constants `UTIME_OMIT` `UTIME_NOW` for `TimeSpec`
8 changes: 7 additions & 1 deletion src/sys/stat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,9 @@ pub fn lutimes<P: ?Sized + NixPath>(

/// Change the access and modification times of the file specified by a file descriptor.
///
/// If you want to set the timestamp to now, use `TimeSpec::UTIME_NOW`. Use
/// `TimeSpec::UTIME_OMIT` if you don't want to change it.
///
/// # References
///
/// [futimens(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/futimens.html).
Expand Down Expand Up @@ -408,6 +411,9 @@ pub enum UtimensatFlags {
/// `utimes(path, times)`. The latter is a deprecated API so prefer using the
/// former if the platforms you care about support it.
///
/// If you want to set the timestamp to now, use `TimeSpec::UTIME_NOW`. Use
/// `TimeSpec::UTIME_OMIT` if you don't want to change it.
///
/// # References
///
/// [utimensat(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/utimens.html).
Expand Down Expand Up @@ -448,4 +454,4 @@ pub fn mkdirat<P: ?Sized + NixPath>(
})?;

Errno::result(res).map(drop)
}
}
11 changes: 11 additions & 0 deletions src/sys/time.rs
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,17 @@ impl TimeValLike for TimeSpec {
}

impl TimeSpec {
/// Leave the timestamp unchanged.
#[cfg(not(target_os = "redox"))]
// At the time of writing this PR, redox does not support this feature
pub const UTIME_OMIT: TimeSpec =
TimeSpec::new(0, libc::UTIME_OMIT as timespec_tv_nsec_t);
/// Update the timestamp to `Now`
// At the time of writing this PR, redox does not support this feature
#[cfg(not(target_os = "redox"))]
pub const UTIME_NOW: TimeSpec =
TimeSpec::new(0, libc::UTIME_NOW as timespec_tv_nsec_t);

/// Construct a new `TimeSpec` from its components
#[cfg_attr(target_env = "musl", allow(deprecated))] // https://github.com/rust-lang/libc/issues/1848
pub const fn new(seconds: time_t, nanoseconds: timespec_tv_nsec_t) -> Self {
Expand Down
72 changes: 72 additions & 0 deletions test/test_stat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -413,3 +413,75 @@ fn test_mknodat() {
assert_eq!(mode & libc::S_IFREG, libc::S_IFREG);
assert_eq!(mode & libc::S_IRWXU, libc::S_IRWXU);
}

#[test]
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
fn test_futimens_unchanged() {
let tempdir = tempfile::tempdir().unwrap();
let fullpath = tempdir.path().join("file");
drop(File::create(&fullpath).unwrap());
let fd = fcntl::open(&fullpath, fcntl::OFlag::empty(), stat::Mode::empty())
.unwrap();

let old_atime = fs::metadata(fullpath.as_path())
.unwrap()
.accessed()
.unwrap();
let old_mtime = fs::metadata(fullpath.as_path())
.unwrap()
.modified()
.unwrap();

futimens(fd, &TimeSpec::UTIME_OMIT, &TimeSpec::UTIME_OMIT).unwrap();

let new_atime = fs::metadata(fullpath.as_path())
.unwrap()
.accessed()
.unwrap();
let new_mtime = fs::metadata(fullpath.as_path())
.unwrap()
.modified()
.unwrap();
assert_eq!(old_atime, new_atime);
assert_eq!(old_mtime, new_mtime);
}

#[test]
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
fn test_utimensat_unchanged() {
let _dr = crate::DirRestore::new();
let tempdir = tempfile::tempdir().unwrap();
let filename = "foo.txt";
let fullpath = tempdir.path().join(filename);
drop(File::create(&fullpath).unwrap());
let dirfd =
fcntl::open(tempdir.path(), fcntl::OFlag::empty(), stat::Mode::empty())
.unwrap();

let old_atime = fs::metadata(fullpath.as_path())
.unwrap()
.accessed()
.unwrap();
let old_mtime = fs::metadata(fullpath.as_path())
.unwrap()
.modified()
.unwrap();
utimensat(
Some(dirfd),
filename,
&TimeSpec::UTIME_OMIT,
&TimeSpec::UTIME_OMIT,
UtimensatFlags::NoFollowSymlink,
)
.unwrap();
let new_atime = fs::metadata(fullpath.as_path())
.unwrap()
.accessed()
.unwrap();
let new_mtime = fs::metadata(fullpath.as_path())
.unwrap()
.modified()
.unwrap();
assert_eq!(old_atime, new_atime);
assert_eq!(old_mtime, new_mtime);
}

0 comments on commit 1c189d9

Please sign in to comment.