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 5, 2016
1 parent 3154b7d commit 0a16991
Show file tree
Hide file tree
Showing 28 changed files with 669 additions and 1,062 deletions.
81 changes: 53 additions & 28 deletions src/errno.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use libc::c_int;
use libc::{c_int, c_long};
use std::{fmt, io, error};

pub use self::consts::*;
pub use self::consts::Errno::*;
Expand Down Expand Up @@ -52,28 +53,64 @@ pub fn errno() -> i32 {
}
}

macro_rules! impl_errno {
($errno:ty) => {
impl $errno {
pub fn last() -> Errno {
super::last()
}
impl Errno {
pub fn last() -> Self {
last()
}

pub fn desc(self) -> &'static str {
super::desc(self)
}
pub fn desc(self) -> &'static str {
desc(self)
}

pub fn from_i32(err: i32) -> Errno {
from_i32(err)
}
pub fn from_i32(err: i32) -> Errno {
from_i32(err)
}

pub unsafe fn clear() -> () {
super::clear()
}
pub unsafe fn clear() -> () {
clear()
}

pub fn result<S: ErrnoSentinel + PartialEq<S>>(value: S) -> Result<S> {
if value == S::sentinel() {
Err(Self::last())
} else {
Ok(value)
}
}
}

pub trait ErrnoSentinel: Sized {
fn sentinel() -> Self;
}

impl ErrnoSentinel for c_int {
fn sentinel() -> Self { -1 }
}

impl ErrnoSentinel for c_long {
fn sentinel() -> Self { -1 }
}

impl error::Error for Errno {
fn description(&self) -> &str {
self.desc()
}
}

impl fmt::Display for Errno {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:?}: {}", self, self.desc())
}
}

impl From<Errno> for io::Error {
fn from(err: Errno) -> Self {
io::Error::from_raw_os_error(err as i32)
}
}

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

fn last() -> Errno {
Errno::from_i32(errno())
}
Expand Down Expand Up @@ -618,8 +655,6 @@ mod consts {
EHWPOISON = 133,
}

impl_errno!(Errno);

pub const EWOULDBLOCK: Errno = Errno::EAGAIN;
pub const EDEADLOCK: Errno = Errno::EDEADLK;

Expand Down Expand Up @@ -880,8 +915,6 @@ mod consts {
EQFULL = 106,
}

impl_errno!(Errno);

pub const ELAST: Errno = Errno::EQFULL;
pub const EWOULDBLOCK: Errno = Errno::EAGAIN;
pub const EDEADLOCK: Errno = Errno::EDEADLK;
Expand Down Expand Up @@ -1108,8 +1141,6 @@ mod consts {

}

impl_errno!(Errno);

pub const ELAST: Errno = Errno::EOWNERDEAD;
pub const EWOULDBLOCK: Errno = Errno::EAGAIN;
pub const EDEADLOCK: Errno = Errno::EDEADLK;
Expand Down Expand Up @@ -1330,8 +1361,6 @@ mod consts {
EASYNC = 99,
}

impl_errno!(Errno);

pub const ELAST: Errno = Errno::EASYNC;
pub const EWOULDBLOCK: Errno = Errno::EAGAIN;
pub const EDEADLOCK: Errno = Errno::EDEADLK;
Expand Down Expand Up @@ -1547,8 +1576,6 @@ mod consts {
ENOTSUP = 91,
}

impl_errno!(Errno);

pub const ELAST: Errno = Errno::ENOTSUP;
pub const EWOULDBLOCK: Errno = Errno::EAGAIN;

Expand Down Expand Up @@ -1758,8 +1785,6 @@ mod consts {
EPROTO = 96,
}

impl_errno!(Errno);

pub const ELAST: Errno = Errno::ENOTSUP;
pub const EWOULDBLOCK: Errno = Errno::EAGAIN;

Expand Down
30 changes: 9 additions & 21 deletions src/fcntl.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use {Error, Result, NixPath};
use errno::Errno;
use NixString;
use errno::{Errno, Result};
use libc::{mode_t, c_int};
use sys::stat::Mode;
use std::os::unix::io::RawFd;
Expand Down Expand Up @@ -97,16 +97,12 @@ 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 mode_t) }
}));

if fd < 0 {
return Err(Error::Sys(Errno::last()));
}
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 mode_t)
};

Ok(fd)
Errno::result(fd)
}

pub enum FcntlArg<'a> {
Expand Down Expand Up @@ -157,11 +153,7 @@ pub fn fcntl(fd: RawFd, arg: FcntlArg) -> Result<c_int> {
}
};

if res < 0 {
return Err(Error::Sys(Errno::last()));
}

Ok(res)
Errno::result(res)
}

pub enum FlockArg {
Expand All @@ -187,11 +179,7 @@ pub fn flock(fd: RawFd, arg: FlockArg) -> Result<()> {
}
};

if res < 0 {
return Err(Error::Sys(Errno::last()));
}

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

#[cfg(any(target_os = "linux", target_os = "android"))]
Expand Down
142 changes: 4 additions & 138 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@ extern crate libc;
#[cfg(test)]
extern crate nix_test as nixtest;

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

pub mod errno;
pub mod features;
Expand All @@ -37,140 +39,4 @@ pub mod sched;
pub mod sys;
pub mod unistd;

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

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

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 [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)
}
}

#[inline]
pub fn from_ffi(res: libc::c_int) -> Result<()> {
if res != 0 {
return Err(Error::Sys(errno::Errno::last()));
}

Ok(())
}
mod nix_string;
Loading

0 comments on commit 0a16991

Please sign in to comment.