1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-10 11:57:35 +00:00

Kernel: Add DirectoryEntryView for VFS directory traversal

Unlike DirectoryEntry (which is used when constructing directories),
DirectoryEntryView does not manage storage for file names. Names are
just StringViews.

This is much more suited to the directory traversal API and makes
it easier to implement this in file system classes since they no
longer need to create temporary name copies while traversing.
This commit is contained in:
Andreas Kling 2020-08-18 12:41:27 +02:00
parent 8abf5048b8
commit eeaba41d13
16 changed files with 61 additions and 53 deletions

View file

@ -136,18 +136,18 @@ InodeMetadata DevPtsFSInode::metadata() const
return m_metadata; return m_metadata;
} }
KResult DevPtsFSInode::traverse_as_directory(Function<bool(const FS::DirectoryEntry&)> callback) const KResult DevPtsFSInode::traverse_as_directory(Function<bool(const FS::DirectoryEntryView&)> callback) const
{ {
if (identifier().index() > 1) if (identifier().index() > 1)
return KResult(-ENOTDIR); return KResult(-ENOTDIR);
callback({ ".", 1, identifier(), 0 }); callback({ ".", identifier(), 0 });
callback({ "..", 2, identifier(), 0 }); callback({ "..", identifier(), 0 });
for (unsigned pty_index : *ptys) { for (unsigned pty_index : *ptys) {
String name = String::number(pty_index); String name = String::number(pty_index);
InodeIdentifier identifier = { fsid(), pty_index_to_inode_index(pty_index) }; InodeIdentifier identifier = { fsid(), pty_index_to_inode_index(pty_index) };
callback({ name.characters(), name.length(), identifier, 0 }); callback({ name, identifier, 0 });
} }
return KSuccess; return KSuccess;

View file

@ -69,7 +69,7 @@ private:
// ^Inode // ^Inode
virtual ssize_t read_bytes(off_t, ssize_t, u8* buffer, FileDescription*) const override; virtual ssize_t read_bytes(off_t, ssize_t, u8* buffer, FileDescription*) const override;
virtual InodeMetadata metadata() const override; virtual InodeMetadata metadata() const override;
virtual KResult traverse_as_directory(Function<bool(const FS::DirectoryEntry&)>) const override; virtual KResult traverse_as_directory(Function<bool(const FS::DirectoryEntryView&)>) const override;
virtual RefPtr<Inode> lookup(StringView name) override; virtual RefPtr<Inode> lookup(StringView name) override;
virtual void flush_metadata() override; virtual void flush_metadata() override;
virtual ssize_t write_bytes(off_t, ssize_t, const u8* buffer, FileDescription*) override; virtual ssize_t write_bytes(off_t, ssize_t, const u8* buffer, FileDescription*) override;

View file

@ -849,7 +849,7 @@ ssize_t Ext2FSInode::write_bytes(off_t offset, ssize_t count, const u8* data, Fi
return nwritten; return nwritten;
} }
KResult Ext2FSInode::traverse_as_directory(Function<bool(const FS::DirectoryEntry&)> callback) const KResult Ext2FSInode::traverse_as_directory(Function<bool(const FS::DirectoryEntryView&)> callback) const
{ {
LOCKER(m_lock); LOCKER(m_lock);
ASSERT(is_directory()); ASSERT(is_directory());
@ -871,7 +871,7 @@ KResult Ext2FSInode::traverse_as_directory(Function<bool(const FS::DirectoryEntr
#ifdef EXT2_DEBUG #ifdef EXT2_DEBUG
dbg() << "Ext2Inode::traverse_as_directory: " << entry->inode << ", name_len: " << entry->name_len << ", rec_len: " << entry->rec_len << ", file_type: " << entry->file_type << ", name: " << String(entry->name, entry->name_len); dbg() << "Ext2Inode::traverse_as_directory: " << entry->inode << ", name_len: " << entry->name_len << ", rec_len: " << entry->rec_len << ", file_type: " << entry->file_type << ", name: " << String(entry->name, entry->name_len);
#endif #endif
if (!callback({ entry->name, entry->name_len, { fsid(), entry->inode }, entry->file_type })) if (!callback({ { entry->name, entry->name_len }, { fsid(), entry->inode }, entry->file_type }))
break; break;
} }
entry = (ext2_dir_entry_2*)((char*)entry + entry->rec_len); entry = (ext2_dir_entry_2*)((char*)entry + entry->rec_len);
@ -961,7 +961,7 @@ KResult Ext2FSInode::add_child(Inode& child, const StringView& name, mode_t mode
name_already_exists = true; name_already_exists = true;
return false; return false;
} }
entries.append(entry); entries.append({ entry.name.characters_without_null_termination(), entry.name.length(), entry.inode, entry.file_type });
return true; return true;
}); });
@ -1008,7 +1008,7 @@ KResult Ext2FSInode::remove_child(const StringView& name)
Vector<FS::DirectoryEntry> entries; Vector<FS::DirectoryEntry> entries;
KResult result = traverse_as_directory([&](auto& entry) { KResult result = traverse_as_directory([&](auto& entry) {
if (name != entry.name) if (name != entry.name)
entries.append(entry); entries.append({ entry.name.characters_without_null_termination(), entry.name.length(), entry.inode, entry.file_type });
return true; return true;
}); });
if (result.is_error()) if (result.is_error())
@ -1478,7 +1478,7 @@ void Ext2FSInode::populate_lookup_cache() const
HashMap<String, unsigned> children; HashMap<String, unsigned> children;
KResult result = traverse_as_directory([&children](auto& entry) { KResult result = traverse_as_directory([&children](auto& entry) {
children.set(String(entry.name, entry.name_length), entry.inode.index()); children.set(entry.name, entry.inode.index());
return true; return true;
}); });

