Skip to content

Commit 771a2fc

Browse files
bors[bot]jmmv
andcommitted
Merge #946
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 <[email protected]>
2 parents a32b46e + 06be3ee commit 771a2fc

File tree

3 files changed

+36
-6
lines changed

3 files changed

+36
-6
lines changed

CHANGELOG.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ This project adheres to [Semantic Versioning](http://semver.org/).
1616
([#916](https://github.com/nix-rust/nix/pull/916))
1717
- Added `kmod` module that allows loading and unloading kernel modules on Linux.
1818
([#930](https://github.com/nix-rust/nix/pull/930))
19-
- Added `futimens` and `utimesat` wrappers.
20-
([#944](https://github.com/nix-rust/nix/pull/944))
19+
- Added `futimens` and `utimesat` wrappers ([#944](https://github.com/nix-rust/nix/pull/944))
20+
and a `utimes` wrapper ([#946](https://github.com/nix-rust/nix/pull/946)).
2121

2222
### Changed
2323
- Increased required Rust version to 1.22.1/

src/sys/stat.rs

+22-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use libc::{self, mode_t};
88
use std::mem;
99
use std::os::raw;
1010
use std::os::unix::io::RawFd;
11-
use sys::time::TimeSpec;
11+
use sys::time::{TimeSpec, TimeVal};
1212

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

193+
/// Change the access and modification times of a file.
194+
///
195+
/// `utimes(path, times)` is identical to
196+
/// `utimensat(None, path, times, UtimensatFlags::FollowSymlink)`. The former
197+
/// is a deprecated API so prefer using the latter if the platforms you care
198+
/// about support it.
199+
///
200+
/// # References
201+
///
202+
/// [utimes(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/utimes.html).
203+
pub fn utimes<P: ?Sized + NixPath>(path: &P, atime: &TimeVal, mtime: &TimeVal) -> Result<()> {
204+
let times: [libc::timeval; 2] = [*atime.as_ref(), *mtime.as_ref()];
205+
let res = path.with_nix_path(|cstr| unsafe {
206+
libc::utimes(cstr.as_ptr(), &times[0])
207+
})?;
208+
209+
Errno::result(res).map(|_| ())
210+
}
211+
193212
/// Change the access and modification times of the file specified by a file descriptor.
194213
///
195214
/// # References
@@ -220,7 +239,8 @@ pub enum UtimensatFlags {
220239
/// then the mode of the symbolic link is changed.
221240
///
222241
/// `utimensat(None, path, times, UtimensatFlags::FollowSymlink)` is identical to
223-
/// `libc::utimes(path, times)`. That's why `utimes` is unimplemented in the `nix` crate.
242+
/// `utimes(path, times)`. The latter is a deprecated API so prefer using the
243+
/// former if the platforms you care about support it.
224244
///
225245
/// # References
226246
///

test/test_stat.rs

+12-2
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ use std::time::{Duration, UNIX_EPOCH};
66
use libc::{S_IFMT, S_IFLNK};
77

88
use nix::fcntl;
9-
use nix::sys::stat::{self, fchmod, fchmodat, fstat, futimens, lstat, stat, utimensat};
9+
use nix::sys::stat::{self, fchmod, fchmodat, fstat, futimens, lstat, stat, utimes, utimensat};
1010
use nix::sys::stat::{FileStat, Mode, FchmodatFlags, UtimensatFlags};
11-
use nix::sys::time::{TimeSpec, TimeValLike};
11+
use nix::sys::time::{TimeSpec, TimeVal, TimeValLike};
1212
use nix::unistd::chdir;
1313
use nix::Result;
1414
use tempfile;
@@ -168,6 +168,16 @@ fn assert_times_eq(exp_atime_sec: u64, exp_mtime_sec: u64, attr: &fs::Metadata)
168168
attr.modified().unwrap().duration_since(UNIX_EPOCH).unwrap());
169169
}
170170

171+
#[test]
172+
fn test_utimes() {
173+
let tempdir = tempfile::tempdir().unwrap();
174+
let fullpath = tempdir.path().join("file");
175+
drop(File::create(&fullpath).unwrap());
176+
177+
utimes(&fullpath, &TimeVal::seconds(9990), &TimeVal::seconds(5550));
178+
assert_times_eq(9990, 5550, &fs::metadata(&fullpath).unwrap());
179+
}
180+
171181
#[test]
172182
fn test_futimens() {
173183
let tempdir = tempfile::tempdir().unwrap();

0 commit comments

Comments
 (0)