1use std::sync::OnceLock;
2
3use monitor_api::CompartmentHandle;
4use secgate::{util::Descriptor, DynamicSecGate};
5use twizzler_rt_abi::object::ObjID;
6
7use crate::{api::NamerAPI, handle::NamingHandle, GetFlags, NsNode, Result};
8
9pub struct DynamicNamerAPI {
10 _handle: &'static CompartmentHandle,
11 put: DynamicSecGate<'static, (Descriptor, usize, ObjID), ()>,
12 mkns: DynamicSecGate<'static, (Descriptor, usize, bool), ()>,
13 link: DynamicSecGate<'static, (Descriptor, usize, usize), ()>,
14 get: DynamicSecGate<'static, (Descriptor, usize, GetFlags), NsNode>,
15 open_handle: DynamicSecGate<'static, (), (Descriptor, ObjID)>,
16 close_handle: DynamicSecGate<'static, (Descriptor,), ()>,
17 enumerate_names: DynamicSecGate<'static, (Descriptor, usize, usize, usize), usize>,
18 enumerate_names_nsid: DynamicSecGate<'static, (Descriptor, ObjID, usize, usize), usize>,
19 remove: DynamicSecGate<'static, (Descriptor, usize), ()>,
20 rename: DynamicSecGate<'static, (Descriptor, usize, usize), ()>,
21 change_namespace: DynamicSecGate<'static, (Descriptor, usize), ()>,
22}
23
24impl NamerAPI for DynamicNamerAPI {
25 fn put(&self, desc: Descriptor, name_len: usize, id: ObjID) -> Result<()> {
26 (self.put)(desc, name_len, id)
27 }
28
29 fn get(&self, desc: Descriptor, name_len: usize, flags: GetFlags) -> Result<NsNode> {
30 (self.get)(desc, name_len, flags)
31 }
32
33 fn open_handle(&self) -> Result<(Descriptor, ObjID)> {
34 (self.open_handle)()
35 }
36
37 fn close_handle(&self, desc: Descriptor) -> Result<()> {
38 let _ = (self.close_handle)(desc);
39 Ok(())
40 }
41
42 fn enumerate_names(
43 &self,
44 desc: Descriptor,
45 name_len: usize,
46 skip: usize,
47 count: usize,
48 ) -> Result<usize> {
49 (self.enumerate_names)(desc, name_len, skip, count)
50 }
51
52 fn enumerate_names_nsid(
53 &self,
54 desc: Descriptor,
55 id: ObjID,
56 skip: usize,
57 count: usize,
58 ) -> Result<usize> {
59 (self.enumerate_names_nsid)(desc, id, skip, count)
60 }
61
62 fn remove(&self, desc: Descriptor, name_len: usize) -> Result<()> {
63 (self.remove)(desc, name_len)
64 }
65
66 fn rename(&self, desc: Descriptor, old_len: usize, new_len: usize) -> Result<()> {
67 (self.rename)(desc, old_len, new_len)
68 }
69
70 fn change_namespace(&self, desc: Descriptor, name_len: usize) -> Result<()> {
71 (self.change_namespace)(desc, name_len)
72 }
73
74 fn mkns(&self, desc: Descriptor, name_len: usize, persist: bool) -> Result<()> {
75 (self.mkns)(desc, name_len, persist)
76 }
77
78 fn link(&self, desc: Descriptor, name_len: usize, link_name: usize) -> Result<()> {
79 (self.link)(desc, name_len, link_name)
80 }
81}
82
83static DYNAMIC_NAMER_API: OnceLock<DynamicNamerAPI> = OnceLock::new();
84
85pub fn dynamic_namer_api() -> &'static DynamicNamerAPI {
86 DYNAMIC_NAMER_API.get_or_init(|| {
87 let handle = Box::leak(Box::new(
88 CompartmentHandle::lookup("naming").expect("failed to open namer compartment"),
89 ));
90 DynamicNamerAPI {
91 _handle: handle,
92 put: unsafe {
93 handle
94 .dynamic_gate("put")
95 .expect("failed to find put gate call")
96 },
97 mkns: unsafe {
98 handle
99 .dynamic_gate("mkns")
100 .expect("failed to find put gate call")
101 },
102 link: unsafe {
103 handle
104 .dynamic_gate("link")
105 .expect("failed to find put gate call")
106 },
107 get: unsafe {
108 handle
109 .dynamic_gate("get")
110 .expect("failed to find get gate call")
111 },
112 open_handle: unsafe {
113 handle
114 .dynamic_gate::<(), (Descriptor, ObjID)>("open_handle")
115 .expect("failed to find open_handle gate call")
116 },
117 close_handle: unsafe {
118 handle
119 .dynamic_gate::<(Descriptor,), ()>("close_handle")
120 .expect("failed to find close_handle gate call")
121 },
122 enumerate_names: unsafe {
123 handle
124 .dynamic_gate("enumerate_names")
125 .expect("failed to find enumerate_names gate call")
126 },
127 enumerate_names_nsid: unsafe {
128 handle
129 .dynamic_gate("enumerate_names_nsid")
130 .expect("failed to find enumerate_names gate call")
131 },
132 remove: unsafe {
133 handle
134 .dynamic_gate("remove")
135 .expect("failed to find remove gate call")
136 },
137 rename: unsafe {
138 handle
139 .dynamic_gate("rename")
140 .expect("failed to find rename gate call")
141 },
142 change_namespace: unsafe {
143 handle
144 .dynamic_gate("change_namespace")
145 .expect("failed to find change_namespace gate call")
146 },
147 }
148 })
149}
150
151pub type DynamicNamingHandle = NamingHandle<'static, DynamicNamerAPI>;
152
153pub fn dynamic_naming_factory() -> Option<DynamicNamingHandle> {
154 NamingHandle::new(dynamic_namer_api())
155}