1use async_io::block_on;
2use object_store::ExternalFile;
3use secgate::{
4 secure_gate,
5 util::{Descriptor, SimpleBuffer},
6};
7use twizzler::object::ObjID;
8use twizzler_abi::{
9 object::Protections,
10 syscall::{sys_object_create, BackingType, LifetimeType, ObjectCreate, ObjectCreateFlags},
11};
12use twizzler_rt_abi::{error::TwzError, object::MapFlags};
13
14use crate::{EXECUTOR, PAGER_CTX};
15
16pub(crate) struct PagerClient {
18 buffer: SimpleBuffer,
19}
20
21impl PagerClient {
22 fn sbid(&self) -> ObjID {
23 self.buffer.handle().id()
24 }
25}
26
27impl PagerClient {
28 pub fn new() -> Result<Self, TwzError> {
29 let id = sys_object_create(
31 ObjectCreate::new(
32 BackingType::Normal,
33 LifetimeType::Volatile,
34 None,
35 ObjectCreateFlags::empty(),
36 Protections::all(),
37 ),
38 &[],
39 &[],
40 )?;
41 let handle =
42 twizzler_rt_abi::object::twz_rt_map_object(id, MapFlags::WRITE | MapFlags::READ)?;
43 let buffer = SimpleBuffer::new(handle);
44 Ok(Self { buffer })
45 }
46}
47
48#[secure_gate(options(info))]
49pub fn pager_open_handle(info: &secgate::GateCallInfo) -> Result<(Descriptor, ObjID), TwzError> {
50 let comp = info.source_context().unwrap_or(0.into());
51 let pager = &PAGER_CTX.get().unwrap().data;
52 let handle = pager.new_handle(comp)?;
53 let id = pager.with_handle(comp, handle, |pc| pc.sbid())?;
54
55 Ok((handle, id))
56}
57
58#[secure_gate(options(info))]
59pub fn pager_close_handle(info: &secgate::GateCallInfo, desc: Descriptor) -> Result<(), TwzError> {
60 let comp = info.source_context().unwrap_or(0.into());
61 let pager = &PAGER_CTX.get().unwrap().data;
62 pager.drop_handle(comp, desc);
63 Ok(())
64}
65
66#[secure_gate(options(info))]
67pub fn pager_enumerate_external(
68 info: &secgate::GateCallInfo,
69 desc: Descriptor,
70 id: ObjID,
71) -> Result<usize, TwzError> {
72 let comp = info.source_context().unwrap_or(0.into());
73 let pager = &PAGER_CTX.get().unwrap();
74
75 let items = block_on(EXECUTOR.get().unwrap().run(pager.enumerate_external(id)))?;
76
77 pager
78 .data
79 .with_handle_mut(comp, desc, |pc| {
80 let mut len = 0;
81 for (idx, item) in items.iter().enumerate() {
82 let ptr = item as *const ExternalFile;
83 let bytes = unsafe {
84 core::slice::from_raw_parts(ptr.cast::<u8>(), size_of::<ExternalFile>())
85 };
86 len += pc
87 .buffer
88 .write_offset(bytes, idx * size_of::<ExternalFile>());
89 }
90 len
91 })
92 .ok_or(TwzError::INVALID_ARGUMENT)
93}