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 26, 2016
1 parent cca8a04 commit c437533
Show file tree
Hide file tree
Showing 19 changed files with 194 additions and 333 deletions.
5 changes: 2 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, result};
use Error;

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,7 +116,7 @@ impl From<Errno> for io::Error {
}
}

pub type Result<T> = result::Result<T, 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 NixPath;
use NixString;
use errno::{Errno, Result};
use libc::{c_int, c_uint};
use sys::stat::Mode;
Expand Down Expand Up @@ -97,10 +97,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
148 changes: 4 additions & 144 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ extern crate nix_test as nixtest;
// Re-exports
pub use libc::{c_int, c_void};
pub use errno::{Errno, Result};
pub use nix_string::NixString;

#[macro_use]
mod nix_string;

pub mod errno;
pub mod features;
Expand All @@ -40,147 +44,3 @@ pub mod sched;

pub mod sys;
pub mod unistd;

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

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

#[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 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 {
self.as_os_str().as_bytes().len()
}

fn with_nix_path<T, F>(&self, f: F) -> Result<T> where F: FnOnce(&CStr) -> T {
self.as_os_str().as_bytes().with_nix_path(f)
}
}

impl NixPath for PathBuf {
fn len(&self) -> usize {
self.as_os_str().as_bytes().len()
}

fn with_nix_path<T, F>(&self, f: F) -> Result<T> where F: FnOnce(&CStr) -> T {
self.as_os_str().as_bytes().with_nix_path(f)
}
}
64 changes: 28 additions & 36 deletions src/mount.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use libc::{c_ulong, c_int};
use NixPath;
use NixString;
use errno::{Errno, Result};

