Skip to content

Commit

Permalink
Merge #1780
Browse files Browse the repository at this point in the history
1780: Implement faccessat r=asomers a=nateavers

This is a re-post of #1134, which seems to have been abandoned. Includes the changes requested in [this comment](#1134 (comment)).

Co-authored-by: Zhang Miaolei <zmlcc@outlook.com>
  • Loading branch information
bors[bot] and zmlcc committed Aug 6, 2022
2 parents 67329c5 + f8c79c6 commit a10078f
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 0 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Expand Up @@ -6,6 +6,8 @@ This project adheres to [Semantic Versioning](https://semver.org/).
## [Unreleased] - ReleaseDate
### Added

- Added `faccessat`
([#1780](https://github.com/nix-rust/nix/pull/1780))
- Added `memfd` on Android.
(#[1773](https://github.com/nix-rust/nix/pull/1773))
- Added ETH_P_ALL to SockProtocol enum
Expand Down
21 changes: 21 additions & 0 deletions src/unistd.rs
Expand Up @@ -2900,6 +2900,27 @@ pub fn access<P: ?Sized + NixPath>(path: &P, amode: AccessFlags) -> Result<()> {
})?;
Errno::result(res).map(drop)
}

/// Checks the file named by `path` for accessibility according to the flags given by `mode`
///
/// If `dirfd` has a value, then `path` is relative to directory associated with the file descriptor.
///
/// If `dirfd` is `None`, then `path` is relative to the current working directory.
///
/// # References
///
/// [faccessat(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/faccessat.html)
// illumos: faccessat(2) appears to be supported, but the libc crate does not provide a binding.
// redox: does not appear to support the *at family of syscalls.
#[cfg(not(any(target_os = "illumos", target_os = "redox")))]
pub fn faccessat<P: ?Sized + NixPath>(dirfd: Option<RawFd>, path: &P, mode: AccessFlags, flags: AtFlags) -> Result<()> {
let res = path.with_nix_path(|cstr| {
unsafe {
libc::faccessat(at_rawfd(dirfd), cstr.as_ptr(), mode.bits(), flags.bits())
}
})?;
Errno::result(res).map(drop)
}
}

feature! {
Expand Down
68 changes: 68 additions & 0 deletions test/test_unistd.rs
Expand Up @@ -1308,3 +1308,71 @@ fn test_getpeereid_invalid_fd() {
// getpeereid is not POSIX, so error codes are inconsistent between different Unices.
getpeereid(-1).expect_err("assertion failed");
}

#[test]
#[cfg(not(any(target_os = "illumos", target_os = "redox")))]
fn test_faccessat_none_not_existing() {
use nix::fcntl::AtFlags;
let tempdir = tempfile::tempdir().unwrap();
let dir = tempdir.path().join("does_not_exist.txt");
assert_eq!(
faccessat(None, &dir, AccessFlags::F_OK, AtFlags::empty())
.err()
.unwrap(),
Errno::ENOENT
);
}

#[test]
#[cfg(not(any(target_os = "illumos", target_os = "redox")))]
fn test_faccessat_not_existing() {
use nix::fcntl::AtFlags;
let tempdir = tempfile::tempdir().unwrap();
let dirfd = open(tempdir.path(), OFlag::empty(), Mode::empty()).unwrap();
let not_exist_file = "does_not_exist.txt";
assert_eq!(
faccessat(
Some(dirfd),
not_exist_file,
AccessFlags::F_OK,
AtFlags::empty()
)
.err()
.unwrap(),
Errno::ENOENT
);
}

#[test]
#[cfg(not(any(target_os = "illumos", target_os = "redox")))]
fn test_faccessat_none_file_exists() {
use nix::fcntl::AtFlags;
let tempdir = tempfile::tempdir().unwrap();
let path = tempdir.path().join("does_exist.txt");
let _file = File::create(path.clone()).unwrap();
assert!(faccessat(
None,
&path,
AccessFlags::R_OK | AccessFlags::W_OK,
AtFlags::empty()
)
.is_ok());
}

#[test]
#[cfg(not(any(target_os = "illumos", target_os = "redox")))]
fn test_faccessat_file_exists() {
use nix::fcntl::AtFlags;
let tempdir = tempfile::tempdir().unwrap();
let dirfd = open(tempdir.path(), OFlag::empty(), Mode::empty()).unwrap();
let exist_file = "does_exist.txt";
let path = tempdir.path().join(exist_file);
let _file = File::create(path.clone()).unwrap();
assert!(faccessat(
Some(dirfd),
&path,
AccessFlags::R_OK | AccessFlags::W_OK,
AtFlags::empty()
)
.is_ok());
}

0 comments on commit a10078f

Please sign in to comment.