1use alloc::collections::BTreeMap;
2use alloc::sync::{Arc, Weak};
3use alloc::{string::String, vec::Vec};
4
5use axfs_vfs::{VfsDirEntry, VfsNodeAttr, VfsNodeOps, VfsNodeRef, VfsNodeType};
6use axfs_vfs::{VfsError, VfsResult};
7use spin::RwLock;
8
9use crate::file::FileNode;
10
11pub struct DirNode {
15 this: Weak<DirNode>,
16 parent: RwLock<Weak<dyn VfsNodeOps>>,
17 children: RwLock<BTreeMap<String, VfsNodeRef>>,
18}
19
20impl DirNode {
21 pub(super) fn new(parent: Option<Weak<dyn VfsNodeOps>>) -> Arc<Self> {
22 Arc::new_cyclic(|this| Self {
23 this: this.clone(),
24 parent: RwLock::new(parent.unwrap_or_else(|| Weak::<Self>::new())),
25 children: RwLock::new(BTreeMap::new()),
26 })
27 }
28
29 pub(super) fn set_parent(&self, parent: Option<&VfsNodeRef>) {
30 *self.parent.write() = parent.map_or(Weak::<Self>::new() as _, Arc::downgrade);
31 }
32
33 pub fn get_entries(&self) -> Vec<String> {
35 self.children.read().keys().cloned().collect()
36 }
37
38 pub fn exist(&self, name: &str) -> bool {
40 self.children.read().contains_key(name)
41 }
42
43 pub fn create_node(&self, name: &str, ty: VfsNodeType) -> VfsResult {
45 if self.exist(name) {
46 log::error!("AlreadyExists {name}");
47 return Err(VfsError::AlreadyExists);
48 }
49 let node: VfsNodeRef = match ty {
50 VfsNodeType::File => Arc::new(FileNode::new()),
51 VfsNodeType::Dir => Self::new(Some(self.this.clone())),
52 _ => return Err(VfsError::Unsupported),
53 };
54 self.children.write().insert(name.into(), node);
55 Ok(())
56 }
57
58 pub fn remove_node(&self, name: &str) -> VfsResult {
60 let mut children = self.children.write();
61 let node = children.get(name).ok_or(VfsError::NotFound)?;
62 if let Some(dir) = node.as_any().downcast_ref::<DirNode>() {
63 if !dir.children.read().is_empty() {
64 return Err(VfsError::DirectoryNotEmpty);
65 }
66 }
67 children.remove(name);
68 Ok(())
69 }
70}
71
72impl VfsNodeOps for DirNode {
73 fn get_attr(&self) -> VfsResult<VfsNodeAttr> {
74 Ok(VfsNodeAttr::new_dir(4096, 0))
75 }
76
77 fn parent(&self) -> Option<VfsNodeRef> {
78 self.parent.read().upgrade()
79 }
80
81 fn lookup(self: Arc<Self>, path: &str) -> VfsResult<VfsNodeRef> {
82 let (name, rest) = split_path(path);
83 let node = match name {
84 "" | "." => Ok(self.clone() as VfsNodeRef),
85 ".." => self.parent().ok_or(VfsError::NotFound),
86 _ => self
87 .children
88 .read()
89 .get(name)
90 .cloned()
91 .ok_or(VfsError::NotFound),
92 }?;
93
94 if let Some(rest) = rest {
95 node.lookup(rest)
96 } else {
97 Ok(node)
98 }
99 }
100
101 fn read_dir(&self, start_idx: usize, dirents: &mut [VfsDirEntry]) -> VfsResult<usize> {
102 let children = self.children.read();
103 let mut children = children.iter().skip(start_idx.max(2) - 2);
104 for (i, ent) in dirents.iter_mut().enumerate() {
105 match i + start_idx {
106 0 => *ent = VfsDirEntry::new(".", VfsNodeType::Dir),
107 1 => *ent = VfsDirEntry::new("..", VfsNodeType::Dir),
108 _ => {
109 if let Some((name, node)) = children.next() {
110 *ent = VfsDirEntry::new(name, node.get_attr().unwrap().file_type());
111 } else {
112 return Ok(i);
113 }
114 }
115 }
116 }
117 Ok(dirents.len())
118 }
119
120 fn create(&self, path: &str, ty: VfsNodeType) -> VfsResult {
121 log::debug!("create {ty:?} at ramfs: {path}");
122 let (name, rest) = split_path(path);
123 if let Some(rest) = rest {
124 match name {
125 "" | "." => self.create(rest, ty),
126 ".." => self.parent().ok_or(VfsError::NotFound)?.create(rest, ty),
127 _ => {
128 let subdir = self
129 .children
130 .read()
131 .get(name)
132 .ok_or(VfsError::NotFound)?
133 .clone();
134 subdir.create(rest, ty)
135 }
136 }
137 } else if name.is_empty() || name == "." || name == ".." {
138 Ok(()) } else {
140 self.create_node(name, ty)
141 }
142 }
143
144 fn remove(&self, path: &str) -> VfsResult {
145 log::debug!("remove at ramfs: {path}");
146 let (name, rest) = split_path(path);
147 if let Some(rest) = rest {
148 match name {
149 "" | "." => self.remove(rest),
150 ".." => self.parent().ok_or(VfsError::NotFound)?.remove(rest),
151 _ => {
152 let subdir = self
153 .children
154 .read()
155 .get(name)
156 .ok_or(VfsError::NotFound)?
157 .clone();
158 subdir.remove(rest)
159 }
160 }
161 } else if name.is_empty() || name == "." || name == ".." {
162 Err(VfsError::InvalidInput) } else {
164 self.remove_node(name)
165 }
166 }
167
168 axfs_vfs::impl_vfs_dir_default! {}
169}
170
171fn split_path(path: &str) -> (&str, Option<&str>) {
172 let trimmed_path = path.trim_start_matches('/');
173 trimmed_path.find('/').map_or((trimmed_path, None), |n| {
174 (&trimmed_path[..n], Some(&trimmed_path[n + 1..]))
175 })
176}