kernel/object/handle/
mod.rs1use alloc::vec::Vec;
2
3use crate::object::{introspection, KernelObject};
4
5pub mod syscall;
6
7#[cfg(test)]
8mod tests;
9
10pub type Handle = u32;
12
13#[derive(Clone)]
14pub struct HandleTable {
15 handles: [Option<KernelObject>; Self::MAX_HANDLES],
17 metadata: [Option<HandleMetadata>; Self::MAX_HANDLES],
19 free_handles: Vec<Handle>,
21}
22
23impl HandleTable {
24 const MAX_HANDLES: usize = 1024; pub fn new() -> Self {
27 let mut free_handles = Vec::with_capacity(Self::MAX_HANDLES);
29 for handle in (0..Self::MAX_HANDLES as Handle).rev() {
30 free_handles.push(handle);
31 }
32
33 Self {
34 handles: [const { None }; Self::MAX_HANDLES],
35 metadata: [const { None }; Self::MAX_HANDLES],
36 free_handles,
37 }
38 }
39
40 pub fn insert(&mut self, obj: KernelObject) -> Result<Handle, &'static str> {
42 let metadata = Self::infer_metadata_from_object(&obj);
43 self.insert_with_metadata(obj, metadata)
44 }
45
46 pub fn insert_with_metadata(&mut self, obj: KernelObject, metadata: HandleMetadata) -> Result<Handle, &'static str> {
48 if let Some(handle) = self.free_handles.pop() {
49 self.handles[handle as usize] = Some(obj);
50 self.metadata[handle as usize] = Some(metadata);
51 Ok(handle)
52 } else {
53 Err("Too many open KernelObjects, limit reached")
54 }
55 }
56
57 fn infer_metadata_from_object(object: &KernelObject) -> HandleMetadata {
62 let handle_type = match object {
63 KernelObject::Pipe(_) => {
64 HandleType::IpcChannel
67 }
68 KernelObject::File(_file_obj) => {
69 HandleType::Regular
74 }
75 };
76
77 HandleMetadata {
78 handle_type,
79 access_mode: AccessMode::ReadWrite, special_semantics: None, }
82 }
83
84 pub fn get(&self, handle: Handle) -> Option<&KernelObject> {
86 if handle as usize >= Self::MAX_HANDLES {
87 return None;
88 }
89 self.handles[handle as usize].as_ref()
90 }
91
92 pub fn remove(&mut self, handle: Handle) -> Option<KernelObject> {
94 if handle as usize >= Self::MAX_HANDLES {
95 return None;
96 }
97
98 if let Some(obj) = self.handles[handle as usize].take() {
99 self.metadata[handle as usize] = None; self.free_handles.push(handle); Some(obj)
102 } else {
103 None
104 }
105 }
106
107 pub fn update_metadata(&mut self, handle: Handle, new_metadata: HandleMetadata) -> Result<(), &'static str> {
109 if handle as usize >= Self::MAX_HANDLES {
110 return Err("Invalid handle");
111 }
112
113 if self.handles[handle as usize].is_some() {
114 self.metadata[handle as usize] = Some(new_metadata);
115 Ok(())
116 } else {
117 Err("Handle does not exist")
118 }
119 }
120
121 pub fn open_count(&self) -> usize {
123 Self::MAX_HANDLES - self.free_handles.len()
124 }
125
126 pub fn active_handles(&self) -> Vec<Handle> {
128 self.handles
129 .iter()
130 .enumerate()
131 .filter_map(|(i, handle)| {
132 if handle.is_some() {
133 Some(i as Handle)
134 } else {
135 None
136 }
137 })
138 .collect()
139 }
140
141 pub fn close_all(&mut self) {
143 for (i, handle) in self.handles.iter_mut().enumerate() {
144 if let Some(_obj) = handle.take() {
145 self.metadata[i] = None; self.free_handles.push(i as Handle);
148 }
149 }
150 }
151
152 pub fn is_valid_handle(&self, handle: Handle) -> bool {
154 if handle as usize >= Self::MAX_HANDLES {
155 return false;
156 }
157 self.handles[handle as usize].is_some()
158 }
159
160 pub fn get_metadata(&self, handle: Handle) -> Option<&HandleMetadata> {
162 if handle as usize >= Self::MAX_HANDLES {
163 return None;
164 }
165 self.metadata[handle as usize].as_ref()
166 }
167
168 pub fn iter_with_metadata(&self) -> impl Iterator<Item = (Handle, &KernelObject, &HandleMetadata)> {
170 self.handles.iter().enumerate()
171 .filter_map(|(i, obj)| {
172 obj.as_ref().and_then(|o| {
173 self.metadata[i].as_ref().map(|m| (i as Handle, o, m))
174 })
175 })
176 }
177
178 pub fn get_object_info(&self, handle: Handle) -> Option<introspection::KernelObjectInfo> {
180 if let Some(kernel_obj) = self.get(handle) {
181 let metadata = self.get_metadata(handle)?;
182 let handle_role = introspection::HandleRole::from(metadata.handle_type.clone());
183 let (readable, writable) = metadata.access_mode.into();
184
185 match kernel_obj {
186 KernelObject::File(_) => {
187 Some(introspection::KernelObjectInfo::for_file(handle_role, readable, writable))
188 }
189 KernelObject::Pipe(_) => {
190 Some(introspection::KernelObjectInfo::for_pipe(handle_role, readable, writable))
191 }
192 }
193 } else {
194 None
195 }
196 }
197}
198
199impl Default for HandleTable {
200 fn default() -> Self {
201 Self::new()
202 }
203}
204
205#[derive(Clone, Debug)]
238pub struct HandleMetadata {
239 pub handle_type: HandleType,
240 pub access_mode: AccessMode,
241 pub special_semantics: Option<SpecialSemantics>,
242}
243
244#[derive(Clone, Debug, PartialEq)]
249pub enum HandleType {
250 StandardInputOutput(StandardInputOutput),
252 IpcChannel,
254 Regular,
256}
257
258#[derive(Clone, Debug, PartialEq)]
259pub enum StandardInputOutput {
260 Stdin,
261 Stdout,
262 Stderr,
263}
264
265#[derive(Clone, Debug, PartialEq, Copy)]
266pub enum AccessMode {
267 ReadOnly,
268 WriteOnly,
269 ReadWrite,
270}
271
272#[derive(Clone, Debug, PartialEq)]
274pub enum SpecialSemantics {
275 CloseOnExec, NonBlocking, Append, Sync, }
280
281impl Default for HandleMetadata {
282 fn default() -> Self {
283 Self {
284 handle_type: HandleType::Regular,
285 access_mode: AccessMode::ReadWrite,
286 special_semantics: None,
287 }
288 }
289}