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