Skip to content

Commit 02e9d39

Browse files
committed
add support for fstatat
1 parent 1fbf1fe commit 02e9d39

File tree

2 files changed

+80
-3
lines changed

2 files changed

+80
-3
lines changed

src/sys/stat.rs

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@ pub use libc::dev_t;
22
pub use libc::stat as FileStat;
33

44
use {Errno, Result, NixPath};
5-
use libc::{self, mode_t};
5+
use libc::{self, c_int, mode_t};
66
use std::mem;
77
use std::os::unix::io::RawFd;
88

9+
pub use self::consts::*;
10+
911
mod ffi {
1012
use libc::{c_char, c_int, mode_t, dev_t};
1113
pub use libc::{stat, fstat, lstat};
@@ -109,3 +111,62 @@ pub fn fstat(fd: RawFd) -> Result<FileStat> {
109111

110112
Ok(dst)
111113
}
114+
115+
#[cfg(any(target_os = "linux", target_os = "android"))]
116+
mod consts {
117+
use libc::c_int;
118+
119+
bitflags!(
120+
flags FstatatFlag: c_int {
121+
const AT_SYMLINK_NOFOLLOW = 0o000400,
122+
const AT_NO_AUTOMOUNT = 0o004000,
123+
const AT_EMPTY_PATH = 0o010000,
124+
}
125+
);
126+
}
127+
128+
#[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
129+
mod consts {
130+
use libc::c_int;
131+
132+
bitflags!(
133+
flags FstatatFlag: c_int {
134+
const AT_SYMLINK_NOFOLLOW = 0o1,
135+
}
136+
);
137+
}
138+
139+
#[cfg(target_os = "openbsd")]
140+
mod consts {
141+
use libc::c_int;
142+
143+
bitflags!(
144+
flags FstatatFlag: c_int {
145+
const AT_SYMLINK_NOFOLLOW = 0o02,
146+
}
147+
);
148+
}
149+
150+
#[cfg(target_os = "netbsd")]
151+
mod consts {
152+
use libc::c_int;
153+
154+
bitflags!(
155+
flags FstatatFlag: c_int {
156+
const AT_SYMLINK_NOFOLLOW = 0o1000,
157+
}
158+
);
159+
}
160+
161+
#[cfg(any(target_os = "linux", target_os = "android", target_os = "freebsd", target_os = "dragonfly", target_os = "netbsd"))]
162+
pub fn fstatat<P: ?Sized + NixPath>(dirfd: RawFd, pathname: &P, f: FstatatFlag) -> Result<FileStat> {
163+
let mut dst = unsafe { mem::uninitialized() };
164+
let res = try!(pathname.with_nix_path(|cstr| {
165+
unsafe { libc::fstatat(dirfd, cstr.as_ptr(), &mut dst as *mut FileStat, f.bits() as c_int) }
166+
}));
167+
168+
try!(Errno::result(res));
169+
170+
Ok(dst)
171+
}
172+

test/test_stat.rs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ use std::os::unix::prelude::AsRawFd;
44

55
use libc::{S_IFMT, S_IFLNK};
66

7-
use nix::sys::stat::{stat, fstat, lstat};
8-
7+
use nix::fcntl;
8+
use nix::sys::stat::{self, stat, fstat, lstat};
99
use nix::sys::stat::FileStat;
1010
use nix::Result;
1111
use tempdir::TempDir;
@@ -74,6 +74,22 @@ fn test_stat_and_fstat() {
7474
assert_stat_results(fstat_result);
7575
}
7676

77+
#[cfg(any(target_os = "linux", target_os = "android", target_os = "freebsd", target_os = "dragonfly", target_os = "netbsd"))]
78+
#[test]
79+
fn test_fstatat() {
80+
let tempdir = TempDir::new("nix-test_stat_and_fstat").unwrap();
81+
let filename = tempdir.path().join("foo.txt");
82+
File::create(&filename).unwrap();
83+
let dirfd = fcntl::open(tempdir.path(),
84+
fcntl::O_PATH,
85+
stat::Mode::empty());
86+
87+
let result = stat::fstatat(dirfd.unwrap(),
88+
&filename,
89+
stat::FstatatFlag::empty());
90+
assert_stat_results(result);
91+
}
92+
7793
#[test]
7894
fn test_stat_fstat_lstat() {
7995
let tempdir = TempDir::new("nix-test_stat_fstat_lstat").unwrap();

0 commit comments

Comments
 (0)