Skip to content

Commit

Permalink
Merge #946
Browse files Browse the repository at this point in the history
946: Add a wrapper for utimes(2) r=asomers a=jmmv

PR #944 added wrappers for the more-modern futimens(2) and utimesat(2),
but unfortunately these APIs are not available on old-ish systems.

In particular, macOS Sierra and below don't implement them, making the
new APIs unusable.  Whether we should care about such "old" systems is
debatable, but the problem is that, at the moment, this is the only
macOS version usable on Travis to test kexts and, thus, to test FUSE
file systems.

Co-authored-by: Julio Merino <julio@meroh.net>
  • Loading branch information
bors[bot] and jmmv committed Oct 4, 2018
2 parents a32b46e + 06be3ee commit 771a2fc
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 6 deletions.
4 changes: 2 additions & 2 deletions CHANGELOG.md
Expand Up @@ -16,8 +16,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))
and a `utimes` wrapper ([#946](https://github.com/nix-rust/nix/pull/946)).

### Changed
- Increased required Rust version to 1.22.1/
Expand Down
24 changes: 22 additions & 2 deletions src/sys/stat.rs
Expand Up @@ -8,7 +8,7 @@ use libc::{self, mode_t};
use std::mem;
use std::os::raw;
use std::os::unix::io::RawFd;
use sys::time::TimeSpec;
use sys::time::{TimeSpec, TimeVal};

libc_bitflags!(
pub struct SFlag: mode_t {
Expand Down Expand Up @@ -190,6 +190,25 @@ pub fn fchmodat<P: ?Sized + NixPath>(
Errno::result(res).map(|_| ())
}

/// Change the access and modification times of a file.
///
/// `utimes(path, times)` is identical to
/// `utimensat(None, path, times, UtimensatFlags::FollowSymlink)`. The former
/// is a deprecated API so prefer using the latter if the platforms you care
/// about support it.
///
/// # References
///
/// [utimes(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/utimes.html).
pub fn utimes<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::utimes(cstr.as_ptr(), &times[0])
})?;

Errno::result(res).map(|_| ())
}

/// Change the access and modification times of the file specified by a file descriptor.
///
/// # References
Expand Down Expand Up @@ -220,7 +239,8 @@ pub enum UtimensatFlags {
/// then the mode of the symbolic link is changed.
///
/// `utimensat(None, path, times, UtimensatFlags::FollowSymlink)` is identical to
/// `libc::utimes(path, times)`. That's why `utimes` is unimplemented in the `nix` crate.
/// `utimes(path, times)`. The latter is a deprecated API so prefer using the
/// former if the platforms you care about support it.
///
/// # References
///
Expand Down
14 changes: 12 additions & 2 deletions test/test_stat.rs
Expand Up @@ -6,9 +6,9 @@ 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, utimensat};
use nix::sys::stat::{self, fchmod, fchmodat, fstat, futimens, lstat, stat, utimes, utimensat};
use nix::sys::stat::{FileStat, Mode, FchmodatFlags, UtimensatFlags};
use nix::sys::time::{TimeSpec, TimeValLike};
use nix::sys::time::{TimeSpec, TimeVal, TimeValLike};
use nix::unistd::chdir;
use nix::Result;
use tempfile;
Expand Down Expand Up @@ -168,6 +168,16 @@ fn assert_times_eq(exp_atime_sec: u64, exp_mtime_sec: u64, attr: &fs::Metadata)
attr.modified().unwrap().duration_since(UNIX_EPOCH).unwrap());
}

#[test]
fn test_utimes() {
let tempdir = tempfile::tempdir().unwrap();
let fullpath = tempdir.path().join("file");
drop(File::create(&fullpath).unwrap());

utimes(&fullpath, &TimeVal::seconds(9990), &TimeVal::seconds(5550));
assert_times_eq(9990, 5550, &fs::metadata(&fullpath).unwrap());
}

#[test]
fn test_futimens() {
let tempdir = tempfile::tempdir().unwrap();
Expand Down

0 comments on commit 771a2fc

Please sign in to comment.