Skip to content

Commit

Permalink
Collapse Error into Errno
Browse files Browse the repository at this point in the history
Now that Nix's weird error types are eliminated, there's no reason not
to simply use Errno as the Error type.
  • Loading branch information
asomers committed Jul 8, 2021
1 parent 6511d02 commit 2d796eb
Show file tree
Hide file tree
Showing 25 changed files with 142 additions and 209 deletions.
74 changes: 63 additions & 11 deletions src/errno.rs
@@ -1,5 +1,6 @@
use cfg_if::cfg_if;
use libc::{c_int, c_void};
use std::convert::TryFrom;
use std::{fmt, io, error};
use crate::{Error, Result};

Expand Down Expand Up @@ -48,6 +49,42 @@ pub fn errno() -> i32 {
}

impl Errno {
/// Convert this `Error` to an [`Errno`](enum.Errno.html).
///
/// # Example
///
/// ```
/// # use nix::Error;
/// # use nix::errno::Errno;
/// let e = Error::from(Errno::EPERM);
/// assert_eq!(Some(Errno::EPERM), e.as_errno());
/// ```
#[deprecated(
since = "0.22.0",
note = "It's a no-op now; just delete it."
)]
pub fn as_errno(self) -> Option<Self> {
Some(self)
}

/// Create a nix Error from a given errno
#[deprecated(
since = "0.22.0",
note = "It's a no-op now; just delete it."
)]
pub fn from_errno(errno: Errno) -> Error {
Error::from(errno)
}

/// Create a new invalid argument error (`EINVAL`)
#[deprecated(
since = "0.22.0",
note = "Use Errno::EINVAL instead"
)]
pub fn invalid_argument() -> Error {
Errno::EINVAL
}

pub fn last() -> Self {
last()
}
Expand All @@ -64,25 +101,30 @@ impl Errno {
clear()
}

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

/// Returns `Ok(value)` if it does not contain the sentinel value. This
/// 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::from(Self::last()))
Err(Self::last())
} else {
Ok(value)
}
}

/// Backwards compatibility hack for Nix <= 0.21.0 users
///
/// In older versions of Nix, `Error::Sys` was an enum variant. Now it's a
/// function, which is compatible with most of the former use cases of the
/// enum variant. But you should use `Error(Errno::...)` instead.
#[deprecated(
since = "0.22.0",
note = "Use Errno::... instead"
)]
#[allow(non_snake_case)]
#[inline]
pub fn Sys(errno: Errno) -> Error {
errno
}
}

/// The sentinel value indicates that a function failed and more detailed
Expand Down Expand Up @@ -125,6 +167,16 @@ impl From<Errno> for io::Error {
}
}

impl TryFrom<io::Error> for Errno {
type Error = io::Error;

fn try_from(ioerror: io::Error) -> std::result::Result<Self, io::Error> {
ioerror.raw_os_error()
.map(Errno::from_i32)
.ok_or(ioerror)
}
}

fn last() -> Errno {
Errno::from_i32(errno())
}
Expand Down
113 changes: 4 additions & 109 deletions src/lib.rs
Expand Up @@ -79,16 +79,15 @@ pub mod unistd;

use libc::{c_char, PATH_MAX};

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

use errno::{Errno, ErrnoSentinel};
use errno::Errno;

/// Nix Result Type
pub type Result<T> = result::Result<T, Error>;
pub type Result<T> = result::Result<T, Errno>;

/// Nix's main error type.
///
Expand All @@ -100,111 +99,7 @@ pub type Result<T> = result::Result<T, Error>;
/// * Small size
/// * Represents all of the system's errnos, instead of just the most common
/// ones.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct Error(pub Errno);

impl Error {
/// Convert this `Error` to an [`Errno`](enum.Errno.html).
///
/// # Example
///
/// ```
/// # use nix::Error;
/// # use nix::errno::Errno;
/// let e = Error::from(Errno::EPERM);
/// assert_eq!(Some(Errno::EPERM), e.as_errno());
/// ```
#[deprecated(
since = "0.22.0",
note = "Use Error::into<Errno> instead"
)]
pub fn as_errno(self) -> Option<Errno> {
Some(self.0)
}

