metrale_storage/tier/
entropy.rs1use anyhow::Result;
15
16pub fn random_u64() -> Result<u64> {
20 let mut buf = [0u8; 8];
21 fill(&mut buf)?;
22 Ok(u64::from_le_bytes(buf))
23}
24
25#[cfg(target_os = "linux")]
26fn fill(buf: &mut [u8]) -> Result<()> {
27 let mut got = 0usize;
28 while got < buf.len() {
29 let r = unsafe { libc::getrandom(buf[got..].as_mut_ptr().cast(), buf.len() - got, 0) };
30 if r < 0 {
31 let e = std::io::Error::last_os_error();
32 if e.raw_os_error() == Some(libc::EINTR) {
33 continue;
34 }
35 anyhow::bail!("getrandom failed (refusing a degraded zero-entropy salt): {e}");
36 }
37 got += r as usize;
38 }
39 Ok(())
40}
41
42#[cfg(all(unix, not(target_os = "linux")))]
43fn fill(buf: &mut [u8]) -> Result<()> {
44 use std::io::Read;
45 let mut f = std::fs::File::open("/dev/urandom")
46 .map_err(|e| anyhow::anyhow!("open /dev/urandom failed (refusing a degraded salt): {e}"))?;
47 f.read_exact(buf)
48 .map_err(|e| anyhow::anyhow!("read /dev/urandom failed (refusing a degraded salt): {e}"))
49}
50
51#[cfg(windows)]
53fn fill(buf: &mut [u8]) -> Result<()> {
54 getrandom::fill(buf)
55 .map_err(|e| anyhow::anyhow!("BCryptGenRandom failed (refusing a degraded salt): {e}"))
56}
57
58#[cfg(test)]
59#[path = "entropy_tests.rs"]
60mod tests;