Skip to content

Commit 1c84ae3

Browse files
committed
add support for futimens/utimensat
1 parent ad170f9 commit 1c84ae3

File tree

3 files changed

+90
-1
lines changed

3 files changed

+90
-1
lines changed

CHANGELOG.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
7474
([#582](https://github.com/nix-rust/nix/pull/582)
7575
- Added `nix::unistd::{openat, fstatat, readlink, readlinkat, rename, renameat, mknodat, unlinkat, mkdirat, link, linkat, symlink, symlinkat, access, faccessat}`
7676
([#552](https://github.com/nix-rust/nix/pull/552), [#561](https://github.com/nix-rust/nix/pull/561))
77-
- Added `nix::stat::{chmod, fchmod, fchmodat}` ([#561](https://github.com/nix-rust/nix/pull/561))
77+
- Added `nix::stat::{chmod, fchmod, fchmodat, futimens, utimensat}` ([#561](https://github.com/nix-rust/nix/pull/561))
7878
- Added `nix::unistd::{chown, lchown, fchown, fchownat}` ([#561](https://github.com/nix-rust/nix/pull/561))
7979
- Added `nix::pty::{grantpt, posix_openpt, ptsname/ptsname_r, unlockpt}`
8080
([#556](https://github.com/nix-rust/nix/pull/556)

src/sys/stat.rs

+72
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ use libc::{self, mode_t};
77
use std::mem;
88
use std::os::unix::io::RawFd;
99

10+
pub use self::linux::*;
11+
1012
libc_bitflags!(
1113
pub struct SFlag: mode_t {
1214
S_IFIFO;
@@ -166,3 +168,73 @@ pub fn fchmodat<P: ?Sized + NixPath>(dirfd: RawFd, pathname: &P, mode: Mode, fla
166168

167169
Errno::result(res).map(drop)
168170
}
171+
172+
#[cfg(target_os = "linux")]
173+
mod linux {
174+
use {Errno, Result, NixPath};
175+
use std::os::unix::io::RawFd;
176+
use libc;
177+
use fcntl::AtFlags;
178+
use sys::time::TimeSpec;
179+
180+
/// A file timestamp.
181+
pub enum UtimeSpec {
182+
/// File timestamp is set to the current time.
183+
Now,
184+
/// The corresponding file timestamp is left unchanged.
185+
Omit,
186+
/// File timestamp is set to value
187+
Time(TimeSpec)
188+
}
189+
190+
impl <'a> From<&'a UtimeSpec> for libc::timespec {
191+
fn from(time: &'a UtimeSpec) -> libc::timespec {
192+
match time {
193+
&UtimeSpec::Now => libc::timespec {
194+
tv_sec: 0,
195+
tv_nsec: libc::UTIME_NOW,
196+
},
197+
&UtimeSpec::Omit => libc::timespec {
198+
tv_sec: 0,
199+
tv_nsec: libc::UTIME_OMIT,
200+
},
201+
&UtimeSpec::Time(spec) => *spec.as_ref()
202+
}
203+
}
204+
}
205+
206+
/// Change file timestamps with nanosecond precision
207+
/// (see [utimensat(2)](http://man7.org/linux/man-pages/man2/utimensat.2.html)).
208+
pub fn utimensat<P: ?Sized + NixPath>(dirfd: RawFd,
209+
pathname: &P,
210+
atime: &UtimeSpec,
211+
mtime: &UtimeSpec,
212+
flags: AtFlags) -> Result<()> {
213+
let time = [atime.into(), mtime.into()];
214+
let res = try!(pathname.with_nix_path(|cstr| {
215+
unsafe {
216+
libc::utimensat(dirfd,
217+
cstr.as_ptr(),
218+
time.as_ptr() as *const libc::timespec,
219+
flags.bits())
220+
}
221+
}));
222+
223+
Errno::result(res).map(drop)
224+
}
225+
226+
/// Change file timestamps with nanosecond precision
227+
/// (see [futimens(2)](http://man7.org/linux/man-pages/man2/futimens.2.html)).
228+
pub fn futimens(fd: RawFd,
229+
atime: &UtimeSpec,
230+
mtime: &UtimeSpec) -> Result<()> {
231+
let time = [atime.into(), mtime.into()];
232+
let res = unsafe {
233+
libc::futimens(fd, time.as_ptr() as *const libc::timespec)
234+
};
235+
236+
Errno::result(res).map(drop)
237+
}
238+
}
239+
#[cfg(not(target_os = "linux"))]
240+
mod linux { }

test/test_stat.rs

+17
Original file line numberDiff line numberDiff line change
@@ -137,3 +137,20 @@ fn test_chmod() {
137137
fcntl::AtFlags::empty()).unwrap();
138138
assert_mode(&tempfile, 0o600);
139139
}
140+
141+
#[test]
142+
#[cfg(target_os = "linux")]
143+
fn test_utime() {
144+
use std::time::UNIX_EPOCH;
145+
use nix::sys::time::{TimeSpec, TimeValLike};
146+
147+
let tempfile = NamedTempFile::new().unwrap();
148+
utimensat(0, // is ignored, if pathname is absolute path
149+
tempfile.path(),
150+
&UtimeSpec::Time(TimeSpec::zero()),
151+
&UtimeSpec::Time(TimeSpec::zero()),
152+
fcntl::AtFlags::empty()).unwrap();
153+
let mtime = tempfile.metadata().unwrap().modified().unwrap();
154+
155+
assert_eq!(mtime, UNIX_EPOCH);
156+
}

0 commit comments

Comments
 (0)