#![crate_name = "nix"]
#![cfg(unix)]
#![allow(non_camel_case_types)]
#![allow(dead_code)]
#![cfg_attr(test, deny(warnings))]
#![recursion_limit = "500"]
#![deny(unused)]
#![deny(unstable_features)]
#![deny(missing_copy_implementations)]
#![deny(missing_debug_implementations)]
#[macro_use]
extern crate bitflags;
#[macro_use]
extern crate cfg_if;
extern crate void;
pub extern crate libc;
#[macro_use] mod macros;
pub mod dirent;
pub mod errno;
#[deny(missing_docs)]
pub mod features;
pub mod fcntl;
#[deny(missing_docs)]
#[cfg(any(target_os = "dragonfly",
target_os = "freebsd",
target_os = "ios",
target_os = "linux",
target_os = "macos",
target_os = "netbsd",
target_os = "openbsd"))]
pub mod ifaddrs;
#[cfg(any(target_os = "linux", target_os = "android"))]
pub mod mount;
#[cfg(any(target_os = "dragonfly",
target_os = "freebsd",
target_os = "fushsia",
target_os = "linux",
target_os = "netbsd"))]
pub mod mqueue;
#[deny(missing_docs)]
pub mod net;
#[deny(missing_docs)]
pub mod poll;
#[deny(missing_docs)]
pub mod pty;
#[cfg(any(target_os = "linux", target_os = "android"))]
pub mod sched;
pub mod sys;
#[cfg(all(target_os = "linux",
any(target_arch = "x86", target_arch = "x86_64")))]
pub mod ucontext;
pub mod unistd;
use libc::{c_char, PATH_MAX};
use std::{error, fmt, ptr, result};
use std::ffi::{CStr, OsStr};
use std::os::unix::ffi::OsStrExt;
use std::path::{Path, PathBuf};
use errno::Errno;
pub type Result<T> = result::Result<T, Error>;
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Error {
Sys(Errno),
InvalidPath,
InvalidUtf8,
UnsupportedOperation,
}
impl Error {
pub fn from_errno(errno: Errno) -> Error {
Error::Sys(errno)
}
pub fn last() -> Error {
Error::Sys(Errno::last())
}
pub fn invalid_argument() -> Error {
Error::Sys(Errno::EINVAL)
}
}
impl From<Errno> for Error {
fn from(errno: Errno) -> Error { Error::from_errno(errno) }
}
impl From<std::string::FromUtf8Error> for Error {
fn from(_: std::string::FromUtf8Error) -> Error { Error::InvalidUtf8 }
}
impl error::Error for Error {
fn description(&self) -> &str {
match *self {
Error::InvalidPath => "Invalid path",
Error::InvalidUtf8 => "Invalid UTF-8 string",
Error::UnsupportedOperation => "Unsupported Operation",
Error::Sys(ref errno) => errno.desc(),
}
}
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Error::InvalidPath => write!(f, "Invalid path"),
Error::InvalidUtf8 => write!(f, "Invalid UTF-8 string"),
Error::UnsupportedOperation => write!(f, "Unsupported Operation"),
Error::Sys(errno) => write!(f, "{:?}: {}", errno, errno.desc()),
}
}
}
pub trait NixPath {
fn len(&self) -> usize;
fn with_nix_path<T, F>(&self, f: F) -> Result<T>
where F: FnOnce(&CStr) -> T;
}
impl NixPath for str {
fn len(&self) -> usize {
NixPath::len(OsStr::new(self))
}
fn with_nix_path<T, F>(&self, f: F) -> Result<T>
where F: FnOnce(&CStr) -> T {
OsStr::new(self).with_nix_path(f)
}
}
impl NixPath for OsStr {
fn len(&self) -> usize {
self.as_bytes().len()
}
fn with_nix_path<T, F>(&self, f: F) -> Result<T>
where F: FnOnce(&CStr) -> T {
self.as_bytes().with_nix_path(f)
}
}
impl NixPath for CStr {
fn len(&self) -> usize {
self.to_bytes().len()
}
fn with_nix_path<T, F>(&self, f: F) -> Result<T>
where F: FnOnce(&CStr) -> T {
if self.len() >= PATH_MAX as usize {
return Err(Error::InvalidPath);
}
Ok(f(self))
}
}
impl NixPath for [u8] {
fn len(&self) -> usize {
self.len()
}
fn with_nix_path<T, F>(&self, f: F) -> Result<T>
where F: FnOnce(&CStr) -> T {
let mut buf = [0u8; PATH_MAX as usize];
if self.len() >= PATH_MAX as usize {
return Err(Error::InvalidPath);
}
match self.iter().position(|b| *b == 0) {
Some(_) => Err(Error::InvalidPath),
None => {
unsafe {
ptr::copy_nonoverlapping(self.as_ptr(), buf.as_mut_ptr(), self.len());
Ok(f(CStr::from_ptr(buf.as_ptr() as *const c_char)))
}
}
}
}
}
impl NixPath for Path {
fn len(&self) -> usize {
NixPath::len(self.as_os_str())
}
fn with_nix_path<T, F>(&self, f: F) -> Result<T> where F: FnOnce(&CStr) -> T {
self.as_os_str().with_nix_path(f)
}
}
impl NixPath for PathBuf {
fn len(&self) -> usize {
NixPath::len(self.as_os_str())
}
fn with_nix_path<T, F>(&self, f: F) -> Result<T> where F: FnOnce(&CStr) -> T {
self.as_os_str().with_nix_path(f)
}
}
impl<'a, NP: ?Sized + NixPath> NixPath for Option<&'a NP> {
fn len(&self) -> usize {
self.map_or(0, NixPath::len)
}
fn with_nix_path<T, F>(&self, f: F) -> Result<T> where F: FnOnce(&CStr) -> T {
if let Some(nix_path) = *self {
nix_path.with_nix_path(f)
} else {
unsafe { CStr::from_ptr("\0".as_ptr() as *const _).with_nix_path(f) }
}
}
}