1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 11:28:12 +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;
}
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)
return KResult(-ENOTDIR);
callback({ ".", 1, identifier(), 0 });
callback({ "..", 2, identifier(), 0 });
callback({ ".", identifier(), 0 });
callback({ "..", identifier(), 0 });
for (unsigned pty_index : *ptys) {
String name = String::number(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;

View file

@ -69,7 +69,7 @@ private:
// ^Inode
virtual ssize_t read_bytes(off_t, ssize_t, u8* buffer, FileDescription*) 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 void flush_metadata() 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;
}
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);
ASSERT(is_directory());
@ -871,7 +871,7 @@ KResult Ext2FSInode::traverse_as_directory(Function<bool(const FS::DirectoryEntr
#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);
#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;
}
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;
return false;
}
entries.append(entry);
entries.append({ entry.name.characters_without_null_termination(), entry.name.length(), entry.inode, entry.file_type });
return true;
});
@ -1008,7 +1008,7 @@ KResult Ext2FSInode::remove_child(const StringView& name)
Vector<FS::DirectoryEntry> entries;
KResult result = traverse_as_directory([&](auto& entry) {
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;
});
if (result.is_error())
@ -1478,7 +1478,7 @@ void Ext2FSInode::populate_lookup_cache() const
HashMap<String, unsigned> children;
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;
});

View file

@ -59,7 +59,7 @@ private:
// ^Inode
virtual ssize_t read_bytes(off_t, ssize_t, u8* buffer, FileDescription*) 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 void flush_metadata() 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) {
stream << (u32)entry.inode.index();
stream << (u8)entry.file_type;
stream << (u32)entry.name_length;
stream << (u32)entry.name.length();
stream << entry.name;
return true;
});

View file

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

View file

@ -29,6 +29,7 @@
#include <AK/RefCounted.h>
#include <AK/RefPtr.h>
#include <AK/String.h>
#include <AK/StringView.h>
#include <Kernel/FileSystem/InodeIdentifier.h>
#include <Kernel/KResult.h>
#include <Kernel/Lock.h>
@ -78,6 +79,14 @@ public:
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() { }
size_t block_size() const { return m_block_size; }

View file

@ -70,7 +70,7 @@ public:
KResultOr<KBuffer> read_entire(FileDescription* = nullptr) const;
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 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;

View file

@ -798,7 +798,7 @@ void Plan9FSInode::flush_metadata()
KResultOr<size_t> Plan9FSInode::directory_entry_count() const
{
size_t count = 0;
KResult result = traverse_as_directory([&count](const FS::DirectoryEntry&) {
KResult result = traverse_as_directory([&count](auto&) {
count++;
return true;
});
@ -809,7 +809,7 @@ KResultOr<size_t> Plan9FSInode::directory_entry_count() const
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;
@ -857,17 +857,7 @@ KResult Plan9FSInode::traverse_as_directory(Function<bool(const FS::DirectoryEnt
u8 type;
StringView name;
decoder >> qid >> offset >> type >> name;
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);
callback({ name, { fsid(), fs().allocate_fid() }, 0 });
}
}

View file

@ -126,7 +126,7 @@ public:
virtual void flush_metadata() 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 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 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;

View file

@ -1246,7 +1246,7 @@ InodeIdentifier ProcFS::ProcFSDirectoryEntry::identifier(unsigned fsid) const
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
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 parent_id = to_parent_id(identifier());
callback({ ".", 1, identifier(), 2 });
callback({ "..", 2, parent_id, 2 });
callback({ ".", identifier(), 2 });
callback({ "..", parent_id, 2 });
switch (proc_file_type) {
case FI_Root:
@ -1268,28 +1268,28 @@ KResult ProcFSInode::traverse_as_directory(Function<bool(const FS::DirectoryEntr
if (!entry.name)
continue;
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()) {
char name[16];
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;
case FI_Root_sys:
for (size_t i = 1; i < sys_variables().size(); ++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;
case FI_Root_net:
callback({ "adapters", 8, 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({ "tcp", 3, 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({ "local", 5, to_identifier(fsid(), PDI_Root_net, 0, FI_Root_net_local), 0 });
callback({ "adapters", to_identifier(fsid(), PDI_Root_net, 0, FI_Root_net_adapters), 0 });
callback({ "arp", to_identifier(fsid(), PDI_Root_net, 0, FI_Root_net_arp), 0 });
callback({ "tcp", to_identifier(fsid(), PDI_Root_net, 0, FI_Root_net_tcp), 0 });
callback({ "udp", to_identifier(fsid(), PDI_Root_net, 0, FI_Root_net_udp), 0 });
callback({ "local", to_identifier(fsid(), PDI_Root_net, 0, FI_Root_net_local), 0 });
break;
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())
continue;
// 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;
@ -1318,7 +1318,7 @@ KResult ProcFSInode::traverse_as_directory(Function<bool(const FS::DirectoryEntr
continue;
char name[16];
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;
@ -1331,7 +1331,7 @@ KResult ProcFSInode::traverse_as_directory(Function<bool(const FS::DirectoryEntr
int tid = thread.tid().value();
char name[16];
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;
});
} break;
@ -1635,7 +1635,7 @@ KResultOr<size_t> ProcFSInode::directory_entry_count() const
{
ASSERT(is_directory());
size_t count = 0;
KResult result = traverse_as_directory([&count](const FS::DirectoryEntry&) {
KResult result = traverse_as_directory([&count](auto&) {
++count;
return true;
});

View file

@ -98,7 +98,7 @@ private:
// ^Inode
virtual ssize_t read_bytes(off_t, ssize_t, u8* buffer, FileDescription*) 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 void flush_metadata() override;
virtual ssize_t write_bytes(off_t, ssize_t, const u8* buffer, FileDescription*) override;
@ -125,7 +125,7 @@ private:
// ^Inode
virtual ssize_t read_bytes(off_t, ssize_t, u8*, FileDescription*) const override { ASSERT_NOT_REACHED(); }
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 void flush_metadata() override {};
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;
}
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);
@ -134,8 +134,10 @@ KResult TmpFSInode::traverse_as_directory(Function<bool(const FS::DirectoryEntry
callback({ ".", identifier(), 0 });
callback({ "..", m_parent, 0 });
for (auto& it : m_children)
callback(it.value.entry);
for (auto& it : m_children) {
auto& entry = it.value.entry;
callback({ { entry.name, entry.name_length }, entry.inode, entry.file_type });
}
return KSuccess;
}

View file

@ -76,7 +76,7 @@ public:
// ^Inode
virtual ssize_t read_bytes(off_t, ssize_t, u8* buffer, FileDescription*) 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 void flush_metadata() 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();
}
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;
if (auto mount = find_mount_for_host(entry.inode))
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.
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);
ASSERT(mount);
ASSERT(mount->host());
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;
});
}

View file

@ -126,7 +126,7 @@ private:
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(InodeIdentifier);