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