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(&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}