pager_srv/
handle.rs

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
16// Per-client metadata.
17pub(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        // Create and map a handle for the simple buffer.
30        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}