Skip to content

Commit

Permalink
add support for futimens/utimensat
Browse files Browse the repository at this point in the history
  • Loading branch information
Mic92 committed Apr 5, 2017
1 parent de9b9c1 commit 6077eef
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 1 deletion.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
<!--### Added-->
- Added `nix::unistd::{openat, fstatat, readlink, readlinkat, rename, renameat, mknodat, unlinkat, mkdirat, link, linkat, symlink, symlinkat, access, faccessat}`
([#552](https://github.com/nix-rust/nix/pull/552), [#561](https://github.com/nix-rust/nix/pull/561))
- Added `nix::stat::{chmod, fchmod, fchmodat}` ([#561](https://github.com/nix-rust/nix/pull/561))
- Added `nix::stat::{chmod, fchmod, fchmodat, futimens, utimensat}` ([#561](https://github.com/nix-rust/nix/pull/561))
- Added `nix::unistd::{chown, lchown, fchown, fchownat}` ([#561](https://github.com/nix-rust/nix/pull/561))

### Changed
Expand Down
63 changes: 63 additions & 0 deletions src/sys/stat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ use libc::{self, mode_t};
use std::mem;
use std::os::unix::io::RawFd;

pub use self::linux::*;

mod ffi {
use libc::{c_char, c_int, mode_t, dev_t};
pub use libc::{stat, fstat, lstat};
Expand Down Expand Up @@ -53,6 +55,7 @@ bitflags! {
}
}


pub fn mknod<P: ?Sized + NixPath>(path: &P, kind: SFlag, perm: Mode, dev: dev_t) -> Result<()> {
let res = try!(path.with_nix_path(|cstr| {
unsafe {
Expand Down Expand Up @@ -171,3 +174,63 @@ pub fn fchmodat<P: ?Sized + NixPath>(dirfd: RawFd, pathname: &P, mode: Mode, fla

Errno::result(res).map(drop)
}

#[cfg(target_os = "linux")]
mod linux {
use {Errno, Result, NixPath};
use std::os::unix::io::RawFd;
use libc;
use fcntl::AtFlags;
use sys::time::TimeSpec;

pub enum UtimeSpec {
Now,
Omit,
Time(TimeSpec)
}

fn to_timespec(time: &UtimeSpec) -> libc::timespec {
match time {
&UtimeSpec::Now => libc::timespec {
tv_sec: 0,
tv_nsec: libc::UTIME_NOW,
},
&UtimeSpec::Omit => libc::timespec {
tv_sec: 0,
tv_nsec: libc::UTIME_OMIT,
},
&UtimeSpec::Time(spec) => *spec.as_ref()
}
}

pub fn utimensat<P: ?Sized + NixPath>(dirfd: RawFd,
pathname: &P,
atime: &UtimeSpec,
mtime: &UtimeSpec,
flags: AtFlags) -> Result<()> {
let time = [to_timespec(atime), to_timespec(mtime)];
let res = try!(pathname.with_nix_path(|cstr| {
unsafe {
libc::utimensat(dirfd,
cstr.as_ptr(),
time.as_ptr() as *const libc::timespec,
flags.bits())
}
}));

Errno::result(res).map(drop)
}

pub fn futimens(fd: RawFd,
atime: &UtimeSpec,
mtime: &UtimeSpec) -> Result<()> {
let time = [to_timespec(atime), to_timespec(mtime)];
let res = unsafe {
libc::futimens(fd, time.as_ptr() as *const libc::timespec)
};

Errno::result(res).map(drop)
}
}
#[cfg(not(target_os = "linux"))]
mod linux { }
17 changes: 17 additions & 0 deletions test/test_stat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,3 +137,20 @@ fn test_chmod() {
fcntl::AtFlags::empty()).unwrap();
assert_mode(&tempfile, 0o600);
}

#[test]
#[cfg(target_os = "linux")]
fn test_utime() {
use std::time::UNIX_EPOCH;
use nix::sys::time::{TimeSpec, TimeValLike};

let tempfile = NamedTempFile::new().unwrap();
utimensat(0, // is ignored, if pathname is absolute path
tempfile.path(),
&UtimeSpec::Time(TimeSpec::zero()),
&UtimeSpec::Time(TimeSpec::zero()),
fcntl::AtFlags::empty()).unwrap();
let mtime = tempfile.metadata().unwrap().modified().unwrap();

assert_eq!(mtime, UNIX_EPOCH);
}

0 comments on commit 6077eef

Please sign in to comment.