mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-12-29 14:14:45 +03:00
FileSystem: Add a Custody class that represents a parent/child guardianship.
A custody is kind of a directory entry abstraction that represents a single entry in a parent directory that tells us the name of a child inode. The idea here is for path resolution to produce a chain of custody objects.
This commit is contained in:
parent
3a1d5fa112
commit
4cb87b1753
Notes:
sideshowbarker
2024-07-19 13:50:03 +09:00
Author: https://github.com/awesomekling Commit: https://github.com/SerenityOS/serenity/commit/4cb87b17536
27
Kernel/FileSystem/Custody.cpp
Normal file
27
Kernel/FileSystem/Custody.cpp
Normal file
@ -0,0 +1,27 @@
|
||||
#include <AK/HashTable.h>
|
||||
#include <Kernel/FileSystem/Custody.h>
|
||||
#include <Kernel/FileSystem/Inode.h>
|
||||
#include <Kernel/Lock.h>
|
||||
|
||||
static Lockable<HashTable<Custody*>>& all_custodies()
|
||||
{
|
||||
static Lockable<HashTable<Custody*>>* table;
|
||||
if (!table)
|
||||
table = new Lockable<HashTable<Custody*>>;
|
||||
return *table;
|
||||
}
|
||||
|
||||
Custody::Custody(Custody* parent, const String& name, Inode& inode)
|
||||
: m_parent(parent)
|
||||
, m_name(name)
|
||||
, m_inode(inode)
|
||||
{
|
||||
LOCKER(all_custodies().lock());
|
||||
all_custodies().resource().set(this);
|
||||
}
|
||||
|
||||
Custody::~Custody()
|
||||
{
|
||||
LOCKER(all_custodies().lock());
|
||||
all_custodies().resource().remove(this);
|
||||
}
|
32
Kernel/FileSystem/Custody.h
Normal file
32
Kernel/FileSystem/Custody.h
Normal file
@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
|
||||
#include <AK/AKString.h>
|
||||
#include <AK/RetainPtr.h>
|
||||
#include <AK/Retainable.h>
|
||||
|
||||
class Inode;
|
||||
|
||||
class Custody : public Retainable<Custody> {
|
||||
public:
|
||||
static Retained<Custody> create(Custody* parent, const String& name, Inode& inode)
|
||||
{
|
||||
return adopt(*new Custody(parent, name, inode));
|
||||
}
|
||||
|
||||
~Custody();
|
||||
|
||||
Custody* parent() { return m_parent.ptr(); }
|
||||
const Custody* parent() const { return m_parent.ptr(); }
|
||||
|
||||
Inode& inode() { return *m_inode; }
|
||||
const Inode& inode() const { return *m_inode; }
|
||||
|
||||
const String& name() const { return m_name; }
|
||||
|
||||
private:
|
||||
Custody(Custody* parent, const String& name, Inode&);
|
||||
|
||||
RetainPtr<Custody> m_parent;
|
||||
String m_name;
|
||||
Retained<Inode> m_inode;
|
||||
};
|
@ -6,6 +6,7 @@
|
||||
#include <Kernel/Devices/CharacterDevice.h>
|
||||
#include <LibC/errno_numbers.h>
|
||||
#include <Kernel/Process.h>
|
||||
#include <Kernel/FileSystem/Custody.h>
|
||||
|
||||
//#define VFS_DEBUG
|
||||
|
||||
@ -739,3 +740,77 @@ void VFS::sync()
|
||||
{
|
||||
FS::sync();
|
||||
}
|
||||
|
||||
Custody& VFS::root_custody()
|
||||
{
|
||||
if (!m_root_custody)
|
||||
m_root_custody = Custody::create(nullptr, "", *root_inode());
|
||||
return *m_root_custody;
|
||||
}
|
||||
|
||||
KResultOr<Retained<Custody>> VFS::resolve_path_to_custody(StringView path, Custody& base, int options)
|
||||
{
|
||||
if (path.is_empty())
|
||||
return KResult(-EINVAL);
|
||||
|
||||
auto parts = path.split_view('/');
|
||||
InodeIdentifier crumb_id;
|
||||
|
||||
Vector<Retained<Custody>, 32> custody_chain;
|
||||
|
||||
if (path[0] == '/') {
|
||||
custody_chain.append(Retained<Custody>(base));
|
||||
crumb_id = root_inode_id();
|
||||
} else {
|
||||
for (auto* custody = &base; custody; custody = custody->parent()) {
|
||||
// FIXME: Prepending here is not efficient! Fix this.
|
||||
custody_chain.prepend(*custody);
|
||||
}
|
||||
crumb_id = base.inode().identifier();
|
||||
}
|
||||
|
||||
for (int i = 0; i < parts.size(); ++i) {
|
||||
bool inode_was_root_at_head_of_loop = crumb_id.is_root_inode();
|
||||
auto& part = parts[i];
|
||||
if (part.is_empty())
|
||||
break;
|
||||
auto crumb_inode = get_inode(crumb_id);
|
||||
if (!crumb_inode)
|
||||
return KResult(-EIO);
|
||||
auto metadata = crumb_inode->metadata();
|
||||
if (!metadata.is_directory())
|
||||
return KResult(-ENOTDIR);
|
||||
if (!metadata.may_execute(current->process()))
|
||||
return KResult(-EACCES);
|
||||
auto parent = crumb_id;
|
||||
crumb_id = crumb_inode->lookup(part);
|
||||
if (!crumb_id.is_valid())
|
||||
return KResult(-ENOENT);
|
||||
if (auto mount = find_mount_for_host(crumb_id))
|
||||
crumb_id = mount->guest();
|
||||
if (inode_was_root_at_head_of_loop && crumb_id.is_root_inode() && !is_vfs_root(crumb_id) && part == "..") {
|
||||
auto mount = find_mount_for_guest(crumb_id);
|
||||
auto dir_inode = get_inode(mount->host());
|
||||
ASSERT(dir_inode);
|
||||
crumb_id = dir_inode->lookup("..");
|
||||
}
|
||||
crumb_inode = get_inode(crumb_id);
|
||||
ASSERT(crumb_inode);
|
||||
custody_chain.append(Custody::create(custody_chain.last().ptr(), part, *crumb_inode));
|
||||
metadata = crumb_inode->metadata();
|
||||
if (metadata.is_symlink()) {
|
||||
if (i == parts.size() - 1) {
|
||||
if (options & O_NOFOLLOW)
|
||||
return KResult(-ELOOP);
|
||||
if (options & O_NOFOLLOW_NOERROR)
|
||||
return custody_chain.last();
|
||||
}
|
||||
auto result = resolve_symbolic_link(parent, *crumb_inode);
|
||||
if (result.is_error())
|
||||
return KResult(-ENOENT);
|
||||
crumb_id = result.value();
|
||||
ASSERT(crumb_id.is_valid());
|
||||
}
|
||||
}
|
||||
return custody_chain.last();
|
||||
}
|
||||
|
@ -25,6 +25,7 @@
|
||||
#define O_CLOEXEC 02000000
|
||||
#define O_NOFOLLOW_NOERROR 0x4000000
|
||||
|
||||
class Custody;
|
||||
class Device;
|
||||
class FileDescriptor;
|
||||
|
||||
@ -96,6 +97,9 @@ public:
|
||||
|
||||
Device* get_device(unsigned major, unsigned minor);
|
||||
|
||||
Custody& root_custody();
|
||||
KResultOr<Retained<Custody>> resolve_path_to_custody(StringView path, Custody& base, int options = 0);
|
||||
|
||||
private:
|
||||
friend class FileDescriptor;
|
||||
|
||||
@ -115,4 +119,6 @@ private:
|
||||
RetainPtr<Inode> m_root_inode;
|
||||
Vector<OwnPtr<Mount>> m_mounts;
|
||||
HashMap<dword, Device*> m_devices;
|
||||
|
||||
RetainPtr<Custody> m_root_custody;
|
||||
};
|
||||
|
@ -50,6 +50,7 @@ KERNEL_OBJS = \
|
||||
ProcessTracer.o \
|
||||
Devices/PCSpeaker.o \
|
||||
FileSystem/InodeFile.o \
|
||||
FileSystem/Custody.o \
|
||||
File.o
|
||||
|
||||
VFS_OBJS = \
|
||||
|
Loading…
Reference in New Issue
Block a user