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(
65 &mut self,
66 nsid: ObjID,
67 skip: usize,
68 count: usize,
69 ) -> Result<Vec<NsNode>> {
70 tracing::trace!(
71 "enumerating namespace {} (skip {}, count {})",
72 nsid,
73 skip,
74 count
75 );
76 let element_count = self
77 .api
78 .enumerate_names_nsid(self.desc, nsid, skip, count)?;
79
80 let mut buf_vec = vec![0u8; element_count * std::mem::size_of::<NsNode>()];
81 self.buffer.read(&mut buf_vec);
82 let mut r_vec = Vec::new();
83
84 for i in 0..element_count {
85 unsafe {
86 let entry_ptr = buf_vec
87 .as_ptr()
88 .offset((std::mem::size_of::<NsNode>() * i).try_into().unwrap())
89 as *const NsNode;
90 r_vec.push(*entry_ptr);
91 }
92 }
93
94 Ok(r_vec)
95 }
96
97 pub fn enumerate_names_relative<P: AsRef<Path>>(
98 &mut self,
99 path: P,
100 skip: usize,
101 count: usize,
102 ) -> Result<Vec<NsNode>> {
103 let name_len = self.write_buffer(path)?;
104 let element_count = self.api.enumerate_names(self.desc, name_len, skip, count)?;
105
106 let mut buf_vec = vec![0u8; element_count * std::mem::size_of::<NsNode>()];
107 self.buffer.read(&mut buf_vec);
108 let mut r_vec = Vec::new();
109
110 for i in 0..element_count {
111 unsafe {
112 let entry_ptr = buf_vec
113 .as_ptr()
114 .offset((std::mem::size_of::<NsNode>() * i).try_into().unwrap())
115 as *const NsNode;
116 r_vec.push(*entry_ptr);
117 }
118 }
119
120 Ok(r_vec)
121 }
122
123 pub fn enumerate_names(&mut self, skip: usize, count: usize) -> Result<Vec<NsNode>> {
124 self.enumerate_names_relative(&".", skip, count)
125 }
126
127 pub fn change_namespace<P: AsRef<Path>>(&mut self, path: P) -> Result<()> {
128 let name_len = self.write_buffer(path)?;
129 self.api.change_namespace(self.desc, name_len)
130 }
131
132 pub fn put_namespace<P: AsRef<Path>>(&mut self, path: P, persist: bool) -> Result<()> {
133 let name_len = self.write_buffer(path)?;
134 self.api.mkns(self.desc, name_len, persist)
135 }
136
137 pub fn rename<P: AsRef<Path>, Q: AsRef<Path>>(&mut self, old: P, new: Q) -> Result<()> {
138 let old_len = self.write_buffer(old)?;
139 let new_len = self.write_buffer_at(new, old_len)?;
140 self.api.rename(self.desc, old_len, new_len)
141 }
142
143 pub fn symlink<P: AsRef<Path>, L: AsRef<Path>>(&mut self, path: P, link: L) -> Result<()> {
144 let name_len = self.write_buffer(path)?;
145 let link_len = self.write_buffer_at(link, name_len)?;
146 self.api.link(self.desc, name_len, link_len)
147 }
148}
149
150impl<'a, API: NamerAPI> Handle for NamingHandle<'a, API> {
151 type OpenError = TwzError;
152
153 type OpenInfo = &'a API;
154
155 fn open(info: Self::OpenInfo) -> std::result::Result<Self, Self::OpenError>
156 where
157 Self: Sized,
158 {
159 let (desc, id) = info.open_handle()?;
160 let handle =
161 twizzler_rt_abi::object::twz_rt_map_object(id, MapFlags::READ | MapFlags::WRITE)?;
162 let sb = SimpleBuffer::new(handle);
163 Ok(Self {
164 desc,
165 buffer: sb,
166 api: info,
167 })
168 }
169
170 fn release(&mut self) {
171 let _ = self
172 .api
173 .close_handle(self.desc)
174 .inspect_err(|e| tracing::warn!("{}", e));
175 }
176}