|
19 | 19 | //! libc::dlsym. |
20 | 20 | extern crate std; |
21 | 21 |
|
| 22 | +use crate::util_libc::Weak; |
22 | 23 | use crate::{use_file, Error}; |
23 | 24 | use core::mem; |
24 | 25 | use core::num::NonZeroU32; |
25 | | -use lazy_static::lazy_static; |
26 | 26 | use std::io; |
27 | 27 |
|
28 | 28 | #[cfg(target_os = "illumos")] |
29 | 29 | type GetRandomFn = unsafe extern "C" fn(*mut u8, libc::size_t, libc::c_uint) -> libc::ssize_t; |
30 | 30 | #[cfg(target_os = "solaris")] |
31 | 31 | type GetRandomFn = unsafe extern "C" fn(*mut u8, libc::size_t, libc::c_uint) -> libc::c_int; |
32 | 32 |
|
33 | | -fn libc_getrandom(rand: GetRandomFn, dest: &mut [u8]) -> Result<(), Error> { |
34 | | - let ret = unsafe { rand(dest.as_mut_ptr(), dest.len(), 0) as libc::ssize_t }; |
35 | | - |
36 | | - if ret == -1 || ret != dest.len() as libc::ssize_t { |
37 | | - error!("getrandom syscall failed with ret={}", ret); |
38 | | - Err(io::Error::last_os_error().into()) |
39 | | - } else { |
40 | | - Ok(()) |
41 | | - } |
42 | | -} |
43 | | - |
44 | 33 | pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> { |
45 | | - lazy_static! { |
46 | | - static ref GETRANDOM_FUNC: Option<GetRandomFn> = fetch_getrandom(); |
47 | | - } |
48 | | - |
49 | | - // 256 bytes is the lowest common denominator across all the Solaris |
50 | | - // derived platforms for atomically obtaining random data. |
51 | | - for chunk in dest.chunks_mut(256) { |
52 | | - match *GETRANDOM_FUNC { |
53 | | - Some(fptr) => libc_getrandom(fptr, chunk)?, |
54 | | - None => use_file::getrandom_inner(chunk)?, |
55 | | - }; |
| 34 | + static GETRANDOM: Weak = unsafe { Weak::new("getrandom\0") }; |
| 35 | + if let Some(fptr) = GETRANDOM.ptr() { |
| 36 | + let func: GetRandomFn = unsafe { mem::transmute(fptr) }; |
| 37 | + // 256 bytes is the lowest common denominator across all the Solaris |
| 38 | + // derived platforms for atomically obtaining random data. |
| 39 | + for chunk in dest.chunks_mut(256) { |
| 40 | + let ret = unsafe { func(chunk.as_mut_ptr(), chunk.len(), 0) }; |
| 41 | + if ret != chunk.len() as _ { |
| 42 | + error!("getrandom syscall failed with ret={}", ret); |
| 43 | + return Err(io::Error::last_os_error().into()); |
| 44 | + } |
| 45 | + } |
| 46 | + Ok(()) |
| 47 | + } else { |
| 48 | + use_file::getrandom_inner(dest) |
56 | 49 | } |
57 | | - Ok(()) |
58 | | -} |
59 | | - |
60 | | -fn fetch_getrandom() -> Option<GetRandomFn> { |
61 | | - let name = "getrandom\0"; |
62 | | - let addr = unsafe { libc::dlsym(libc::RTLD_DEFAULT, name.as_ptr() as *const _) }; |
63 | | - unsafe { mem::transmute(addr) } |
64 | 50 | } |
65 | 51 |
|
66 | 52 | #[inline(always)] |
|
0 commit comments