1use alloc::{
9 collections::BTreeMap,
10 string::{String, ToString},
11 sync::{Arc, Weak},
12 vec::Vec,
13};
14use core::fmt;
15use core::sync::atomic::{AtomicU64, Ordering};
16use core::{any::Any, fmt::Debug};
17use spin::RwLock;
18
19use super::mount_tree::MountPoint;
20use crate::fs::{
21 FileMetadata, FileObject, FileSystemError, FileSystemErrorKind, FileType, SeekFrom,
22};
23use crate::object::capability::selectable::{
24 ReadyInterest, ReadySet, SelectWaitOutcome, Selectable,
25};
26use crate::object::capability::{ControlOps, MemoryMappingOps, StreamError, StreamOps};
27
28#[derive(Debug, Clone)]
30pub struct DirectoryEntryInternal {
31 pub name: String,
32 pub file_type: FileType,
33 pub file_id: u64,
34}
35
36#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
38pub struct FileSystemId(u64);
39
40impl FileSystemId {
41 pub fn new() -> Self {
43 static NEXT_ID: AtomicU64 = AtomicU64::new(1);
44 Self(NEXT_ID.fetch_add(1, Ordering::Relaxed))
45 }
46
47 #[inline]
49 pub const fn get(self) -> u64 {
50 self.0
51 }
52}
53
54pub type FileSystemRef = Arc<dyn FileSystemOperations>;
56
57pub struct VfsEntry {
67 parent: RwLock<Weak<VfsEntry>>,
69
70 name: String,
72
73 node: Arc<dyn VfsNode>,
75
76 children: RwLock<BTreeMap<String, Weak<VfsEntry>>>,
78}
79
80impl VfsEntry {
81 pub fn new(parent: Option<Weak<VfsEntry>>, name: String, node: Arc<dyn VfsNode>) -> Arc<Self> {
83 debug_assert!(
85 node.filesystem().is_some(),
86 "VfsEntry::new - node.filesystem() is None for name '{}'",
87 name
88 );
89 debug_assert!(
90 node.filesystem().unwrap().upgrade().is_some(),
91 "VfsEntry::new - node.filesystem().upgrade() failed for name '{}'",
92 name
93 );
94
95 Arc::new(Self {
96 parent: RwLock::new(parent.unwrap_or_else(|| Weak::new())),
97 name,
98 node,
99 children: RwLock::new(BTreeMap::new()),
100 })
101 }
102
103 pub fn name(&self) -> &String {
105 &self.name
106 }
107
108 pub fn node(&self) -> Arc<dyn VfsNode> {
110 Arc::clone(&self.node)
111 }
112
113 pub fn parent(&self) -> Option<Arc<VfsEntry>> {
115 self.parent.read().upgrade()
116 }
117
118 pub fn set_parent(&self, parent: Weak<VfsEntry>) {
119 *self.parent.write() = parent;
120 }
121
122 pub fn add_child(self: &Arc<Self>, name: String, child: Arc<VfsEntry>) {
124 child.set_parent(Arc::downgrade(self));
125 let mut children = self.children.write();
126 children.insert(name, Arc::downgrade(&child));
127 }
128
129 pub fn get_child(&self, name: &String) -> Option<Arc<VfsEntry>> {
131 let mut children = self.children.write();
132
133 if let Some(weak_ref) = children.get(name) {
135 if let Some(strong_ref) = weak_ref.upgrade() {
136 return Some(strong_ref);
137 } else {
138 children.remove(name);
140 }
141 }
142
143 None
144 }
145
146 pub fn remove_child(&self, name: &String) -> Option<Arc<VfsEntry>> {
148 let mut children = self.children.write();
149 if let Some(weak_ref) = children.remove(name) {
150 weak_ref.upgrade()
151 } else {
152 None
153 }
154 }
155
156 pub fn cleanup_cache(&self) {
158 let mut children = self.children.write();
159 children.retain(|_, weak_ref| weak_ref.strong_count() > 0);
160 }
161}
162
163impl Clone for VfsEntry {
164 fn clone(&self) -> Self {
165 Self {
166 parent: RwLock::new(self.parent.read().clone()),
167 name: self.name.clone(),
168 node: Arc::clone(&self.node),
169 children: RwLock::new(self.children.read().clone()),
170 }
171 }
172}
173
174impl fmt::Debug for VfsEntry {
175 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
176 f.debug_struct("VfsEntry")
177 .field("name", &self.name)
178 .field("node", &self.node)
179 .field("children_count", &self.children.read().len())
180 .finish()
181 }
182}
183
184pub trait VfsNode: Send + Sync + Any {
189 fn id(&self) -> u64;
191
192 fn filesystem(&self) -> Option<Weak<dyn FileSystemOperations>>;
194
195 fn metadata(&self) -> Result<FileMetadata, FileSystemError>;
197
198 fn file_type(&self) -> Result<FileType, FileSystemError> {
200 Ok(self.metadata()?.file_type)
201 }
202
203 fn as_any(&self) -> &dyn Any;
205
206 fn is_directory(&self) -> Result<bool, FileSystemError> {
208 Ok(self.file_type()? == FileType::Directory)
209 }
210
211 fn is_symlink(&self) -> Result<bool, FileSystemError> {
213 Ok(matches!(self.file_type()?, FileType::SymbolicLink(_)))
214 }
215
216 fn read_link(&self) -> Result<String, FileSystemError> {
218 Err(FileSystemError::new(
219 crate::fs::FileSystemErrorKind::NotSupported,
220 "Not a symbolic link",
221 ))
222 }
223}
224
225impl fmt::Debug for dyn VfsNode {
227 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
228 f.debug_struct("VfsNode")
229 .field("id", &self.id())
230 .field("file_type", &self.file_type().unwrap_or(FileType::Unknown))
231 .field("metadata", &self.metadata())
232 .field(
233 "filesystem",
234 &self
235 .filesystem()
236 .and_then(|fs| fs.upgrade().map(|fs| fs.name().to_string())),
237 )
238 .finish()
239 }
240}
241
242pub trait FileSystemOperations: Send + Sync {
248 fn fs_id(&self) -> FileSystemId;
253
254 fn lookup(
259 &self,
260 parent_node: &Arc<dyn VfsNode>,
261 name: &String,
262 ) -> Result<Arc<dyn VfsNode>, FileSystemError>;
263
264 fn open(
269 &self,
270 node: &Arc<dyn VfsNode>,
271 flags: u32,
272 ) -> Result<Arc<dyn FileObject>, FileSystemError>;
273
274 fn create(
276 &self,
277 parent_node: &Arc<dyn VfsNode>,
278 name: &String,
279 file_type: FileType,
280 mode: u32,
281 ) -> Result<Arc<dyn VfsNode>, FileSystemError>;
282
283 fn remove(&self, parent_node: &Arc<dyn VfsNode>, name: &String) -> Result<(), FileSystemError>;
285
286 fn readdir(
288 &self,
289 node: &Arc<dyn VfsNode>,
290 ) -> Result<Vec<DirectoryEntryInternal>, FileSystemError>;
291
292 fn root_node(&self) -> Arc<dyn VfsNode>;
294
295 fn name(&self) -> &str;
297
298 fn is_read_only(&self) -> bool {
300 false
301 }
302
303 fn as_any(&self) -> &dyn Any;
305
306 fn create_hardlink(
326 &self,
327 link_parent: &Arc<dyn VfsNode>,
328 link_name: &String,
329 target_node: &Arc<dyn VfsNode>,
330 ) -> Result<Arc<dyn VfsNode>, FileSystemError> {
331 let _ = (link_parent, link_name, target_node);
333 Err(FileSystemError::new(
334 FileSystemErrorKind::NotSupported,
335 "Hard links not supported by this filesystem",
336 ))
337 }
338}
339
340impl fmt::Debug for dyn FileSystemOperations {
341 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
342 f.debug_struct("FileSystemOperations")
343 .field("name", &self.name())
344 .field("root", &self.root_node())
345 .finish()
346 }
347}
348
349pub struct VfsFileObject {
354 inner: Arc<dyn FileObject>,
356 vfs_entry: Arc<VfsEntry>,
358 mount_point: Arc<MountPoint>,
360 original_path: String,
362}
363
364impl VfsFileObject {
365 pub fn new(
367 inner: Arc<dyn FileObject>,
368 vfs_entry: Arc<VfsEntry>,
369 mount_point: Arc<MountPoint>,
370 original_path: String,
371 ) -> Self {
372 Self {
373 inner,
374 vfs_entry,
375 mount_point,
376 original_path,
377 }
378 }
379
380 pub fn get_vfs_entry(&self) -> &Arc<VfsEntry> {
382 &self.vfs_entry
383 }
384
385 pub fn get_mount_point(&self) -> &Arc<MountPoint> {
387 &self.mount_point
388 }
389
390 pub fn get_original_path(&self) -> &str {
392 &self.original_path
393 }
394
395 pub fn as_any(&self) -> &dyn Any {
397 self
398 }
399}
400
401impl StreamOps for VfsFileObject {
402 fn read(&self, buffer: &mut [u8]) -> Result<usize, StreamError> {
403 self.inner.read(buffer)
404 }
405
406 fn write(&self, buffer: &[u8]) -> Result<usize, StreamError> {
407 self.inner.write(buffer)
408 }
409}
410
411impl ControlOps for VfsFileObject {
412 fn control(&self, command: u32, arg: usize) -> Result<i32, &'static str> {
413 self.inner.control(command, arg)
414 }
415}
416
417impl MemoryMappingOps for VfsFileObject {
418 fn get_mapping_info(
419 &self,
420 offset: usize,
421 length: usize,
422 ) -> Result<(usize, usize, bool), &'static str> {
423 self.inner.get_mapping_info(offset, length)
424 }
425
426 fn on_mapped(&self, vaddr: usize, paddr: usize, length: usize, offset: usize) {
427 self.inner.on_mapped(vaddr, paddr, length, offset);
428 }
429
430 fn on_unmapped(&self, vaddr: usize, length: usize) {
431 self.inner.on_unmapped(vaddr, length);
432 }
433
434 fn supports_mmap(&self) -> bool {
435 self.inner.supports_mmap()
436 }
437
438 fn mmap_owner_name(&self) -> alloc::string::String {
439 alloc::format!("vfs:{}", self.get_original_path())
440 }
441}
442
443impl FileObject for VfsFileObject {
444 fn read_at(&self, offset: u64, buffer: &mut [u8]) -> Result<usize, StreamError> {
445 self.inner.read_at(offset, buffer)
446 }
447
448 fn write_at(&self, offset: u64, buffer: &[u8]) -> Result<usize, StreamError> {
449 self.inner.write_at(offset, buffer)
450 }
451
452 fn seek(&self, whence: SeekFrom) -> Result<u64, StreamError> {
453 self.inner.seek(whence)
454 }
455
456 fn metadata(&self) -> Result<FileMetadata, StreamError> {
457 self.inner.metadata()
458 }
459
460 fn truncate(&self, size: u64) -> Result<(), StreamError> {
461 self.inner.truncate(size)
462 }
463
464 fn as_any(&self) -> &dyn Any {
465 self
466 }
467}
468
469impl Selectable for VfsFileObject {
470 fn current_ready(&self, interest: ReadyInterest) -> ReadySet {
471 self.inner.current_ready(interest)
472 }
473
474 fn wait_until_ready(
475 &self,
476 interest: ReadyInterest,
477 trapframe: &mut crate::arch::Trapframe,
478 timeout_ticks: Option<u64>,
479 ) -> SelectWaitOutcome {
480 self.inner
481 .wait_until_ready(interest, trapframe, timeout_ticks)
482 }
483
484 fn set_nonblocking(&self, enabled: bool) {
485 self.inner.set_nonblocking(enabled)
486 }
487
488 fn is_nonblocking(&self) -> bool {
489 self.inner.is_nonblocking()
490 }
491}