1use alloc::collections::BTreeMap;
2use alloc::sync::{Arc, Weak};
3use axfs_vfs::{VfsDirEntry, VfsNodeAttr, VfsNodeOps, VfsNodeRef, VfsNodeType};
4use axfs_vfs::{VfsError, VfsResult};
5use spin::RwLock;
6
7pub struct DirNode {
11 parent: RwLock<Weak<dyn VfsNodeOps>>,
12 children: RwLock<BTreeMap<&'static str, VfsNodeRef>>,
13}
14
15impl DirNode {
16 pub(super) fn new(parent: Option<&VfsNodeRef>) -> Arc<Self> {
17 let parent = parent.map_or(Weak::<Self>::new() as _, Arc::downgrade);
18 Arc::new(Self {
19 parent: RwLock::new(parent),
20 children: RwLock::new(BTreeMap::new()),
21 })
22 }
23
24 pub(super) fn set_parent(&self, parent: Option<&VfsNodeRef>) {
25 *self.parent.write() = parent.map_or(Weak::<Self>::new() as _, Arc::downgrade);
26 }
27
28 pub fn mkdir(self: &Arc<Self>, name: &'static str) -> Arc<Self> {
30 let parent = self.clone() as VfsNodeRef;
31 let node = Self::new(Some(&parent));
32 self.children.write().insert(name, node.clone());
33 node
34 }
35
36 pub fn add(&self, name: &'static str, node: VfsNodeRef) {
38 self.children.write().insert(name, node);
39 }
40}
41
42impl VfsNodeOps for DirNode {
43 fn get_attr(&self) -> VfsResult<VfsNodeAttr> {
44 Ok(VfsNodeAttr::new_dir(4096, 0))
45 }
46
47 fn parent(&self) -> Option<VfsNodeRef> {
48 self.parent.read().upgrade()
49 }
50
51 fn lookup(self: Arc<Self>, path: &str) -> VfsResult<VfsNodeRef> {
52 let (name, rest) = split_path(path);
53 let node = match name {
54 "" | "." => Ok(self.clone() as VfsNodeRef),
55 ".." => self.parent().ok_or(VfsError::NotFound),
56 _ => self
57 .children
58 .read()
59 .get(name)
60 .cloned()
61 .ok_or(VfsError::NotFound),
62 }?;
63
64 if let Some(rest) = rest {
65 node.lookup(rest)
66 } else {
67 Ok(node)
68 }
69 }
70
71 fn read_dir(&self, start_idx: usize, dirents: &mut [VfsDirEntry]) -> VfsResult<usize> {
72 let children = self.children.read();
73 let mut children = children.iter().skip(start_idx.max(2) - 2);
74 for (i, ent) in dirents.iter_mut().enumerate() {
75 match i + start_idx {
76 0 => *ent = VfsDirEntry::new(".", VfsNodeType::Dir),
77 1 => *ent = VfsDirEntry::new("..", VfsNodeType::Dir),
78 _ => {
79 if let Some((name, node)) = children.next() {
80 *ent = VfsDirEntry::new(name, node.get_attr().unwrap().file_type());
81 } else {
82 return Ok(i);
83 }
84 }
85 }
86 }
87 Ok(dirents.len())
88 }
89
90 fn create(&self, path: &str, ty: VfsNodeType) -> VfsResult {
91 log::debug!("create {ty:?} at devfs: {path}");
92 let (name, rest) = split_path(path);
93 if let Some(rest) = rest {
94 match name {
95 "" | "." => self.create(rest, ty),
96 ".." => self.parent().ok_or(VfsError::NotFound)?.create(rest, ty),
97 _ => self
98 .children
99 .read()
100 .get(name)
101 .ok_or(VfsError::NotFound)?
102 .create(rest, ty),
103 }
104 } else if name.is_empty() || name == "." || name == ".." {
105 Ok(()) } else {
107 Err(VfsError::PermissionDenied) }
109 }
110
111 fn remove(&self, path: &str) -> VfsResult {
112 log::debug!("remove at devfs: {path}");
113 let (name, rest) = split_path(path);
114 if let Some(rest) = rest {
115 match name {
116 "" | "." => self.remove(rest),
117 ".." => self.parent().ok_or(VfsError::NotFound)?.remove(rest),
118 _ => self
119 .children
120 .read()
121 .get(name)
122 .ok_or(VfsError::NotFound)?
123 .remove(rest),
124 }
125 } else {
126 Err(VfsError::PermissionDenied) }
128 }
129
130 axfs_vfs::impl_vfs_dir_default! {}
131}
132
133fn split_path(path: &str) -> (&str, Option<&str>) {
134 let trimmed_path = path.trim_start_matches('/');
135 trimmed_path.find('/').map_or((trimmed_path, None), |n| {
136 (&trimmed_path[..n], Some(&trimmed_path[n + 1..]))
137 })
138}