Skip to content

Commit 0bfe592

Browse files
authored
Move backend implementations to src/backends/ (#538)
This makes it easier to get list of existing backends. It also makes lib.rs and the backends `cfg_if` a bit less cluttered.
1 parent 5bf25bc commit 0bfe592

24 files changed

+208
-170
lines changed

src/backends.rs

+152
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
//! System-specific implementations.
2+
//!
3+
//! This module should provide `fill_inner` with the signature
4+
//! `fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error>`.
5+
//! The function MUST fully initialize `dest` when `Ok(())` is returned.
6+
//! The function MUST NOT ever write uninitialized bytes into `dest`,
7+
//! regardless of what value it returns.
8+
9+
cfg_if! {
10+
if #[cfg(getrandom_backend = "custom")] {
11+
mod custom;
12+
pub use custom::*;
13+
} else if #[cfg(getrandom_backend = "linux_getrandom")] {
14+
mod linux_android;
15+
pub use linux_android::*;
16+
} else if #[cfg(getrandom_backend = "linux_rustix")] {
17+
mod linux_rustix;
18+
pub use linux_rustix::*;
19+
} else if #[cfg(getrandom_backend = "rdrand")] {
20+
mod rdrand;
21+
pub use rdrand::*;
22+
} else if #[cfg(getrandom_backend = "rndr")] {
23+
mod rndr;
24+
pub use rndr::*;
25+
} else if #[cfg(getrandom_backend = "wasm_js")] {
26+
mod wasm_js;
27+
pub use wasm_js::*;
28+
} else if #[cfg(getrandom_backend = "esp_idf")] {
29+
mod esp_idf;
30+
pub use esp_idf::*;
31+
} else if #[cfg(any(
32+
target_os = "haiku",
33+
target_os = "redox",
34+
target_os = "nto",
35+
target_os = "aix",
36+
))] {
37+
mod use_file;
38+
pub use use_file::*;
39+
} else if #[cfg(any(
40+
target_os = "macos",
41+
target_os = "openbsd",
42+
target_os = "vita",
43+
target_os = "emscripten",
44+
))] {
45+
mod getentropy;
46+
pub use getentropy::*;
47+
} else if #[cfg(any(
48+
target_os = "dragonfly",
49+
target_os = "freebsd",
50+
target_os = "hurd",
51+
target_os = "illumos",
52+
// Check for target_arch = "arm" to only include the 3DS. Does not
53+
// include the Nintendo Switch (which is target_arch = "aarch64").
54+
all(target_os = "horizon", target_arch = "arm"),
55+
))] {
56+
mod getrandom;
57+
pub use getrandom::*;
58+
} else if #[cfg(any(
59+
// Rust supports Android API level 19 (KitKat) [0] and the next upgrade targets
60+
// level 21 (Lollipop) [1], while `getrandom(2)` was added only in
61+
// level 23 (Marshmallow). Note that it applies only to the "old" `target_arch`es,
62+
// RISC-V Android targets sufficiently new API level, same will apply for potential
63+
// new Android `target_arch`es.
64+
// [0]: https://blog.rust-lang.org/2023/01/09/android-ndk-update-r25.html
65+
// [1]: https://github.com/rust-lang/rust/pull/120593
66+
all(
67+
target_os = "android",
68+
any(
69+
target_arch = "aarch64",
70+
target_arch = "arm",
71+
target_arch = "x86",
72+
target_arch = "x86_64",
73+
),
74+
),
75+
// Only on these `target_arch`es Rust supports Linux kernel versions (3.2+)
76+
// that precede the version (3.17) in which `getrandom(2)` was added:
77+
// https://doc.rust-lang.org/stable/rustc/platform-support.html
78+
all(
79+
target_os = "linux",
80+
any(
81+
target_arch = "aarch64",
82+
target_arch = "arm",
83+
target_arch = "powerpc",
84+
target_arch = "powerpc64",
85+
target_arch = "s390x",
86+
target_arch = "x86",
87+
target_arch = "x86_64",
88+
// Minimum supported Linux kernel version for MUSL targets
89+
// is not specified explicitly (as of Rust 1.77) and they
90+
// are used in practice to target pre-3.17 kernels.
91+
target_env = "musl",
92+
),
93+
)
94+
))] {
95+
mod use_file;
96+
mod linux_android_with_fallback;
97+
pub use linux_android_with_fallback::*;
98+
} else if #[cfg(any(target_os = "android", target_os = "linux"))] {
99+
mod linux_android;
100+
pub use linux_android::*;
101+
} else if #[cfg(target_os = "solaris")] {
102+
mod solaris;
103+
pub use solaris::*;
104+
} else if #[cfg(target_os = "netbsd")] {
105+
mod netbsd;
106+
pub use netbsd::*;
107+
} else if #[cfg(target_os = "fuchsia")] {
108+
mod fuchsia;
109+
pub use fuchsia::*;
110+
} else if #[cfg(any(
111+
target_os = "ios",
112+
target_os = "visionos",
113+
target_os = "watchos",
114+
target_os = "tvos",
115+
))] {
116+
mod apple_other;
117+
pub use apple_other::*;
118+
} else if #[cfg(all(target_arch = "wasm32", target_os = "wasi"))] {
119+
mod wasi;
120+
pub use wasi::*;
121+
} else if #[cfg(target_os = "hermit")] {
122+
mod hermit;
123+
pub use hermit::*;
124+
} else if #[cfg(target_os = "vxworks")] {
125+
mod vxworks;
126+
pub use vxworks::*;
127+
} else if #[cfg(target_os = "solid_asp3")] {
128+
mod solid;
129+
pub use solid::*;
130+
} else if #[cfg(all(windows, target_vendor = "win7"))] {
131+
mod windows7;
132+
pub use windows7::*;
133+
} else if #[cfg(windows)] {
134+
mod windows;
135+
pub use windows::*;
136+
} else if #[cfg(all(target_arch = "x86_64", target_env = "sgx"))] {
137+
mod rdrand;
138+
pub use rdrand::*;
139+
} else if #[cfg(all(
140+
any(target_arch = "wasm32", target_arch = "wasm64"),
141+
target_os = "unknown",
142+
))] {
143+
compile_error!("the wasm*-unknown-unknown targets are not supported by \
144+
default, you may need to enable the \"wasm_js\" \
145+
configuration flag. For more information see: \
146+
https://docs.rs/getrandom/#webassembly-support");
147+
} else {
148+
compile_error!("target is not supported. You may need to define \
149+
a custom backend see: \
150+
https://docs.rs/getrandom/#custom-backends");
151+
}
152+
}
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.

src/getentropy.rs renamed to src/backends/getentropy.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,17 @@
77
//! - vita newlib since Dec 2021
88
//!
99
//! For these targets, we use getentropy(2) because getrandom(2) doesn't exist.
10-
use crate::{util_libc::last_os_error, Error};
10+
use crate::Error;
1111
use core::{ffi::c_void, mem::MaybeUninit};
1212

13+
#[path = "../util_libc.rs"]
14+
mod util_libc;
15+
1316
pub fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
1417
for chunk in dest.chunks_mut(256) {
1518
let ret = unsafe { libc::getentropy(chunk.as_mut_ptr().cast::<c_void>(), chunk.len()) };
1619
if ret != 0 {
17-
return Err(last_os_error());
20+
return Err(util_libc::last_os_error());
1821
}
1922
}
2023
Ok(())

src/getrandom.rs renamed to src/backends/getrandom.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,14 @@
1515
//! GRND_RANDOM is not recommended. On NetBSD/FreeBSD/Dragonfly/3ds, it does
1616
//! nothing. On illumos, the default pool is used to implement getentropy(2),
1717
//! so we assume it is acceptable here.
18-
use crate::{util_libc::sys_fill_exact, Error};
18+
use crate::Error;
1919
use core::{ffi::c_void, mem::MaybeUninit};
2020

21+
#[path = "../util_libc.rs"]
22+
mod util_libc;
23+
2124
pub fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
22-
sys_fill_exact(dest, |buf| unsafe {
25+
util_libc::sys_fill_exact(dest, |buf| unsafe {
2326
libc::getrandom(buf.as_mut_ptr().cast::<c_void>(), buf.len(), 0)
2427
})
2528
}
File renamed without changes.

src/linux_android.rs renamed to src/backends/linux_android.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
//! Implementation for Linux / Android without `/dev/urandom` fallback
2-
use crate::{util_libc, Error};
2+
use crate::Error;
33
use core::mem::MaybeUninit;
44

5+
#[path = "../util_libc.rs"]
6+
mod util_libc;
7+
58
#[cfg(not(any(target_os = "android", target_os = "linux")))]
69
compile_error!("`linux_getrandom` backend can be enabled only for Linux/Android targets!");
710

src/linux_android_with_fallback.rs renamed to src/backends/linux_android_with_fallback.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
//! Implementation for Linux / Android with `/dev/urandom` fallback
2-
use crate::{use_file, util_libc, Error};
2+
use super::use_file;
3+
use crate::Error;
34
use core::{
45
ffi::c_void,
56
mem::{self, MaybeUninit},
67
ptr::{self, NonNull},
78
sync::atomic::{AtomicPtr, Ordering},
89
};
10+
use use_file::util_libc;
911

1012
type GetRandomFn = unsafe extern "C" fn(*mut c_void, libc::size_t, libc::c_uint) -> libc::ssize_t;
1113

File renamed without changes.

src/netbsd.rs renamed to src/backends/netbsd.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
//! `getrandom(2)` was introduced in NetBSD 10. To support older versions we
44
//! implement our own weak linkage to it, and provide a fallback based on the
55
//! KERN_ARND sysctl.
6-
use crate::{util_libc::sys_fill_exact, Error};
6+
use crate::Error;
77
use core::{
88
cmp,
99
ffi::c_void,
@@ -12,6 +12,9 @@ use core::{
1212
sync::atomic::{AtomicPtr, Ordering},
1313
};
1414

15+
#[path = "../util_libc.rs"]
16+
mod util_libc;
17+
1518
unsafe extern "C" fn polyfill_using_kern_arand(
1619
buf: *mut c_void,
1720
buflen: libc::size_t,
@@ -69,7 +72,7 @@ pub fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
6972
fptr = init();
7073
}
7174
let fptr = unsafe { mem::transmute::<*mut c_void, GetRandomFn>(fptr) };
72-
sys_fill_exact(dest, |buf| unsafe {
75+
util_libc::sys_fill_exact(dest, |buf| unsafe {
7376
fptr(buf.as_mut_ptr().cast::<c_void>(), buf.len(), 0)
7477
})
7578
}

src/rdrand.rs renamed to src/backends/rdrand.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
//! RDRAND backend for x86(-64) targets
2-
use crate::{lazy::LazyBool, util::slice_as_uninit, Error};
2+
use crate::{util::slice_as_uninit, Error};
33
use core::mem::{size_of, MaybeUninit};
44

5+
#[path = "../lazy.rs"]
6+
mod lazy;
7+
58
#[cfg(not(any(target_arch = "x86_64", target_arch = "x86")))]
69
compile_error!("`rdrand` backend can be enabled only for x86 and x86-64 targets!");
710

@@ -97,7 +100,7 @@ fn is_rdrand_good() -> bool {
97100
}
98101

99102
pub fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
100-
static RDRAND_GOOD: LazyBool = LazyBool::new();
103+
static RDRAND_GOOD: lazy::LazyBool = lazy::LazyBool::new();
101104
if !RDRAND_GOOD.unsync_init(is_rdrand_good) {
102105
return Err(Error::NO_RDRAND);
103106
}

src/rndr.rs renamed to src/backends/rndr.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -84,12 +84,12 @@ fn is_rndr_available() -> bool {
8484
(id_aa64isar0 >> 60) & 0xf >= 1
8585
}
8686

87-
#[path = "../src/lazy.rs"] mod lazy;
87+
#[path = "../lazy.rs"] mod lazy;
8888
static RNDR_GOOD: lazy::LazyBool = lazy::LazyBool::new();
8989
RNDR_GOOD.unsync_init(mrs_check)
9090
} else if #[cfg(feature = "std")] {
9191
extern crate std;
92-
#[path = "../src/lazy.rs"] mod lazy;
92+
#[path = "../lazy.rs"] mod lazy;
9393
static RNDR_GOOD: lazy::LazyBool = lazy::LazyBool::new();
9494
RNDR_GOOD.unsync_init(|| std::arch::is_aarch64_feature_detected!("rand"))
9595
} else {

src/solaris.rs renamed to src/backends/solaris.rs

+9-3
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,12 @@
1212
//! For more information, see the man page linked in lib.rs and this blog post:
1313
//! https://blogs.oracle.com/solaris/post/solaris-new-system-calls-getentropy2-and-getrandom2
1414
//! which also explains why this crate should not use getentropy(2).
15-
use crate::{util_libc::last_os_error, Error};
15+
use crate::Error;
1616
use core::{ffi::c_void, mem::MaybeUninit};
1717

18+
#[path = "../util_libc.rs"]
19+
mod util_libc;
20+
1821
const MAX_BYTES: usize = 1024;
1922

2023
pub fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
@@ -24,8 +27,11 @@ pub fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
2427
// In case the man page has a typo, we also check for negative ret.
2528
// If getrandom(2) succeeds, it should have completely filled chunk.
2629
match usize::try_from(ret) {
27-
Ok(ret) if ret == chunk.len() => {} // Good. Keep going.
28-
Ok(0) => return Err(last_os_error()), // The syscall failed.
30+
// Good. Keep going.
31+
Ok(ret) if ret == chunk.len() => {}
32+
// The syscall failed.
33+
Ok(0) => return Err(util_libc::last_os_error()),
34+
// All other cases should be impossible.
2935
_ => return Err(Error::UNEXPECTED),
3036
}
3137
}
File renamed without changes.

src/use_file.rs renamed to src/backends/use_file.rs

+7-7
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
//! Implementations that just need to read from a file
2-
use crate::{
3-
util_libc::{last_os_error, sys_fill_exact},
4-
Error,
5-
};
2+
use crate::Error;
63
use core::{
74
ffi::c_void,
85
mem::MaybeUninit,
96
sync::atomic::{AtomicI32, Ordering},
107
};
118

9+
#[path = "../util_libc.rs"]
10+
pub(super) mod util_libc;
11+
1212
/// For all platforms, we use `/dev/urandom` rather than `/dev/random`.
1313
/// For more information see the linked man pages in lib.rs.
1414
/// - On Linux, "/dev/urandom is preferred and sufficient in all use cases".
@@ -42,7 +42,7 @@ pub fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
4242
if fd == FD_UNINIT || fd == FD_ONGOING_INIT {
4343
fd = open_or_wait()?;
4444
}
45-
sys_fill_exact(dest, |buf| unsafe {
45+
util_libc::sys_fill_exact(dest, |buf| unsafe {
4646
libc::read(fd, buf.as_mut_ptr().cast::<c_void>(), buf.len())
4747
})
4848
}
@@ -65,7 +65,7 @@ fn open_readonly(path: &[u8]) -> Result<libc::c_int, Error> {
6565
if fd >= 0 {
6666
return Ok(fd);
6767
}
68-
let err = last_os_error();
68+
let err = util_libc::last_os_error();
6969
// We should try again if open() was interrupted.
7070
if err.raw_os_error() != Some(libc::EINTR) {
7171
return Err(err);
@@ -142,7 +142,7 @@ mod sync {
142142

143143
#[cfg(any(target_os = "android", target_os = "linux"))]
144144
mod sync {
145-
use super::{last_os_error, open_readonly, Error, FD, FD_ONGOING_INIT};
145+
use super::{open_readonly, util_libc::last_os_error, Error, FD, FD_ONGOING_INIT};
146146

147147
/// Wait for atomic `FD` to change value from `FD_ONGOING_INIT` to something else.
148148
///

src/vxworks.rs renamed to src/backends/vxworks.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
//! Implementation for VxWorks
2-
use crate::{util_libc::last_os_error, Error};
2+
use crate::Error;
33
use core::{
44
cmp::Ordering::{Equal, Greater, Less},
55
mem::MaybeUninit,
66
sync::atomic::{AtomicBool, Ordering::Relaxed},
77
};
88

9+
#[path = "../util_libc.rs"]
10+
mod util_libc;
11+
912
pub fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
1013
static RNG_INIT: AtomicBool = AtomicBool::new(false);
1114
while !RNG_INIT.load(Relaxed) {
@@ -32,7 +35,7 @@ pub fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
3235
let p: *mut libc::c_uchar = chunk.as_mut_ptr().cast();
3336
let ret = unsafe { libc::randABytes(p, chunk_len) };
3437
if ret != 0 {
35-
return Err(last_os_error());
38+
return Err(util_libc::last_os_error());
3639
}
3740
}
3841
Ok(())
File renamed without changes.

src/wasm_js.rs renamed to src/backends/wasm_js.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ thread_local!(
3030
static RNG_SOURCE: Result<RngSource, Error> = getrandom_init();
3131
);
3232

33-
pub(crate) fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
33+
pub fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
3434
RNG_SOURCE.with(|result| {
3535
let source = result.as_ref().map_err(|&e| e)?;
3636

File renamed without changes.
File renamed without changes.
File renamed without changes.

0 commit comments

Comments
 (0)