Skip to content

Commit a26a5a7

Browse files
committed
Add unistd::{access, faccessat}
1 parent ba5c837 commit a26a5a7

File tree

2 files changed

+77
-3
lines changed

2 files changed

+77
-3
lines changed

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,9 @@ This project adheres to [Semantic Versioning](http://semver.org/).
88
### Added
99
- Added `AioCb::from_boxed_slice`
1010
([#582](https://github.com/nix-rust/nix/pull/582)
11-
- Added `nix::unistd::{openat, fstatat, readlink, readlinkat}`
11+
- Added `nix::unistd::{openat, fstatat, readlink, readlinkat, access, faccessat}`
1212
([#551](https://github.com/nix-rust/nix/pull/551))
13+
([#605](https://github.com/nix-rust/nix/pull/605))
1314
- Added `nix::pty::{grantpt, posix_openpt, ptsname/ptsname_r, unlockpt}`
1415
([#556](https://github.com/nix-rust/nix/pull/556)
1516

src/unistd.rs

Lines changed: 75 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
//! Safe wrappers around functions found in libc "unistd.h" header
22
33
use {Errno, Error, Result, NixPath};
4-
use fcntl::{fcntl, OFlag, O_CLOEXEC, FD_CLOEXEC};
4+
use fcntl::{AtFlags, fcntl, OFlag, O_CLOEXEC, FD_CLOEXEC};
55
use fcntl::FcntlArg::F_SETFD;
66
use libc::{self, c_char, c_void, c_int, c_uint, size_t, pid_t, off_t, uid_t, gid_t, mode_t};
77
use std::mem;
88
use std::ffi::{CString, CStr, OsString, OsStr};
99
use std::os::unix::ffi::{OsStringExt, OsStrExt};
1010
use std::os::unix::io::RawFd;
11-
use std::path::{PathBuf};
11+
use std::path::PathBuf;
1212
use void::Void;
1313
use sys::stat::Mode;
1414

@@ -819,6 +819,79 @@ pub fn mkstemp<P: ?Sized + NixPath>(template: &P) -> Result<(RawFd, PathBuf)> {
819819
Ok((fd, PathBuf::from(pathname)))
820820
}
821821

822+
libc_bitflags!{
823+
/// Flags that determine what permissions to check for in [`access`](fn.access.html)
824+
/// and [`faccessat`](fn.faccessat.html) functions.
825+
pub flags AccessFlags: c_int {
826+
/// Read permission.
827+
R_OK,
828+
/// Write permission.
829+
W_OK,
830+
/// Execute permission.
831+
X_OK,
832+
}
833+
}
834+
835+
/// Whether [`access`](fn.access.html) and [`faccessat`](fn.faccessat.html) functions
836+
/// should check whether a file exists or whether the current process has the requested
837+
/// permissions to access it.
838+
pub enum AccessMode {
839+
/// Check whether the file exists.
840+
F_OK,
841+
/// Check whether the file exists and the current process has the requested
842+
/// permissions to access it.
843+
Flags(AccessFlags),
844+
}
845+
846+
impl AccessMode {
847+
/// Convert the `enum AccessMode` + `flags AccessFlags` combo to the plain
848+
/// `mode: c_int` syscalls expect.
849+
fn to_libc_type(&self) -> c_int {
850+
match self {
851+
&AccessMode::F_OK => libc::F_OK,
852+
&AccessMode::Flags(flags) => flags.bits(),
853+
}
854+
}
855+
}
856+
857+
/// Check whether a file exists or whether the current process can access a file ([see access(2)]
858+
/// (http://man7.org/linux/man-pages/man2/access.2.html)).
859+
///
860+
/// # Example
861+
/// ```
862+
/// use nix::unistd::*;
863+
///
864+
/// let devnull_exists = access("/dev/null", AccessMode::F_OK);
865+
/// assert!(devnull_exists.is_ok());
866+
/// ```
867+
pub fn access<P: ?Sized + NixPath>(path: &P, mode: AccessMode) -> Result<()> {
868+
let res = try!(path.with_nix_path(|path|
869+
unsafe {
870+
libc::access(path.as_ptr(), mode.to_libc_type())
871+
}
872+
));
873+
Errno::result(res).map(drop)
874+
}
875+
876+
/// Check whether a file exists or whether the current process can access a file,
877+
/// relative to a directory file descriptor ([see faccessat(2)]
878+
/// (http://man7.org/linux/man-pages/man2/faccessat.2.html)).
879+
pub fn faccessat<P: ?Sized + NixPath>(dirfd: RawFd,
880+
path: &P,
881+
mode: AccessMode,
882+
flags: AtFlags)
883+
-> Result<()> {
884+
let res = try!(path.with_nix_path(|path|
885+
unsafe {
886+
libc::faccessat(dirfd,
887+
path.as_ptr(),
888+
mode.to_libc_type(),
889+
flags.bits())
890+
}
891+
));
892+
Errno::result(res).map(drop)
893+
}
894+
822895
#[cfg(any(target_os = "linux", target_os = "android"))]
823896
mod linux {
824897
use libc::{self, uid_t, gid_t};

0 commit comments

Comments
 (0)