@@ -10,8 +10,10 @@ use core::{
10
10
sync:: atomic:: { AtomicI32 , Ordering } ,
11
11
} ;
12
12
use std:: {
13
- fs, io,
14
- os:: fd:: { IntoRawFd as _, RawFd } ,
13
+ fs,
14
+ io,
15
+ // TODO(MSRV 1.66): use `std::os::fd` instead of `std::unix::io`.
16
+ os:: unix:: io:: { AsRawFd as _, BorrowedFd , IntoRawFd as _, RawFd } ,
15
17
} ;
16
18
17
19
/// For all platforms, we use `/dev/urandom` rather than `/dev/random`.
@@ -28,14 +30,14 @@ const FILE_PATH: &str = "/dev/urandom";
28
30
pub fn getrandom_inner ( dest : & mut [ MaybeUninit < u8 > ] ) -> Result < ( ) , Error > {
29
31
let fd = get_rng_fd ( ) ?;
30
32
sys_fill_exact ( dest, |buf| unsafe {
31
- libc:: read ( fd, buf. as_mut_ptr ( ) . cast :: < c_void > ( ) , buf. len ( ) )
33
+ libc:: read ( fd. as_raw_fd ( ) , buf. as_mut_ptr ( ) . cast :: < c_void > ( ) , buf. len ( ) )
32
34
} )
33
35
}
34
36
35
37
// Returns the file descriptor for the device file used to retrieve random
36
38
// bytes. The file will be opened exactly once. All subsequent calls will
37
39
// return the same file descriptor. This file descriptor is never closed.
38
- fn get_rng_fd ( ) -> Result < RawFd , Error > {
40
+ fn get_rng_fd ( ) -> Result < BorrowedFd < ' static > , Error > {
39
41
// std::os::fd::{BorrowedFd, OwnedFd} guarantee that -1 is not a valid file descriptor.
40
42
const FD_UNINIT : RawFd = -1 ;
41
43
@@ -55,22 +57,19 @@ fn get_rng_fd() -> Result<RawFd, Error> {
55
57
// `Ordering::Acquire` to synchronize with it.
56
58
static FD : AtomicI32 = AtomicI32 :: new ( FD_UNINIT ) ;
57
59
58
- fn get_fd ( ) -> Option < RawFd > {
60
+ fn get_fd ( ) -> Option < BorrowedFd < ' static > > {
59
61
match FD . load ( Ordering :: Acquire ) {
60
62
FD_UNINIT => None ,
61
- val => Some ( val) ,
63
+ val => Some ( unsafe { BorrowedFd :: borrow_raw ( val) } ) ,
62
64
}
63
65
}
64
66
65
67
#[ cold]
66
- fn get_fd_locked ( ) -> Result < RawFd , Error > {
68
+ fn get_fd_locked ( ) -> Result < BorrowedFd < ' static > , Error > {
67
69
// This mutex is used to prevent multiple threads from opening file
68
70
// descriptors concurrently, which could run into the limit on the
69
71
// number of open file descriptors. Our goal is to have no more than one
70
72
// file descriptor open, ever.
71
- //
72
- // SAFETY: We use the mutex only in this method, and we always unlock it
73
- // before returning, making sure we don't violate the pthread_mutex_t API.
74
73
static MUTEX : Mutex = Mutex :: new ( ) ;
75
74
unsafe { MUTEX . lock ( ) } ;
76
75
let _guard = DropGuard ( || unsafe { MUTEX . unlock ( ) } ) ;
@@ -89,7 +88,7 @@ fn get_rng_fd() -> Result<RawFd, Error> {
89
88
debug_assert ! ( fd != FD_UNINIT ) ;
90
89
FD . store ( fd, Ordering :: Release ) ;
91
90
92
- Ok ( fd )
91
+ Ok ( unsafe { BorrowedFd :: borrow_raw ( fd ) } )
93
92
}
94
93
95
94
// Use double-checked locking to avoid acquiring the lock if possible.
@@ -130,8 +129,6 @@ fn get_rng_fd() -> Result<RawFd, Error> {
130
129
// libsodium uses `libc::poll` similarly to this.
131
130
#[ cfg( any( target_os = "android" , target_os = "linux" ) ) ]
132
131
fn wait_until_rng_ready ( ) -> Result < ( ) , Error > {
133
- use std:: os:: unix:: io:: AsRawFd as _;
134
-
135
132
let file = fs:: File :: open ( "/dev/random" ) . map_err ( map_io_error) ?;
136
133
let mut pfd = libc:: pollfd {
137
134
fd : file. as_raw_fd ( ) ,
0 commit comments