Skip to content

Commit 82d87b6

Browse files
committed
Errno::result()
1 parent e8f014d commit 82d87b6

28 files changed

+258
-505
lines changed

src/errno.rs

+61-28
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
use libc::c_int;
2+
use std::{fmt, io, error, result};
3+
use Error;
24

35
pub use self::consts::*;
46
pub use self::consts::Errno::*;
57

6-
78
#[cfg(any(target_os = "macos",
89
target_os = "ios",
910
target_os = "freebsd"))]
@@ -52,28 +53,72 @@ pub fn errno() -> i32 {
5253
}
5354
}
5455

55-
macro_rules! impl_errno {
56-
($errno:ty) => {
57-
impl $errno {
58-
pub fn last() -> Errno {
59-
super::last()
60-
}
56+
impl Errno {
57+
pub fn last() -> Self {
58+
last()
59+
}
60+
61+
pub fn desc(self) -> &'static str {
62+
desc(self)
63+
}
6164

62-
pub fn desc(self) -> &'static str {
63-
super::desc(self)
64-
}
65+
pub fn from_i32(err: i32) -> Errno {
66+
from_i32(err)
67+
}
6568

66-
pub fn from_i32(err: i32) -> Errno {
67-
from_i32(err)
68-
}
69+
pub unsafe fn clear() -> () {
70+
clear()
71+
}
6972

70-
pub unsafe fn clear() -> () {
71-
super::clear()
72-
}
73+
/// Returns `Ok(value)` if it does not contain the sentinel value. This
74+
/// should not be used when `-1` is not the errno sentinel value.
75+
pub fn result<S: ErrnoSentinel + PartialEq<S>>(value: S) -> Result<S> {
76+
if value == S::sentinel() {
77+
Err(Error::Sys(Self::last()))
78+
} else {
79+
Ok(value)
7380
}
7481
}
7582
}
7683

84+
/// The sentinel value indicates that a function failed and more detailed
85+
/// information about the error can be found in `errno`
86+
pub trait ErrnoSentinel: Sized {
87+
fn sentinel() -> Self;
88+
}
89+
90+
impl ErrnoSentinel for isize {
91+
fn sentinel() -> Self { -1 }
92+
}
93+
94+
impl ErrnoSentinel for i32 {
95+
fn sentinel() -> Self { -1 }
96+
}
97+
98+
impl ErrnoSentinel for i64 {
99+
fn sentinel() -> Self { -1 }
100+
}
101+
102+
impl error::Error for Errno {
103+
fn description(&self) -> &str {
104+
self.desc()
105+
}
106+
}
107+
108+
impl fmt::Display for Errno {
109+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
110+
write!(f, "{:?}: {}", self, self.desc())
111+
}
112+
}
113+
114+
impl From<Errno> for io::Error {
115+
fn from(err: Errno) -> Self {
116+
io::Error::from_raw_os_error(err as i32)
117+
}
118+
}
119+
120+
pub type Result<T> = result::Result<T, Error>;
121+
77122
fn last() -> Errno {
78123
Errno::from_i32(errno())
79124
}
@@ -618,8 +663,6 @@ mod consts {
618663
EHWPOISON = 133,
619664
}
620665

621-
impl_errno!(Errno);
622-
623666
pub const EWOULDBLOCK: Errno = Errno::EAGAIN;
624667
pub const EDEADLOCK: Errno = Errno::EDEADLK;
625668

@@ -880,8 +923,6 @@ mod consts {
880923
EQFULL = 106,
881924
}
882925

883-
impl_errno!(Errno);
884-
885926
pub const ELAST: Errno = Errno::EQFULL;
886927
pub const EWOULDBLOCK: Errno = Errno::EAGAIN;
887928
pub const EDEADLOCK: Errno = Errno::EDEADLK;
@@ -1108,8 +1149,6 @@ mod consts {
11081149

11091150
}
11101151

1111-
impl_errno!(Errno);
1112-
11131152
pub const ELAST: Errno = Errno::EOWNERDEAD;
11141153
pub const EWOULDBLOCK: Errno = Errno::EAGAIN;
11151154
pub const EDEADLOCK: Errno = Errno::EDEADLK;
@@ -1330,8 +1369,6 @@ mod consts {
13301369
EASYNC = 99,
13311370
}
13321371

