pager_dynamic/
lib.rs

1use std::sync::OnceLock;
2
3use monitor_api::CompartmentHandle;
4pub use object_store::paged_object_store::{
5    ExternalFile, ExternalKind, MAX_EXTERNAL_PATH, NAME_MAX,
6};
7use secgate::{
8    util::{Descriptor, Handle, SimpleBuffer},
9    DynamicSecGate,
10};
11use twizzler_abi::object::ObjID;
12use twizzler_rt_abi::{error::TwzError, object::MapFlags, Result};
13
14struct PagerAPI {
15    _handle: &'static CompartmentHandle,
16    open_handle: DynamicSecGate<'static, (), (Descriptor, ObjID)>,
17    close_handle: DynamicSecGate<'static, (Descriptor,), ()>,
18    enumerate_external: DynamicSecGate<'static, (Descriptor, ObjID), usize>,
19}
20
21static PAGER_API: OnceLock<PagerAPI> = OnceLock::new();
22
23fn pager_api() -> &'static PagerAPI {
24    PAGER_API.get_or_init(|| {
25        let handle = Box::leak(Box::new(
26            CompartmentHandle::lookup("pager-srv").expect("failed to open pager compartment"),
27        ));
28        let open_handle = unsafe {
29            handle
30                .dynamic_gate("pager_open_handle")
31                .expect("failed to find open handle gate call")
32        };
33        let close_handle = unsafe {
34            handle
35                .dynamic_gate("pager_close_handle")
36                .expect("failed to find close handle gate call")
37        };
38        let enumerate_external = unsafe {
39            handle
40                .dynamic_gate("pager_enumerate_external")
41                .expect("failed to find enumerate external gate call")
42        };
43        PagerAPI {
44            _handle: handle,
45            open_handle,
46            close_handle,
47            enumerate_external,
48        }
49    })
50}
51
52pub struct PagerHandle {
53    desc: Descriptor,
54    buffer: SimpleBuffer,
55}
56
57impl Handle for PagerHandle {
58    type OpenError = TwzError;
59
60    type OpenInfo = ();
61
62    fn open(_info: Self::OpenInfo) -> Result<Self>
63    where
64        Self: Sized,
65    {
66        let (desc, id) = (pager_api().open_handle)()?;
67        let handle =
68            twizzler_rt_abi::object::twz_rt_map_object(id, MapFlags::READ | MapFlags::WRITE)?;
69        let sb = SimpleBuffer::new(handle);
70        Ok(Self { desc, buffer: sb })
71    }
72
73    fn release(&mut self) {
74        let _ = (pager_api().close_handle)(self.desc);
75    }
76}
77
78// On drop, release the handle.
79impl Drop for PagerHandle {
80    fn drop(&mut self) {
81        self.release()
82    }
83}
84
85impl PagerHandle {
86    /// Open a new logging handle.
87    pub fn new() -> Option<Self> {
88        Self::open(()).ok()
89    }
90
91    pub fn enumerate_external(&mut self, id: ObjID) -> Result<Vec<ExternalFile>> {
92        let len = (pager_api().enumerate_external)(self.desc, id)?;
93
94        let mut off = 0;
95        let mut v = Vec::new();
96        while off < len {
97            let mut file = std::mem::MaybeUninit::<ExternalFile>::uninit();
98            let ptr = file.as_mut_ptr().cast::<u8>();
99            let slice = unsafe {
100                core::slice::from_raw_parts_mut(ptr, std::mem::size_of::<ExternalFile>())
101            };
102            let thislen = self.buffer.read_offset(slice, off);
103
104            if thislen < std::mem::size_of::<ExternalFile>() {
105                break;
106            }
107
108            unsafe {
109                v.push(file.assume_init());
110            }
111
112            off += thislen;
113        }
114        Ok(v)
115    }
116}