From 78d7aea35ef838a88d85a79a0acf36c5506d76ed Mon Sep 17 00:00:00 2001 From: jr Date: Fri, 19 Apr 2019 23:52:59 +0200 Subject: [PATCH] Add a access(2) wrapper --- CHANGELOG.md | 2 ++ src/unistd.rs | 25 +++++++++++++++++++++++++ test/test_unistd.rs | 17 +++++++++++++++++ 3 files changed, 44 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b09bc70967..c52fd5271c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,8 @@ This project adheres to [Semantic Versioning](http://semver.org/). - Added `nix::unistd:seteuid` and `nix::unistd::setegid` for those platforms that do not support `setresuid` nor `setresgid` respectively. ([#1044](https://github.com/nix-rust/nix/pull/1044)) +- Added a `access` wrapper + ([#1045](https://github.com/nix-rust/nix/pull/1045)) ### Changed - `PollFd` event flags renamed to `PollFlags` ([#1024](https://github.com/nix-rust/nix/pull/1024/)) diff --git a/src/unistd.rs b/src/unistd.rs index c3b2b61ef5..f855c0af84 100644 --- a/src/unistd.rs +++ b/src/unistd.rs @@ -2334,3 +2334,28 @@ mod setres { Errno::result(res).map(drop) } } + +libc_bitflags!{ + /// Options for access() + pub struct AccessFlags : c_int { + /// Test for existence of file. + F_OK; + /// Test for read permission. + R_OK; + /// Test for write permission. + W_OK; + /// Test for execute (search) permission. + X_OK; + } +} + +/// Checks the file named by `path` for accessibility according to the flags given by `amode` +/// See [access(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/access.html) +pub fn access(path: &P, amode: AccessFlags) -> Result<()> { + let res = path.with_nix_path(|cstr| { + unsafe { + libc::access(cstr.as_ptr(), amode.bits) + } + })?; + Errno::result(res).map(drop) +} diff --git a/test/test_unistd.rs b/test/test_unistd.rs index 3fb5053512..3f13883c7e 100644 --- a/test/test_unistd.rs +++ b/test/test_unistd.rs @@ -4,6 +4,7 @@ use nix::unistd::ForkResult::*; use nix::sys::signal::{SaFlags, SigAction, SigHandler, SigSet, Signal, sigaction}; use nix::sys::wait::*; use nix::sys::stat::{self, Mode, SFlag}; +use nix::errno::Errno; use std::{env, iter}; use std::ffi::CString; use std::fs::{self, File}; @@ -574,3 +575,19 @@ fn test_symlinkat() { target ); } + +#[test] +fn test_access_not_existing() { + let tempdir = tempfile::tempdir().unwrap(); + let dir = tempdir.path().join("does_not_exist.txt"); + assert_eq!(access(&dir, AccessFlags::F_OK).err().unwrap().as_errno().unwrap(), + Errno::ENOENT); +} + +#[test] +fn test_access_file_exists() { + let tempdir = tempfile::tempdir().unwrap(); + let path = tempdir.path().join("does_exist.txt"); + let _file = File::create(path.clone()).unwrap(); + assert!(access(&path, AccessFlags::R_OK | AccessFlags::W_OK).is_ok()); +}