1use std::path::Path;
2
3use secgate::util::{Handle, SimpleBuffer};
4use twizzler::object::ObjID;
5use twizzler_rt_abi::{
6 error::{ArgumentError, TwzError},
7 object::MapFlags,
8};
9
10use crate::{api::NamerAPI, GetFlags, NsNode, Result, PATH_MAX};
11
12pub struct NamingHandle<'a, API: NamerAPI> {
13 desc: u32,
14 buffer: SimpleBuffer,
15 api: &'a API,
16}
17
18impl<'a, API: NamerAPI> Drop for NamingHandle<'a, API> {
19 fn drop(&mut self) {
20 self.release();
21 }
22}
23
24impl<'a, API: NamerAPI> NamingHandle<'a, API> {
26 fn write_buffer<P: AsRef<Path>>(&mut self, path: P) -> Result<usize> {
27 let bytes = path.as_ref().as_os_str().as_encoded_bytes();
28 if bytes.len() > PATH_MAX {
29 Err(ArgumentError::InvalidArgument.into())
30 } else {
31 Ok(self.buffer.write(bytes))
32 }
33 }
34
35 fn write_buffer_at<P: AsRef<Path>>(&mut self, path: P, off: usize) -> Result<usize> {
36 let bytes = path.as_ref().as_os_str().as_encoded_bytes();
37 if bytes.len() > PATH_MAX {
38 Err(ArgumentError::InvalidArgument.into())
39 } else {
40 Ok(self.buffer.write_offset(bytes, off))
41 }
42 }
43
44 pub fn new(api: &'a API) -> Option<Self> {
46 NamingHandle::open(api).ok()
47 }
48
49 pub fn put<P: AsRef<Path>>(&mut self, path: P, id: ObjID) -> Result<()> {
50 let name_len = self.write_buffer(path)?;
51 self.api.put(self.desc, name_len, id)
52 }
53
54 pub fn get(&mut self, path: &str, flags: GetFlags) -> Result<NsNode> {
55 let name_len = self.write_buffer(path)?;
56 self.api.get(self.desc, name_len, flags)
57 }
58
59 pub fn remove(&mut self, path: &str) -> Result<()> {
60 let name_len = self.write_buffer(path)?;
61 self.api.remove(self.desc, name_len)
62 }
63
64 pub fn enumerate_names_nsid(&mut self, nsid: ObjID) -> Result<Vec<NsNode>> {
65 let element_count = self.api.enumerate_names_nsid(self.desc, nsid)?;
66
67 let mut buf_vec = vec![0u8; element_count * std::mem::size_of::<NsNode>()];
68 self.buffer.read(&mut buf_vec);
69 let mut r_vec = Vec::new();
70
71 for i in 0..element_count {
72 unsafe {
73 let entry_ptr = buf_vec
74 .as_ptr()
75 .offset((std::mem::size_of::<NsNode>() * i).try_into().unwrap())
76 as *const NsNode;
77 r_vec.push(*entry_ptr);
78 }
79 }
80
81 Ok(r_vec)
82 }
83
84 pub fn enumerate_names_relative<P: AsRef<Path>>(&mut self, path: P) -> Result<Vec<NsNode>> {
85 let name_len = self.write_buffer(path)?;
86 let element_count = self.api.enumerate_names(self.desc, name_len)?;
87
88 let mut buf_vec = vec![0u8; element_count * std::mem::size_of::<NsNode>()];
89 self.buffer.read(&mut buf_vec);
90 let mut r_vec = Vec::new();
91
92 for i in 0..element_count {
93 unsafe {
94 let entry_ptr = buf_vec
95 .as_ptr()
96 .offset((std::mem::size_of::<NsNode>() * i).try_into().unwrap())
97 as *const NsNode;
98 r_vec.push(*entry_ptr);
99 }
100 }
101
102 Ok(r_vec)
103 }
104
105 pub fn enumerate_names(&mut self) -> Result<Vec<NsNode>> {
106 self.enumerate_names_relative(&".")
107 }
108
109 pub fn change_namespace<P: AsRef<Path>>(&mut self, path: P) -> Result<()> {
110 let name_len = self.write_buffer(path)?;
111 self.api.change_namespace(self.desc, name_len)
112 }
113
114 pub fn put_namespace<P: AsRef<Path>>(&mut self, path: P, persist: bool) -> Result<()> {
115 let name_len = self.write_buffer(path)?;
116 self.api.mkns(self.desc, name_len, persist)
117 }
118
119 pub fn symlink<P: AsRef<Path>, L: AsRef<Path>>(&mut self, path: P, link: L) -> Result<()> {
120 let name_len = self.write_buffer(path)?;
121 let link_len = self.write_buffer_at(link, name_len)?;
122 self.api.link(self.desc, name_len, link_len)
123 }
124}
125
126impl<'a, API: NamerAPI> Handle for NamingHandle<'a, API> {
127 type OpenError = TwzError;
128
129 type OpenInfo = &'a API;
130
131 fn open(info: Self::OpenInfo) -> std::result::Result<Self, Self::OpenError>
132 where
133 Self: Sized,
134 {
135 let (desc, id) = info.open_handle()?;
136 let handle =
137 twizzler_rt_abi::object::twz_rt_map_object(id, MapFlags::READ | MapFlags::WRITE)?;
138 let sb = SimpleBuffer::new(handle);
139 Ok(Self {
140 desc,
141 buffer: sb,
142 api: info,
143 })
144 }
145
146 fn release(&mut self) {
147 let _ = self
148 .api
149 .close_handle(self.desc)
150 .inspect_err(|e| tracing::warn!("{}", e));
151 }
152}