|
1 | 1 | //! Safe wrappers around functions found in libc "unistd.h" header
|
2 | 2 |
|
3 | 3 | use {Errno, Error, Result, NixPath};
|
4 |
| -use fcntl::{fcntl, OFlag, O_CLOEXEC, FD_CLOEXEC}; |
| 4 | +use fcntl::{fcntl, OFlag, AtFlags, O_CLOEXEC, FD_CLOEXEC}; |
5 | 5 | use fcntl::FcntlArg::F_SETFD;
|
6 | 6 | use libc::{self, c_char, c_void, c_int, c_uint, size_t, pid_t, off_t, uid_t, gid_t, mode_t};
|
7 | 7 | use std::mem;
|
8 | 8 | use std::ffi::{CString, CStr, OsString, OsStr};
|
9 | 9 | use std::os::unix::ffi::{OsStringExt, OsStrExt};
|
10 | 10 | use std::os::unix::io::RawFd;
|
11 |
| -use std::path::{PathBuf}; |
| 11 | +use std::path::PathBuf; |
12 | 12 | use void::Void;
|
13 | 13 | use sys::stat::Mode;
|
14 | 14 |
|
@@ -819,6 +819,64 @@ pub fn mkstemp<P: ?Sized + NixPath>(template: &P) -> Result<(RawFd, PathBuf)> {
|
819 | 819 | Ok((fd, PathBuf::from(pathname)))
|
820 | 820 | }
|
821 | 821 |
|
| 822 | +libc_bitflags!{ |
| 823 | + pub flags AccessFlags: c_int { |
| 824 | + R_OK, |
| 825 | + W_OK, |
| 826 | + X_OK, |
| 827 | + } |
| 828 | +} |
| 829 | + |
| 830 | +pub enum AccessMode { |
| 831 | + F_OK, |
| 832 | + Flags(AccessFlags), |
| 833 | +} |
| 834 | + |
| 835 | +impl AccessMode { |
| 836 | + fn to_libc_type(&self) -> c_int { |
| 837 | + match self { |
| 838 | + &AccessMode::F_OK => libc::F_OK, |
| 839 | + &AccessMode::Flags(flags) => flags.bits(), |
| 840 | + } |
| 841 | + } |
| 842 | +} |
| 843 | + |
| 844 | +/// Check whether a file exists or whether the current process can access a file. |
| 845 | +/// |
| 846 | +/// # Example |
| 847 | +/// ``` |
| 848 | +/// use nix::unistd::*; |
| 849 | +/// |
| 850 | +/// let devnull_exists = access("/dev/null", AccessMode::F_OK); |
| 851 | +/// assert!(devnull_exists.is_ok()); |
| 852 | +/// ``` |
| 853 | +pub fn access<P: ?Sized + NixPath>(path: &P, mode: AccessMode) -> Result<()> { |
| 854 | + let res = try!(path.with_nix_path(|path| |
| 855 | + unsafe { |
| 856 | + libc::access(path.as_ptr(), mode.to_libc_type()) |
| 857 | + } |
| 858 | + )); |
| 859 | + Errno::result(res).map(drop) |
| 860 | +} |
| 861 | + |
| 862 | +/// Check whether a file exists or whether the current process can access a file, |
| 863 | +/// relative to a directory file descriptor. |
| 864 | +pub fn faccessat<P: ?Sized + NixPath>(dirfd: RawFd, |
| 865 | + path: &P, |
| 866 | + mode: AccessMode, |
| 867 | + flags: AtFlags) |
| 868 | + -> Result<()> { |
| 869 | + let res = try!(path.with_nix_path(|path| |
| 870 | + unsafe { |
| 871 | + libc::faccessat(dirfd, |
| 872 | + path.as_ptr(), |
| 873 | + mode.to_libc_type(), |
| 874 | + flags.bits()) |
| 875 | + } |
| 876 | + )); |
| 877 | + Errno::result(res).map(drop) |
| 878 | +} |
| 879 | + |
822 | 880 | #[cfg(any(target_os = "linux", target_os = "android"))]
|
823 | 881 | mod linux {
|
824 | 882 | use libc::{self, uid_t, gid_t};
|
|
0 commit comments