1919//! libc::dlsym.
2020extern crate std;
2121
22- use crate :: Error ;
23- use crate :: utils:: use_init;
24- use std:: { thread_local, io:: { self , Read } , fs:: File } ;
25- use core:: cell:: RefCell ;
22+ use crate :: { use_file, Error } ;
23+ use core:: mem;
2624use core:: num:: NonZeroU32 ;
25+ use lazy_static:: lazy_static;
26+ use std:: io;
2727
2828#[ cfg( target_os = "illumos" ) ]
2929type GetRandomFn = unsafe extern "C" fn ( * mut u8 , libc:: size_t , libc:: c_uint ) -> libc:: ssize_t ;
3030#[ cfg( target_os = "solaris" ) ]
3131type GetRandomFn = unsafe extern "C" fn ( * mut u8 , libc:: size_t , libc:: c_uint ) -> libc:: c_int ;
3232
33- enum RngSource {
34- GetRandom ( GetRandomFn ) ,
35- Device ( File ) ,
36- }
37-
38- thread_local ! (
39- static RNG_SOURCE : RefCell <Option <RngSource >> = RefCell :: new( None ) ;
40- ) ;
41-
4233fn libc_getrandom ( rand : GetRandomFn , dest : & mut [ u8 ] ) -> Result < ( ) , Error > {
4334 let ret = unsafe { rand ( dest. as_mut_ptr ( ) , dest. len ( ) , 0 ) as libc:: ssize_t } ;
4435
@@ -51,51 +42,23 @@ fn libc_getrandom(rand: GetRandomFn, dest: &mut [u8]) -> Result<(), Error> {
5142}
5243
5344pub fn getrandom_inner ( dest : & mut [ u8 ] ) -> Result < ( ) , Error > {
45+ lazy_static ! { static ref GETRANDOM_FUNC : Option <GetRandomFn > = fetch_getrandom( ) ; }
46+
5447 // 256 bytes is the lowest common denominator across all the Solaris
5548 // derived platforms for atomically obtaining random data.
56- RNG_SOURCE . with ( |f| {
57- use_init (
58- f,
59- || {
60- let s = match fetch_getrandom ( ) {
61- Some ( fptr) => RngSource :: GetRandom ( fptr) ,
62- None => RngSource :: Device ( File :: open ( "/dev/random" ) ?) ,
63- } ;
64- Ok ( s)
65- } ,
66- |f| {
67- match f {
68- RngSource :: GetRandom ( rp) => {
69- for chunk in dest. chunks_mut ( 256 ) {
70- libc_getrandom ( * rp, chunk) ?
71- }
72- }
73- RngSource :: Device ( randf) => {
74- for chunk in dest. chunks_mut ( 256 ) {
75- randf. read_exact ( chunk) ?
76- }
77- }
78- } ;
79- Ok ( ( ) )
80- } ,
81- )
82- } )
49+ for chunk in dest. chunks_mut ( 256 ) {
50+ match * GETRANDOM_FUNC {
51+ Some ( fptr) => libc_getrandom ( fptr, chunk) ?,
52+ None => use_file:: getrandom_inner ( chunk) ?,
53+ } ;
54+ }
55+ Ok ( ( ) )
8356}
8457
8558fn fetch_getrandom ( ) -> Option < GetRandomFn > {
86- use std:: mem;
87- use std:: sync:: atomic:: { AtomicUsize , Ordering } ;
88-
89- static FPTR : AtomicUsize = AtomicUsize :: new ( 1 ) ;
90-
91- if FPTR . load ( Ordering :: SeqCst ) == 1 {
92- let name = "getrandom\0 " ;
93- let addr = unsafe { libc:: dlsym ( libc:: RTLD_DEFAULT , name. as_ptr ( ) as * const _ ) as usize } ;
94- FPTR . store ( addr, Ordering :: SeqCst ) ;
95- }
96-
97- let ptr = FPTR . load ( Ordering :: SeqCst ) ;
98- unsafe { mem:: transmute :: < usize , Option < GetRandomFn > > ( ptr) }
59+ let name = "getrandom\0 " ;
60+ let addr = unsafe { libc:: dlsym ( libc:: RTLD_DEFAULT , name. as_ptr ( ) as * const _ ) } ;
61+ unsafe { mem:: transmute ( addr) }
9962}
10063
10164#[ inline( always) ]
0 commit comments