bitflags!(
Expand Down Expand Up @@ -50,18 +50,15 @@ bitflags!(
);

mod ffi {
use libc::{c_char, c_int};
use libc::{c_char, c_int, c_ulong, c_void};

extern {
/*
* TODO: Bring back
pub fn mount(
source: *const c_char,
target: *const c_char,
fstype: *const c_char,
flags: c_ulong,
data: *const c_void) -> c_int;
*/

pub fn umount(target: *const c_char) -> c_int;

Expand All @@ -72,47 +69,42 @@ mod ffi {
/*
* TODO: Bring this back with a test
*
pub fn mount<P1: ?Sized + NixPath, P2: ?Sized + NixPath, P3: ?Sized + NixPath, P4: ?Sized + NixPath>(
source: Option<&P1>,
pub fn mount<P1: NixString, P2: NixString, P3: NixString, P4: NixString>(
source: Option<P1>,
target: P2,
fstype: Option<&P3>,
fstype: Option<P3>,
flags: MsFlags,
data: Option<&P4>) -> Result<()> {
data: Option<P4>) -> Result<()> {
use std::ffi::CStr;
use std::ptr;
use libc;
let res = try!(try!(try!(try!(
source.with_nix_path(|source| {
target.with_nix_path(|target| {
fstype.with_nix_path(|fstype| {
data.with_nix_path(|data| {
unsafe {
ffi::mount(source.as_ext_str(),
target.as_ext_str(),
fstype,
flags.bits,
data as *const libc::c_void)
}
})
})
})
})))));
let source = source.as_ref().map(NixString::as_ref);
let fstype = fstype.as_ref().map(NixString::as_ref);
let data = data.as_ref().map(NixString::as_ref);
let res = unsafe {
ffi::mount(source.map(CStr::as_ptr).unwrap_or(ptr::null()),
target.as_ref().as_ptr(),
fstype.map(CStr::as_ptr).unwrap_or(ptr::null()),
flags.bits,
data.map(CStr::as_ptr).unwrap_or(ptr::null()) as *const libc::c_void)
};
return from_ffi(res);
}
*/
Errno::result(res).map(drop)
}*/

pub fn umount<P: ?Sized + NixPath>(target: &P) -> Result<()> {
let res = try!(target.with_nix_path(|cstr| {
unsafe { ffi::umount(cstr.as_ptr()) }
}));
pub fn umount<P: NixString>(target: P) -> Result<()> {
let res = unsafe {
ffi::umount(target.as_ref().as_ptr())
};

Errno::result(res).map(drop)
}

pub fn umount2<P: ?Sized + NixPath>(target: &P, flags: MntFlags) -> Result<()> {
let res = try!(target.with_nix_path(|cstr| {
unsafe { ffi::umount2(cstr.as_ptr(), flags.bits) }
}));
pub fn umount2<P: NixString>(target: P, flags: MntFlags) -> Result<()> {
let res = unsafe {
ffi::umount2(target.as_ref().as_ptr(), flags.bits)
};

Errno::result(res).map(drop)
}
40 changes: 40 additions & 0 deletions src/nix_string.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
use std::ffi::{CStr, CString};

/// Represents a type that can be converted to a `&CStr` without fail.
///
/// Note: this trait exists in place of `AsRef<CStr>` because is not
/// implemented until Rust 1.7.0
pub trait NixString {
fn as_ref(&self) -> &CStr;
}

impl NixString for CStr {
fn as_ref(&self) -> &CStr {
self
}
}

impl NixString for CString {
fn as_ref(&self) -> &CStr {
self
}
}

impl<'a, T: ?Sized + NixString> NixString for &'a T {
fn as_ref(&self) -> &CStr {
NixString::as_ref(*self)
}
}

impl<'a, T: ?Sized + NixString> NixString for &'a mut T {
fn as_ref(&self) -> &CStr {
NixString::as_ref(*self)
}
}

#[macro_export]
macro_rules! cstr {
($s:expr) => {
unsafe { ::std::ffi::CStr::from_ptr(concat!($s, "\0").as_ptr() as *const _) }
}
}
26 changes: 10 additions & 16 deletions src/sys/mman.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use {NixPath, Error};
use NixString;
use errno::{Errno, Result};
use fcntl::OFlag;
use libc::{c_void, size_t, off_t, mode_t};
Expand Down Expand Up @@ -204,7 +204,7 @@ pub fn mmap(addr: *mut c_void, length: size_t, prot: MmapProt, flags: MmapFlag,
let ret = unsafe { ffi::mmap(addr, length, prot, flags, fd, offset) };

if ret as isize == MAP_FAILED {
Err(Error::Sys(Errno::last()))
Err(Errno::last())
} else {
Ok(ret)
}
Expand All @@ -222,20 +222,14 @@ pub fn msync(addr: *const c_void, length: size_t, flags: MmapSync) -> Result<()>
Errno::result(unsafe { ffi::msync(addr, length, flags) }).map(drop)
}

pub fn shm_open<P: ?Sized + NixPath>(name: &P, flag: OFlag, mode: Mode) -> Result<RawFd> {
let ret = try!(name.with_nix_path(|cstr| {
unsafe {
ffi::shm_open(cstr.as_ptr(), flag.bits(), mode.bits() as mode_t)
}
}));

Errno::result(ret)
pub fn shm_open<P: NixString>(name: P, flag: OFlag, mode: Mode) -> Result<RawFd> {
unsafe {
Errno::result(ffi::shm_open(name.as_ref().as_ptr(), flag.bits(), mode.bits() as mode_t))
}
}

pub fn shm_unlink<P: ?Sized + NixPath>(name: &P) -> Result<()> {
let ret = try!(name.with_nix_path(|cstr| {
unsafe { ffi::shm_unlink(cstr.as_ptr()) }
}));

Errno::result(ret).map(drop)
pub fn shm_unlink<P: NixString>(name: P) -> Result<()> {
unsafe {
Errno::result(ffi::shm_unlink(name.as_ref().as_ptr())).map(drop)
}
}
Loading

0 comments on commit c437533

Please sign in to comment.