Skip to content

Commit 1e2a5aa

Browse files
committed
new error
1 parent f860bde commit 1e2a5aa

17 files changed

+106
-51
lines changed

Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,7 @@ fuchsia-cprng = "0.1"
2121
[target.wasm32-unknown-unknown.dependencies]
2222
wasm-bindgen = { version = "0.2.12", optional = true }
2323
stdweb = { version = "0.4", optional = true }
24+
25+
[features]
26+
# Forces syscall usage on Linux, Android and Solaris
27+
force_syscall = []

src/cloudabi.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ pub fn getrandom(dest: &mut [u8]) -> Result<(), Error> {
1616
if errno == 0 {
1717
Ok(())
1818
} else {
19-
Err(Error::Unknown)
19+
Err(Error(unsafe {
20+
NonZeroU32::new_unchecked(errno as u32)
21+
}))
2022
}
2123
}

src/dragonfly_haiku.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ thread_local!(static RNG_FILE: RefCell<Option<File>> = RefCell::new(None));
1717

1818
pub fn getrandom(dest: &mut [u8]) -> Result<(), Error> {
1919
RNG_FILE.with(|f| {
20-
use_init(f, || File::open("/dev/random"), |f| f.read_exact(dest))
21-
}).map_err(|_| Error::Unknown)
20+
use_init(f,
21+
|| File::open("/dev/random").map_err(From::from),
22+
|f| f.read_exact(dest).map_err(From::from),
23+
)
24+
})
2225
}

src/dummy.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@
77
// except according to those terms.
88

99
//! A dummy implementation for unsupported targets which always returns
10-
//! `Err(Error::Unavailable)`
11-
use super::Error;
10+
//! `Err(UNAVAILABLE_ERROR)`
11+
use super::UNAVAILABLE_ERROR;
1212

1313
pub fn getrandom(dest: &mut [u8]) -> Result<(), Error> {
14-
Err(Error::Unavailable)
14+
Err(UNAVAILABLE_ERROR)
1515
}

src/emscripten.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,11 @@ pub fn getrandom(dest: &mut [u8]) -> Result<(), Error> {
2121
// task length variation, partition large randomBytes requests when
2222
// doing so as part of fulfilling a client request.
2323
RNG_FILE.with(|f| {
24-
use_init(f, || File::open("/dev/random"), |f| {
24+
use_init(f, || File::open("/dev/random").map_err(From::from), |f| {
2525
for chunk in dest.chunks_mut(65536) {
2626
f.read_exact(chunk)?;
2727
}
2828
Ok(())
2929
})
30-
}).map_err(|_| Error::Unknown)
30+
})
3131
}

src/error.rs

Lines changed: 59 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,64 @@
66
// option. This file may not be copied, modified, or distributed
77
// except according to those terms.
88

9+
use core::num::NonZeroU32;
10+
use core::convert::From;
11+
use core::fmt;
12+
#[cfg(not(target_env = "sgx"))]
13+
use std::{io, error};
14+
15+
pub const UNKNOWN_ERROR: Error = Error(unsafe {
16+
NonZeroU32::new_unchecked(0x756e6b6e) // "unkn"
17+
});
18+
19+
pub const UNAVAILABLE_ERROR: Error = Error(unsafe {
20+
NonZeroU32::new_unchecked(0x4e416e61) // "NAna"
21+
});
22+
923
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
10-
pub enum Error {
11-
/// Call was interrupted.
12-
///
13-
/// Typically it can be retried.
14-
Interrupted,
15-
/// RNG source is unavailable on a given system.
16-
Unavailable,
17-
/// Unknown error.
18-
Unknown,
19-
#[doc(hidden)]
20-
__Nonexhaustive,
24+
pub struct Error(NonZeroU32);
25+
26+
impl Error {
27+
pub fn code(&self) -> NonZeroU32 {
28+
self.0
29+
}
30+
}
31+
32+
impl fmt::Display for Error {
33+
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
34+
match *self {
35+
UNKNOWN_ERROR => write!(f, "Getrandom Error: unknown"),
36+
UNAVAILABLE_ERROR => write!(f, "Getrandom Error: unavailable"),
37+
code => write!(f, "Getrandom Error: {}", code.0.get()),
38+
}
39+
}
2140
}
41+
42+
#[cfg(not(target_env = "sgx"))]
43+
impl From<io::Error> for Error {
44+
fn from(err: io::Error) -> Self {
45+
err.raw_os_error()
46+
.map(|code| Error(unsafe {
47+
// all supported targets use 0 as success code
48+
NonZeroU32::new_unchecked(code as u32)
49+
}))
50+
// in practice this should never happen
51+
.unwrap_or(UNKNOWN_ERROR)
52+
}
53+
}
54+
55+
#[cfg(not(target_env = "sgx"))]
56+
impl Into<io::Error> for Error {
57+
fn into(self) -> io::Error {
58+
match self {
59+
UNKNOWN_ERROR => io::Error::new(io::ErrorKind::Other,
60+
"getrandom error: unknown"),
61+
UNAVAILABLE_ERROR => io::Error::new(io::ErrorKind::Other,
62+
"getrandom error: entropy source is unavailable"),
63+
code => io::Error::from_raw_os_error(code.0.get() as i32),
64+
}
65+
}
66+
}
67+
68+
#[cfg(not(target_env = "sgx"))]
69+
impl error::Error for Error { }

