diff --git a/Kernel/FileSystem/Ext2FileSystem.cpp b/Kernel/FileSystem/Ext2FileSystem.cpp index 753863dcd5..c1c07963a9 100644 --- a/Kernel/FileSystem/Ext2FileSystem.cpp +++ b/Kernel/FileSystem/Ext2FileSystem.cpp @@ -704,85 +704,10 @@ bool Ext2FSInode::traverse_as_directory(Function& entries) { LOCKER(m_lock); - ASSERT(is_directory()); - - //#ifdef EXT2_DEBUG - dbgprintf("Ext2FS: Adding inode %u with name '%s' to directory %u\n", child_id.index(), name.characters(), index()); - //#endif - - Vector entries; - bool name_already_exists = false; - traverse_as_directory([&](auto& entry) { - if (!strcmp(entry.name, name.characters())) { - name_already_exists = true; - return false; - } - entries.append(entry); - return true; - }); - if (name_already_exists) { - kprintf("Ext2FS: Name '%s' already exists in directory inode %u\n", name.characters(), index()); - return KResult(-EEXIST); - } - - auto child_inode = fs().get_inode(child_id); - if (child_inode) - child_inode->increment_link_count(); - - entries.append({ name.characters(), name.length(), child_id, to_ext2_file_type(mode) }); - bool success = fs().write_directory_inode(index(), move(entries)); - if (success) - m_lookup_cache.set(name, child_id.index()); - return KSuccess; -} - -KResult Ext2FSInode::remove_child(const StringView& name) -{ - LOCKER(m_lock); -#ifdef EXT2_DEBUG - dbgprintf("Ext2FSInode::remove_child(%s) in inode %u\n", name.characters(), index()); -#endif - ASSERT(is_directory()); - - unsigned child_inode_index; - auto it = m_lookup_cache.find(name); - if (it == m_lookup_cache.end()) - return KResult(-ENOENT); - child_inode_index = (*it).value; - - InodeIdentifier child_id { fsid(), child_inode_index }; - - //#ifdef EXT2_DEBUG - dbgprintf("Ext2FS: Removing '%s' in directory %u\n", name.characters(), index()); - //#endif - - Vector entries; - traverse_as_directory([&](auto& entry) { - if (strcmp(entry.name, name.characters()) != 0) - entries.append(entry); - return true; - }); - - bool success = fs().write_directory_inode(index(), move(entries)); - if (!success) { - // FIXME: Plumb error from write_directory_inode(). - return KResult(-EIO); - } - - m_lookup_cache.remove(name); - - auto child_inode = fs().get_inode(child_id); - child_inode->decrement_link_count(); - return KSuccess; -} - -bool Ext2FS::write_directory_inode(InodeIndex directory_inode_index, Vector&& entries) -{ - LOCKER(m_lock); - dbgprintf("Ext2FS: New directory inode %u contents to write:\n", directory_inode_index); + dbgprintf("Ext2FS: New directory inode %u contents to write:\n", index()); int directory_size = 0; for (auto& entry : entries) { @@ -790,8 +715,10 @@ bool Ext2FS::write_directory_inode(InodeIndex directory_inode_index, Vectorwrite_bytes(0, directory_data.size(), directory_data.pointer(), nullptr); + ssize_t nwritten = write_bytes(0, directory_data.size(), directory_data.pointer(), nullptr); return nwritten == directory_data.size(); } +KResult Ext2FSInode::add_child(InodeIdentifier child_id, const StringView& name, mode_t mode) +{ + LOCKER(m_lock); + ASSERT(is_directory()); + + //#ifdef EXT2_DEBUG + dbgprintf("Ext2FS: Adding inode %u with name '%s' to directory %u\n", child_id.index(), name.characters(), index()); + //#endif + + Vector entries; + bool name_already_exists = false; + traverse_as_directory([&](auto& entry) { + if (!strcmp(entry.name, name.characters())) { + name_already_exists = true; + return false; + } + entries.append(entry); + return true; + }); + if (name_already_exists) { + kprintf("Ext2FS: Name '%s' already exists in directory inode %u\n", name.characters(), index()); + return KResult(-EEXIST); + } + + auto child_inode = fs().get_inode(child_id); + if (child_inode) + child_inode->increment_link_count(); + + entries.append({ name.characters(), name.length(), child_id, to_ext2_file_type(mode) }); + bool success = write_directory(entries); + if (success) + m_lookup_cache.set(name, child_id.index()); + return KSuccess; +} + +KResult Ext2FSInode::remove_child(const StringView& name) +{ + LOCKER(m_lock); +#ifdef EXT2_DEBUG + dbgprintf("Ext2FSInode::remove_child(%s) in inode %u\n", name.characters(), index()); +#endif + ASSERT(is_directory()); + + unsigned child_inode_index; + auto it = m_lookup_cache.find(name); + if (it == m_lookup_cache.end()) + return KResult(-ENOENT); + child_inode_index = (*it).value; + + InodeIdentifier child_id { fsid(), child_inode_index }; + + //#ifdef EXT2_DEBUG + dbgprintf("Ext2FS: Removing '%s' in directory %u\n", name.characters(), index()); + //#endif + + Vector entries; + traverse_as_directory([&](auto& entry) { + if (strcmp(entry.name, name.characters()) != 0) + entries.append(entry); + return true; + }); + + bool success = write_directory(entries); + if (!success) { + // FIXME: Plumb error from write_directory(). + return KResult(-EIO); + } + + m_lookup_cache.remove(name); + + auto child_inode = fs().get_inode(child_id); + child_inode->decrement_link_count(); + return KSuccess; +} + unsigned Ext2FS::inodes_per_block() const { return EXT2_INODES_PER_BLOCK(&super_block()); @@ -1106,7 +1107,7 @@ RetainPtr Ext2FS::create_directory(InodeIdentifier parent_id, const Strin entries.append({ ".", inode->identifier(), EXT2_FT_DIR }); entries.append({ "..", parent_id, EXT2_FT_DIR }); - bool success = write_directory_inode(inode->identifier().index(), move(entries)); + bool success = static_cast(*inode).write_directory(entries); ASSERT(success); auto parent_inode = get_inode(parent_id); diff --git a/Kernel/FileSystem/Ext2FileSystem.h b/Kernel/FileSystem/Ext2FileSystem.h index ac7fff9946..ead3e9ec62 100644 --- a/Kernel/FileSystem/Ext2FileSystem.h +++ b/Kernel/FileSystem/Ext2FileSystem.h @@ -43,6 +43,7 @@ private: virtual KResult chown(uid_t, gid_t) override; virtual KResult truncate(off_t) override; + bool write_directory(const Vector&); void populate_lookup_cache() const; bool resize(qword); @@ -103,8 +104,6 @@ private: Vector block_list_for_inode(const ext2_inode&, bool include_block_list_blocks = false) const; bool write_block_list_for_inode(InodeIndex, ext2_inode&, const Vector&); - bool add_inode_to_directory(InodeIndex parent, InodeIndex child, const String& name, byte file_type, int& error); - bool write_directory_inode(InodeIndex, Vector&&); bool get_inode_allocation_state(InodeIndex) const; bool set_inode_allocation_state(InodeIndex, bool); bool set_block_allocation_state(BlockIndex, bool);