a653rs_linux_core/
mfd.rs

1//! Implementation of a memory fd
2
3use std::{
4    io::{Read, Seek, SeekFrom, Write},
5    os::fd::{AsFd, AsRawFd, BorrowedFd, OwnedFd, RawFd},
6};
7
8use anyhow::{bail, Result};
9use memfd::{FileSeal, Memfd, MemfdOptions};
10
11pub struct Mfd(Memfd);
12
13pub enum Seals {
14    /// No seals are placed
15    Unsealed,
16    /// SealShrink + SealGrow + SealWrite + SealSeal
17    Readable,
18    /// SealSeal
19    Writable,
20}
21
22impl Mfd {
23    /// Creates an empty named Memfd
24    pub fn create(name: &str) -> Result<Self> {
25        let opts = MemfdOptions::default().allow_sealing(true);
26        let mfd = opts.create(name)?;
27        Ok(Self(mfd))
28    }
29
30    /// Reads all data available
31    pub fn read_all(&mut self) -> Result<Vec<u8>> {
32        self.0.as_file().seek(SeekFrom::Start(0))?;
33        // TODO: Evaluate whether inlining ofsmall message directly into the dtagram
34        // makes sense.
35        let mut buf: Vec<u8> = Vec::new();
36        self.0.as_file().read_to_end(&mut buf)?;
37
38        Ok(buf)
39    }
40
41    /// Wipes the mfd and overwrites it
42    pub fn write(&mut self, data: &[u8]) -> Result<()> {
43        self.0.as_file().seek(SeekFrom::Start(0))?;
44        self.0.as_file().set_len(0)?;
45        self.0.as_file().write_all(data)?;
46        Ok(())
47    }
48
49    /// Finalizes the mfd so that it becomes immutable
50    pub fn finalize(&mut self, seals: Seals) -> Result<()> {
51        let file_seals: Vec<FileSeal> = match seals {
52            Seals::Unsealed => vec![],
53            Seals::Readable => vec![
54                FileSeal::SealShrink,
55                FileSeal::SealGrow,
56                FileSeal::SealWrite,
57                FileSeal::SealSeal,
58            ],
59            Seals::Writable => vec![FileSeal::SealSeal],
60        };
61
62        for seal in file_seals {
63            self.0.add_seal(seal)?;
64        }
65
66        Ok(())
67    }
68
69    /// Creates a memfd from a fd
70    // TODO: Use some Rust try_from stuff
71    pub fn from_fd(fd: OwnedFd) -> Result<Self> {
72        let fd = match Memfd::try_from_fd(fd) {
73            Ok(memfd) => memfd,
74            Err(_) => bail!("cannot get Memfd from RawFd"),
75        };
76        Ok(Self(fd))
77    }
78}
79
80impl AsFd for Mfd {
81    fn as_fd(&self) -> BorrowedFd<'_> {
82        self.0.as_file().as_fd()
83    }
84}
85
86impl AsRawFd for Mfd {
87    fn as_raw_fd(&self) -> RawFd {
88        self.0.as_raw_fd()
89    }
90}
91
92#[cfg(test)]
93mod tests {
94    use super::*;
95
96    #[test]
97    fn test_mfd() {
98        let mut mfd = Mfd::create("test").unwrap();
99        mfd.write("Hello, world!".as_bytes()).unwrap();
100        mfd.finalize(Seals::Readable).unwrap();
101
102        assert_eq!(mfd.read_all().unwrap(), "Hello, world!".as_bytes());
103    }
104}