1use alloc::collections::BTreeMap;
10use alloc::format;
11use alloc::string::{String, ToString};
12use alloc::sync::{Arc, Weak};
13use alloc::vec::Vec;
14use core::sync::atomic::{AtomicU64, Ordering};
15use spin::RwLock;
16
17use super::core::{FileSystemOperations, VfsEntry};
18use super::manager::{PathResolutionOptions, VfsManager};
19use crate::fs::{FileSystemError, FileSystemErrorKind};
20
21pub type VfsResult<T> = Result<T, FileSystemError>;
22pub type VfsEntryRef = Arc<VfsEntry>;
23pub type VfsEntryWeakRef = Weak<VfsEntry>;
24
25fn vfs_error(kind: FileSystemErrorKind, message: &str) -> FileSystemError {
27 FileSystemError::new(kind, message)
28}
29
30#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
32pub struct MountId(u64);
33
34impl MountId {
35 fn new() -> Self {
36 static COUNTER: AtomicU64 = AtomicU64::new(1);
37 Self(COUNTER.fetch_add(1, Ordering::Relaxed))
38 }
39}
40
41#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
43pub struct VfsManagerId(u64);
44
45impl VfsManagerId {
46 pub fn new() -> Self {
47 static COUNTER: AtomicU64 = AtomicU64::new(1);
48 Self(COUNTER.fetch_add(1, Ordering::Relaxed))
49 }
50}
51
52#[derive(Debug, Clone)]
54pub enum MountType {
55 Regular,
57 Bind,
59 Overlay {
61 layers: Vec<VfsEntryRef>,
63 },
64}
65
66#[derive(Debug, Clone, Default)]
68pub struct MountOptionsV2 {
69 pub readonly: bool,
70 pub flags: u32,
71}
72
73#[derive(Debug)]
75pub struct MountPoint {
76 pub id: MountId,
78 pub mount_type: MountType,
80 pub path: String,
82 pub root: VfsEntryRef,
84 pub filesystem: Option<Arc<dyn FileSystemOperations>>,
86 pub parent: Option<Weak<MountPoint>>,
88 pub parent_entry: Option<VfsEntryRef>,
90 pub children: Arc<RwLock<BTreeMap<u64, Arc<MountPoint>>>>,
92}
93
94impl MountPoint {
95 pub fn new_regular(
97 path: String,
98 root: VfsEntryRef,
99 filesystem: Arc<dyn FileSystemOperations>,
100 ) -> Arc<Self> {
101 Arc::new(Self {
102 id: MountId::new(),
103 mount_type: MountType::Regular,
104 path,
105 root,
106 filesystem: Some(filesystem),
107 parent: None,
108 parent_entry: None,
109 children: Arc::new(RwLock::new(BTreeMap::new())),
110 })
111 }
112
113 pub fn new_bind(path: String, source: VfsEntryRef) -> Arc<Self> {
115 Arc::new(Self {
116 id: MountId::new(),
117 mount_type: MountType::Bind,
118 path,
119 root: source,
120 filesystem: None,
121 parent: None,
122 parent_entry: None,
123 children: Arc::new(RwLock::new(BTreeMap::new())),
124 })
125 }
126
127 pub fn new_overlay(path: String, layers: Vec<VfsEntryRef>) -> VfsResult<Arc<Self>> {
129 if layers.is_empty() {
130 return Err(vfs_error(
131 FileSystemErrorKind::InvalidPath,
132 "Overlay mount requires at least one layer",
133 ));
134 }
135
136 let root = layers[0].clone();
138
139 Ok(Arc::new(Self {
140 id: MountId::new(),
141 mount_type: MountType::Overlay {
142 layers: layers.clone(),
143 },
144 path,
145 root,
146 filesystem: None,
147 parent: None,
148 parent_entry: None,
149 children: Arc::new(RwLock::new(BTreeMap::new())),
150 }))
151 }
152
153 pub fn get_parent(&self) -> Option<Arc<MountPoint>> {
155 self.parent.as_ref().and_then(|weak| weak.upgrade())
156 }
157
158 pub fn is_root_mount(&self) -> bool {
160 self.parent.is_none()
161 }
162
163 pub fn get_child(&self, entry: &VfsEntryRef) -> Option<Arc<MountPoint>> {
165 let key = entry.node().id();
166 self.children.read().get(&key).cloned()
167 }
168
169 pub fn add_child(
171 self: &Arc<Self>,
172 entry: &VfsEntryRef,
173 child: Arc<MountPoint>,
174 ) -> VfsResult<()> {
175 let mut_child: *const MountPoint = Arc::as_ptr(&child);
177 unsafe {
178 let mut_child = mut_child as *mut MountPoint;
179 (*mut_child).parent = Some(Arc::downgrade(self));
180 (*mut_child).parent_entry = Some(entry.clone());
181 }
182 let key = entry.node().id();
183 self.children.write().insert(key, child);
184 Ok(())
185 }
186
187 pub fn remove_child(&self, entry: &VfsEntryRef) -> Option<Arc<MountPoint>> {
189 let key = entry.node().id();
190 self.children.write().remove(&key)
191 }
192
193 pub fn list_children(&self) -> Vec<u64> {
195 self.children.read().keys().cloned().collect()
196 }
197
198 pub fn is_bind_mount(&self) -> bool {
200 matches!(self.mount_type, MountType::Bind { .. })
201 }
202
203 pub fn get_bind_source(&self) -> Option<VfsEntryRef> {
205 match &self.mount_type {
206 MountType::Bind { .. } => Some(self.root.clone()),
207 _ => None,
208 }
209 }
210
211 pub fn get_cross_vfs_info(&self) -> Option<(Weak<VfsManager>, &str, u64)> {
213 match &self.mount_type {
214 MountType::Bind { .. } => None,
215 _ => None,
216 }
217 }
218}
219
220#[derive(Debug)]
222pub struct MountTree {
223 pub root_mount: RwLock<Arc<MountPoint>>,
225}
226
227impl MountTree {
228 pub fn new(root_entry: VfsEntryRef, root_fs: Arc<dyn FileSystemOperations>) -> Self {
230 let root_mount = MountPoint::new_regular("/".to_string(), root_entry, root_fs);
231 let root_id = root_mount.id;
232
233 let mut mounts = BTreeMap::new();
234 mounts.insert(root_id, Arc::downgrade(&root_mount));
235
236 Self {
237 root_mount: RwLock::new(root_mount.clone()),
238 }
239 }
240
241 pub fn bind_mount(
248 &self,
249 source_entry: VfsEntryRef,
250 target_entry: VfsEntryRef,
251 target_mount_point: Arc<MountPoint>,
252 ) -> VfsResult<MountId> {
253 let bind_mount = MountPoint::new_bind(target_entry.name().clone(), source_entry);
255 let mount_id = bind_mount.id;
256
257 target_mount_point.add_child(&target_entry, bind_mount.clone())?;
259
260 Ok(mount_id)
261 }
262
263 pub fn mount(
265 &self,
266 target_entry: VfsEntryRef,
267 target_mount_point: Arc<MountPoint>,
268 filesystem: Arc<dyn FileSystemOperations>,
269 ) -> VfsResult<MountId> {
270 let new_fs_root_node = filesystem.root_node();
272
273 let new_fs_root_entry = VfsEntry::new(None, "/".to_string(), new_fs_root_node);
275
276 let new_mount = MountPoint::new_regular(
278 target_entry.name().clone(),
279 new_fs_root_entry,
280 filesystem.clone(),
281 );
282 let mount_id = new_mount.id;
283
284 target_mount_point.add_child(&target_entry, new_mount.clone())?;
286
287 Ok(mount_id)
288 }
289
290 pub fn replace_root(&self, new_root: Arc<MountPoint>) {
292 *self.root_mount.write() = new_root.clone();
293 }
294
295 pub fn is_mount_point(
304 &self,
305 entry_to_check: &VfsEntryRef,
306 mount_point_to_check: &Arc<MountPoint>,
307 ) -> bool {
308 let children = mount_point_to_check.children.read();
329 children.contains_key(&entry_to_check.node().id())
330 }
331
332 pub fn is_bind_source(&self, entry_to_check: &VfsEntryRef) -> bool {
334 let node_to_check = entry_to_check.node();
335 let node_id = node_to_check.id();
336
337 let fs_ptr_to_check = match node_to_check.filesystem().and_then(|w| w.upgrade()) {
338 Some(fs) => Arc::as_ptr(&fs) as *const (),
339 None => return false,
340 };
341
342 false
343 }
344
345 pub fn is_entry_used_in_mount(
347 &self,
348 entry_to_check: &VfsEntryRef,
349 mount_point_to_check: &Arc<MountPoint>,
350 ) -> bool {
351 self.is_mount_point(entry_to_check, mount_point_to_check)
353 }
354
355 pub fn unmount(
357 &self,
358 entry: &VfsEntryRef,
359 parent_mount_point: &Arc<MountPoint>,
360 ) -> VfsResult<Arc<MountPoint>> {
361 let removed_mount = parent_mount_point.remove_child(&entry);
362 match removed_mount {
363 Some(mount) => Ok(mount),
364 None => Err(vfs_error(
365 FileSystemErrorKind::NotFound,
366 "Mount point not found for unmount",
367 )),
368 }
369 }
370
371 pub fn resolve_path(&self, path: &str) -> VfsResult<(VfsEntryRef, Arc<MountPoint>)> {
373 self.resolve_path_from(None, None, path)
374 }
375
376 pub fn resolve_path_with_options(
378 &self,
379 path: &str,
380 options: &PathResolutionOptions,
381 ) -> VfsResult<(VfsEntryRef, Arc<MountPoint>)> {
382 self.resolve_path_from_with_options(None, None, path, options)
383 }
384
385 pub fn resolve_path_from(
387 &self,
388 base_entry: Option<&VfsEntryRef>,
389 base_mount: Option<&Arc<MountPoint>>,
390 path: &str,
391 ) -> VfsResult<(VfsEntryRef, Arc<MountPoint>)> {
392 self.resolve_path_from_with_options(
393 base_entry,
394 base_mount,
395 path,
396 &PathResolutionOptions::default(),
397 )
398 }
399
400 pub fn resolve_path_from_with_options(
402 &self,
403 base_entry: Option<&VfsEntryRef>,
404 base_mount: Option<&Arc<MountPoint>>,
405 path: &str,
406 options: &PathResolutionOptions,
407 ) -> VfsResult<(VfsEntryRef, Arc<MountPoint>)> {
408 if path.starts_with('/') {
409 self.resolve_path_internal(path, false, options)
411 } else if let (Some(entry), Some(mount)) = (base_entry, base_mount) {
412 self.resolve_path_from_internal(entry, mount, path, false, options)
414 } else {
415 Err(vfs_error(
416 FileSystemErrorKind::InvalidPath,
417 "Relative path resolution requires base entry and mount",
418 ))
419 }
420 }
421
422 pub fn resolve_mount_point(&self, path: &str) -> VfsResult<(VfsEntryRef, Arc<MountPoint>)> {
425 self.resolve_mount_point_with_options(path, &PathResolutionOptions::default())
427 }
428
429 pub fn resolve_mount_point_with_options(
431 &self,
432 path: &str,
433 options: &PathResolutionOptions,
434 ) -> VfsResult<(VfsEntryRef, Arc<MountPoint>)> {
435 self.resolve_mount_point_from_with_options(None, None, path, options)
436 }
437
438 pub fn resolve_mount_point_from(
439 &self,
440 base_entry: &VfsEntryRef,
441 base_mount: &Arc<MountPoint>,
442 path: &str,
443 ) -> VfsResult<(VfsEntryRef, Arc<MountPoint>)> {
444 self.resolve_mount_point_from_with_options(
445 Some(base_entry),
446 Some(base_mount),
447 path,
448 &PathResolutionOptions::default(),
449 )
450 }
451
452 pub fn resolve_mount_point_from_with_options(
453 &self,
454 base_entry: Option<&VfsEntryRef>,
455 base_mount: Option<&Arc<MountPoint>>,
456 path: &str,
457 options: &PathResolutionOptions,
458 ) -> VfsResult<(VfsEntryRef, Arc<MountPoint>)> {
459 if path.starts_with('/') {
460 self.resolve_path_internal(path, true, options)
462 } else if let (Some(entry), Some(mount)) = (base_entry, base_mount) {
463 self.resolve_path_from_internal(entry, mount, path, true, options)
465 } else {
466 Err(vfs_error(
467 FileSystemErrorKind::InvalidPath,
468 "Relative path resolution requires base entry and mount",
469 ))
470 }
471 }
472
473 fn resolve_path_internal(
474 &self,
475 path: &str,
476 resolve_mount: bool,
477 options: &PathResolutionOptions,
478 ) -> VfsResult<(VfsEntryRef, Arc<MountPoint>)> {
479 assert!(
481 path.starts_with('/'),
482 "resolve_path_internal: Path must be absolute, got '{}'",
483 path
484 );
485
486 let root_mount = self.root_mount.read();
487 let root_entry = root_mount.root.clone();
488 self.resolve_path_from_internal(&root_entry, &root_mount, path, resolve_mount, options)
489 }
490
491 fn resolve_path_from_internal(
492 &self,
493 base_entry: &VfsEntryRef,
494 base_mount: &Arc<MountPoint>,
495 path: &str,
496 resolve_mount: bool,
497 options: &PathResolutionOptions,
498 ) -> VfsResult<(VfsEntryRef, Arc<MountPoint>)> {
499 if path.is_empty() {
500 return Ok((base_entry.clone(), base_mount.clone()));
501 } else if path == "/" {
502 return Ok((
504 self.root_mount.read().root.clone(),
505 self.root_mount.read().clone(),
506 ));
507 }
508
509 let components = self.parse_path(path);
510 let mut current_mount = base_mount.clone();
511 let mut current_entry = base_entry.clone();
512
513 let mut resolved_path = String::new();
514 for (i, component) in components.iter().enumerate() {
515 let is_final_component = i == components.len() - 1;
516
517 if component == ".." {
518 let is_at_mount_root = current_entry.node().id() == current_mount.root.node().id();
520
521 if is_at_mount_root {
522 let parent_info = current_mount
523 .get_parent()
524 .zip(current_mount.parent_entry.clone());
525 match parent_info {
526 Some((parent_mount, parent_entry)) => {
527 current_mount = parent_mount;
528 current_entry = self.resolve_component(parent_entry, &"..")?;
529 }
530 None => {
531 }
533 }
534 } else {
535 current_entry = self.resolve_component(current_entry, &component)?;
536 }
537 } else {
538 let should_follow_symlinks = if is_final_component {
540 !options.no_follow
542 } else {
543 true
545 };
546
547 if should_follow_symlinks {
548 current_entry = self.resolve_component(current_entry, &component)?;
550 } else {
551 current_entry = self.resolve_component_no_symlink(current_entry, &component)?;
553 }
554
555 if resolve_mount && is_final_component {
557 if let Some(_child_mount) = current_mount.get_child(¤t_entry) {
558 return Ok((current_entry, current_mount));
559 }
560 } else {
561 if let Some(child_mount) = current_mount.get_child(¤t_entry) {
562 current_mount = child_mount;
563 current_entry = current_mount.root.clone();
564 }
565 }
566 }
567
568 resolved_path.push('/');
569 resolved_path.push_str(&component);
570 }
571
572 Ok((current_entry, current_mount))
573 }
574
575 fn resolve_component_no_symlink(
577 &self,
578 entry: VfsEntryRef,
579 component: &str,
580 ) -> VfsResult<VfsEntryRef> {
581 if component == "." {
583 return Ok(entry);
584 }
585
586 let component_string = component.to_string();
588 if let Some(cached_child) = entry.get_child(&component_string) {
589 return Ok(cached_child);
590 }
591
592 let parent_node = entry.node();
594 debug_assert!(
595 parent_node.filesystem().is_some(),
596 "resolve_component_no_symlink: parent_node.filesystem() is None"
597 );
598 let filesystem = parent_node
599 .filesystem()
600 .and_then(|w| w.upgrade())
601 .ok_or_else(|| {
602 vfs_error(FileSystemErrorKind::NotSupported, "No filesystem reference")
603 })?;
604
605 let child_node = filesystem
607 .lookup(&parent_node, &component_string)
608 .map_err(|e| vfs_error(e.kind, &e.message))?;
609
610 let child_entry = VfsEntry::new(
612 Some(Arc::downgrade(&entry)),
613 component_string.clone(),
614 child_node,
615 );
616
617 entry.add_child(component_string, child_entry.clone());
619
620 Ok(child_entry)
621 }
622
623 pub fn parse_path(&self, path: &str) -> Vec<String> {
627 path.split('/')
628 .filter(|s| !s.is_empty() && *s != ".")
629 .map(|s| s.to_string())
630 .collect()
631 }
632
633 fn get_mount_path(&self, mount: &Arc<MountPoint>) -> String {
635 if mount.is_root_mount() {
636 return "/".to_string();
637 }
638
639 let mut components = Vec::new();
640 let mut current = Some(mount.clone());
641
642 while let Some(mount) = current {
643 if !mount.is_root_mount() {
644 components.push(mount.path.clone());
645 current = mount.get_parent();
646 } else {
647 break;
648 }
649 }
650
651 components.reverse();
652 if components.is_empty() {
653 "/".to_string()
654 } else {
655 format!("/{}", components.join("/"))
656 }
657 }
658
659 pub fn get_mount_absolute_path(&self, mount: &Arc<MountPoint>) -> String {
670 self.get_mount_path(mount)
671 }
672
673 fn resolve_component(&self, entry: VfsEntryRef, component: &str) -> VfsResult<VfsEntryRef> {
675 self.resolve_component_with_depth(entry, component, 0)
676 }
677
678 fn resolve_component_with_depth(
680 &self,
681 entry: VfsEntryRef,
682 component: &str,
683 symlink_depth: u32,
684 ) -> VfsResult<VfsEntryRef> {
685 const MAX_SYMLINK_DEPTH: u32 = 32; if symlink_depth > MAX_SYMLINK_DEPTH {
688 return Err(vfs_error(
689 FileSystemErrorKind::InvalidPath,
690 "Too many symbolic links",
691 ));
692 }
693
694 if component == "." {
696 return Ok(entry);
697 }
698
699 let component_string = component.to_string();
701 if let Some(cached_child) = entry.get_child(&component_string) {
702 if cached_child.node().is_symlink()? {
704 let link_target = cached_child
705 .node()
706 .read_link()
707 .map_err(|e| vfs_error(e.kind, &e.message))?;
708 return self.resolve_symlink_target_with_depth(
709 &entry,
710 &link_target,
711 symlink_depth + 1,
712 );
713 }
714 return Ok(cached_child);
715 }
716
717 let parent_node = entry.node();
719 debug_assert!(
720 parent_node.filesystem().is_some(),
721 "resolve_component: parent_node.filesystem() is None"
722 );
723 let filesystem = parent_node
724 .filesystem()
725 .and_then(|w| w.upgrade())
726 .ok_or_else(|| {
727 vfs_error(FileSystemErrorKind::NotSupported, "No filesystem reference")
728 })?;
729 let child_node = filesystem
731 .lookup(&parent_node, &component_string)
732 .map_err(|e| vfs_error(e.kind, &e.message))?;
733
734 if child_node.is_symlink()? {
736 let link_target = child_node
738 .read_link()
739 .map_err(|e| vfs_error(e.kind, &e.message))?;
740
741 return self.resolve_symlink_target_with_depth(&entry, &link_target, symlink_depth + 1);
743 }
744
745 let child_entry = VfsEntry::new(
747 Some(Arc::downgrade(&entry)),
748 component_string.clone(),
749 child_node,
750 );
751
752 entry.add_child(component_string, child_entry.clone());
754
755 Ok(child_entry)
756 }
757
758 fn resolve_symlink_target(
760 &self,
761 base_entry: &VfsEntryRef,
762 target: &str,
763 ) -> VfsResult<VfsEntryRef> {
764 self.resolve_symlink_target_with_depth(base_entry, target, 0)
765 }
766
767 fn resolve_symlink_target_with_depth(
769 &self,
770 base_entry: &VfsEntryRef,
771 target: &str,
772 symlink_depth: u32,
773 ) -> VfsResult<VfsEntryRef> {
774 const MAX_SYMLINK_DEPTH: u32 = 32; if symlink_depth > MAX_SYMLINK_DEPTH {
777 return Err(vfs_error(
778 FileSystemErrorKind::InvalidPath,
779 "Too many symbolic links",
780 ));
781 }
782
783 if target.starts_with('/') {
784 let (resolved_entry, _mount) = self.resolve_path_internal(
786 target,
787 false,
788 &PathResolutionOptions { no_follow: false },
789 )?;
790 Ok(resolved_entry)
791 } else {
792 let components = self.parse_path(target);
794 let mut current_entry = base_entry.clone();
795
796 for component in components {
797 current_entry =
798 self.resolve_component_with_depth(current_entry, &component, symlink_depth)?;
799 }
800
801 Ok(current_entry)
802 }
803 }
804
805 }