1333-
impl_errno!(Errno);
1334-
13351372
pub const ELAST: Errno = Errno::EASYNC;
13361373
pub const EWOULDBLOCK: Errno = Errno::EAGAIN;
13371374
pub const EDEADLOCK: Errno = Errno::EDEADLK;
@@ -1547,8 +1584,6 @@ mod consts {
15471584
ENOTSUP = 91,
15481585
}
15491586

1550-
impl_errno!(Errno);
1551-
15521587
pub const ELAST: Errno = Errno::ENOTSUP;
15531588
pub const EWOULDBLOCK: Errno = Errno::EAGAIN;
15541589

@@ -1758,8 +1793,6 @@ mod consts {
17581793
EPROTO = 96,
17591794
}
17601795

1761-
impl_errno!(Errno);
1762-
17631796
pub const ELAST: Errno = Errno::ENOTSUP;
17641797
pub const EWOULDBLOCK: Errno = Errno::EAGAIN;
17651798

src/fcntl.rs

+5-17
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
use {Error, Result, NixPath};
2-
use errno::Errno;
1+
use NixPath;
2+
use errno::{Errno, Result};
33
use libc::{c_int, c_uint};
44
use sys::stat::Mode;
55
use std::os::unix::io::RawFd;
@@ -102,11 +102,7 @@ pub fn open<P: ?Sized + NixPath>(path: &P, oflag: OFlag, mode: Mode) -> Result<R
102102
unsafe { ffi::open(cstr.as_ptr(), oflag.bits(), mode.bits() as c_uint) }
103103
}));
104104

105-
if fd < 0 {
106-
return Err(Error::Sys(Errno::last()));
107-
}
108-
109-
Ok(fd)
105+
Errno::result(fd)
110106
}
111107

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

160-
if res < 0 {
161-
return Err(Error::Sys(Errno::last()));
162-
}
163-
164-
Ok(res)
156+
Errno::result(res)
165157
}
166158

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

190-
if res < 0 {
191-
return Err(Error::Sys(Errno::last()));
192-
}
193-
194-
Ok(())
182+
Errno::result(res).map(drop)
195183
}
196184

197185
#[cfg(any(target_os = "linux", target_os = "android"))]

src/lib.rs

+4-14
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,9 @@ extern crate libc;
1818
#[cfg(test)]
1919
extern crate nix_test as nixtest;
2020

21-
// Re-export some libc constants
21+
// Re-exports
2222
pub use libc::{c_int, c_void};
23+
pub use errno::{Errno, Result};
2324

2425
pub mod errno;
2526
pub mod features;
@@ -42,12 +43,12 @@ pub mod unistd;
4243

4344
/*
4445
*
45-
* ===== Result / Error =====
46+
* ===== Error =====
4647
*
4748
*/
4849

4950
use libc::c_char;
50-
use std::{ptr, result};
51+
use std::ptr;
5152
use std::ffi::CStr;
5253
use std::path::{Path, PathBuf};
5354
use std::os::unix::ffi::OsStrExt;
@@ -56,8 +57,6 @@ use std::fmt;
5657
use std::error;
5758
use libc::PATH_MAX;
5859

59-
pub type Result<T> = result::Result<T, Error>;
60-
6160
#[derive(Clone, Copy, Debug, PartialEq)]
6261
pub enum Error {
6362
Sys(errno::Errno),
@@ -185,12 +184,3 @@ impl NixPath for PathBuf {
185184
self.as_os_str().as_bytes().with_nix_path(f)
186185
}
187186
}
188-
189-
#[inline]
190-
pub fn from_ffi(res: libc::c_int) -> Result<()> {
191-
if res != 0 {
192-
return Err(Error::Sys(errno::Errno::last()));
193-
}
194-
195-
Ok(())
196-
}

src/mount.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use libc::{c_ulong, c_int};
2-
use {Result, NixPath, from_ffi};
2+
use NixPath;
3+
use errno::{Errno, Result};
34

45
bitflags!(
56
flags MsFlags: c_ulong {
@@ -105,13 +106,13 @@ pub fn umount<P: ?Sized + NixPath>(target: &P) -> Result<()> {
105106
unsafe { ffi::umount(cstr.as_ptr()) }
106107
}));
107108

108-
from_ffi(res)
109+
Errno::result(res).map(drop)
109110
}
110111

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

