1use std::collections::HashMap;
10use std::io::{Error, ErrorKind, SeekFrom};
11use std::sync::{Arc, Mutex};
12use std::time::SystemTime;
13
14use bytes::{Buf, Bytes};
15use futures_util::{
16 future,
17 future::{BoxFuture, FutureExt},
18 StreamExt,
19};
20use http::StatusCode;
21
22use crate::davpath::DavPath;
23use crate::fs::*;
24use crate::tree;
25
26type Tree = tree::Tree<Vec<u8>, MemFsNode>;
27
28#[derive(Debug)]
30pub struct MemFs {
31 tree: Arc<Mutex<Tree>>,
32}
33
34#[derive(Debug, Clone)]
35enum MemFsNode {
36 Dir(MemFsDirNode),
37 File(MemFsFileNode),
38}
39
40#[derive(Debug, Clone)]
41struct MemFsDirNode {
42 props: HashMap<String, DavProp>,
43 mtime: SystemTime,
44 crtime: SystemTime,
45}
46
47#[derive(Debug, Clone)]
48struct MemFsFileNode {
49 props: HashMap<String, DavProp>,
50 mtime: SystemTime,
51 crtime: SystemTime,
52 data: Vec<u8>,
53}
54
55#[derive(Debug, Clone)]
56struct MemFsDirEntry {
57 mtime: SystemTime,
58 crtime: SystemTime,
59 is_dir: bool,
60 name: Vec<u8>,
61 size: u64,
62}
63
64#[derive(Debug)]
65struct MemFsFile {
66 tree: Arc<Mutex<Tree>>,
67 node_id: u64,
68 pos: usize,
69 append: bool,
70}
71
72impl MemFs {
73 pub fn new() -> Box<MemFs> {
75 let root = MemFsNode::new_dir();
76 Box::new(MemFs {
77 tree: Arc::new(Mutex::new(Tree::new(root))),
78 })
79 }
80
81 fn do_open(
82 &self,
83 tree: &mut Tree,
84 path: &[u8],
85 options: OpenOptions,
86 ) -> FsResult<Box<dyn DavFile>> {
87 let node_id = match tree.lookup(path) {
88 Ok(n) => {
89 if options.create_new {
90 return Err(FsError::Exists);
91 }
92 n
93 }
94 Err(FsError::NotFound) => {
95 if !options.create {
96 return Err(FsError::NotFound);
97 }
98 let parent_id = tree.lookup_parent(path)?;
99 tree.add_child(parent_id, file_name(path), MemFsNode::new_file(), true)?
100 }
101 Err(e) => return Err(e),
102 };
103 let node = tree.get_node_mut(node_id).unwrap();
104 if node.is_dir() {
105 return Err(FsError::Forbidden);
106 }
107 if options.truncate {
108 node.as_file_mut()?.data.truncate(0);
109 node.update_mtime(SystemTime::now());
110 }
111 Ok(Box::new(MemFsFile {
112 tree: self.tree.clone(),
113 node_id,
114 pos: 0,
115 append: options.append,
116 }))
117 }
118}
119
120impl Clone for MemFs {
121 fn clone(&self) -> Self {
122 MemFs {
123 tree: Arc::clone(&self.tree),
124 }
125 }
126}
127
128impl DavFileSystem for MemFs {
129 fn metadata<'a>(&'a self, path: &'a DavPath) -> FsFuture<'a, Box<dyn DavMetaData>> {
130 async move {
131 let tree = &*self.tree.lock().unwrap();
132 let node_id = tree.lookup(path.as_bytes())?;
133 let meta = tree.get_node(node_id)?.as_dirent(path.as_bytes());
134 Ok(Box::new(meta) as Box<dyn DavMetaData>)
135 }
136 .boxed()
137 }
138
139 fn read_dir<'a>(
140 &'a self,
141 path: &'a DavPath,
142 _meta: ReadDirMeta,
143 ) -> FsFuture<'a, FsStream<Box<dyn DavDirEntry>>> {
144 async move {
145 let tree = &*self.tree.lock().unwrap();
146 let node_id = tree.lookup(path.as_bytes())?;
147 if !tree.get_node(node_id)?.is_dir() {
148 return Err(FsError::Forbidden);
149 }
150 let mut v: Vec<Box<dyn DavDirEntry>> = Vec::new();
151 for (name, dnode_id) in tree.get_children(node_id)? {
152 if let Ok(node) = tree.get_node(dnode_id) {
153 v.push(Box::new(node.as_dirent(&name)));
154 }
155 }
156 let strm = futures_util::stream::iter(v).map(Ok);
157 Ok(Box::pin(strm) as FsStream<Box<dyn DavDirEntry>>)
158 }
159 .boxed()
160 }
161
162 fn open<'a>(
163 &'a self,
164 path: &'a DavPath,
165 options: OpenOptions,
166 ) -> FsFuture<'a, Box<dyn DavFile>> {
167 async move {
168 let tree = &mut *self.tree.lock().unwrap();
169 self.do_open(tree, path.as_bytes(), options)
170 }
171 .boxed()
172 }
173
174 fn create_dir<'a>(&'a self, path: &'a DavPath) -> FsFuture<'a, ()> {
175 async move {
176 trace!("FS: create_dir {:?}", path);
177 let tree = &mut *self.tree.lock().unwrap();
178 let path = path.as_bytes();
179 let parent_id = tree.lookup_parent(path)?;
180 tree.add_child(parent_id, file_name(path), MemFsNode::new_dir(), false)?;
181 tree.get_node_mut(parent_id)?
182 .update_mtime(SystemTime::now());
183 Ok(())
184 }
185 .boxed()
186 }
187
188 fn remove_file<'a>(&'a self, path: &'a DavPath) -> FsFuture<'a, ()> {
189 async move {
190 let tree = &mut *self.tree.lock().unwrap();
191 let parent_id = tree.lookup_parent(path.as_bytes())?;
192 let node_id = tree.lookup(path.as_bytes())?;
193 tree.delete_node(node_id)?;
194 tree.get_node_mut(parent_id)?
195 .update_mtime(SystemTime::now());
196 Ok(())
197 }
198 .boxed()
199 }
200
201 fn remove_dir<'a>(&'a self, path: &'a DavPath) -> FsFuture<'a, ()> {
202 async move {
203 let tree = &mut *self.tree.lock().unwrap();
204 let parent_id = tree.lookup_parent(path.as_bytes())?;
205 let node_id = tree.lookup(path.as_bytes())?;
206 tree.delete_node(node_id)?;
207 tree.get_node_mut(parent_id)?
208 .update_mtime(SystemTime::now());
209 Ok(())
210 }
211 .boxed()
212 }
213
214 fn rename<'a>(&'a self, from: &'a DavPath, to: &'a DavPath) -> FsFuture<'a, ()> {
215 async move {
216 let tree = &mut *self.tree.lock().unwrap();
217 let node_id = tree.lookup(from.as_bytes())?;
218 let parent_id = tree.lookup_parent(from.as_bytes())?;
219 let dst_id = tree.lookup_parent(to.as_bytes())?;
220 tree.move_node(node_id, dst_id, file_name(to.as_bytes()), true)?;
221 tree.get_node_mut(parent_id)?
222 .update_mtime(SystemTime::now());
223 tree.get_node_mut(dst_id)?.update_mtime(SystemTime::now());
224 Ok(())
225 }
226 .boxed()
227 }
228
229 fn copy<'a>(&'a self, from: &'a DavPath, to: &'a DavPath) -> FsFuture<'a, ()> {
230 async move {
231 let tree = &mut *self.tree.lock().unwrap();
232
233 let snode_id = tree.lookup(from.as_bytes())?;
235
236 {
238 let mut oo = OpenOptions::write();
239 oo.create = true;
240 self.do_open(tree, to.as_bytes(), oo)?;
241 }
242 let dnode_id = tree.lookup(to.as_bytes())?;
243
244 let mut data = (*tree.get_node_mut(snode_id)?).clone();
246 match data {
247 MemFsNode::Dir(ref mut d) => d.crtime = SystemTime::now(),
248 MemFsNode::File(ref mut f) => f.crtime = SystemTime::now(),
249 }
250 *tree.get_node_mut(dnode_id)? = data;
251
252 Ok(())
253 }
254 .boxed()
255 }
256
257 fn have_props<'a>(&'a self, _path: &'a DavPath) -> BoxFuture<'a, bool> {
258 future::ready(true).boxed()
259 }
260
261 fn patch_props<'a>(
262 &'a self,
263 path: &'a DavPath,
264 mut patch: Vec<(bool, DavProp)>,
265 ) -> FsFuture<'a, Vec<(StatusCode, DavProp)>> {
266 async move {
267 let tree = &mut *self.tree.lock().unwrap();
268 let node_id = tree.lookup(path.as_bytes())?;
269 let node = tree.get_node_mut(node_id)?;
270 let props = node.get_props_mut();
271
272 let mut res = Vec::new();
273
274 for (set, p) in patch.drain(..) {
275 let prop = cloneprop(&p);
276 let status = if set {
277 props.insert(propkey(&p.namespace, &p.name), p);
278 StatusCode::OK
279 } else {
280 props.remove(&propkey(&p.namespace, &p.name));
281 StatusCode::OK
286 };
287 res.push((status, prop));
288 }
289 Ok(res)
290 }
291 .boxed()
292 }
293
294 fn get_props<'a>(&'a self, path: &'a DavPath, do_content: bool) -> FsFuture<'a, Vec<DavProp>> {
295 async move {
296 let tree = &mut *self.tree.lock().unwrap();
297 let node_id = tree.lookup(path.as_bytes())?;
298 let node = tree.get_node(node_id)?;
299 let mut res = Vec::new();
300 for p in node.get_props().values() {
301 res.push(if do_content { p.clone() } else { cloneprop(p) });
302 }
303 Ok(res)
304 }
305 .boxed()
306 }
307
308 fn get_prop<'a>(&'a self, path: &'a DavPath, prop: DavProp) -> FsFuture<'a, Vec<u8>> {
309 async move {
310 let tree = &mut *self.tree.lock().unwrap();
311 let node_id = tree.lookup(path.as_bytes())?;
312 let node = tree.get_node(node_id)?;
313 let p = node
314 .get_props()
315 .get(&propkey(&prop.namespace, &prop.name))
316 .ok_or(FsError::NotFound)?;
317 p.xml.clone().ok_or(FsError::NotFound)
318 }
319 .boxed()
320 }
321}
322
323fn propkey(ns: &Option<String>, name: &str) -> String {
325 ns.to_owned().as_ref().unwrap_or(&"".to_string()).clone() + name
326}
327
328fn cloneprop(p: &DavProp) -> DavProp {
330 DavProp {
331 name: p.name.clone(),
332 namespace: p.namespace.clone(),
333 prefix: p.prefix.clone(),
334 xml: None,
335 }
336}
337
338impl DavDirEntry for MemFsDirEntry {
339 fn metadata(&self) -> FsFuture<Box<dyn DavMetaData>> {
340 let meta = (*self).clone();
341 Box::pin(future::ok(Box::new(meta) as Box<dyn DavMetaData>))
342 }
343
344 fn name(&self) -> Vec<u8> {
345 self.name.clone()
346 }
347}
348
349impl DavFile for MemFsFile {
350 fn metadata(&mut self) -> FsFuture<Box<dyn DavMetaData>> {
351 async move {
352 let tree = &*self.tree.lock().unwrap();
353 let node = tree.get_node(self.node_id)?;
354 let meta = node.as_dirent(b"");
355 Ok(Box::new(meta) as Box<dyn DavMetaData>)
356 }
357 .boxed()
358 }
359
360 fn read_bytes(&mut self, count: usize) -> FsFuture<Bytes> {
361 async move {
362 let tree = &*self.tree.lock().unwrap();
363 let node = tree.get_node(self.node_id)?;
364 let file = node.as_file()?;
365 let curlen = file.data.len();
366 let mut start = self.pos;
367 let mut end = self.pos + count;
368 if start > curlen {
369 start = curlen
370 }
371 if end > curlen {
372 end = curlen
373 }
374 let cnt = end - start;
375 self.pos += cnt;
376 Ok(Bytes::copy_from_slice(&file.data[start..end]))
377 }
378 .boxed()
379 }
380
381 fn write_bytes(&mut self, buf: Bytes) -> FsFuture<()> {
382 async move {
383 let tree = &mut *self.tree.lock().unwrap();
384 let node = tree.get_node_mut(self.node_id)?;
385 let file = node.as_file_mut()?;
386 if self.append {
387 self.pos = file.data.len();
388 }
389 let end = self.pos + buf.len();
390 if end > file.data.len() {
391 file.data.resize(end, 0);
392 }
393 file.data[self.pos..end].copy_from_slice(&buf);
394 self.pos = end;
395 Ok(())
396 }
397 .boxed()
398 }
399
400 fn write_buf(&mut self, mut buf: Box<dyn Buf + Send>) -> FsFuture<()> {
401 async move {
402 let tree = &mut *self.tree.lock().unwrap();
403 let node = tree.get_node_mut(self.node_id)?;
404 let file = node.as_file_mut()?;
405 if self.append {
406 self.pos = file.data.len();
407 }
408 let end = self.pos + buf.remaining();
409 if end > file.data.len() {
410 file.data.resize(end, 0);
411 }
412 while buf.has_remaining() {
413 let b = buf.chunk();
414 let len = b.len();
415 file.data[self.pos..self.pos + len].copy_from_slice(b);
416 buf.advance(len);
417 self.pos += len;
418 }
419 Ok(())
420 }
421 .boxed()
422 }
423
424 fn flush(&mut self) -> FsFuture<()> {
425 future::ok(()).boxed()
426 }
427
428 fn seek(&mut self, pos: SeekFrom) -> FsFuture<u64> {
429 async move {
430 let (start, offset): (u64, i64) = match pos {
431 SeekFrom::Start(npos) => {
432 self.pos = npos as usize;
433 return Ok(npos);
434 }
435 SeekFrom::Current(npos) => (self.pos as u64, npos),
436 SeekFrom::End(npos) => {
437 let tree = &*self.tree.lock().unwrap();
438 let node = tree.get_node(self.node_id)?;
439 let curlen = node.as_file()?.data.len() as u64;
440 (curlen, npos)
441 }
442 };
443 if offset < 0 {
444 if -offset as u64 > start {
445 return Err(Error::new(ErrorKind::InvalidInput, "invalid seek").into());
446 }
447 self.pos = (start - (-offset as u64)) as usize;
448 } else {
449 self.pos = (start + offset as u64) as usize;
450 }
451 Ok(self.pos as u64)
452 }
453 .boxed()
454 }
455}
456
457impl DavMetaData for MemFsDirEntry {
458 fn len(&self) -> u64 {
459 self.size
460 }
461
462 fn created(&self) -> FsResult<SystemTime> {
463 Ok(self.crtime)
464 }
465
466 fn modified(&self) -> FsResult<SystemTime> {
467 Ok(self.mtime)
468 }
469
470 fn is_dir(&self) -> bool {
471 self.is_dir
472 }
473}
474
475impl MemFsNode {
476 fn new_dir() -> MemFsNode {
477 MemFsNode::Dir(MemFsDirNode {
478 crtime: SystemTime::now(),
479 mtime: SystemTime::now(),
480 props: HashMap::new(),
481 })
482 }
483
484 fn new_file() -> MemFsNode {
485 MemFsNode::File(MemFsFileNode {
486 crtime: SystemTime::now(),
487 mtime: SystemTime::now(),
488 props: HashMap::new(),
489 data: Vec::new(),
490 })
491 }
492
493 fn as_dirent(&self, name: &[u8]) -> MemFsDirEntry {
495 let (is_dir, size, mtime, crtime) = match *self {
496 MemFsNode::File(ref file) => (false, file.data.len() as u64, file.mtime, file.crtime),
497 MemFsNode::Dir(ref dir) => (true, 0, dir.mtime, dir.crtime),
498 };
499 MemFsDirEntry {
500 name: name.to_vec(),
501 mtime,
502 crtime,
503 is_dir,
504 size,
505 }
506 }
507
508 fn update_mtime(&mut self, tm: std::time::SystemTime) {
509 match *self {
510 MemFsNode::Dir(ref mut d) => d.mtime = tm,
511 MemFsNode::File(ref mut f) => f.mtime = tm,
512 }
513 }
514
515 fn is_dir(&self) -> bool {
516 match *self {
517 MemFsNode::Dir(_) => true,
518 MemFsNode::File(_) => false,
519 }
520 }
521
522 fn as_file(&self) -> FsResult<&MemFsFileNode> {
523 match *self {
524 MemFsNode::File(ref n) => Ok(n),
525 _ => Err(FsError::Forbidden),
526 }
527 }
528
529 fn as_file_mut(&mut self) -> FsResult<&mut MemFsFileNode> {
530 match *self {
531 MemFsNode::File(ref mut n) => Ok(n),
532 _ => Err(FsError::Forbidden),
533 }
534 }
535
536 fn get_props(&self) -> &HashMap<String, DavProp> {
537 match *self {
538 MemFsNode::File(ref n) => &n.props,
539 MemFsNode::Dir(ref d) => &d.props,
540 }
541 }
542
543 fn get_props_mut(&mut self) -> &mut HashMap<String, DavProp> {
544 match *self {
545 MemFsNode::File(ref mut n) => &mut n.props,
546 MemFsNode::Dir(ref mut d) => &mut d.props,
547 }
548 }
549}
550
551trait TreeExt {
552 fn lookup_segs(&self, segs: Vec<&[u8]>) -> FsResult<u64>;
553 fn lookup(&self, path: &[u8]) -> FsResult<u64>;
554 fn lookup_parent(&self, path: &[u8]) -> FsResult<u64>;
555}
556
557impl TreeExt for Tree {
558 fn lookup_segs(&self, segs: Vec<&[u8]>) -> FsResult<u64> {
559 let mut node_id = tree::ROOT_ID;
560 let mut is_dir = true;
561 for seg in segs.into_iter() {
562 if !is_dir {
563 return Err(FsError::Forbidden);
564 }
565 if self.get_node(node_id)?.is_dir() {
566 node_id = self.get_child(node_id, seg)?;
567 } else {
568 is_dir = false;
569 }
570 }
571 Ok(node_id)
572 }
573
574 fn lookup(&self, path: &[u8]) -> FsResult<u64> {
575 self.lookup_segs(
576 path.split(|&c| c == b'/')
577 .filter(|s| !s.is_empty())
578 .collect(),
579 )
580 }
581
582 fn lookup_parent(&self, path: &[u8]) -> FsResult<u64> {
585 let mut segs: Vec<&[u8]> = path
586 .split(|&c| c == b'/')
587 .filter(|s| !s.is_empty())
588 .collect();
589 segs.pop();
590 let node_id = self.lookup_segs(segs)?;
591 if !self.get_node(node_id)?.is_dir() {
592 return Err(FsError::Forbidden);
593 }
594 Ok(node_id)
595 }
596}
597
598fn file_name(path: &[u8]) -> Vec<u8> {
600 path.split(|&c| c == b'/')
601 .filter(|s| !s.is_empty())
602 .next_back()
603 .unwrap_or(b"")
604 .to_vec()
605}