src/freebsd.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ extern crate libc;
1111

1212
use super::Error;
1313
use core::ptr;
14+
use std::io;
1415

1516
pub fn getrandom(dest: &mut [u8]) -> Result<(), Error> {
1617
let mib = [libc::CTL_KERN, libc::KERN_ARND];
@@ -24,7 +25,7 @@ pub fn getrandom(dest: &mut [u8]) -> Result<(), Error> {
2425
)
2526
};
2627
if ret == -1 || len != chunk.len() {
27-
return Err(Error::Unknown);
28+
return Err(io::Error::last_os_error().into());
2829
}
2930
}
3031
Ok(())

src/lib.rs

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,7 @@
77
// except according to those terms.
88
#![no_std]
99

10-
#[cfg(any(
11-
target_os = "android",
12-
target_os = "netbsd",
13-
target_os = "solaris",
14-
target_os = "redox",
15-
target_os = "dragonfly",
16-
target_os = "haiku",
17-
target_os = "emscripten",
18-
target_os = "linux",
19-
))]
10+
#[cfg(not(target_env = "sgx"))]
2011
#[macro_use] extern crate std;
2112

2213
#[cfg(any(
@@ -31,7 +22,7 @@
3122
))]
3223
mod utils;
3324
mod error;
34-
pub use error::Error;
25+
pub use error::{Error, UNKNOWN_ERROR, UNAVAILABLE_ERROR};
3526

3627
macro_rules! mod_use {
3728
($cond:meta, $module:ident) => {

src/linux_android.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,8 @@ pub fn getrandom(dest: &mut [u8]) -> Result<(), Error> {
5858
match f {
5959
RngSource::GetRandom => syscall_getrandom(dest),
6060
RngSource::Device(f) => f.read_exact(dest),
61-
}
62-
}).map_err(|_| Error::Unknown)
61+
}.map_err(From::from)
62+
})
6363
})
6464
}
6565

src/macos.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
//! Implementation for MacOS / iOS
1010
use super::Error;
11+
use std::io;
1112

1213
// TODO: check correctness
1314
#[allow(non_upper_case_globals)]
@@ -29,7 +30,7 @@ pub fn getrandom(dest: &mut [u8]) -> Result<(), Error> {
2930
)
3031
};
3132
if ret == -1 {
32-
Err(Error::Unknown)
33+
Err(io::Error::last_os_error().into())
3334
} else {
3435
Ok(())
3536
}

src/netbsd.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ pub fn getrandom(dest: &mut [u8]) -> Result<(), Error> {
2828
File::open("/dev/random")?.read_exact(&mut [0u8; 1])?;
2929
RNG_INIT.store(true, Ordering::Relaxed)
3030
}
31-
File::open("/dev/urandom")
32-
}, |f| f.read_exact(dest))
33-
}).map_err(|_| Error::Unknown)
31+
File::open("/dev/urandom").map_err(From::from)
32+
}, |f| f.read_exact(dest).map_err(From::from))
33+
})
3434
}

src/openbsd_bitrig.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
extern crate libc;
1111

1212
use super::Error;
13+
use std::io;
1314

1415
pub fn getrandom(dest: &mut [u8]) -> Result<(), Error> {
1516
for chunk in dest.chunks_mut(256) {
@@ -20,7 +21,7 @@ pub fn getrandom(dest: &mut [u8]) -> Result<(), Error> {
2021
)
2122
};
2223
if ret == -1 {
23-
return Err(Error::Unknown);
24+
return Err(io::Error::last_os_error().into());
2425
}
2526
}
2627
Ok(())

