naming_core/
handle.rs

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
24// TODO don't need seperate functions for names and namespaces?
25impl<'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    /// Open a new logging handle.
45    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}