Skip to content

Commit bb8b80c

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

File tree

3 files changed

+87
-0
lines changed

3 files changed

+87
-0
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
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

Lines changed: 21 additions & 0 deletions
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

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1308,3 +1308,67 @@ 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+
fn test_faccessat_none_not_existing() {
1314+
use nix::fcntl::AtFlags;
1315+
let tempdir = tempfile::tempdir().unwrap();
1316+
let dir = tempdir.path().join("does_not_exist.txt");
1317+
assert_eq!(
1318+
faccessat(None, &dir, AccessFlags::F_OK, AtFlags::empty())
1319+
.err()
1320+
.unwrap(),
1321+
Errno::ENOENT
1322+
);
1323+
}
1324+
1325+
#[test]
1326+
fn test_faccessat_not_existing() {
1327+
use nix::fcntl::AtFlags;
1328+
let tempdir = tempfile::tempdir().unwrap();
1329+
let dirfd = open(tempdir.path(), OFlag::empty(), Mode::empty()).unwrap();
1330+
let not_exist_file = "does_not_exist.txt";
1331+
assert_eq!(
1332+
faccessat(
1333+
Some(dirfd),
1334+
not_exist_file,
1335+
AccessFlags::F_OK,
1336+
AtFlags::empty()
1337+
)
1338+
.err()
1339+
.unwrap(),
1340+
Errno::ENOENT
1341+
);
1342+
}
1343+
1344+
#[test]
1345+
fn test_faccessat_none_file_exists() {
1346+
use nix::fcntl::AtFlags;
1347+
let tempdir = tempfile::tempdir().unwrap();
1348+
let path = tempdir.path().join("does_exist.txt");
1349+
let _file = File::create(path.clone()).unwrap();
1350+
assert!(faccessat(
1351+
None,
1352+
&path,
1353+
AccessFlags::R_OK | AccessFlags::W_OK,
1354+
AtFlags::empty()
1355+
)
1356+
.is_ok());
1357+
}
1358+
1359+
#[test]
1360+
fn test_faccessat_file_exists() {
1361+
use nix::fcntl::AtFlags;
1362+
let tempdir = tempfile::tempdir().unwrap();
1363+
let dirfd = open(tempdir.path(), OFlag::empty(), Mode::empty()).unwrap();
1364+
let exist_file = "does_exist.txt";
1365+
let path = tempdir.path().join(exist_file);
1366+
let _file = File::create(path.clone()).unwrap();
1367+
assert!(faccessat(
1368+
Some(dirfd),
1369+
&path,
1370+
AccessFlags::R_OK | AccessFlags::W_OK,
1371+
AtFlags::empty()
1372+
)
1373+
.is_ok());
1374+
}

0 commit comments

Comments
 (0)