View file

@ -59,7 +59,7 @@ private:
// ^Inode // ^Inode
virtual ssize_t read_bytes(off_t, ssize_t, u8* buffer, FileDescription*) const override; virtual ssize_t read_bytes(off_t, ssize_t, u8* buffer, FileDescription*) const override;
virtual InodeMetadata metadata() const override; virtual InodeMetadata metadata() const override;
virtual KResult traverse_as_directory(Function<bool(const FS::DirectoryEntry&)>) const override; virtual KResult traverse_as_directory(Function<bool(const FS::DirectoryEntryView&)>) const override;
virtual RefPtr<Inode> lookup(StringView name) override; virtual RefPtr<Inode> lookup(StringView name) override;
virtual void flush_metadata() override; virtual void flush_metadata() override;
virtual ssize_t write_bytes(off_t, ssize_t, const u8* data, FileDescription*) override; virtual ssize_t write_bytes(off_t, ssize_t, const u8* data, FileDescription*) override;

View file

@ -191,7 +191,7 @@ ssize_t FileDescription::get_dir_entries(u8* buffer, ssize_t size)
KResult result = VFS::the().traverse_directory_inode(*m_inode, [&stream](auto& entry) { KResult result = VFS::the().traverse_directory_inode(*m_inode, [&stream](auto& entry) {
stream << (u32)entry.inode.index(); stream << (u32)entry.inode.index();
stream << (u8)entry.file_type; stream << (u8)entry.file_type;
stream << (u32)entry.name_length; stream << (u32)entry.name.length();
stream << entry.name; stream << entry.name;
return true; return true;
}); });

View file

@ -85,6 +85,13 @@ FS::DirectoryEntry::DirectoryEntry(const char* n, size_t nl, InodeIdentifier i,
name[nl] = '\0'; name[nl] = '\0';
} }
FS::DirectoryEntryView::DirectoryEntryView(const StringView& n, InodeIdentifier i, u8 ft)
: name(n)
, inode(i)
, file_type(ft)
{
}
void FS::sync() void FS::sync()
{ {
Inode::sync(); Inode::sync();

View file

@ -29,6 +29,7 @@
#include <AK/RefCounted.h> #include <AK/RefCounted.h>
#include <AK/RefPtr.h> #include <AK/RefPtr.h>
#include <AK/String.h> #include <AK/String.h>
#include <AK/StringView.h>
#include <Kernel/FileSystem/InodeIdentifier.h> #include <Kernel/FileSystem/InodeIdentifier.h>
#include <Kernel/KResult.h> #include <Kernel/KResult.h>
#include <Kernel/Lock.h> #include <Kernel/Lock.h>
@ -78,6 +79,14 @@ public:
u8 file_type { 0 }; u8 file_type { 0 };
}; };
struct DirectoryEntryView {
DirectoryEntryView(const StringView& name, InodeIdentifier, u8 file_type);
StringView name;
InodeIdentifier inode;
u8 file_type { 0 };
};
virtual void flush_writes() { } virtual void flush_writes() { }
size_t block_size() const { return m_block_size; } size_t block_size() const { return m_block_size; }

View file

