//! Implementations that just need to read from a file usecrate::{
util_libc::{open_readonly, sys_fill_exact},
Error,
}; use core::{
cell::UnsafeCell,
mem::MaybeUninit,
sync::atomic::{AtomicUsize, Ordering::Relaxed},
};
// We prefer using /dev/urandom and only use /dev/random if the OS // documentation indicates that /dev/urandom is insecure. // On Solaris/Illumos, see src/solaris_illumos.rs // On Dragonfly, Haiku, and QNX Neutrino the devices are identical. #[cfg(any(target_os = "solaris", target_os = "illumos"))] const FILE_PATH: &str = "/dev/random\0"; #[cfg(any(
target_os = "aix",
target_os = "android",
target_os = "linux",
target_os = "redox",
target_os = "dragonfly",
target_os = "haiku",
target_os = "nto",
))] const FILE_PATH: &str = "/dev/urandom\0"; const FD_UNINIT: usize = usize::max_value();
// Returns the file descriptor for the device file used to retrieve random // bytes. The file will be opened exactly once. All subsequent calls will // return the same file descriptor. This file descriptor is never closed. fn get_rng_fd() -> Result<libc::c_int, Error> { static FD: AtomicUsize = AtomicUsize::new(FD_UNINIT); fn get_fd() -> Option<libc::c_int> { match FD.load(Relaxed) {
FD_UNINIT => None,
val => Some(val as libc::c_int),
}
}
// Use double-checked locking to avoid acquiring the lock if possible. iflet Some(fd) = get_fd() { return Ok(fd);
}
// SAFETY: We use the mutex only in this method, and we always unlock it // before returning, making sure we don't violate the pthread_mutex_t API. static MUTEX: Mutex = Mutex::new(); unsafe { MUTEX.lock() }; let _guard = DropGuard(|| unsafe { MUTEX.unlock() });
let fd = unsafe { open_readonly(FILE_PATH)? }; // The fd always fits in a usize without conflicting with FD_UNINIT.
debug_assert!(fd >= 0 && (fd as usize) < FD_UNINIT);
FD.store(fd as usize, Relaxed);
Ok(fd)
}
// Succeeds once /dev/urandom is safe to read from #[cfg(any(target_os = "android", target_os = "linux"))] fn wait_until_rng_ready() -> Result<(), Error> { // Poll /dev/random to make sure it is ok to read from /dev/urandom. let fd = unsafe { open_readonly("/dev/random\0")? }; letmut pfd = libc::pollfd {
fd,
events: libc::POLLIN,
revents: 0,
}; let _guard = DropGuard(|| unsafe {
libc::close(fd);
});
loop { // A negative timeout means an infinite timeout. let res = unsafe { libc::poll(&mut pfd, 1, -1) }; if res >= 0 {
debug_assert_eq!(res, 1); // We only used one fd, and cannot timeout. return Ok(());
} let err = crate::util_libc::last_os_error(); match err.raw_os_error() {
Some(libc::EINTR) | Some(libc::EAGAIN) => continue,
_ => return Err(err),
}
}
}
struct Mutex(UnsafeCell<libc::pthread_mutex_t>);
impl Mutex { constfn new() -> Self { Self(UnsafeCell::new(libc::PTHREAD_MUTEX_INITIALIZER))
} unsafefn lock(&self) { let r = libc::pthread_mutex_lock(self.0.get());
debug_assert_eq!(r, 0);
} unsafefn unlock(&self) { let r = libc::pthread_mutex_unlock(self.0.get());
debug_assert_eq!(r, 0);
}
}
unsafeimpl Sync for Mutex {}
struct DropGuard<F: FnMut()>(F);
impl<F: FnMut()> Drop for DropGuard<F> { fn drop(&mutself) { self.0()
}
}
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.17 Sekunden
(vorverarbeitet am 2026-06-19)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.