axfs_devfs/
urandom.rs

1use axfs_vfs::{VfsNodeAttr, VfsNodeOps, VfsNodePerm, VfsNodeType, VfsResult};
2use core::sync::atomic::{AtomicU64, Ordering};
3
4/// A urandom device behaves like `/dev/urandom`.
5///
6/// It produces random bytes when read.
7pub struct UrandomDev {
8    seed: AtomicU64,
9}
10
11impl UrandomDev {
12    /// Create a new instance of the urandom device.
13    pub const fn new(seed: u64) -> Self {
14        Self {
15            seed: AtomicU64::new(seed),
16        }
17    }
18
19    /// Create a new instance with a default seed.
20    fn new_with_default_seed() -> Self {
21        Self::new(0xa2ce_a2ce)
22    }
23
24    /// LCG pseudo-random number generator
25    fn next_u64(&self) -> u64 {
26        let new_seed = self
27            .seed
28            .load(Ordering::SeqCst)
29            .wrapping_mul(6364136223846793005)
30            + 1;
31        self.seed.store(new_seed, Ordering::SeqCst);
32        new_seed
33    }
34}
35
36impl Default for UrandomDev {
37    fn default() -> Self {
38        Self::new_with_default_seed()
39    }
40}
41
42impl VfsNodeOps for UrandomDev {
43    fn get_attr(&self) -> VfsResult<VfsNodeAttr> {
44        Ok(VfsNodeAttr::new(
45            VfsNodePerm::default_file(),
46            VfsNodeType::CharDevice,
47            0,
48            0,
49        ))
50    }
51
52    fn read_at(&self, _offset: u64, buf: &mut [u8]) -> VfsResult<usize> {
53        for chunk in buf.chunks_mut(8) {
54            let random_value = self.next_u64();
55            let bytes = random_value.to_ne_bytes();
56            for (i, byte) in chunk.iter_mut().enumerate() {
57                if i < bytes.len() {
58                    *byte = bytes[i];
59                }
60            }
61        }
62        Ok(buf.len())
63    }
64
65    fn write_at(&self, _offset: u64, buf: &[u8]) -> VfsResult<usize> {
66        Ok(buf.len())
67    }
68
69    fn truncate(&self, _size: u64) -> VfsResult {
70        Ok(())
71    }
72
73    axfs_vfs::impl_vfs_non_dir_default! {}
74}