Skip to content

Commit

Permalink
NixPath -> NixString and Error -> Errno
Browse files Browse the repository at this point in the history
  • Loading branch information
arcnmx committed Jan 28, 2016
1 parent 745c791 commit 1da348c
Show file tree
Hide file tree
Showing 25 changed files with 335 additions and 428 deletions.
80 changes: 80 additions & 0 deletions src/cstr.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
use std::ffi::{OsStr, OsString, CString, NulError};
use std::path::{Path, PathBuf};
use std::os::unix::ffi::{OsStrExt, OsStringExt};

pub trait ToCString {
fn to_cstring(&self) -> Result<CString, NulError>;
fn into_cstring(self) -> Result<CString, NulError> where Self: Sized { unimplemented!() }
}

impl ToCString for [u8] {
fn to_cstring(&self) -> Result<CString, NulError> {
CString::new(self)
}
}

impl ToCString for Vec<u8> {
fn to_cstring(&self) -> Result<CString, NulError> {
ToCString::to_cstring(&**self)
}

fn into_cstring(self) -> Result<CString, NulError> {
CString::new(self)
}
}

impl ToCString for str {
fn to_cstring(&self) -> Result<CString, NulError> {
CString::new(self.as_bytes())
}
}

impl ToCString for String {
fn to_cstring(&self) -> Result<CString, NulError> {
ToCString::to_cstring(&**self)
}

fn into_cstring(self) -> Result<CString, NulError> {
CString::new(self.into_bytes())
}
}

impl ToCString for OsStr {
fn to_cstring(&self) -> Result<CString, NulError> {
CString::new(self.as_bytes())
}
}

impl ToCString for OsString {
fn to_cstring(&self) -> Result<CString, NulError> {
ToCString::to_cstring(&**self)
}

fn into_cstring(self) -> Result<CString, NulError> {
CString::new(self.into_vec())
}
}

impl ToCString for Path {
fn to_cstring(&self) -> Result<CString, NulError> {
ToCString::to_cstring(self.as_os_str())
}
}

impl ToCString for PathBuf {
fn to_cstring(&self) -> Result<CString, NulError> {
ToCString::to_cstring(self.as_os_str())
}

fn into_cstring(self) -> Result<CString, NulError> {
ToCString::into_cstring(self.into_os_string())
}
}

// TODO: allow this in consts/statics
#[macro_export]
macro_rules! cstr {
($s:expr) => {
unsafe { ::std::ffi::CStr::from_ptr(concat!($s, "\0").as_ptr() as *const _) }
}
}
7 changes: 4 additions & 3 deletions src/errno.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use libc::c_int;
use std::{fmt, io, error};
use {Error, Result};
use std::{fmt, io, error, result};

pub use self::consts::*;
pub use self::consts::Errno::*;
Expand Down Expand Up @@ -74,7 +73,7 @@ impl Errno {
/// should not be used when `-1` is not the errno sentinel value.
pub fn result<S: ErrnoSentinel + PartialEq<S>>(value: S) -> Result<S> {
if value == S::sentinel() {
Err(Error::Sys(Self::last()))
Err(Self::last())
} else {
Ok(value)
}
Expand Down Expand Up @@ -117,6 +116,8 @@ impl From<Errno> for io::Error {
}
}

pub type Result<T> = result::Result<T, Errno>;

fn last() -> Errno {
Errno::from_i32(errno())
}
Expand Down
10 changes: 5 additions & 5 deletions src/fcntl.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use {Errno, Result, NixPath};
use {Errno, Result, NixString};
use libc::{c_int, c_uint};
use sys::stat::Mode;
use std::os::unix::io::RawFd;
Expand Down Expand Up @@ -96,10 +96,10 @@ mod ffi {
}
}

pub fn open<P: ?Sized + NixPath>(path: &P, oflag: OFlag, mode: Mode) -> Result<RawFd> {
let fd = try!(path.with_nix_path(|cstr| {
unsafe { ffi::open(cstr.as_ptr(), oflag.bits(), mode.bits() as c_uint) }
}));
pub fn open<P: NixString>(path: P, oflag: OFlag, mode: Mode) -> Result<RawFd> {
let fd = unsafe {
ffi::open(path.as_ref().as_ptr(), oflag.bits(), mode.bits() as c_uint)
};

Errno::result(fd)
}
Expand Down
191 changes: 7 additions & 184 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,13 @@ extern crate nix_test as nixtest;

// Re-exports
pub use libc::{c_int, c_void};
pub use errno::Errno;
pub use errno::{Errno, Result};
pub use nix_string::NixString;

mod nix_string;

#[macro_use]
pub mod cstr;

pub mod errno;
pub mod features;
Expand All @@ -42,186 +48,3 @@ pub mod sched;

pub mod sys;
pub mod unistd;

/*
*
* ===== Result / Error =====
*
*/

use libc::c_char;
use std::{ptr, result};
use std::ffi::{CStr, OsStr};
use std::path::{Path, PathBuf};
use std::os::unix::ffi::OsStrExt;
use std::io;
use std::fmt;
use std::error;
use libc::PATH_MAX;

pub type Result<T> = result::Result<T, Error>;

#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Error {
Sys(errno::Errno),
InvalidPath,
}

impl Error {
pub fn from_errno(errno: errno::Errno) -> Error {
Error::Sys(errno)
}

pub fn last() -> Error {
Error::Sys(errno::Errno::last())
}

pub fn invalid_argument() -> Error {
Error::Sys(errno::EINVAL)
}

pub fn errno(&self) -> errno::Errno {
match *self {
Error::Sys(errno) => errno,
Error::InvalidPath => errno::Errno::EINVAL,
}
}
}

impl From<errno::Errno> for Error {
fn from(errno: errno::Errno) -> Error { Error::from_errno(errno) }
}

impl error::Error for Error {
fn description(&self) -> &str {
match self {
&Error::InvalidPath => "Invalid path",
&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::Sys(errno) => write!(f, "{:?}: {}", errno, errno.desc()),
}
}
}

impl From<Error> for io::Error {
fn from(err: Error) -> Self {
match err {
Error::InvalidPath => io::Error::new(io::ErrorKind::InvalidInput, err),
Error::Sys(errno) => io::Error::from_raw_os_error(errno as i32),
}
}
}

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 {
// Equivalence with the [u8] impl.
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 {
// TODO: Replace with bytes::copy_memory. rust-lang/rust#24028
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)
}
}

/// Treats `None` as an empty string.
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) }
}
}
}
Loading

0 comments on commit 1da348c

Please sign in to comment.