@ -70,7 +70,7 @@ public:
KResultOr<KBuffer> read_entire(FileDescription* = nullptr) const; KResultOr<KBuffer> read_entire(FileDescription* = nullptr) const;
virtual ssize_t read_bytes(off_t, ssize_t, u8* buffer, FileDescription*) const = 0; virtual ssize_t read_bytes(off_t, ssize_t, u8* buffer, FileDescription*) const = 0;
virtual KResult traverse_as_directory(Function<bool(const FS::DirectoryEntry&)>) const = 0; virtual KResult traverse_as_directory(Function<bool(const FS::DirectoryEntryView&)>) const = 0;
virtual RefPtr<Inode> lookup(StringView name) = 0; virtual RefPtr<Inode> lookup(StringView name) = 0;
virtual ssize_t write_bytes(off_t, ssize_t, const u8* data, FileDescription*) = 0; virtual ssize_t write_bytes(off_t, ssize_t, const u8* data, FileDescription*) = 0;
virtual KResultOr<NonnullRefPtr<Inode>> create_child(const String& name, mode_t, dev_t, uid_t, gid_t) = 0; virtual KResultOr<NonnullRefPtr<Inode>> create_child(const String& name, mode_t, dev_t, uid_t, gid_t) = 0;

View file

@ -798,7 +798,7 @@ void Plan9FSInode::flush_metadata()
KResultOr<size_t> Plan9FSInode::directory_entry_count() const KResultOr<size_t> Plan9FSInode::directory_entry_count() const
{ {
size_t count = 0; size_t count = 0;
KResult result = traverse_as_directory([&count](const FS::DirectoryEntry&) { KResult result = traverse_as_directory([&count](auto&) {
count++; count++;
return true; return true;
}); });
@ -809,7 +809,7 @@ KResultOr<size_t> Plan9FSInode::directory_entry_count() const
return count; return count;
} }
KResult Plan9FSInode::traverse_as_directory(Function<bool(const FS::DirectoryEntry&)> callback) const KResult Plan9FSInode::traverse_as_directory(Function<bool(const FS::DirectoryEntryView&)> callback) const
{ {
KResult result = KSuccess; KResult result = KSuccess;
@ -857,17 +857,7 @@ KResult Plan9FSInode::traverse_as_directory(Function<bool(const FS::DirectoryEnt
u8 type; u8 type;
StringView name; StringView name;
decoder >> qid >> offset >> type >> name; decoder >> qid >> offset >> type >> name;
callback({ name, { fsid(), fs().allocate_fid() }, 0 });
FS::DirectoryEntry entry {
"",
name.length(),
{ fsid(), fs().allocate_fid() },
0
};
size_t size_to_copy = min(sizeof(entry.name) - 1, name.length());
memcpy(entry.name, name.characters_without_null_termination(), size_to_copy);
entry.name[size_to_copy] = 0;
callback(entry);
} }
} }

View file

@ -126,7 +126,7 @@ public:
virtual void flush_metadata() override; virtual void flush_metadata() override;
virtual ssize_t read_bytes(off_t, ssize_t, u8* buffer, FileDescription*) const override; virtual ssize_t read_bytes(off_t, ssize_t, u8* buffer, FileDescription*) const override;
virtual ssize_t write_bytes(off_t, ssize_t, const u8* data, FileDescription*) override; virtual ssize_t write_bytes(off_t, ssize_t, const u8* data, FileDescription*) override;
virtual KResult traverse_as_directory(Function<bool(const FS::DirectoryEntry&)>) const override; virtual KResult traverse_as_directory(Function<bool(const FS::DirectoryEntryView&)>) const override;
virtual RefPtr<Inode> lookup(StringView name) override; virtual RefPtr<Inode> lookup(StringView name) override;
virtual KResultOr<NonnullRefPtr<Inode>> create_child(const String& name, mode_t, dev_t, uid_t, gid_t) override; virtual KResultOr<NonnullRefPtr<Inode>> create_child(const String& name, mode_t, dev_t, uid_t, gid_t) override;
virtual KResult add_child(Inode&, const StringView& name, mode_t) override; virtual KResult add_child(Inode&, const StringView& name, mode_t) override;

View file