/// Create a nix Error from a given errno
#[deprecated(
since = "0.22.0",
note = "Use Error::from instead"
)]
pub fn from_errno(errno: Errno) -> Error {
Error::from(errno)
}

/// Get the current errno and convert it to a nix Error
pub fn last() -> Error {
Error::from(Errno::last())
}

/// Create a new invalid argument error (`EINVAL`)
#[deprecated(
since = "0.22.0",
note = "Use Error::from(Errno::EINVAL) instead"
)]
pub fn invalid_argument() -> Error {
Error::from(Errno::EINVAL)
}

/// Returns `Ok(value)` if it does not contain the sentinel value. This
/// should not be used when `-1` is not the errno sentinel value.
pub(crate) fn result<S: ErrnoSentinel + PartialEq<S>>(value: S)
-> std::result::Result<S, Error>
{
Errno::result2(value).map_err(Self::from)
}

/// Backwards compatibility hack for Nix <= 0.21.0 users
///
/// In older versions of Nix, `Error::Sys` was an enum variant. Now it's a
/// function, which is compatible with most of the former use cases of the
/// enum variant. But you should use `Error(Errno::...)` instead.
#[deprecated(
since = "0.22.0",
note = "Use Error(Errno::...) instead"
)]
#[allow(non_snake_case)]
#[inline]
pub fn Sys(errno: Errno) -> Error {
Error::from(errno)
}
}

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

impl error::Error for Error {}

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

impl From<Error> for Errno {
fn from(error: Error) -> Self {
error.0
}
}

impl TryFrom<io::Error> for Error {
type Error = io::Error;

fn try_from(ioerror: io::Error) -> std::result::Result<Self, io::Error> {
ioerror.raw_os_error()
.map(Errno::from_i32)
.map(Error::from)
.ok_or(ioerror)
}
}

impl From<Error> for io::Error {
fn from(error: Error) -> Self {
Self::from_raw_os_error(error.0 as i32)
}
}
pub type Error = Errno;

