diff --git a/Kernel/FileSystem/Ext2FS/FileSystem.cpp b/Kernel/FileSystem/Ext2FS/FileSystem.cpp index 1bd0fd1fb3c..a277c04dcd0 100644 --- a/Kernel/FileSystem/Ext2FS/FileSystem.cpp +++ b/Kernel/FileSystem/Ext2FS/FileSystem.cpp @@ -38,7 +38,7 @@ ErrorOr Ext2FS::rename(Inode& old_parent_inode, StringView old_basename, I auto old_inode = TRY(old_parent_inode.lookup(old_basename)); TRY(new_parent_inode.add_child(old_inode, new_basename, old_inode->mode())); - TRY(old_parent_inode.remove_child(old_basename)); + TRY(static_cast(old_parent_inode).remove_child_impl(old_basename, Ext2FSInode::RemoveDotEntries::No)); // If the inode that we moved is a directory and we changed parent // directories, then we also have to make .. point to the new parent inode, diff --git a/Kernel/FileSystem/Ext2FS/Inode.cpp b/Kernel/FileSystem/Ext2FS/Inode.cpp index 0f4f46adc46..0977c169761 100644 --- a/Kernel/FileSystem/Ext2FS/Inode.cpp +++ b/Kernel/FileSystem/Ext2FS/Inode.cpp @@ -793,10 +793,9 @@ ErrorOr Ext2FSInode::add_child(Inode& child, StringView name, mode_t mode) return {}; } -ErrorOr Ext2FSInode::remove_child(StringView name) +ErrorOr Ext2FSInode::remove_child_impl(StringView name, RemoveDotEntries remove_dot_entries) { MutexLocker locker(m_inode_lock); - dbgln_if(EXT2_DEBUG, "Ext2FSInode[{}]::remove_child(): Removing '{}'", identifier(), name); VERIFY(is_directory()); TRY(populate_lookup_cache()); @@ -807,6 +806,12 @@ ErrorOr Ext2FSInode::remove_child(StringView name) auto child_inode_index = (*it).value; InodeIdentifier child_id { fsid(), child_inode_index }; + auto child_inode = TRY(fs().get_inode(child_id)); + if (child_inode->is_directory() && remove_dot_entries == RemoveDotEntries::Yes) { + TRY(static_cast(*child_inode).remove_child_impl("."sv, RemoveDotEntries::No)); + TRY(static_cast(*child_inode).remove_child_impl(".."sv, RemoveDotEntries::No)); + } + bool has_file_type_attribute = has_flag(fs().get_features_optional(), Ext2FS::FeaturesOptional::ExtendedAttributes); Vector entries; @@ -822,13 +827,19 @@ ErrorOr Ext2FSInode::remove_child(StringView name) m_lookup_cache.remove(it); - auto child_inode = TRY(fs().get_inode(child_id)); TRY(child_inode->decrement_link_count()); did_remove_child(child_id, name); return {}; } +ErrorOr Ext2FSInode::remove_child(StringView name) +{ + dbgln_if(EXT2_DEBUG, "Ext2FSInode[{}]::remove_child(): Removing '{}'", identifier(), name); + // TODO: Implement something like remove_directory so we can get rid of remove_child_impl. + return remove_child_impl(name, RemoveDotEntries::Yes); +} + ErrorOr Ext2FSInode::populate_lookup_cache() { VERIFY(m_inode_lock.is_exclusively_locked_by_current_thread()); diff --git a/Kernel/FileSystem/Ext2FS/Inode.h b/Kernel/FileSystem/Ext2FS/Inode.h index a8dfe6f78aa..049ba170f1f 100644 --- a/Kernel/FileSystem/Ext2FS/Inode.h +++ b/Kernel/FileSystem/Ext2FS/Inode.h @@ -57,6 +57,12 @@ private: ErrorOr allocate_block(BlockBasedFileSystem::BlockIndex, bool zero_newly_allocated_block, bool allow_cache); ErrorOr allocate_and_zero_block(); + enum class RemoveDotEntries { + Yes, + No, + }; + + ErrorOr remove_child_impl(StringView name, RemoveDotEntries); ErrorOr write_directory(Vector&); ErrorOr populate_lookup_cache(); ErrorOr resize(u64); diff --git a/Kernel/FileSystem/VirtualFileSystem.cpp b/Kernel/FileSystem/VirtualFileSystem.cpp index 8129bd951b9..42a5e9deafb 100644 --- a/Kernel/FileSystem/VirtualFileSystem.cpp +++ b/Kernel/FileSystem/VirtualFileSystem.cpp @@ -1038,9 +1038,6 @@ ErrorOr VirtualFileSystem::rmdir(VFSRootContext const& vfs_root_context, C if (custody->is_readonly()) return EROFS; - TRY(inode.remove_child("."sv)); - TRY(inode.remove_child(".."sv)); - return parent_inode.remove_child(KLexicalPath::basename(path)); }