@ -1246,7 +1246,7 @@ InodeIdentifier ProcFS::ProcFSDirectoryEntry::identifier(unsigned fsid) const
return to_identifier(fsid, PDI_Root, 0, (ProcFileType)proc_file_type); return to_identifier(fsid, PDI_Root, 0, (ProcFileType)proc_file_type);
} }
KResult ProcFSInode::traverse_as_directory(Function<bool(const FS::DirectoryEntry&)> callback) const KResult ProcFSInode::traverse_as_directory(Function<bool(const FS::DirectoryEntryView&)> callback) const
{ {
#ifdef PROCFS_DEBUG #ifdef PROCFS_DEBUG
dbg() << "ProcFS: traverse_as_directory " << index(); dbg() << "ProcFS: traverse_as_directory " << index();
@ -1258,8 +1258,8 @@ KResult ProcFSInode::traverse_as_directory(Function<bool(const FS::DirectoryEntr
auto proc_file_type = to_proc_file_type(identifier()); auto proc_file_type = to_proc_file_type(identifier());
auto parent_id = to_parent_id(identifier()); auto parent_id = to_parent_id(identifier());
callback({ ".", 1, identifier(), 2 }); callback({ ".", identifier(), 2 });
callback({ "..", 2, parent_id, 2 }); callback({ "..", parent_id, 2 });
switch (proc_file_type) { switch (proc_file_type) {
case FI_Root: case FI_Root:
@ -1268,28 +1268,28 @@ KResult ProcFSInode::traverse_as_directory(Function<bool(const FS::DirectoryEntr
if (!entry.name) if (!entry.name)
continue; continue;
if (entry.proc_file_type > __FI_Root_Start && entry.proc_file_type < __FI_Root_End) if (entry.proc_file_type > __FI_Root_Start && entry.proc_file_type < __FI_Root_End)
callback({ entry.name, strlen(entry.name), to_identifier(fsid(), PDI_Root, 0, (ProcFileType)entry.proc_file_type), 0 }); callback({ { entry.name, strlen(entry.name) }, to_identifier(fsid(), PDI_Root, 0, (ProcFileType)entry.proc_file_type), 0 });
} }
for (auto pid_child : Process::all_pids()) { for (auto pid_child : Process::all_pids()) {
char name[16]; char name[16];
size_t name_length = (size_t)sprintf(name, "%d", pid_child.value()); size_t name_length = (size_t)sprintf(name, "%d", pid_child.value());
callback({ name, name_length, to_identifier(fsid(), PDI_Root, pid_child, FI_PID), 0 }); callback({ { name, name_length }, to_identifier(fsid(), PDI_Root, pid_child, FI_PID), 0 });
} }
break; break;
case FI_Root_sys: case FI_Root_sys:
for (size_t i = 1; i < sys_variables().size(); ++i) { for (size_t i = 1; i < sys_variables().size(); ++i) {
auto& variable = sys_variables()[i]; auto& variable = sys_variables()[i];
callback({ variable.name.characters(), variable.name.length(), sys_var_to_identifier(fsid(), i), 0 }); callback({ variable.name, sys_var_to_identifier(fsid(), i), 0 });
} }
break; break;
case FI_Root_net: case FI_Root_net:
callback({ "adapters", 8, to_identifier(fsid(), PDI_Root_net, 0, FI_Root_net_adapters), 0 }); callback({ "adapters", to_identifier(fsid(), PDI_Root_net, 0, FI_Root_net_adapters), 0 });
callback({ "arp", 3, to_identifier(fsid(), PDI_Root_net, 0, FI_Root_net_arp), 0 }); callback({ "arp", to_identifier(fsid(), PDI_Root_net, 0, FI_Root_net_arp), 0 });
callback({ "tcp", 3, to_identifier(fsid(), PDI_Root_net, 0, FI_Root_net_tcp), 0 }); callback({ "tcp", to_identifier(fsid(), PDI_Root_net, 0, FI_Root_net_tcp), 0 });
callback({ "udp", 3, to_identifier(fsid(), PDI_Root_net, 0, FI_Root_net_udp), 0 }); callback({ "udp", to_identifier(fsid(), PDI_Root_net, 0, FI_Root_net_udp), 0 });
callback({ "local", 5, to_identifier(fsid(), PDI_Root_net, 0, FI_Root_net_local), 0 }); callback({ "local", to_identifier(fsid(), PDI_Root_net, 0, FI_Root_net_local), 0 });
break; break;
case FI_PID: { case FI_PID: {
@ -1302,7 +1302,7 @@ KResult ProcFSInode::traverse_as_directory(Function<bool(const FS::DirectoryEntr
if (entry.proc_file_type == FI_PID_exe && !process->executable()) if (entry.proc_file_type == FI_PID_exe && !process->executable())
continue; continue;
// FIXME: strlen() here is sad. // FIXME: strlen() here is sad.
callback({ entry.name, strlen(entry.name), to_identifier(fsid(), PDI_PID, pid, (ProcFileType)entry.proc_file_type), 0 }); callback({ { entry.name, strlen(entry.name) }, to_identifier(fsid(), PDI_PID, pid, (ProcFileType)entry.proc_file_type), 0 });
} }
} }
} break; } break;
@ -1318,7 +1318,7 @@ KResult ProcFSInode::traverse_as_directory(Function<bool(const FS::DirectoryEntr
continue; continue;
char name[16]; char name[16];
size_t name_length = (size_t)sprintf(name, "%d", i); size_t name_length = (size_t)sprintf(name, "%d", i);
callback({ name, name_length, to_identifier_with_fd(fsid(), pid, i), 0 }); callback({ { name, name_length }, to_identifier_with_fd(fsid(), pid, i), 0 });
} }
} break; } break;
@ -1331,7 +1331,7 @@ KResult ProcFSInode::traverse_as_directory(Function<bool(const FS::DirectoryEntr
int tid = thread.tid().value(); int tid = thread.tid().value();
char name[16]; char name[16];
size_t name_length = (size_t)sprintf(name, "%d", tid); size_t name_length = (size_t)sprintf(name, "%d", tid);
callback({ name, name_length, to_identifier_with_stack(fsid(), tid), 0 }); callback({ { name, name_length }, to_identifier_with_stack(fsid(), tid), 0 });
return IterationDecision::Continue; return IterationDecision::Continue;
}); });
} break; } break;
@ -1635,7 +1635,7 @@ KResultOr<size_t> ProcFSInode::directory_entry_count() const
{ {
ASSERT(is_directory()); ASSERT(is_directory());
size_t count = 0; size_t count = 0;
KResult result = traverse_as_directory([&count](const FS::DirectoryEntry&) { KResult result = traverse_as_directory([&count](auto&) {
++count; ++count;
return true; return true;
}); });

View file

@ -98,7 +98,7 @@ private:
// ^Inode // ^Inode
virtual ssize_t read_bytes(off_t, ssize_t, u8* buffer, FileDescription*) const override; virtual ssize_t read_bytes(off_t, ssize_t, u8* buffer, FileDescription*) const override;
virtual InodeMetadata metadata() const override; virtual InodeMetadata metadata() const override;
virtual KResult traverse_as_directory(Function<bool(const FS::DirectoryEntry&)>) const override; virtual KResult traverse_as_directory(Function<bool(const FS::DirectoryEntryView&)>) const override;
virtual RefPtr<Inode> lookup(StringView name) override; virtual RefPtr<Inode> lookup(StringView name) override;
virtual void flush_metadata() override; virtual void flush_metadata() override;
virtual ssize_t write_bytes(off_t, ssize_t, const u8* buffer, FileDescription*) override; virtual ssize_t write_bytes(off_t, ssize_t, const u8* buffer, FileDescription*) override;
@ -125,7 +125,7 @@ private:
// ^Inode // ^Inode
virtual ssize_t read_bytes(off_t, ssize_t, u8*, FileDescription*) const override { ASSERT_NOT_REACHED(); } virtual ssize_t read_bytes(off_t, ssize_t, u8*, FileDescription*) const override { ASSERT_NOT_REACHED(); }
virtual InodeMetadata metadata() const override; virtual InodeMetadata metadata() const override;
virtual KResult traverse_as_directory(Function<bool(const FS::DirectoryEntry&)>) const override { ASSERT_NOT_REACHED(); } virtual KResult traverse_as_directory(Function<bool(const FS::DirectoryEntryView&)>) const override { ASSERT_NOT_REACHED(); }
virtual RefPtr<Inode> lookup(StringView name) override; virtual RefPtr<Inode> lookup(StringView name) override;
virtual void flush_metadata() override {}; virtual void flush_metadata() override {};
virtual ssize_t write_bytes(off_t, ssize_t, const u8*, FileDescription*) override { ASSERT_NOT_REACHED(); } virtual ssize_t write_bytes(off_t, ssize_t, const u8*, FileDescription*) override { ASSERT_NOT_REACHED(); }

View file

@ -124,7 +124,7 @@ InodeMetadata TmpFSInode::metadata() const
return m_metadata; return m_metadata;
} }
KResult TmpFSInode::traverse_as_directory(Function<bool(const FS::DirectoryEntry&)> callback) const KResult TmpFSInode::traverse_as_directory(Function<bool(const FS::DirectoryEntryView&)> callback) const
{ {
LOCKER(m_lock, Lock::Mode::Shared); LOCKER(m_lock, Lock::Mode::Shared);
@ -134,8 +134,10 @@ KResult TmpFSInode::traverse_as_directory(Function<bool(const FS::DirectoryEntry
callback({ ".", identifier(), 0 }); callback({ ".", identifier(), 0 });
callback({ "..", m_parent, 0 }); callback({ "..", m_parent, 0 });
for (auto& it : m_children) for (auto& it : m_children) {
callback(it.value.entry); auto& entry = it.value.entry;
callback({ { entry.name, entry.name_length }, entry.inode, entry.file_type });
}
return KSuccess; return KSuccess;
} }

View file

@ -76,7 +76,7 @@ public:
// ^Inode // ^Inode
virtual ssize_t read_bytes(off_t, ssize_t, u8* buffer, FileDescription*) const override; virtual ssize_t read_bytes(off_t, ssize_t, u8* buffer, FileDescription*) const override;
virtual InodeMetadata metadata() const override; virtual InodeMetadata metadata() const override;
virtual KResult traverse_as_directory(Function<bool(const FS::DirectoryEntry&)>) const override; virtual KResult traverse_as_directory(Function<bool(const FS::DirectoryEntryView&)>) const override;
virtual RefPtr<Inode> lookup(StringView name) override; virtual RefPtr<Inode> lookup(StringView name) override;
virtual void flush_metadata() override; virtual void flush_metadata() override;
virtual ssize_t write_bytes(off_t, ssize_t, const u8* buffer, FileDescription*) override; virtual ssize_t write_bytes(off_t, ssize_t, const u8* buffer, FileDescription*) override;

View file

@ -191,9 +191,9 @@ bool VFS::is_vfs_root(InodeIdentifier inode) const
return inode == root_inode_id(); return inode == root_inode_id();
} }
KResult VFS::traverse_directory_inode(Inode& dir_inode, Function<bool(const FS::DirectoryEntry&)> callback) KResult VFS::traverse_directory_inode(Inode& dir_inode, Function<bool(const FS::DirectoryEntryView&)> callback)
{ {
return dir_inode.traverse_as_directory([&](const FS::DirectoryEntry& entry) { return dir_inode.traverse_as_directory([&](auto& entry) {
InodeIdentifier resolved_inode; InodeIdentifier resolved_inode;
if (auto mount = find_mount_for_host(entry.inode)) if (auto mount = find_mount_for_host(entry.inode))
resolved_inode = mount->guest().identifier(); resolved_inode = mount->guest().identifier();
@ -202,13 +202,13 @@ KResult VFS::traverse_directory_inode(Inode& dir_inode, Function<bool(const FS::
// FIXME: This is now broken considering chroot and bind mounts. // FIXME: This is now broken considering chroot and bind mounts.
bool is_root_inode = dir_inode.identifier() == dir_inode.fs().root_inode()->identifier(); bool is_root_inode = dir_inode.identifier() == dir_inode.fs().root_inode()->identifier();
if (is_root_inode && !is_vfs_root(dir_inode.identifier()) && !strcmp(entry.name, "..")) { if (is_root_inode && !is_vfs_root(dir_inode.identifier()) && entry.name == "..") {
auto mount = find_mount_for_guest(dir_inode); auto mount = find_mount_for_guest(dir_inode);
ASSERT(mount); ASSERT(mount);
ASSERT(mount->host()); ASSERT(mount->host());
resolved_inode = mount->host()->identifier(); resolved_inode = mount->host()->identifier();
} }
callback(FS::DirectoryEntry(entry.name, entry.name_length, resolved_inode, entry.file_type)); callback({ entry.name, resolved_inode, entry.file_type });
return true; return true;
}); });
} }

View file

@ -126,7 +126,7 @@ private:
bool is_vfs_root(InodeIdentifier) const; bool is_vfs_root(InodeIdentifier) const;
KResult traverse_directory_inode(Inode&, Function<bool(const FS::DirectoryEntry&)>); KResult traverse_directory_inode(Inode&, Function<bool(const FS::DirectoryEntryView&)>);
Mount* find_mount_for_host(Inode&); Mount* find_mount_for_host(Inode&);
Mount* find_mount_for_host(InodeIdentifier); Mount* find_mount_for_host(InodeIdentifier);