Skip to content

Commit f8c79c6

Browse files
zmlccnateavers
authored andcommitted
add faccessat
1 parent 67329c5 commit f8c79c6

File tree

3 files changed

+91
-0
lines changed

3 files changed

+91
-0
lines changed

CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ This project adheres to [Semantic Versioning](https://semver.org/).
66
## [Unreleased] - ReleaseDate
77
### Added
88

9+
- Added `faccessat`
10+
([#1780](https://github.com/nix-rust/nix/pull/1780))
911
- Added `memfd` on Android.
1012
(#[1773](https://github.com/nix-rust/nix/pull/1773))
1113
- Added ETH_P_ALL to SockProtocol enum

src/unistd.rs

+21
Original file line numberDiff line numberDiff line change
@@ -2900,6 +2900,27 @@ pub fn access<P: ?Sized + NixPath>(path: &P, amode: AccessFlags) -> Result<()> {
29002900
})?;
29012901
Errno::result(res).map(drop)
29022902
}
2903+
2904+
/// Checks the file named by `path` for accessibility according to the flags given by `mode`
2905+
///
2906+
/// If `dirfd` has a value, then `path` is relative to directory associated with the file descriptor.
2907+
///
2908+
/// If `dirfd` is `None`, then `path` is relative to the current working directory.
2909+
///
2910+
/// # References
2911+
///
2912+
/// [faccessat(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/faccessat.html)
2913+
// illumos: faccessat(2) appears to be supported, but the libc crate does not provide a binding.
2914+
// redox: does not appear to support the *at family of syscalls.
2915+
#[cfg(not(any(target_os = "illumos", target_os = "redox")))]
2916+
pub fn faccessat<P: ?Sized + NixPath>(dirfd: Option<RawFd>, path: &P, mode: AccessFlags, flags: AtFlags) -> Result<()> {
2917+
let res = path.with_nix_path(|cstr| {
2918+
unsafe {
2919+
libc::faccessat(at_rawfd(dirfd), cstr.as_ptr(), mode.bits(), flags.bits())
2920+
}
2921+
})?;
2922+
Errno::result(res).map(drop)
2923+
}
29032924
}
29042925

29052926
feature! {

test/test_unistd.rs

+68
Original file line numberDiff line numberDiff line change
@@ -1308,3 +1308,71 @@ fn test_getpeereid_invalid_fd() {
13081308
// getpeereid is not POSIX, so error codes are inconsistent between different Unices.
13091309
getpeereid(-1).expect_err("assertion failed");
13101310
}
1311+
1312+
#[test]
1313+
#[cfg(not(any(target_os = "illumos", target_os = "redox")))]
1314+
fn test_faccessat_none_not_existing() {
1315+
use nix::fcntl::AtFlags;
1316+
let tempdir = tempfile::tempdir().unwrap();
1317+
let dir = tempdir.path().join("does_not_exist.txt");
1318+
assert_eq!(
1319+
faccessat(None, &dir, AccessFlags::F_OK, AtFlags::empty())
1320+
.err()
1321+
.unwrap(),
1322+
Errno::ENOENT
1323+
);
1324+
}
1325+
1326+
#[test]
1327+
#[cfg(not(any(target_os = "illumos", target_os = "redox")))]
1328+
fn test_faccessat_not_existing() {
1329+
use nix::fcntl::AtFlags;
1330+
let tempdir = tempfile::tempdir().unwrap();
1331+
let dirfd = open(tempdir.path(), OFlag::empty(), Mode::empty()).unwrap();
1332+
let not_exist_file = "does_not_exist.txt";
1333+
assert_eq!(
1334+
faccessat(
1335+
Some(dirfd),
1336+
not_exist_file,
1337+
AccessFlags::F_OK,
1338+
AtFlags::empty()
1339+
)
1340+
.err()
1341+
.unwrap(),
1342+
Errno::ENOENT
1343+
);
1344+
}
1345+
1346+
#[test]
1347+
#[cfg(not(any(target_os = "illumos", target_os = "redox")))]
1348+
fn test_faccessat_none_file_exists() {
1349+
use nix::fcntl::AtFlags;
1350+
let tempdir = tempfile::tempdir().unwrap();
1351+
let path = tempdir.path().join("does_exist.txt");
1352+
let _file = File::create(path.clone()).unwrap();
1353+
assert!(faccessat(
1354+
None,
1355+
&path,
1356+
AccessFlags::R_OK | AccessFlags::W_OK,
1357+
AtFlags::empty()
1358+
)
1359+
.is_ok());
1360+
}
1361+
1362+
#[test]
1363+
#[cfg(not(any(target_os = "illumos", target_os = "redox")))]
1364+
fn test_faccessat_file_exists() {
1365+
use nix::fcntl::AtFlags;
1366+
let tempdir = tempfile::tempdir().unwrap();
1367+
let dirfd = open(tempdir.path(), OFlag::empty(), Mode::empty()).unwrap();
1368+
let exist_file = "does_exist.txt";
1369+
let path = tempdir.path().join(exist_file);
1370+
let _file = File::create(path.clone()).unwrap();
1371+
assert!(faccessat(
1372+
Some(dirfd),
1373+
&path,
1374+
AccessFlags::R_OK | AccessFlags::W_OK,
1375+
AtFlags::empty()
1376+
)
1377+
.is_ok());
1378+
}

0 commit comments

Comments
 (0)