1use std::collections::HashMap;
10use std::sync::{Arc, Mutex};
11use std::time::{Duration, SystemTime};
12
13use uuid::Uuid;
14use xmltree::Element;
15
16use crate::davpath::DavPath;
17use crate::fs::FsResult;
18use crate::ls::*;
19use crate::tree;
20
21type Tree = tree::Tree<Vec<u8>, Vec<DavLock>>;
22
23#[derive(Debug, Clone)]
25pub struct MemLs(Arc<Mutex<MemLsInner>>);
26
27#[derive(Debug)]
28struct MemLsInner {
29 tree: Tree,
30 locks: HashMap<Vec<u8>, u64>,
31}
32
33impl MemLs {
34 pub fn new() -> Box<MemLs> {
36 let inner = MemLsInner {
37 tree: Tree::new(Vec::new()),
38 locks: HashMap::new(),
39 };
40 Box::new(MemLs(Arc::new(Mutex::new(inner))))
41 }
42}
43
44impl DavLockSystem for MemLs {
45 fn lock(
46 &self,
47 path: &DavPath,
48 principal: Option<&str>,
49 owner: Option<&Element>,
50 timeout: Option<Duration>,
51 shared: bool,
52 deep: bool,
53 ) -> Result<DavLock, DavLock>
54 {
55 let inner = &mut *self.0.lock().unwrap();
56
57 let rc = check_locks_to_path(&inner.tree, path, None, true, &Vec::new(), shared);
59 trace!("lock: check_locks_to_path: {:?}", rc);
60 rc?;
61
62 if deep {
64 let rc = check_locks_from_path(&inner.tree, path, None, true, &Vec::new(), shared);
65 trace!("lock: check_locks_from_path: {:?}", rc);
66 rc?;
67 }
68
69 let node = get_or_create_path_node(&mut inner.tree, path);
71 let timeout_at = match timeout {
72 None => None,
73 Some(d) => Some(SystemTime::now() + d),
74 };
75 let lock = DavLock {
76 token: Uuid::new_v4().to_urn().to_string(),
77 path: path.clone(),
78 principal: principal.map(|s| s.to_string()),
79 owner: owner.cloned(),
80 timeout_at: timeout_at,
81 timeout: timeout,
82 shared: shared,
83 deep: deep,
84 };
85 trace!("lock {} created", &lock.token);
86 let slock = lock.clone();
87 node.push(slock);
88 Ok(lock)
89 }
90
91 fn unlock(&self, path: &DavPath, token: &str) -> Result<(), ()> {
92 let inner = &mut *self.0.lock().unwrap();
93 let node_id = match lookup_lock(&inner.tree, path, token) {
94 None => {
95 trace!("unlock: {} not found at {}", token, path);
96 return Err(());
97 },
98 Some(n) => n,
99 };
100 let len = {
101 let node = inner.tree.get_node_mut(node_id).unwrap();
102 let idx = node.iter().position(|n| n.token.as_str() == token).unwrap();
103 node.remove(idx);
104 node.len()
105 };
106 if len == 0 {
107 inner.tree.delete_node(node_id).ok();
108 }
109 Ok(())
110 }
111
112 fn refresh(&self, path: &DavPath, token: &str, timeout: Option<Duration>) -> Result<DavLock, ()> {
113 trace!("refresh lock {}", token);
114 let inner = &mut *self.0.lock().unwrap();
115 let node_id = match lookup_lock(&inner.tree, path, token) {
116 None => {
117 trace!("lock not found");
118 return Err(());
119 },
120 Some(n) => n,
121 };
122 let node = (&mut inner.tree).get_node_mut(node_id).unwrap();
123 let idx = node.iter().position(|n| n.token.as_str() == token).unwrap();
124 let lock = &mut node[idx];
125 let timeout_at = match timeout {
126 None => None,
127 Some(d) => Some(SystemTime::now() + d),
128 };
129 lock.timeout = timeout;
130 lock.timeout_at = timeout_at;
131 Ok(lock.clone())
132 }
133
134 fn check(
135 &self,
136 path: &DavPath,
137 principal: Option<&str>,
138 ignore_principal: bool,
139 deep: bool,
140 submitted_tokens: Vec<&str>,
141 ) -> Result<(), DavLock>
142 {
143 let inner = &*self.0.lock().unwrap();
144 let _st = submitted_tokens.clone();
145 let rc = check_locks_to_path(
146 &inner.tree,
147 path,
148 principal,
149 ignore_principal,
150 &submitted_tokens,
151 false,
152 );
153 trace!("check: check_lock_to_path: {:?}: {:?}", _st, rc);
154 rc?;
155
156 if deep {
158 let rc = check_locks_from_path(
159 &inner.tree,
160 path,
161 principal,
162 ignore_principal,
163 &submitted_tokens,
164 false,
165 );
166 trace!("check: check_locks_from_path: {:?}", rc);
167 rc?;
168 }
169 Ok(())
170 }
171
172 fn discover(&self, path: &DavPath) -> Vec<DavLock> {
173 let inner = &*self.0.lock().unwrap();
174 list_locks(&inner.tree, path)
175 }
176
177 fn delete(&self, path: &DavPath) -> Result<(), ()> {
178 let inner = &mut *self.0.lock().unwrap();
179 if let Some(node_id) = lookup_node(&inner.tree, path) {
180 (&mut inner.tree).delete_subtree(node_id).ok();
181 }
182 Ok(())
183 }
184}
185
186fn check_locks_to_path(
188 tree: &Tree,
189 path: &DavPath,
190 principal: Option<&str>,
191 ignore_principal: bool,
192 submitted_tokens: &Vec<&str>,
193 shared_ok: bool,
194) -> Result<(), DavLock>
195{
196 let segs = path_to_segs(path, true);
198 let last_seg = segs.len() - 1;
199
200 let mut holds_lock = false;
202 let mut first_lock_seen: Option<&DavLock> = None;
203
204 let mut node_id = tree::ROOT_ID;
206 for (i, seg) in segs.into_iter().enumerate() {
207 node_id = match get_child(tree, node_id, seg) {
208 Ok(n) => n,
209 Err(_) => break,
210 };
211 let node_locks = match tree.get_node(node_id) {
212 Ok(n) => n,
213 Err(_) => break,
214 };
215
216 for nl in node_locks {
217 if i < last_seg && !nl.deep {
218 continue;
219 }
220 if submitted_tokens.iter().any(|t| &nl.token == t) &&
221 (ignore_principal || principal == nl.principal.as_ref().map(|p| p.as_str()))
222 {
223 holds_lock = true;
225 } else {
226 if !nl.shared {
228 return Err(nl.to_owned());
229 }
230 if !shared_ok {
232 first_lock_seen.get_or_insert(nl);
233 }
234 }
235 }
236 }
237
238 if !holds_lock && first_lock_seen.is_some() {
240 return Err(first_lock_seen.unwrap().to_owned());
241 }
242
243 Ok(())
244}
245
246fn check_locks_from_path(
248 tree: &Tree,
249 path: &DavPath,
250 principal: Option<&str>,
251 ignore_principal: bool,
252 submitted_tokens: &Vec<&str>,
253 shared_ok: bool,
254) -> Result<(), DavLock>
255{
256 let node_id = match lookup_node(tree, path) {
257 Some(id) => id,
258 None => return Ok(()),
259 };
260 check_locks_from_node(
261 tree,
262 node_id,
263 principal,
264 ignore_principal,
265 submitted_tokens,
266 shared_ok,
267 )
268}
269
270fn check_locks_from_node(
272 tree: &Tree,
273 node_id: u64,
274 principal: Option<&str>,
275 ignore_principal: bool,
276 submitted_tokens: &Vec<&str>,
277 shared_ok: bool,
278) -> Result<(), DavLock>
279{
280 let node_locks = match tree.get_node(node_id) {
281 Ok(n) => n,
282 Err(_) => return Ok(()),
283 };
284 for nl in node_locks {
285 if !nl.shared || !shared_ok {
286 if !submitted_tokens.iter().any(|t| t == &nl.token) ||
287 (!ignore_principal && principal != nl.principal.as_ref().map(|p| p.as_str()))
288 {
289 return Err(nl.to_owned());
290 }
291 }
292 }
293 if let Ok(children) = tree.get_children(node_id) {
294 for (_, node_id) in children {
295 if let Err(l) = check_locks_from_node(
296 tree,
297 node_id,
298 principal,
299 ignore_principal,
300 submitted_tokens,
301 shared_ok,
302 ) {
303 return Err(l);
304 }
305 }
306 }
307 Ok(())
308}
309
310fn get_or_create_path_node<'a>(tree: &'a mut Tree, path: &DavPath) -> &'a mut Vec<DavLock> {
312 let mut node_id = tree::ROOT_ID;
313 for seg in path_to_segs(path, false) {
314 node_id = match tree.get_child(node_id, seg) {
315 Ok(n) => n,
316 Err(_) => tree.add_child(node_id, seg.to_vec(), Vec::new(), false).unwrap(),
317 };
318 }
319 tree.get_node_mut(node_id).unwrap()
320}
321
322fn lookup_lock(tree: &Tree, path: &DavPath, token: &str) -> Option<u64> {
324 trace!("lookup_lock: {}", token);
325
326 let mut node_id = tree::ROOT_ID;
327 for seg in path_to_segs(path, true) {
328 trace!(
329 "lookup_lock: node {} seg {}",
330 node_id,
331 String::from_utf8_lossy(seg)
332 );
333 node_id = match get_child(tree, node_id, seg) {
334 Ok(n) => n,
335 Err(_) => break,
336 };
337 let node = tree.get_node(node_id).unwrap();
338 trace!("lookup_lock: locks here: {:?}", &node);
339 if node.iter().any(|n| n.token == token) {
340 return Some(node_id);
341 }
342 }
343 trace!("lookup_lock: fail");
344 None
345}
346
347fn lookup_node(tree: &Tree, path: &DavPath) -> Option<u64> {
349 let mut node_id = tree::ROOT_ID;
350 for seg in path_to_segs(path, false) {
351 node_id = match tree.get_child(node_id, seg) {
352 Ok(n) => n,
353 Err(_) => return None,
354 };
355 }
356 Some(node_id)
357}
358
359fn list_locks(tree: &Tree, path: &DavPath) -> Vec<DavLock> {
361 let mut locks = Vec::new();
362
363 let mut node_id = tree::ROOT_ID;
364 if let Ok(node) = tree.get_node(node_id) {
365 locks.extend_from_slice(node);
366 }
367 for seg in path_to_segs(path, false) {
368 node_id = match tree.get_child(node_id, seg) {
369 Ok(n) => n,
370 Err(_) => break,
371 };
372 if let Ok(node) = tree.get_node(node_id) {
373 locks.extend_from_slice(node);
374 }
375 }
376 locks
377}
378
379fn path_to_segs(path: &DavPath, include_root: bool) -> Vec<&[u8]> {
380 let path = path.as_bytes();
381 let mut segs: Vec<&[u8]> = path.split(|&c| c == b'/').filter(|s| s.len() > 0).collect();
382 if include_root {
383 segs.insert(0, b"");
384 }
385 segs
386}
387
388fn get_child(tree: &Tree, node_id: u64, seg: &[u8]) -> FsResult<u64> {
389 if seg.len() == 0 {
390 return Ok(node_id);
391 }
392 tree.get_child(node_id, seg)
393}