fs/
dentry.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
use alloc::{sync::Arc, vec::Vec};
use libc_core::fcntl::OpenFlags;
use sync::Mutex;
use vfscore::{FileSystem, INodeInterface, VfsResult};

use crate::{file::File, pathbuf::PathBuf};

pub static MOUNTED_FS: Mutex<Vec<(PathBuf, DEntryNode)>> = Mutex::new(Vec::new());

#[derive(Clone)]
pub struct DEntryNode {
    pub fs: Arc<dyn FileSystem>,
    node: Arc<dyn INodeInterface>,
}

impl DEntryNode {
    #[inline]
    pub fn node(&self) -> Arc<dyn INodeInterface> {
        self.node.clone()
    }
}

/// 获取挂载的文件系统和挂载后的路径
///
/// # Arguments
///
/// - `path`  需要搜索的路径
///
/// # Returns
///
/// - [DEntryNode] `path` 对应挂载的文件系统
/// - [PathBuf]    `path` 减去挂载路径后的路径
///
pub fn get_mounted(path: &PathBuf) -> (DEntryNode, PathBuf) {
    let mounted = MOUNTED_FS.lock();
    let finded = mounted
        .iter()
        .rev()
        .find(|x| path.starts_with(&x.0))
        .unwrap();
    (finded.1.clone(), path.trim_start(&finded.0))
}

/// 挂载文件系统
///
/// # Arguments
///
/// - `fs`   需要挂载的文件系统
/// - `path` 文件系统挂载的路径
pub fn mount_fs(fs: Arc<dyn FileSystem>, path: &str) {
    if path != "/" {
        // 在挂载之前创建对应的文件夹
        let _ = File::open(path, OpenFlags::DIRECTORY | OpenFlags::CREAT);
    }
    let path = PathBuf::from(path);
    info!("SYSTEM FS mount {} @ {}", fs.name(), path);
    let node = fs.root_dir();
    MOUNTED_FS.lock().push((path, DEntryNode { fs, node }));
}

/// 取消挂载文件系统
///
/// # Arguments
///
/// - `path` 需要取消挂载的路径
pub fn umount(path: PathBuf) -> VfsResult<()> {
    MOUNTED_FS.lock().retain(|x| x.0 != path);
    Ok(())
}