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
78impl Drop for PagerHandle {
80 fn drop(&mut self) {
81 self.release()
82 }
83}
84
85impl PagerHandle {
86 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}