116-
from_ffi(res)
117+
Errno::result(res).map(drop)
117118
}

src/mqueue.rs

+8-25
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,7 @@
22
//!
33
//! [Further reading and details on the C API](http://man7.org/linux/man-pages/man7/mq_overview.7.html)
44
5-
use {Error, Result, from_ffi};
6-
use errno::Errno;
5+
use errno::{Errno, Result};
76

87
use libc::{c_int, c_long, c_char, size_t, mode_t, strlen};
98
use std::ffi::CString;
@@ -80,52 +79,38 @@ impl MqAttr {
8079
pub fn mq_open(name: &CString, oflag: MQ_OFlag, mode: Mode, attr: &MqAttr) -> Result<MQd> {
8180
let res = unsafe { ffi::mq_open(name.as_ptr(), oflag.bits(), mode.bits() as mode_t, attr as *const MqAttr) };
8281

83-
if res < 0 {
84-
return Err(Error::Sys(Errno::last()));
85-
}
86-
87-
Ok(res)
82+
Errno::result(res)
8883
}
8984

9085
pub fn mq_unlink(name: &CString) -> Result<()> {
9186
let res = unsafe { ffi::mq_unlink(name.as_ptr()) };
92-
from_ffi(res)
87+
Errno::result(res).map(drop)
9388
}
9489

9590
pub fn mq_close(mqdes: MQd) -> Result<()> {
9691
let res = unsafe { ffi::mq_close(mqdes) };
97-
from_ffi(res)
92+
Errno::result(res).map(drop)
9893
}
9994

10095

10196
pub fn mq_receive(mqdes: MQd, message: &mut [u8], msq_prio: u32) -> Result<usize> {
10297
let len = message.len() as size_t;
10398
let res = unsafe { ffi::mq_receive(mqdes, message.as_mut_ptr() as *mut c_char, len, &msq_prio) };
10499

105-
if res < 0 {
106-
return Err(Error::Sys(Errno::last()));
107-
}
108-
109-
Ok(res as usize)
100+
Errno::result(res).map(|r| r as usize)
110101
}
111102

112103
pub fn mq_send(mqdes: MQd, message: &CString, msq_prio: u32) -> Result<usize> {
113104
let len = unsafe { strlen(message.as_ptr()) as size_t };
114105
let res = unsafe { ffi::mq_send(mqdes, message.as_ptr(), len, msq_prio) };
115106

116-
if res < 0 {
117-
return Err(Error::Sys(Errno::last()));
118-
}
119-
120-
Ok(res as usize)
107+
Errno::result(res).map(|r| r as usize)
121108
}
122109

123110
pub fn mq_getattr(mqd: MQd) -> Result<MqAttr> {
124111
let mut attr = MqAttr::new(0, 0, 0, 0);
125112
let res = unsafe { ffi::mq_getattr(mqd, &mut attr) };
126-
if res < 0 {
127-
return Err(Error::Sys(Errno::last()));
128-
}
113+
try!(Errno::result(res));
129114
Ok(attr)
130115
}
131116

@@ -137,9 +122,7 @@ pub fn mq_getattr(mqd: MQd) -> Result<MqAttr> {
137122
pub fn mq_setattr(mqd: MQd, newattr: &MqAttr) -> Result<MqAttr> {
138123
let mut attr = MqAttr::new(0, 0, 0, 0);
139124
let res = unsafe { ffi::mq_setattr(mqd, newattr as *const MqAttr, &mut attr) };
140-
if res < 0 {
141-
return Err(Error::Sys(Errno::last()));
142-
}
125+
try!(Errno::result(res));
143126
Ok(attr)
144127
}
145128

src/poll.rs

+2-7
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
use libc::c_int;
2-
use {Error, Result};
3-
use errno::Errno;
2+
use errno::{Errno, Result};
43

54
pub use self::ffi::PollFd;
65
pub use self::ffi::consts::*;
@@ -72,9 +71,5 @@ pub fn poll(fds: &mut [PollFd], timeout: c_int) -> Result<c_int> {
7271
ffi::poll(fds.as_mut_ptr(), fds.len() as ffi::nfds_t, timeout)
7372
};
7473

75-
if res < 0 {
76-
return Err(Error::Sys(Errno::last()));
77-
}
78-
79-
Ok(res)
74+
Errno::result(res)
8075
}

0 commit comments

Comments
 (0)