1use crate::security;
6use crate::task::CurrentTask;
7use crate::vfs::{
8 CheckAccessReason, DirectoryMode, FileHandle, FileObject, FsLockDepType, FsNodeHandle,
9 FsNodeLinkBehavior, FsStr, FsString, LookupVec, MountInfo, Mounts, NamespaceNode, UnlinkKind,
10 inotify_hook, path,
11};
12use atomic_bitflags::atomic_bitflags;
13use bitflags::bitflags;
14use bstr::ByteSlice;
15use fuchsia_rcu::{RcuArc, RcuReadScope};
16use fuchsia_sync::ResetDependencies;
17use fxfs_unicode::{CasefoldStr, utf8_bytes};
18use smallvec::SmallVec;
19use starnix_rcu::RcuString;
20use starnix_sync::{
21 DirEntryChildrenLevel, DirEntryChildrenRecursiveLevel, DynamicLockDepRwLock,
22 FuseDirEntryChildrenLevel, LockDepWriteGuard, allow_subclass,
23};
24use starnix_uapi::auth::FsCred;
25use starnix_uapi::errors::{ENOENT, Errno};
26use starnix_uapi::file_mode::{Access, FileMode};
27use starnix_uapi::inotify_mask::InotifyMask;
28use starnix_uapi::open_flags::OpenFlags;
29use starnix_uapi::{NAME_MAX, RENAME_EXCHANGE, RENAME_NOREPLACE, RENAME_WHITEOUT, error};
30use std::collections::BTreeMap;
31use std::fmt;
32use std::ops::Deref;
33use std::sync::atomic::Ordering;
34use std::sync::{Arc, Weak};
35
36bitflags! {
37 #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
38 pub struct RenameFlags: u32 {
39 const EXCHANGE = RENAME_EXCHANGE;
41
42 const NOREPLACE = RENAME_NOREPLACE;
44
45 const WHITEOUT = RENAME_WHITEOUT;
47
48 const REPLACE_ANY = 1 << 31;
51
52 const INTERNAL = Self::REPLACE_ANY.bits();
54 }
55}
56
57pub trait DirEntryOps: Send + Sync + 'static {
58 fn revalidate(&self, _: &CurrentTask, _: &DirEntry) -> Result<bool, Errno> {
75 Ok(true)
76 }
77}
78
79atomic_bitflags! {
80 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
81 pub struct DirEntryFlags: u8 {
82 const IS_DEAD = 1 << 0;
84
85 const HAS_MOUNTS = 1 << 1;
87 }
88}
89
90pub struct DefaultDirEntryOps;
91
92impl DirEntryOps for DefaultDirEntryOps {}
93
94pub struct DirEntry {
106 pub node: FsNodeHandle,
111
112 ops: Box<dyn DirEntryOps>,
117
118 parent: RcuArc<DirEntry>,
125
126 flags: AtomicDirEntryFlags,
128
129 local_name: RcuString,
138
139 children: DynamicLockDepRwLock<DirEntryChildren>,
149}
150
151pub type DirEntryHandle = Arc<DirEntry>;
152
153impl DirEntry {
154 #[allow(clippy::let_and_return)]
155 pub fn new_uncached(
156 node: FsNodeHandle,
157 parent: Option<DirEntryHandle>,
158 local_name: FsString,
159 ) -> DirEntryHandle {
160 let ops = node.create_dir_entry_ops();
161 let fs_lockdep_type = node.fs().fs_lockdep_type();
162 let casefold = node.info().casefold;
163 let initial_children = DirEntryChildren::new(casefold);
164 let result = Arc::new(DirEntry {
165 node,
166 ops,
167 parent: RcuArc::new(parent),
168 flags: Default::default(),
169 local_name: local_name.into(),
170 children: match fs_lockdep_type {
171 FsLockDepType::Normal => {
172 DynamicLockDepRwLock::new::<DirEntryChildrenLevel>(initial_children)
173 }
174 FsLockDepType::Recursive => {
175 DynamicLockDepRwLock::new::<DirEntryChildrenRecursiveLevel>(initial_children)
176 }
177 FsLockDepType::Fuse => {
178 DynamicLockDepRwLock::new::<FuseDirEntryChildrenLevel>(initial_children)
179 }
180 },
181 });
182 #[cfg(any(test, debug_assertions))]
183 {
184 let _token = allow_subclass();
187 let _l1 = result.children.read();
188 }
189 result
190 }
191
192 pub fn new(
193 node: FsNodeHandle,
194 parent: Option<DirEntryHandle>,
195 local_name: FsString,
196 ) -> DirEntryHandle {
197 let result = Self::new_uncached(node, parent, local_name);
198 result.node.fs().did_create_dir_entry(&result);
199 result
200 }
201
202 pub fn new_unrooted(node: FsNodeHandle) -> DirEntryHandle {
205 Self::new_uncached(node, None, FsString::default())
206 }
207
208 pub fn new_deleted(
210 node: FsNodeHandle,
211 parent: Option<DirEntryHandle>,
212 local_name: FsString,
213 ) -> DirEntryHandle {
214 let entry = DirEntry::new_uncached(node, parent, local_name);
215 entry.raise_flags(DirEntryFlags::IS_DEAD);
216 entry
217 }
218
219 pub fn open_anonymous(
221 self: &DirEntryHandle,
222 current_task: &CurrentTask,
223 flags: OpenFlags,
224 ) -> Result<FileHandle, Errno> {
225 let ops = self.node.create_file_ops(current_task, flags)?;
226 FileObject::new(current_task, ops, NamespaceNode::new_anonymous(self.clone()), flags)
227 }
228
229 pub fn set_children(self: &DirEntryHandle, children: BTreeMap<FsString, DirEntryHandle>) {
232 let mut dir_entry_children = self.lock_children();
233 assert!(dir_entry_children.children.is_empty());
234 for (name, child) in children.into_iter() {
235 child.set_parent(self.clone());
236 dir_entry_children.children.insert(name.as_ref(), Arc::downgrade(&child));
237 }
238 }
239
240 fn lock_children<'a>(self: &'a DirEntryHandle) -> DirEntryLockedChildren<'a> {
241 DirEntryLockedChildren { entry: self, children: self.children.write() }
242 }
243
244 pub fn set_casefold(&self, current_task: &CurrentTask, casefold: bool) -> Result<(), Errno> {
253 if self.node.info().casefold == casefold {
254 return Ok(());
255 }
256 if !self.node.is_dir() {
257 return error!(ENOTDIR);
258 }
259 if casefold && !self.node.fs().has_casefold_support() {
260 return error!(ENOTSUP);
261 }
262
263 let mut children = self.children.write();
268 if children.is_casefold() == casefold {
269 return Ok(());
270 }
271
272 self.node.update_attributes(current_task, |info| {
273 info.casefold = casefold;
274 Ok(())
275 })?;
276
277 children.set_casefold(casefold);
278 Ok(())
279 }
280
281 pub fn parent(&self) -> Option<DirEntryHandle> {
283 self.parent.upgrade()
284 }
285
286 pub fn set_parent(&self, parent: DirEntryHandle) {
288 self.parent.update(Some(parent));
289 }
290
291 pub fn parent_or_self(self: &DirEntryHandle) -> DirEntryHandle {
301 self.parent().unwrap_or_else(|| self.clone())
302 }
303
304 pub fn local_name<'a>(&self, scope: &'a RcuReadScope) -> &'a FsStr {
308 self.local_name.read(scope)
309 }
310
311 pub fn is_reserved_name(name: &FsStr) -> bool {
316 name.is_empty() || name == "." || name == ".."
317 }
318
319 pub fn flags(&self) -> DirEntryFlags {
321 self.flags.load(Ordering::Acquire)
322 }
323
324 pub fn raise_flags(&self, flags: DirEntryFlags) -> DirEntryFlags {
328 self.flags.fetch_or(flags, Ordering::AcqRel)
329 }
330
331 pub fn lower_flags(&self, flags: DirEntryFlags) -> DirEntryFlags {
335 self.flags.fetch_and(!flags, Ordering::AcqRel)
336 }
337
338 pub fn is_dead(&self) -> bool {
340 self.flags().contains(DirEntryFlags::IS_DEAD)
341 }
342
343 pub fn component_lookup(
346 self: &DirEntryHandle,
347 current_task: &CurrentTask,
348 mount: &MountInfo,
349 name: &FsStr,
350 ) -> Result<DirEntryHandle, Errno> {
351 let (node, _) = self.get_or_create_child(current_task, mount, name, |d, mount, name| {
352 d.lookup(current_task, mount, name)
353 })?;
354 Ok(node)
355 }
356
357 pub fn get_children_pipelined(
358 self: &DirEntryHandle,
359 current_task: &CurrentTask,
360 mount: &MountInfo,
361 names: &[&FsStr],
362 ) -> LookupVec<Result<DirEntryHandle, Errno>> {
363 let mut nodes = LookupVec::new();
364 let mut results = LookupVec::new();
365 let mut current_parent = self.clone();
366 for i in 0..names.len() {
367 let next_node = nodes.pop();
368 match current_parent.get_or_create_child(
369 current_task,
370 mount,
371 names[i],
372 |parent_node, _mount, _name| {
373 if let Some(node) = next_node {
374 return node;
375 }
376 nodes =
377 parent_node.ops().lookup_pipelined(parent_node, current_task, &names[i..]);
378 nodes.reverse();
379 nodes.pop().unwrap()
380 },
381 ) {
382 Ok((entry, _)) => {
383 results.push(Ok(entry.clone()));
384 current_parent = entry;
385 }
386 Err(e) => {
387 results.push(Err(e));
388 break;
389 }
390 }
391 }
392 results
393 }
394
395 pub fn create_entry(
403 self: &DirEntryHandle,
404 current_task: &CurrentTask,
405 mount: &MountInfo,
406 name: &FsStr,
407 create_node_fn: impl FnOnce(&FsNodeHandle, &MountInfo, &FsStr) -> Result<FsNodeHandle, Errno>,
408 ) -> Result<DirEntryHandle, Errno> {
409 let (entry, exists) =
410 self.create_entry_internal(current_task, mount, name, create_node_fn)?;
411 if exists {
412 return error!(EEXIST);
413 }
414 Ok(entry)
415 }
416
417 pub fn get_or_create_entry(
420 self: &DirEntryHandle,
421 current_task: &CurrentTask,
422 mount: &MountInfo,
423 name: &FsStr,
424 create_node_fn: impl FnOnce(&FsNodeHandle, &MountInfo, &FsStr) -> Result<FsNodeHandle, Errno>,
425 ) -> Result<DirEntryHandle, Errno> {
426 let (entry, _exists) =
427 self.create_entry_internal(current_task, mount, name, create_node_fn)?;
428 Ok(entry)
429 }
430
431 fn create_entry_internal(
432 self: &DirEntryHandle,
433 current_task: &CurrentTask,
434 mount: &MountInfo,
435 name: &FsStr,
436 create_node_fn: impl FnOnce(&FsNodeHandle, &MountInfo, &FsStr) -> Result<FsNodeHandle, Errno>,
437 ) -> Result<(DirEntryHandle, bool), Errno> {
438 if DirEntry::is_reserved_name(name) {
439 return error!(EEXIST);
440 }
441 if name.len() > NAME_MAX as usize {
443 return error!(ENAMETOOLONG);
444 }
445 if name.contains(&path::SEPARATOR) {
446 return error!(EINVAL);
447 }
448 let (entry, exists) =
449 self.get_or_create_child(current_task, mount, name, create_node_fn)?;
450 if !exists {
451 self.node.update_ctime_mtime();
453 entry.notify_creation();
454 }
455 Ok((entry, exists))
456 }
457
458 #[cfg(test)]
461 pub fn create_dir(
462 self: &DirEntryHandle,
463 current_task: &CurrentTask,
464 name: &FsStr,
465 ) -> Result<DirEntryHandle, Errno> {
466 self.create_dir_for_testing(current_task, name)
467 }
468
469 pub fn create_dir_for_testing(
472 self: &DirEntryHandle,
473 current_task: &CurrentTask,
474 name: &FsStr,
475 ) -> Result<DirEntryHandle, Errno> {
476 self.create_entry(current_task, &MountInfo::detached(), name, |dir, mount, name| {
478 dir.create_node(
479 current_task,
480 mount,
481 name,
482 starnix_uapi::file_mode::mode!(IFDIR, 0o777),
483 starnix_uapi::device_id::DeviceId::NONE,
484 FsCred::root(),
485 )
486 })
487 }
488
489 pub fn create_tmpfile(
495 self: &DirEntryHandle,
496 current_task: &CurrentTask,
497 mount: &MountInfo,
498 mode: FileMode,
499 owner: FsCred,
500 flags: OpenFlags,
501 ) -> Result<DirEntryHandle, Errno> {
502 if !self.node.is_dir() {
504 return error!(ENOTDIR);
505 }
506 assert!(mode.is_reg());
507
508 let link_behavior = if flags.contains(OpenFlags::EXCL) {
516 FsNodeLinkBehavior::Disallowed
517 } else {
518 FsNodeLinkBehavior::Allowed
519 };
520
521 let node = self.node.create_tmpfile(current_task, mount, mode, owner, link_behavior)?;
522 let local_name = format!("#{}", node.ino).into();
523 Ok(DirEntry::new_deleted(node, Some(self.clone()), local_name))
524 }
525
526 pub fn unlink(
527 self: &DirEntryHandle,
528 current_task: &CurrentTask,
529 mount: &MountInfo,
530 name: &FsStr,
531 kind: UnlinkKind,
532 directory_mode: DirectoryMode,
533 ) -> Result<(), Errno> {
534 assert!(!DirEntry::is_reserved_name(name));
535
536 let child_to_unlink;
538
539 let mut self_children = self.lock_children();
540 child_to_unlink = self_children.component_lookup(current_task, mount, name)?;
541 child_to_unlink.require_no_mounts(mount)?;
542
543 if directory_mode == DirectoryMode::MustBeDirectory && !child_to_unlink.node.is_dir() {
550 return error!(ENOTDIR);
551 }
552
553 match kind {
554 UnlinkKind::Directory => {
555 if !child_to_unlink.node.is_dir() {
556 return error!(ENOTDIR);
557 }
558 }
559 UnlinkKind::NonDirectory => {
560 if child_to_unlink.node.is_dir() {
561 return error!(EISDIR);
562 }
563 }
564 }
565
566 self.node.unlink(current_task, mount, name, &child_to_unlink.node)?;
567 self_children.children.remove(name);
568
569 std::mem::drop(self_children);
570 child_to_unlink.destroy(¤t_task.kernel().mounts);
571
572 Ok(())
573 }
574
575 fn destroy(self: DirEntryHandle, mounts: &Mounts) {
579 let was_already_dead =
580 self.raise_flags(DirEntryFlags::IS_DEAD).contains(DirEntryFlags::IS_DEAD);
581 if was_already_dead {
582 return;
583 }
584 let unmount =
585 self.lower_flags(DirEntryFlags::HAS_MOUNTS).contains(DirEntryFlags::HAS_MOUNTS);
586 self.node.fs().will_destroy_dir_entry(&self);
587 if unmount {
588 mounts.unmount(&self);
589 }
590 self.notify_deletion();
591 }
592
593 pub fn is_descendant_of(self: &DirEntryHandle, other: &DirEntryHandle) -> bool {
595 let mut current = self.clone();
596 loop {
597 if Arc::ptr_eq(¤t, other) {
598 return true;
600 }
601 if let Some(parent) = current.parent() {
602 current = parent;
603 } else {
604 return false;
606 }
607 }
608 }
609
610 pub fn rename(
615 current_task: &CurrentTask,
616 old_parent: &DirEntryHandle,
617 old_mount: &MountInfo,
618 old_basename: &FsStr,
619 new_parent: &DirEntryHandle,
620 new_mount: &MountInfo,
621 new_basename: &FsStr,
622 flags: RenameFlags,
623 ) -> Result<(), Errno> {
624 if old_mount != new_mount {
626 return error!(EXDEV);
627 }
628
629 let mount = old_mount;
631
632 if DirEntry::is_reserved_name(old_basename) || DirEntry::is_reserved_name(new_basename) {
635 if flags.contains(RenameFlags::NOREPLACE) {
636 return error!(EEXIST);
637 }
638 return error!(EBUSY);
639 }
640
641 if Arc::ptr_eq(&old_parent.node, &new_parent.node) && old_basename == new_basename {
644 if flags.contains(RenameFlags::NOREPLACE) {
645 return error!(EEXIST);
646 }
647 return Ok(());
648 }
649
650 old_parent.node.check_access(
652 current_task,
653 mount,
654 Access::WRITE,
655 CheckAccessReason::InternalPermissionChecks,
656 old_parent,
657 )?;
658 new_parent.node.check_access(
659 current_task,
660 mount,
661 Access::WRITE,
662 CheckAccessReason::InternalPermissionChecks,
663 new_parent,
664 )?;
665
666 let fs = old_parent.node.fs();
669
670 let renamed;
673 let mut maybe_replaced = None;
674
675 {
676 let _lock = fs.rename_mutex.lock();
686
687 let mut state = RenameGuard::lock(old_parent, new_parent);
692
693 renamed =
696 state.old_parent_children().component_lookup(current_task, mount, old_basename)?;
697
698 let lookup_replaced =
703 state.new_parent_children().component_lookup(current_task, mount, new_basename);
704
705 if let Ok(replaced) = &lookup_replaced {
714 if old_parent.is_descendant_of(replaced) {
715 if flags.contains(RenameFlags::EXCHANGE) {
716 return error!(EINVAL);
717 } else {
718 return error!(ENOTEMPTY);
719 }
720 }
721 }
722
723 let mut state =
726 state.lock_info(old_parent, new_parent, &renamed, lookup_replaced.as_ref().ok());
727
728 if new_parent.is_descendant_of(&renamed) {
731 return error!(EINVAL);
732 }
733
734 {
737 let _token = allow_subclass();
741 old_parent.node.check_sticky_bit(
742 current_task,
743 &renamed.node,
744 state.old_parent_info(),
745 )?;
746 }
747
748 renamed.require_no_mounts(mount)?;
753
754 match &lookup_replaced {
759 Ok(replaced) => {
760 let replaced = maybe_replaced.insert(replaced.clone());
762
763 if flags.contains(RenameFlags::NOREPLACE) {
764 return error!(EEXIST);
770 }
771
772 if Arc::ptr_eq(&renamed.node, &replaced.node) {
773 if !Arc::ptr_eq(&renamed, &replaced) {
774 return Ok(());
780 }
781
782 if flags.contains(RenameFlags::EXCHANGE) {
787 return Ok(());
788 }
789 }
790
791 if state.replaced_is_dir() {
796 replaced.require_no_mounts(mount)?;
801 }
802
803 if !flags.intersects(RenameFlags::EXCHANGE | RenameFlags::REPLACE_ANY) {
804 let renamed_is_dir = state.renamed_is_dir();
805 let replaced_is_dir = state.replaced_is_dir();
806 if renamed_is_dir && !replaced_is_dir {
807 return error!(ENOTDIR);
808 } else if !renamed_is_dir && replaced_is_dir {
809 return error!(EISDIR);
810 }
811 }
812 }
813 Err(errno) if *errno == ENOENT => {
815 if flags.contains(RenameFlags::EXCHANGE) {
816 return error!(ENOENT);
817 }
818 }
819 Err(e) => return Err(e.clone()),
821 }
822
823 security::check_fs_node_rename_access(
824 current_task,
825 &old_parent.node,
826 &renamed.node,
827 &new_parent.node,
828 maybe_replaced.as_ref().map(|dir_entry| dir_entry.node.deref().as_ref()),
829 old_basename,
830 new_basename,
831 )?;
832
833 if let Some(replaced) = maybe_replaced.as_ref() {
834 let _token = allow_subclass();
838 new_parent.node.check_sticky_bit(
839 current_task,
840 &replaced.node,
841 state.new_parent_info().unwrap_or_else(|| state.old_parent_info()),
842 )?;
843 }
844
845 if state.replaced.is_some_and(|r| Arc::ptr_eq(&renamed, r)) {
850 state.replaced = None;
851 }
852
853 if flags.contains(RenameFlags::EXCHANGE) {
854 fs.exchange(current_task, &mut state, old_basename, new_basename)?;
855 } else {
856 fs.rename(current_task, &mut state, old_basename, new_basename)?;
857 }
858
859 if flags.contains(RenameFlags::EXCHANGE) {
860 let replaced =
862 maybe_replaced.as_ref().expect("replaced expected with RENAME_EXCHANGE");
863 replaced.set_parent(old_parent.clone());
864 replaced.local_name.update(old_basename.to_owned());
865 state.old_parent_children().children.insert(old_basename, Arc::downgrade(replaced));
866 } else {
867 state.old_parent_children().children.remove(old_basename);
872 }
873
874 renamed.set_parent(new_parent.clone());
877 renamed.local_name.update(new_basename.to_owned());
878
879 state.new_parent_children().children.insert(new_basename, Arc::downgrade(&renamed));
883
884 unsafe {
893 if let Some(replaced) =
894 maybe_replaced.as_ref().filter(|_| flags.contains(RenameFlags::EXCHANGE))
895 {
896 replaced.children.reset_dependencies();
897 replaced.node.info_lock().reset_dependencies();
898 }
899 renamed.children.reset_dependencies();
900 renamed.node.info_lock().reset_dependencies();
901 old_parent.children.reset_dependencies();
902 old_parent.node.info_lock().reset_dependencies();
903 new_parent.children.reset_dependencies();
904 new_parent.node.info_lock().reset_dependencies();
905 }
906 };
907
908 fs.purge_old_entries();
909
910 if let Some(replaced) = maybe_replaced {
911 if !flags.contains(RenameFlags::EXCHANGE) && !Arc::ptr_eq(&renamed, &replaced) {
912 replaced.destroy(¤t_task.kernel().mounts);
913 }
914 }
915
916 renamed.node.update_ctime();
918
919 let mode = renamed.node.info().mode;
920 if let Some(hook) =
921 current_task.kernel().expando.peek::<Arc<dyn inotify_hook::NotifyHook>>()
922 {
923 let cookie = hook.get_next_cookie();
924 old_parent.node.notify(InotifyMask::MOVE_FROM, cookie, old_basename, mode, false);
925 new_parent.node.notify(InotifyMask::MOVE_TO, cookie, new_basename, mode, false);
926 renamed.node.notify(InotifyMask::MOVE_SELF, 0, Default::default(), mode, false);
927 }
928
929 Ok(())
930 }
931
932 pub(crate) fn get_children<F, T>(&self, callback: F) -> T
933 where
934 F: FnOnce(&DirEntryChildren) -> T,
935 {
936 let children = self.children.read();
937 callback(&children)
938 }
939
940 pub fn remove_child(&self, name: &FsStr, mounts: &Mounts) {
943 let mut children = self.children.write();
944 let child = children.remove(name).and_then(|weak| weak.upgrade());
945 if let Some(child) = child {
946 std::mem::drop(children);
947 child.destroy(mounts);
948 }
949 }
950
951 fn get_or_create_child(
952 self: &DirEntryHandle,
953 current_task: &CurrentTask,
954 mount: &MountInfo,
955 name: &FsStr,
956 create_fn: impl FnOnce(&FsNodeHandle, &MountInfo, &FsStr) -> Result<FsNodeHandle, Errno>,
957 ) -> Result<(DirEntryHandle, bool), Errno> {
958 assert!(!DirEntry::is_reserved_name(name));
959 if !self.node.is_dir() {
961 return error!(ENOTDIR);
962 }
963 self.node.check_access(
965 current_task,
966 mount,
967 Access::EXEC,
968 CheckAccessReason::InternalPermissionChecks,
969 self,
970 )?;
971
972 let child = self.children.read().get(name).and_then(Weak::upgrade);
975 let (child, create_result) = if let Some(child) = child {
976 if self.node.fail_if_locked(current_task, &self.node.info()).is_ok() {
978 child.node.fs().did_access_dir_entry(&child);
979 }
980 (child, CreationResult::Existed { create_fn })
981 } else {
982 let (child, create_result) =
983 self.lock_children().get_or_create_child(current_task, mount, name, create_fn)?;
984 child.node.fs().purge_old_entries();
985 (child, create_result)
986 };
987
988 let (child, exists) = match create_result {
989 CreationResult::Created => (child, false),
990 CreationResult::Existed { create_fn } => {
991 if child.ops.revalidate(current_task, &child)? {
992 (child, true)
993 } else {
994 self.internal_remove_child(&child);
995 child.destroy(¤t_task.kernel().mounts);
996
997 let (child, create_result) = self.lock_children().get_or_create_child(
998 current_task,
999 mount,
1000 name,
1001 create_fn,
1002 )?;
1003 child.node.fs().purge_old_entries();
1004 (child, matches!(create_result, CreationResult::Existed { .. }))
1005 }
1006 }
1007 };
1008
1009 Ok((child, exists))
1010 }
1011
1012 #[cfg(test)]
1020 pub fn copy_child_names(&self) -> Vec<FsString> {
1021 let scope = RcuReadScope::new();
1022 self.children.read().copy_child_names(&scope)
1023 }
1024
1025 fn internal_remove_child(&self, child: &DirEntry) {
1026 let mut children = self.children.write();
1027 let scope = RcuReadScope::new();
1028 let local_name = child.local_name.read(&scope);
1029 children.remove_if_child_matches(local_name, child);
1030 }
1031
1032 pub fn notify(&self, event_mask: InotifyMask) {
1034 self.notify_watchers(event_mask, self.is_dead());
1035 }
1036
1037 pub fn notify_ignoring_excl_unlink(&self, event_mask: InotifyMask) {
1041 self.notify_watchers(event_mask, false);
1043 }
1044
1045 fn notify_watchers(&self, event_mask: InotifyMask, is_dead: bool) {
1046 let mode = self.node.info().mode;
1047 {
1048 let scope = RcuReadScope::new();
1049 if let Some(parent) = self.parent() {
1050 let local_name = self.local_name.read(&scope);
1051 parent.node.notify(event_mask, 0, local_name, mode, is_dead);
1052 }
1053 }
1054 self.node.notify(event_mask, 0, Default::default(), mode, is_dead);
1055 }
1056
1057 fn notify_creation(&self) {
1059 let mode = self.node.info().mode;
1060 if Arc::strong_count(&self.node) > 1 {
1061 self.node.notify(InotifyMask::ATTRIB, 0, Default::default(), mode, false);
1063 }
1064 let scope = RcuReadScope::new();
1065 if let Some(parent) = self.parent() {
1066 let local_name = self.local_name.read(&scope);
1067 parent.node.notify(InotifyMask::CREATE, 0, local_name, mode, false);
1068 }
1069 }
1070
1071 fn notify_deletion(&self) {
1075 let mode = self.node.info().mode;
1076 if !mode.is_dir() {
1077 self.node.notify(InotifyMask::ATTRIB, 0, Default::default(), mode, false);
1079 }
1080
1081 if Arc::strong_count(&self.node) == 1 {
1084 self.node.notify(InotifyMask::DELETE_SELF, 0, Default::default(), mode, false);
1085 }
1086
1087 let scope = RcuReadScope::new();
1088 if let Some(parent) = self.parent() {
1089 let local_name = self.local_name.read(&scope);
1090 parent.node.notify(InotifyMask::DELETE, 0, local_name, mode, false);
1091 }
1092 }
1093
1094 pub fn has_mounts(&self) -> bool {
1096 self.flags().contains(DirEntryFlags::HAS_MOUNTS)
1097 }
1098
1099 pub fn set_has_mounts(&self, v: bool) {
1101 if v {
1102 self.raise_flags(DirEntryFlags::HAS_MOUNTS);
1103 } else {
1104 self.lower_flags(DirEntryFlags::HAS_MOUNTS);
1105 }
1106 }
1107
1108 fn require_no_mounts(self: &Arc<Self>, parent_mount: &MountInfo) -> Result<(), Errno> {
1110 if self.has_mounts() {
1111 if let Some(mount) = parent_mount.as_ref() {
1112 if mount.has_submount(self) {
1113 return error!(EBUSY);
1114 }
1115 }
1116 }
1117 Ok(())
1118 }
1119}
1120
1121#[inline]
1124fn canonicalize_name(name: impl AsRef<[u8]>) -> SmallVec<[u8; NAME_MAX as usize]> {
1125 let name = name.as_ref();
1126 match std::str::from_utf8(name) {
1127 Ok(valid) => {
1128 CasefoldStr::new(valid).casefold_normalized_chars().flat_map(utf8_bytes).collect()
1129 }
1130 Err(_) => SmallVec::from_slice(name),
1131 }
1132}
1133
1134#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
1139pub(crate) struct DirEntryChildKey(FsString);
1140
1141impl DirEntryChildKey {
1142 pub fn new(name: &FsStr, casefold: bool) -> Self {
1143 if casefold {
1144 Self(canonicalize_name(name).into_vec().into())
1145 } else {
1146 Self(name.to_owned())
1147 }
1148 }
1149}
1150
1151impl std::borrow::Borrow<FsStr> for DirEntryChildKey {
1152 fn borrow(&self) -> &FsStr {
1153 self.0.as_bstr()
1154 }
1155}
1156
1157#[derive(Default, Debug)]
1164pub(crate) struct DirEntryChildren {
1165 entries: BTreeMap<DirEntryChildKey, Weak<DirEntry>>,
1166 casefold: bool,
1167}
1168
1169impl std::ops::Deref for DirEntryChildren {
1170 type Target = BTreeMap<DirEntryChildKey, Weak<DirEntry>>;
1171
1172 fn deref(&self) -> &Self::Target {
1173 &self.entries
1174 }
1175}
1176
1177impl DirEntryChildren {
1178 pub fn new(casefold: bool) -> Self {
1179 Self { entries: BTreeMap::new(), casefold }
1180 }
1181
1182 pub fn is_casefold(&self) -> bool {
1183 self.casefold
1184 }
1185
1186 pub fn set_casefold(&mut self, casefold: bool) {
1187 self.entries.clear();
1188 self.casefold = casefold;
1189 }
1190
1191 pub fn get(&self, name: &FsStr) -> Option<&Weak<DirEntry>> {
1193 if self.casefold {
1194 let key = canonicalize_name(name);
1195 self.entries.get(FsStr::new(&key))
1196 } else {
1197 self.entries.get(name)
1198 }
1199 }
1200
1201 pub fn insert(&mut self, name: &FsStr, child: Weak<DirEntry>) -> Option<Weak<DirEntry>> {
1204 self.entries.insert(DirEntryChildKey::new(name, self.casefold), child)
1205 }
1206
1207 pub fn remove(&mut self, name: &FsStr) -> Option<Weak<DirEntry>> {
1210 if self.casefold {
1211 let key = canonicalize_name(name);
1212 self.entries.remove(FsStr::new(&key))
1213 } else {
1214 self.entries.remove(name)
1215 }
1216 }
1217
1218 pub fn remove_if_child_matches(&mut self, name: &FsStr, expected_child: &DirEntry) -> bool {
1221 if let Some(weak_child) = self.get(name) {
1222 if std::ptr::eq(weak_child.as_ptr(), expected_child) {
1223 let _ = self.remove(name);
1224 return true;
1225 }
1226 }
1227 false
1228 }
1229
1230 #[cfg(test)]
1231 fn copy_child_names(&self, scope: &RcuReadScope) -> Vec<FsString> {
1234 self.entries
1235 .values()
1236 .filter_map(|child| Weak::upgrade(child).map(|c| c.local_name.read(scope).to_owned()))
1237 .collect()
1238 }
1239}
1240
1241struct DirEntryLockedChildren<'a> {
1242 entry: &'a DirEntryHandle,
1243 children: LockDepWriteGuard<'a, DirEntryChildren>,
1244}
1245
1246enum CreationResult<F> {
1247 Created,
1248 Existed { create_fn: F },
1249}
1250
1251impl<'a> DirEntryLockedChildren<'a> {
1252 fn component_lookup(
1253 &mut self,
1254 current_task: &CurrentTask,
1255 mount: &MountInfo,
1256 name: &FsStr,
1257 ) -> Result<DirEntryHandle, Errno> {
1258 assert!(!DirEntry::is_reserved_name(name));
1259 let (node, _) =
1260 self.get_or_create_child(current_task, mount, name, |_, _, _| error!(ENOENT))?;
1261 Ok(node)
1262 }
1263
1264 fn get_or_create_child<
1265 F: FnOnce(&FsNodeHandle, &MountInfo, &FsStr) -> Result<FsNodeHandle, Errno>,
1266 >(
1267 &mut self,
1268 current_task: &CurrentTask,
1269 mount: &MountInfo,
1270 name: &FsStr,
1271 create_fn: F,
1272 ) -> Result<(DirEntryHandle, CreationResult<F>), Errno> {
1273 let create_child = |create_fn: F| {
1274 let (node, create_result) = match self.entry.node.lookup(current_task, mount, name) {
1276 Ok(node) => (node, CreationResult::Existed { create_fn }),
1277 Err(e) if e == ENOENT => {
1278 (create_fn(&self.entry.node, mount, name)?, CreationResult::Created)
1279 }
1280 Err(e) => return Err(e),
1281 };
1282
1283 assert!(
1284 node.info().mode & FileMode::IFMT != FileMode::EMPTY,
1285 "FsNode initialization did not populate the FileMode in FsNodeInfo."
1286 );
1287
1288 let entry = DirEntry::new(node, Some(self.entry.clone()), name.to_owned());
1289
1290 if let Err(err) = security::fs_node_init_with_dentry(current_task, &entry) {
1291 entry.parent.update(None);
1294 return Err(err);
1295 }
1296
1297 Ok((entry, create_result))
1298 };
1299
1300 if let Some(child) = self.children.get(name).and_then(Weak::upgrade) {
1301 if self.entry.node.fail_if_locked(current_task, &self.entry.node.info()).is_ok() {
1303 child.node.fs().did_access_dir_entry(&child);
1304 }
1305 return Ok((child, CreationResult::Existed { create_fn }));
1306 }
1307
1308 let (child, create_result) = create_child(create_fn)?;
1309 if self.entry.node.fail_if_locked(current_task, &self.entry.node.info()).is_ok() {
1311 self.children.insert(name, Arc::downgrade(&child));
1312 }
1313
1314 Ok((child, create_result))
1315 }
1316}
1317
1318impl fmt::Debug for DirEntry {
1319 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1320 let scope = RcuReadScope::new();
1321 let mut parents = vec![];
1322 let mut maybe_parent = self.parent();
1323 while let Some(parent) = maybe_parent {
1324 parents.push(parent.local_name.read(&scope));
1325 maybe_parent = parent.parent();
1326 }
1327 let mut builder = f.debug_struct("DirEntry");
1328 builder.field("id", &(self as *const DirEntry));
1329 builder.field("local_name", &self.local_name.read(&scope).to_owned());
1330 if !parents.is_empty() {
1331 builder.field("parents", &parents);
1332 }
1333 builder.finish()
1334 }
1335}
1336
1337#[derive(Copy, Clone, Debug, Eq, PartialEq)]
1338enum RenameRelationship {
1339 Same,
1340 NewIsDescendant,
1341 OldIsDescendant,
1342 Independent,
1343}
1344
1345struct RenameGuard<'a> {
1346 old_parent_guard: DirEntryLockedChildren<'a>,
1347 new_parent_guard: Option<DirEntryLockedChildren<'a>>,
1348 relationship: RenameRelationship,
1349}
1350
1351impl<'a> RenameGuard<'a> {
1352 fn lock(old_parent: &'a DirEntryHandle, new_parent: &'a DirEntryHandle) -> Self {
1353 if Arc::ptr_eq(old_parent, new_parent) {
1354 let old_parent_guard = old_parent.lock_children();
1355 Self {
1356 old_parent_guard,
1357 new_parent_guard: None,
1358 relationship: RenameRelationship::Same,
1359 }
1360 } else if new_parent.is_descendant_of(old_parent) {
1361 let old_parent_guard = old_parent.lock_children();
1362 let _token = allow_subclass();
1363 let new_parent_guard = new_parent.lock_children();
1364 Self {
1365 old_parent_guard,
1366 new_parent_guard: Some(new_parent_guard),
1367 relationship: RenameRelationship::NewIsDescendant,
1368 }
1369 } else if old_parent.is_descendant_of(new_parent) {
1370 let new_parent_guard = new_parent.lock_children();
1371 let _token = allow_subclass();
1372 let old_parent_guard = old_parent.lock_children();
1373 Self {
1374 old_parent_guard,
1375 new_parent_guard: Some(new_parent_guard),
1376 relationship: RenameRelationship::OldIsDescendant,
1377 }
1378 } else {
1379 let (g1, g2) =
1381 starnix_sync::ordered_write_lock(&old_parent.children, &new_parent.children);
1382 let old_parent_guard = DirEntryLockedChildren { entry: old_parent, children: g1 };
1383 let new_parent_guard = DirEntryLockedChildren { entry: new_parent, children: g2 };
1384 Self {
1385 old_parent_guard,
1386 new_parent_guard: Some(new_parent_guard),
1387 relationship: RenameRelationship::Independent,
1388 }
1389 }
1390 }
1391
1392 fn lock_info(
1396 self,
1397 old_parent: &'a DirEntryHandle,
1398 new_parent: &'a DirEntryHandle,
1399 renamed: &'a DirEntryHandle,
1400 replaced: Option<&'a DirEntryHandle>,
1401 ) -> RenameContext<'a> {
1402 let (g1, g2) = match self.relationship {
1403 RenameRelationship::Same => (old_parent.node.info_lock().write(), None),
1404 RenameRelationship::NewIsDescendant => {
1405 let g1 = old_parent.node.info_lock().write();
1406 let _token = allow_subclass();
1407 let g2 = new_parent.node.info_lock().write();
1408 (g1, Some(g2))
1409 }
1410 RenameRelationship::OldIsDescendant => {
1411 let g2 = new_parent.node.info_lock().write();
1412 let _token = allow_subclass();
1413 let g1 = old_parent.node.info_lock().write();
1414 (g1, Some(g2))
1415 }
1416 RenameRelationship::Independent => {
1417 let (g1, g2) = starnix_sync::ordered_write_lock(
1418 old_parent.node.info_lock(),
1419 new_parent.node.info_lock(),
1420 );
1421 (g1, Some(g2))
1422 }
1423 };
1424
1425 RenameContext {
1426 renamed,
1427 replaced,
1428 old_parent_guard: self.old_parent_guard,
1429 new_parent_guard: self.new_parent_guard,
1430 old_parent_info_guard: g1,
1431 new_parent_info_guard: g2,
1432 }
1433 }
1434
1435 fn old_parent_children(&mut self) -> &mut DirEntryLockedChildren<'a> {
1436 &mut self.old_parent_guard
1437 }
1438
1439 fn new_parent_children(&mut self) -> &mut DirEntryLockedChildren<'a> {
1440 if let Some(new_guard) = self.new_parent_guard.as_mut() {
1441 new_guard
1442 } else {
1443 &mut self.old_parent_guard
1444 }
1445 }
1446}
1447
1448pub struct RenameContext<'a> {
1461 pub renamed: &'a DirEntryHandle,
1462 pub replaced: Option<&'a DirEntryHandle>,
1463 old_parent_guard: DirEntryLockedChildren<'a>,
1464 new_parent_guard: Option<DirEntryLockedChildren<'a>>,
1465 old_parent_info_guard: LockDepWriteGuard<'a, crate::vfs::FsNodeInfo>,
1466 new_parent_info_guard: Option<LockDepWriteGuard<'a, crate::vfs::FsNodeInfo>>,
1467}
1468
1469impl<'a> RenameContext<'a> {
1470 pub fn renamed_is_dir(&self) -> bool {
1477 self.is_dir(&self.renamed.node)
1478 }
1479
1480 pub fn replaced_is_dir(&self) -> bool {
1489 self.replaced.map(|r| self.is_dir(&r.node)).unwrap_or(false)
1490 }
1491
1492 pub fn old_parent(&self) -> &DirEntryHandle {
1497 self.old_parent_guard.entry
1498 }
1499
1500 pub fn new_parent(&self) -> &DirEntryHandle {
1505 self.new_parent_guard.as_ref().map(|g| g.entry).unwrap_or(self.old_parent_guard.entry)
1506 }
1507
1508 pub fn parent_infos_mut(
1517 &mut self,
1518 ) -> (&mut crate::vfs::FsNodeInfo, Option<&mut crate::vfs::FsNodeInfo>) {
1519 let old = &mut *self.old_parent_info_guard;
1520 let new = self.new_parent_info_guard.as_mut().map(|g| &mut **g);
1521 (old, new)
1522 }
1523
1524 pub fn old_parent_info(&self) -> &crate::vfs::FsNodeInfo {
1527 &self.old_parent_info_guard
1528 }
1529 pub fn new_parent_info(&self) -> Option<&crate::vfs::FsNodeInfo> {
1534 self.new_parent_info_guard.as_deref()
1535 }
1536
1537 fn new_parent_children(&mut self) -> &mut DirEntryLockedChildren<'a> {
1538 self.new_parent_guard.as_mut().unwrap_or(&mut self.old_parent_guard)
1539 }
1540
1541 fn old_parent_children(&mut self) -> &mut DirEntryLockedChildren<'a> {
1542 &mut self.old_parent_guard
1543 }
1544
1545 fn is_dir(&self, node: &FsNodeHandle) -> bool {
1546 if Arc::ptr_eq(node, &self.old_parent().node) {
1547 self.old_parent_info_guard.mode.is_dir()
1548 } else if Arc::ptr_eq(node, &self.new_parent().node) {
1549 self.new_parent_info_guard
1550 .as_ref()
1551 .map(|g| g.mode.is_dir())
1552 .unwrap_or_else(|| self.old_parent_info_guard.mode.is_dir())
1553 } else {
1554 let _token = allow_subclass();
1555 node.is_dir()
1556 }
1557 }
1558}
1559
1560impl Drop for DirEntry {
1564 fn drop(&mut self) {
1565 let maybe_parent = self.parent();
1566 self.parent.update(None);
1567 if let Some(parent) = maybe_parent {
1568 parent.internal_remove_child(self);
1569 }
1570 }
1571}
1572
1573#[cfg(test)]
1574mod tests {
1575 use super::*;
1576
1577 #[test]
1578 fn test_canonicalize_name() {
1579 let upper = canonicalize_name("FooBar.TXT");
1580 let lower = canonicalize_name("foobar.txt");
1581 let mixed = canonicalize_name("FOOBAR.TXT");
1582 let diff = canonicalize_name("other.txt");
1583
1584 assert_eq!(upper.as_slice(), lower.as_slice());
1585 assert_eq!(upper.as_slice(), mixed.as_slice());
1586 assert_ne!(upper.as_slice(), diff.as_slice());
1587
1588 let composed = canonicalize_name("\u{03AA}");
1590 let decomposed = canonicalize_name("\u{0399}\u{0308}");
1591 assert_eq!(composed.as_slice(), decomposed.as_slice());
1592
1593 let e_accent_lower = canonicalize_name("e\u{0301}");
1595 let e_accent_upper = canonicalize_name("\u{00c9}");
1596 assert_eq!(e_accent_lower.as_slice(), e_accent_upper.as_slice());
1597
1598 let strasse_lower = canonicalize_name("straße");
1600 let strasse_upper = canonicalize_name("STRASSE");
1601 assert_eq!(strasse_lower.as_slice(), strasse_upper.as_slice());
1602
1603 let non_utf8 = canonicalize_name(b"foo\x80bar");
1605 assert_eq!(non_utf8.as_slice(), b"foo\x80bar");
1606 }
1607
1608 #[test]
1609 fn test_dir_entry_children_casefold() {
1610 let mut children = DirEntryChildren::new(true);
1611 assert!(children.is_casefold());
1612
1613 children.insert("FooBar.TXT".into(), Weak::new());
1615 assert!(children.get("foobar.txt".into()).is_some());
1616 assert!(children.get("FOOBAR.TXT".into()).is_some());
1617 assert!(children.get("FooBar.TXT".into()).is_some());
1618 assert!(children.get("other.txt".into()).is_none());
1619
1620 children.insert("\u{03AA}".into(), Weak::new());
1622 assert!(children.get("\u{0399}\u{0308}".into()).is_some());
1623
1624 children.insert(b"foo\x80bar".into(), Weak::new());
1626 assert!(children.get(b"foo\x80bar".into()).is_some());
1627 assert!(children.get(b"FOO\x80bar".into()).is_none());
1628
1629 assert!(children.remove("FOOBAR.TXT".into()).is_some());
1631 assert!(children.get("foobar.txt".into()).is_none());
1632 assert!(children.remove("\u{0399}\u{0308}".into()).is_some());
1633 assert!(children.get("\u{03AA}".into()).is_none());
1634 assert!(children.remove(b"foo\x80bar".into()).is_some());
1635 assert!(children.get(b"foo\x80bar".into()).is_none());
1636 assert!(children.is_empty());
1637
1638 children.insert("Foo.TXT".into(), Weak::new());
1640 assert!(!children.is_empty());
1641 children.set_casefold(false);
1642 assert!(!children.is_casefold());
1643 assert!(children.is_empty());
1644 children.set_casefold(true);
1645 assert!(children.is_casefold());
1646 }
1647}