diff --git a/Kernel/FileSystem/VirtualFileSystem.cpp b/Kernel/FileSystem/VirtualFileSystem.cpp index d9d0a9cea2..a4a4951706 100644 --- a/Kernel/FileSystem/VirtualFileSystem.cpp +++ b/Kernel/FileSystem/VirtualFileSystem.cpp @@ -675,7 +675,7 @@ Custody& VFS::root_custody() return *m_root_custody; } -KResultOr> VFS::resolve_path(StringView path, Custody& base, RefPtr* parent_custody, int options, int symlink_recursion_level) +KResultOr> VFS::resolve_path(StringView path, Custody& base, RefPtr* out_parent, int options, int symlink_recursion_level) { if (symlink_recursion_level >= symlink_recursion_limit) return KResult(-ELOOP); @@ -684,23 +684,13 @@ KResultOr> VFS::resolve_path(StringView path, Custody& ba return KResult(-EINVAL); auto parts = path.split_view('/', true); - auto& current_root = current->process().root_directory(); - NonnullRefPtrVector custody_chain; - - if (path[0] == '/') { - custody_chain.append(current_root); - } else { - for (auto* custody = &base; custody; custody = custody->parent()) { - // FIXME: Prepending here is not efficient! Fix this. - custody_chain.prepend(*custody); - } - } + NonnullRefPtr custody = path[0] == '/' ? current_root : base; for (int i = 0; i < parts.size(); ++i) { - auto& current_parent = custody_chain.last(); - auto parent_metadata = current_parent.inode().metadata(); + Custody& parent = custody; + auto parent_metadata = parent.inode().metadata(); if (!parent_metadata.is_directory()) return KResult(-ENOTDIR); // Ensure the current user is allowed to resolve paths inside this directory. @@ -712,27 +702,27 @@ KResultOr> VFS::resolve_path(StringView path, Custody& ba if (part == "..") { // If we encounter a "..", take a step back, but don't go beyond the root. - if (custody_chain.size() > 1) - custody_chain.take_last(); + if (custody->parent()) + custody = *custody->parent(); continue; } else if (part == "." || part.is_empty()) { continue; } // Okay, let's look up this part. - auto child_id = current_parent.inode().lookup(part); + auto child_id = parent.inode().lookup(part); if (!child_id.is_valid()) { - if (parent_custody) { + if (out_parent) { // ENOENT with a non-null parent custody signals to caller that // we found the immediate parent of the file, but the file itself // does not exist yet. - *parent_custody = have_more_parts ? nullptr : ¤t_parent; + *out_parent = have_more_parts ? nullptr : &parent; } return KResult(-ENOENT); } - int mount_flags_for_child = current_parent.mount_flags(); + int mount_flags_for_child = parent.mount_flags(); // See if there's something mounted on the child; in that case // we would need to return the guest inode, not the host inode. if (auto mount = find_mount_for_host(child_id)) { @@ -742,7 +732,7 @@ KResultOr> VFS::resolve_path(StringView path, Custody& ba auto child_inode = get_inode(child_id); ASSERT(child_inode); - custody_chain.append(Custody::create(¤t_parent, part, *child_inode, mount_flags_for_child)); + custody = Custody::create(&parent, part, *child_inode, mount_flags_for_child); if (child_inode->metadata().is_symlink()) { if (!have_more_parts) { @@ -753,13 +743,13 @@ KResultOr> VFS::resolve_path(StringView path, Custody& ba } auto symlink_contents = child_inode->read_entire(); if (!symlink_contents) { - if (parent_custody) - *parent_custody = nullptr; + if (out_parent) + *out_parent = nullptr; return KResult(-ENOENT); } auto symlink_path = StringView(symlink_contents.data(), symlink_contents.size()); - auto symlink_target = resolve_path(symlink_path, current_parent, parent_custody, options, symlink_recursion_level + 1); + auto symlink_target = resolve_path(symlink_path, parent, out_parent, options, symlink_recursion_level + 1); if (symlink_target.is_error() || !have_more_parts) return symlink_target; @@ -771,11 +761,11 @@ KResultOr> VFS::resolve_path(StringView path, Custody& ba remaining_path.append('.'); remaining_path.append(path.substring_view_starting_after_substring(part)); - return resolve_path(remaining_path.to_string(), *symlink_target.value(), parent_custody, options, symlink_recursion_level + 1); + return resolve_path(remaining_path.to_string(), *symlink_target.value(), out_parent, options, symlink_recursion_level + 1); } } - if (parent_custody) - *parent_custody = custody_chain.last().parent(); - return custody_chain.last(); + if (out_parent) + *out_parent = custody->parent(); + return custody; } diff --git a/Kernel/FileSystem/VirtualFileSystem.h b/Kernel/FileSystem/VirtualFileSystem.h index 2fa748487d..c8b381eb28 100644 --- a/Kernel/FileSystem/VirtualFileSystem.h +++ b/Kernel/FileSystem/VirtualFileSystem.h @@ -103,7 +103,7 @@ public: void sync(); Custody& root_custody(); - KResultOr> resolve_path(StringView path, Custody& base, RefPtr* parent = nullptr, int options = 0, int symlink_recursion_level = 0); + KResultOr> resolve_path(StringView path, Custody& base, RefPtr* out_parent = nullptr, int options = 0, int symlink_recursion_level = 0); private: friend class FileDescription;