summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md3
-rw-r--r--src/sys/stat.rs20
-rw-r--r--test/test_stat.rs21
3 files changed, 42 insertions, 2 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6688c8f8..d2a97bc4 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -18,7 +18,8 @@ This project adheres to [Semantic Versioning](http://semver.org/).
([#916](https://github.com/nix-rust/nix/pull/916))
- Added `kmod` module that allows loading and unloading kernel modules on Linux.
([#930](https://github.com/nix-rust/nix/pull/930))
-- Added `futimens` and `utimesat` wrappers ([#944](https://github.com/nix-rust/nix/pull/944))
+- Added `futimens` and `utimesat` wrappers ([#944](https://github.com/nix-rust/nix/pull/944)),
+ an `lutimes` wrapper ([#967](https://github.com/nix-rust/nix/pull/967)),
and a `utimes` wrapper ([#946](https://github.com/nix-rust/nix/pull/946)).
- Added `AF_UNSPEC` wrapper to `AddressFamily` ([#948](https://github.com/nix-rust/nix/pull/948))
- Added the `mode_t` public alias within `sys::stat`.
diff --git a/src/sys/stat.rs b/src/sys/stat.rs
index a0b3aafc..925c0ede 100644
--- a/src/sys/stat.rs
+++ b/src/sys/stat.rs
@@ -199,6 +199,26 @@ pub fn utimes<P: ?Sized + NixPath>(path: &P, atime: &TimeVal, mtime: &TimeVal) -
Errno::result(res).map(|_| ())
}
+/// Change the access and modification times of a file without following symlinks.
+///
+/// `lutimes(path, times)` is identical to
+/// `utimensat(None, path, times, UtimensatFlags::NoFollowSymlink)`. The former
+/// is a deprecated API so prefer using the latter if the platforms you care
+/// about support it.
+///
+/// # References
+///
+/// [lutimes(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/lutimes.html).
+#[cfg(not(target_os = "android"))]
+pub fn lutimes<P: ?Sized + NixPath>(path: &P, atime: &TimeVal, mtime: &TimeVal) -> Result<()> {
+ let times: [libc::timeval; 2] = [*atime.as_ref(), *mtime.as_ref()];
+ let res = path.with_nix_path(|cstr| unsafe {
+ libc::lutimes(cstr.as_ptr(), &times[0])
+ })?;
+
+ Errno::result(res).map(|_| ())
+}
+
/// Change the access and modification times of the file specified by a file descriptor.
///
/// # References
diff --git a/test/test_stat.rs b/test/test_stat.rs
index 01d86a79..bd16e635 100644
--- a/test/test_stat.rs
+++ b/test/test_stat.rs
@@ -6,7 +6,7 @@ use std::time::{Duration, UNIX_EPOCH};
use libc::{S_IFMT, S_IFLNK};
use nix::fcntl;
-use nix::sys::stat::{self, fchmod, fchmodat, fstat, futimens, lstat, stat, utimes, utimensat};
+use nix::sys::stat::{self, fchmod, fchmodat, fstat, futimens, lstat, lutimes, stat, utimes, utimensat};
use nix::sys::stat::{FileStat, Mode, FchmodatFlags, UtimensatFlags};
use nix::sys::time::{TimeSpec, TimeVal, TimeValLike};
use nix::unistd::chdir;
@@ -179,6 +179,25 @@ fn test_utimes() {
}
#[test]
+fn test_lutimes() {
+ let tempdir = tempfile::tempdir().unwrap();
+ let target = tempdir.path().join("target");
+ let fullpath = tempdir.path().join("symlink");
+ drop(File::create(&target).unwrap());
+ symlink(&target, &fullpath).unwrap();
+
+ let exp_target_metadata = fs::symlink_metadata(&target).unwrap();
+ lutimes(&fullpath, &TimeVal::seconds(4560), &TimeVal::seconds(1230)).unwrap();
+ assert_times_eq(4560, 1230, &fs::symlink_metadata(&fullpath).unwrap());
+
+ let target_metadata = fs::symlink_metadata(&target).unwrap();
+ assert_eq!(exp_target_metadata.accessed().unwrap(), target_metadata.accessed().unwrap(),
+ "atime of symlink target was unexpectedly modified");
+ assert_eq!(exp_target_metadata.modified().unwrap(), target_metadata.modified().unwrap(),
+ "mtime of symlink target was unexpectedly modified");
+}
+
+#[test]
fn test_futimens() {
let tempdir = tempfile::tempdir().unwrap();
let fullpath = tempdir.path().join("file");