9
9
//! Implementations that just need to read from a file
10
10
extern crate std;
11
11
12
+ use crate :: util_libc:: LazyFd ;
12
13
use crate :: Error ;
14
+ use core:: mem:: ManuallyDrop ;
13
15
use core:: num:: NonZeroU32 ;
14
- use lazy_static :: lazy_static ;
16
+ use std :: os :: unix :: io :: { FromRawFd , IntoRawFd , RawFd } ;
15
17
use std:: { fs:: File , io:: Read } ;
16
18
17
19
#[ cfg( target_os = "redox" ) ]
@@ -29,28 +31,31 @@ const FILE_PATH: &str = "/dev/urandom";
29
31
const FILE_PATH : & str = "/dev/random" ;
30
32
31
33
pub fn getrandom_inner ( dest : & mut [ u8 ] ) -> Result < ( ) , Error > {
32
- lazy_static ! {
33
- static ref FILE : Result < File , Error > = init_file( ) ;
34
- }
35
- let mut f = FILE . as_ref ( ) ? ;
34
+ static FD : LazyFd = LazyFd :: new ( ) ;
35
+ let fd = FD . init ( init_file) . ok_or ( Error :: UNKNOWN ) ? ;
36
+ let file = ManuallyDrop :: new ( unsafe { File :: from_raw_fd ( fd ) } ) ;
37
+ let mut file_ref : & File = & file ;
36
38
37
39
if cfg ! ( target_os = "emscripten" ) {
38
40
// `Crypto.getRandomValues` documents `dest` should be at most 65536 bytes.
39
41
for chunk in dest. chunks_mut ( 65536 ) {
40
- f . read_exact ( chunk) ?;
42
+ file_ref . read_exact ( chunk) ?;
41
43
}
42
44
} else {
43
- f . read_exact ( dest) ?;
45
+ file_ref . read_exact ( dest) ?;
44
46
}
45
47
Ok ( ( ) )
46
48
}
47
49
48
- fn init_file ( ) -> Result < File , Error > {
50
+ fn init_file ( ) -> Option < RawFd > {
49
51
if FILE_PATH == "/dev/urandom" {
50
52
// read one byte from "/dev/random" to ensure that OS RNG has initialized
51
- File :: open ( "/dev/random" ) ?. read_exact ( & mut [ 0u8 ; 1 ] ) ?;
53
+ File :: open ( "/dev/random" )
54
+ . ok ( ) ?
55
+ . read_exact ( & mut [ 0u8 ; 1 ] )
56
+ . ok ( ) ?;
52
57
}
53
- Ok ( File :: open ( FILE_PATH ) ? )
58
+ Some ( File :: open ( FILE_PATH ) . ok ( ) ? . into_raw_fd ( ) )
54
59
}
55
60
56
61
#[ inline( always) ]
0 commit comments