src/redox.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ thread_local!(static RNG_FILE: RefCell<Option<File>> = RefCell::new(None));
1717

1818
pub fn getrandom(dest: &mut [u8]) -> Result<(), Error> {
1919
RNG_FILE.with(|f| {
20-
use_init(f, || File::open("rand:"), |f| f.read_exact(dest))
21-
}).map_err(|_| Error::Unknown)
20+
use_init(f,
21+
|| File::open("rand:").map_err(From::from),
22+
|f| f.read_exact(dest).map_err(From::from),
23+
)
24+
}).map_err(From::from)
2225
}

src/sgx.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
// except according to those terms.
88

99
//! Implementation for SGX using RDRAND instruction
10-
use super::Error;
10+
use super::{Error, UNKNOWN_ERROR};
1111

1212
use core::{mem, ptr};
1313
use core::arch::x86_64::_rdrand64_step;
@@ -26,7 +26,7 @@ fn get_rand_u64() -> Result<u64, Error> {
2626
}
2727
};
2828
}
29-
Err(Error::Unknown)
29+
Err(UNKNOWN_ERROR)
3030
}
3131

3232
pub fn getrandom(mut dest: &mut [u8]) -> Result<(), Error> {

src/solaris.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ thread_local!(
3636
static RNG_SOURCE: RefCell<Option<RngSource>> = RefCell::new(None);
3737
);
3838

39-
fn syscall_getrandom(dest: &mut [u8]) -> Result<(), io::Error> {
39+
fn syscall_getrandom(dest: &mut [u8]) -> Result<(), Error> {
4040
// repalce with libc?
4141
const SYS_GETRANDOM: libc::c_long = 143;
4242

@@ -48,7 +48,7 @@ fn syscall_getrandom(dest: &mut [u8]) -> Result<(), io::Error> {
4848
syscall(SYS_GETRANDOM, dest.as_mut_ptr(), dest.len(), 0)
4949
};
5050
if ret == -1 || ret != dest.len() as i64 {
51-
return Err(io::Error::last_os_error());
51+
return Err(io::Error::last_os_error().from());
5252
}
5353
Ok(())
5454
}
@@ -71,7 +71,7 @@ pub fn getrandom(dest: &mut [u8]) -> Result<(), Error> {
7171
syscall_getrandom(chunk)
7272
},
7373
RngSource::Device(f) => for chunk in dest.chunks_mut(1040) {
74-
f.read_exact(dest)
74+
f.read_exact(dest).map_err(From::from)
7575
},
7676
}
7777
})

src/utils.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,16 @@
55
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
66
// option. This file may not be copied, modified, or distributed
77
// except according to those terms.
8-
use std::cell::RefCell;
9-
use std::ops::DerefMut;
10-
use std::io;
8+
use super::Error;
9+
use core::cell::RefCell;
10+
use core::ops::DerefMut;
1111

1212
/// If `f` contains `Some(T)` call `use_f` using contents of `f` as an argument,
1313
/// otherwise initialize `f` value using `init_f`, store resulting value in `f`
1414
/// and call `use_f`.
1515
pub(crate) fn use_init<T, F, U>(f: &RefCell<Option<T>>, init_f: F, mut use_f: U)
16-
-> io::Result<()>
17-
where F: FnOnce() -> io::Result<T>, U: FnMut(&mut T) -> io::Result<()>
16+
-> Result<(), Error>
17+
where F: FnOnce() -> Result<T, Error>, U: FnMut(&mut T) -> Result<(), Error>
1818
{
1919
let mut f = f.borrow_mut();
2020
let f: &mut Option<T> = f.deref_mut();

src/windows.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,13 @@ extern crate winapi;
1212
use self::winapi::shared::minwindef::ULONG;
1313
use self::winapi::um::ntsecapi::RtlGenRandom;
1414
use self::winapi::um::winnt::PVOID;
15+
use std::io;
1516
use super::Error;
1617

1718
pub fn getrandom(dest: &mut [u8]) -> Result<(), Error> {
1819
let ret = unsafe {
1920
RtlGenRandom(dest.as_mut_ptr() as PVOID, dest.len() as ULONG)
2021
};
21-
if ret == 0 { return Err(Error::Unknown); }
22+
if ret == 0 { return Err(io::Error::last_os_error().into()); }
2223
Ok(())
2324
}

0 commit comments

Comments
 (0)