pub trait NixPath {
fn is_empty(&self) -> bool;
Expand Down
11 changes: 6 additions & 5 deletions src/mount/bsd.rs
@@ -1,4 +1,5 @@
use crate::{
Error,
Errno,
NixPath,
Result,
Expand Down Expand Up @@ -99,7 +100,7 @@ libc_bitflags!(
/// by `nmount(2)`.
#[derive(Debug)]
pub struct NmountError {
errno: Errno,
errno: Error,
errmsg: Option<String>
}

Expand All @@ -109,14 +110,14 @@ impl NmountError {
self.errmsg.as_deref()
}

/// Returns the inner [`Errno`]
pub fn errno(&self) -> Errno {
/// Returns the inner [`Error`]
pub fn error(&self) -> Error {
self.errno
}

fn new(errno: Errno, errmsg: Option<&CStr>) -> Self {
fn new(error: Error, errmsg: Option<&CStr>) -> Self {
Self {
errno,
errno: error,
errmsg: errmsg.map(CStr::to_string_lossy).map(Cow::into_owned)
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/pty.rs
Expand Up @@ -70,7 +70,7 @@ impl Drop for PtyMaster {
// condition, which can cause confusing errors for future I/O
// operations.
let e = unistd::close(self.0);
if e == Err(Error(Errno::EBADF)) {
if e == Err(Errno::EBADF) {
panic!("Closing an invalid file descriptor!");
};
}
Expand Down
6 changes: 3 additions & 3 deletions src/sys/aio.rs
Expand Up @@ -983,13 +983,13 @@ impl<'a> LioCb<'a> {
// aiocb is complete; collect its status and don't resubmit
self.results[i] = Some(a.aio_return_unpinned());
},
Err(Error(Errno::EAGAIN)) => {
Err(Errno::EAGAIN) => {
self.list.push(a as *mut AioCb<'a> as *mut libc::aiocb);
},
Err(Error(Errno::EINPROGRESS)) => {
Err(Errno::EINPROGRESS) => {
// aiocb is was successfully queued; no need to do anything
},
Err(Error(Errno::EINVAL)) => panic!(
Err(Errno::EINVAL) => panic!(
"AioCb was never submitted, or already finalized"),
_ => unreachable!()
}
Expand Down
4 changes: 2 additions & 2 deletions src/sys/ptrace/linux.rs
Expand Up @@ -2,7 +2,7 @@

use cfg_if::cfg_if;
use std::{mem, ptr};
use crate::{Error, Result};
use crate::Result;
use crate::errno::Errno;
use libc::{self, c_void, c_long, siginfo_t};
use crate::unistd::Pid;
Expand Down Expand Up @@ -180,7 +180,7 @@ fn ptrace_peek(request: Request, pid: Pid, addr: AddressType, data: *mut c_void)
libc::ptrace(request as RequestType, libc::pid_t::from(pid), addr, data)
};
match Errno::result(ret) {
Ok(..) | Err(Error(Errno::UnknownErrno)) => Ok(ret),
Ok(..) | Err(Errno::UnknownErrno) => Ok(ret),
err @ Err(..) => err,
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/sys/signalfd.rs
Expand Up @@ -108,7 +108,7 @@ impl SignalFd {
match res {
Ok(SIGNALFD_SIGINFO_SIZE) => Ok(Some(unsafe { mem::transmute(buffer.assume_init()) })),
Ok(_) => unreachable!("partial read on signalfd"),
Err(Error(Errno::EAGAIN)) => Ok(None),
Err(Errno::EAGAIN) => Ok(None),
Err(error) => Err(error)
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/sys/socket/mod.rs
Expand Up @@ -1572,7 +1572,7 @@ pub fn recvfrom(sockfd: RawFd, buf: &mut [u8])
&mut len as *mut socklen_t))? as usize;

match sockaddr_storage_to_addr(&addr, len as usize) {
Err(Error(Errno::ENOTCONN)) => Ok((ret, None)),
Err(Errno::ENOTCONN) => Ok((ret, None)),
Ok(addr) => Ok((ret, Some(addr))),
Err(e) => Err(e)
}
Expand Down
6 changes: 3 additions & 3 deletions src/sys/timerfd.rs
Expand Up @@ -30,7 +30,7 @@
//! ```
use crate::sys::time::TimeSpec;
use crate::unistd::read;
use crate::{errno::Errno, Error, Result};
use crate::{errno::Errno, Result};
use bitflags::bitflags;
use libc::c_int;
use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
Expand Down Expand Up @@ -259,7 +259,7 @@ impl TimerFd {
loop {
if let Err(e) = read(self.fd, &mut [0u8; 8]) {
match e {
Error(Errno::EINTR) => continue,
Errno::EINTR => continue,
_ => return Err(e),
}
} else {
Expand All @@ -277,7 +277,7 @@ impl Drop for TimerFd {
let result = Errno::result(unsafe {
libc::close(self.fd)
});
if let Err(Error(Errno::EBADF)) = result {
if let Err(Errno::EBADF) = result {
panic!("close of TimerFd encountered EBADF");
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/unistd.rs
Expand Up @@ -1432,7 +1432,7 @@ pub fn getgroups() -> Result<Vec<Gid>> {
unsafe { groups.set_len(s as usize) };
return Ok(groups);
},
Err(Error(Errno::EINVAL)) => {
Err(Errno::EINVAL) => {
// EINVAL indicates that the buffer size was too
// small, resize it up to ngroups_max as limit.
reserve_double_buffer_size(&mut groups, ngroups_max)
Expand Down
2 changes: 1 addition & 1 deletion test/sys/test_aio.rs
Expand Up @@ -177,7 +177,7 @@ fn test_aio_suspend() {
let cbbuf = [wcb.as_ref(), rcb.as_ref()];
let r = aio_suspend(&cbbuf[..], Some(timeout));
match r {
Err(Error(Errno::EINTR)) => continue,
Err(Errno::EINTR) => continue,
Err(e) => panic!("aio_suspend returned {:?}", e),
Ok(_) => ()
};
Expand Down

0 comments on commit 2d796eb

Please sign in to comment.