diskit/virtual_diskit/
helpers.rs1use std::{
2 collections::HashMap,
3 ffi::{OsStr, OsString},
4 io::{Error, ErrorKind},
5 path::{Component, Path},
6};
7
8use super::implementation::{Inode, InodeInner, VirtualDiskitInner};
9
10impl VirtualDiskitInner
11{
12 pub fn get_inode_by_id(&self, id: usize) -> Result<&Inode, Error>
13 {
14 if self.content.len() <= id
15 {
16 Err(ErrorKind::NotFound.into())
17 }
18 else
19 {
20 Ok(&self.content[id])
21 }
22 }
23
24 pub fn get_mut_inode_by_id(&mut self, id: usize) -> Result<&mut Inode, Error>
25 {
26 if self.content.len() <= id
27 {
28 Err(ErrorKind::NotFound.into())
29 }
30 else
31 {
32 Ok(&mut self.content[id])
33 }
34 }
35
36 pub fn get_inode_by_path_and_dir(
37 &self,
38 dir: &HashMap<OsString, usize>,
39 path: &OsStr,
40 ) -> Result<&Inode, Error>
41 {
42 self.get_inode_by_id(*dir.get(path).ok_or(ErrorKind::NotFound)?)
43 }
44
45 pub fn get_inode_by_path_and_inode(&self, inode: &Inode, path: &OsStr)
46 -> Result<&Inode, Error>
47 {
48 if let InodeInner::Dir(dir) = &inode.inner
49 {
50 self.get_inode_by_path_and_dir(dir, path)
51 }
52 else
53 {
54 Err(From::from(ErrorKind::NotADirectory))
55 }
56 }
57
58 pub fn get_first_walkdir_pos(
59 &self,
60 path: &Path,
61 contents_first: bool,
62 ) -> Result<Vec<usize>, Error>
63 {
64 if !contents_first
65 {
66 return Ok(vec![]);
67 }
68
69 let mut inode = self
70 .get_inode_by_full_path(path)
71 .and_then(|x| x.map_err(|_| ErrorKind::NotFound.into()))?;
72 let mut rv = 0;
73
74 while let Some((_, inode_id)) = Self::get_dir_as_iterator(inode)
75 .ok()
76 .and_then(|mut x| x.next())
77 {
78 inode = self.get_inode_by_id(*inode_id)?;
79 rv += 1;
80 }
81
82 Ok(vec![0; rv])
83 }
84
85 pub fn get_dir_from_inode(inode: &Inode) -> Result<&HashMap<OsString, usize>, Error>
86 {
87 match &inode.inner
88 {
89 InodeInner::Dir(dir) => Ok(dir),
90 _ => Err(ErrorKind::NotADirectory.into()),
91 }
92 }
93
94 pub fn get_reference_to_pwd(&self) -> Result<&Inode, Error>
95 {
96 let mut inode = &self.content[0];
97
98 for component in self.pwd.components().skip(1)
99 {
100 match component
101 {
102 Component::ParentDir =>
103 {
104 inode = self.get_inode_by_path_and_dir(
105 Self::get_dir_from_inode(inode)?,
106 OsStr::new(".."),
107 )?;
108 }
109 Component::Normal(path) =>
110 {
111 inode =
112 self.get_inode_by_path_and_dir(Self::get_dir_from_inode(inode)?, path)?;
113 }
114 Component::CurDir =>
116 {}
117 _ => panic!("Windows is not supported"),
122 }
123 }
124
125 let _ = Self::get_dir_from_inode(inode)?;
127
128 Ok(inode)
129 }
130
131 pub fn get_inode_by_full_path(&self, path: &Path) -> Result<Result<&Inode, &Inode>, Error>
132 {
133 let mut inode = if path.starts_with("/")
134 {
135 &self.content[0]
136 }
137 else
138 {
139 self.get_reference_to_pwd()?
140 };
141
142 let mut not_found = false;
143
144 for component in path.components()
145 {
146 if not_found
147 {
148 return Err(ErrorKind::NotFound.into());
149 }
150
151 if !matches!(inode.inner, InodeInner::Dir(_))
152 {
153 return Err(ErrorKind::NotADirectory.into());
155 }
156
157 inode = match component
158 {
159 Component::CurDir => self.get_inode_by_path_and_inode(inode, OsStr::new("."))?,
160 Component::ParentDir =>
161 {
162 self.get_inode_by_path_and_inode(inode, OsStr::new(".."))?
163 }
164 Component::Normal(path) =>
165 {
166 let val = self.get_inode_by_path_and_inode(inode, path);
167
168 if val
169 .as_ref()
170 .err()
171 .map_or(false, |x| x.kind() == ErrorKind::NotFound)
172 {
173 not_found = true;
174 continue;
175 }
176
177 val?
178 }
179 Component::RootDir => &self.content[0],
180 Component::Prefix(_) => panic!("Windows is not supported"),
181 };
182 }
183
184 if not_found
185 {
186 return Ok(Err(inode));
187 }
188
189 Ok(Ok(inode))
190 }
191
192 pub fn get_dir_as_iterator(
193 inode: &Inode,
194 ) -> Result<impl Iterator<Item = (&OsString, &usize)>, Error>
195 {
196 Ok(Self::get_dir_from_inode(inode)?
197 .iter()
198 .filter(|(path, _)| *path != "." && *path != ".."))
199 }
200
201 pub fn check_pos_path(&self, root_inode: &Inode, pos: &[usize]) -> Option<()>
202 {
203 let mut inode = root_inode;
204
205 for &index in pos
206 {
207 let (_, &content_inode) = Self::get_dir_as_iterator(inode).ok()?.nth(index)?;
208
209 inode = self.get_inode_by_id(content_inode).ok()?;
210 }
211
212 Some(())
213 }
214}
215
216#[cfg(feature = "trash")]
218impl VirtualDiskitInner
219{
220 pub fn get_mut_dir_from_inode(inode: &mut Inode)
221 -> Result<&mut HashMap<OsString, usize>, Error>
222 {
223 match &mut inode.inner
224 {
225 InodeInner::Dir(dir) => Ok(dir),
226 _ => Err(ErrorKind::NotADirectory.into()),
227 }
228 }
229
230 pub fn get_dir_by_id(&self, inode: usize) -> Result<&HashMap<OsString, usize>, Error>
231 {
232 match &self.content[inode].inner
233 {
234 InodeInner::Dir(dir) => Ok(dir),
235 _ => Err(ErrorKind::NotADirectory.into()),
236 }
237 }
238
239 pub fn get_mut_inode_by_full_path(&mut self, path: &Path) -> Result<&mut Inode, Error>
240 {
241 self.get_mut_inode_by_id(
242 self.get_inode_by_full_path(path)?
243 .map_err(|_| ErrorKind::NotFound)?
244 .id,
245 )
246 }
247
248 pub fn collect_inodes(&self, inode: &Inode, vec: &mut Vec<usize>) -> Result<(), Error>
249 {
250 vec.push(inode.id);
251 if let InodeInner::Dir(dir) = &inode.inner
252 {
253 dir.iter()
254 .map(|(_, &id)| {
255 self.get_inode_by_id(id)
256 .and_then(|inode| self.collect_inodes(inode, vec))
257 })
258 .collect::<Result<Vec<_>, _>>()?;
259 }
260
261 Ok(())
262 }
263}