Skip to content
Open
8 changes: 8 additions & 0 deletions AK/FixedStringBuffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,14 @@ class FixedStringBuffer {

size_t stored_length() const { return m_stored_length; }

void set_stored_length(size_t length)
{
VERIFY(length <= Size);
m_stored_length = length;
}

[[nodiscard]] ALWAYS_INLINE static constexpr size_t max_length() { return Size; }

FixedStringBuffer()
{
m_storage.fill(0);
Expand Down
3 changes: 2 additions & 1 deletion Kernel/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ set(KERNEL_SOURCES
FileSystem/AnonymousFile.cpp
FileSystem/BlockBasedFileSystem.cpp
FileSystem/Custody.cpp
FileSystem/CustodyBase.cpp
FileSystem/CanonicalizedPath.cpp
FileSystem/DevLoopFS/FileSystem.cpp
FileSystem/DevLoopFS/Inode.cpp
FileSystem/DevPtsFS/FileSystem.cpp
Expand Down Expand Up @@ -171,6 +171,7 @@ set(KERNEL_SOURCES
FileSystem/MountFile.cpp
FileSystem/OpenFileDescription.cpp
FileSystem/UnsharedResourceFile.cpp
FileSystem/UnresolvedPath.cpp
FileSystem/Plan9FS/FileSystem.cpp
FileSystem/Plan9FS/Inode.cpp
FileSystem/Plan9FS/Message.cpp
Expand Down
2 changes: 1 addition & 1 deletion Kernel/Devices/Storage/StorageManagement.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -462,7 +462,7 @@ ErrorOr<NonnullRefPtr<VFSRootContext>> StorageManagement::create_first_vfs_root_
dump_storage_devices_and_partitions();
PANIC("StorageManagement: Couldn't find a suitable device to boot from");
}
auto description = TRY(OpenFileDescription::try_create(boot_device_description.release_nonnull()));
auto description = TRY(OpenFileDescription::try_create(*boot_device_description));

auto fs = TRY(FileBackedFileSystem::create_and_append_filesystems_list_from_mount_file_and_description(mount_file, description));
return TRY(VFSRootContext::create_with_filesystem(VFSRootContext::AddToGlobalContextList::Yes, fs));
Expand Down
66 changes: 66 additions & 0 deletions Kernel/FileSystem/CanonicalizedPath.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/*
* Copyright (c) 2024, Liav A. <liavalb@hotmail.co.il>
*
* SPDX-License-Identifier: BSD-2-Clause
*/

#include <AK/Singleton.h>
#include <Kernel/FileSystem/CanonicalizedPath.h>
#include <Kernel/Library/KLexicalPath.h>

namespace Kernel {

static RawPtr<CanonicalizedPath> s_root_path;

ErrorOr<NonnullRefPtr<CanonicalizedPath>> CanonicalizedPath::clone() const
{
auto cloned_full_path = TRY(KString::try_create(full_path()));
return TRY(adopt_nonnull_ref_or_enomem(new (nothrow) CanonicalizedPath(move(cloned_full_path))));
}

CanonicalizedPath& CanonicalizedPath::fake_root_path()
{
// NOTE: The fake root path is used only during tear down of VFSRootContexts
// or in Kernel processes.
if (!s_root_path)
s_root_path = &MUST(adopt_nonnull_ref_or_enomem(new (nothrow) CanonicalizedPath())).leak_ref();
return *s_root_path;
}

ErrorOr<NonnullRefPtr<CanonicalizedPath>> CanonicalizedPath::create(Custody const& base, StringView raw_path)
{
auto custody_absolute_base_path = TRY(base.try_serialize_absolute_path());
OwnPtr<KString> full_path;
if (KLexicalPath::is_absolute(raw_path))
full_path = TRY(KString::try_create(raw_path));
else
full_path = TRY(KLexicalPath::try_join_non_canonical_second(custody_absolute_base_path->view(), raw_path));

KLexicalPath::canonicalize_absolute_path(*full_path);
return TRY(adopt_nonnull_ref_or_enomem(new (nothrow) CanonicalizedPath(full_path.release_nonnull())));
}

CanonicalizedPath::CanonicalizedPath()
{
}

StringView CanonicalizedPath::dirname() const
{
if (!m_path)
return "/"sv;
return KLexicalPath::dirname(m_path->view());
}

StringView CanonicalizedPath::basename() const
{
if (!m_path)
return ""sv;
return KLexicalPath::basename(m_path->view());
}

CanonicalizedPath::CanonicalizedPath(NonnullOwnPtr<KString> path)
: m_path(move(path))
{
}

}
50 changes: 50 additions & 0 deletions Kernel/FileSystem/CanonicalizedPath.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* Copyright (c) 2024, Liav A. <liavalb@hotmail.co.il>
*
* SPDX-License-Identifier: BSD-2-Clause
*/

#pragma once

#include <AK/OwnPtr.h>
#include <AK/RefPtr.h>
#include <AK/StringView.h>
#include <Kernel/FileSystem/Custody.h>

namespace Kernel {

// NOTE: A CanonicalizedPath is simply a path that we know that is absolute
// and containers no .. or . nor excessive slashes.

class CanonicalizedPath : public AtomicRefCounted<CanonicalizedPath> {
public:
// FIXME: We might be able to create proper copy and move constructors to eliminate the
// need for creating this with NonnullOwnPtr
static ErrorOr<NonnullRefPtr<CanonicalizedPath>> create(Custody const& base, StringView raw_path);

static CanonicalizedPath& fake_root_path();

ErrorOr<NonnullRefPtr<CanonicalizedPath>> clone() const;

StringView full_path() const
{
// NOTE: An empty path (or simply when m_path is nullptr) signals for being root path
// It should be noted that a symlink can give an empty string, so m_path is still not a null pointer.
if (!m_path)
return "/"sv;
return m_path->view();
}

StringView basename() const;
StringView dirname() const;

bool is_root() const { return m_path.ptr() == nullptr; }

private:
explicit CanonicalizedPath(NonnullOwnPtr<KString> path);
CanonicalizedPath();

OwnPtr<KString> const m_path;
};

}
47 changes: 0 additions & 47 deletions Kernel/FileSystem/CustodyBase.h

This file was deleted.

12 changes: 6 additions & 6 deletions Kernel/FileSystem/Inode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,19 +53,19 @@ void Inode::sync()
}
}

ErrorOr<NonnullRefPtr<Custody>> Inode::resolve_as_link(VFSRootContext const& vfs_root_context, Credentials const& credentials, CustodyBase const& base, RefPtr<Custody>* out_parent, int options, int symlink_recursion_level) const
ErrorOr<Inode::TargetLinkPath> Inode::read_as_link() const
{
// The default implementation simply treats the stored
// contents as a path and resolves that. That is, it
// behaves exactly how you would expect a symlink to work.

// Make sure that our assumptions about the path length hold up.
// Note that this doesn't mean that the reported size can be trusted, some inodes just report zero.
VERIFY(size() <= MAXPATHLEN);

Array<u8, MAXPATHLEN> contents;
auto read_bytes = TRY(read_until_filled_or_end(0, contents.size(), UserOrKernelBuffer::for_kernel_buffer(contents.data()), nullptr));
return VirtualFileSystem::resolve_path(vfs_root_context, credentials, StringView { contents.span().trim(read_bytes) }, base, out_parent, options, symlink_recursion_level);
VERIFY(size() <= TargetLinkPath::max_length());
TargetLinkPath contents;
auto read_bytes = TRY(read_until_filled_or_end(0, contents.max_length(), UserOrKernelBuffer::for_kernel_buffer(contents.storage().data()), nullptr));
contents.set_stored_length(read_bytes);
return contents;
}

Inode::Inode(FileSystem& fs, InodeIndex index)
Expand Down
11 changes: 7 additions & 4 deletions Kernel/FileSystem/Inode.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@
#include <AK/Function.h>
#include <AK/HashTable.h>
#include <AK/IntrusiveList.h>
#include <Kernel/FileSystem/CustodyBase.h>
#include <Kernel/FileSystem/FIFO.h>
#include <Kernel/FileSystem/FileSystem.h>
#include <Kernel/FileSystem/InodeIdentifier.h>
#include <Kernel/FileSystem/InodeMetadata.h>
#include <Kernel/FileSystem/UnresolvedPath.h>
#include <Kernel/Forward.h>
#include <Kernel/Library/ListedRefCounted.h>
#include <Kernel/Library/LockWeakPtr.h>
Expand Down Expand Up @@ -55,7 +55,10 @@ class Inode : public ListedRefCounted<Inode, LockType::Spinlock>

ErrorOr<size_t> write_bytes(off_t, size_t, UserOrKernelBuffer const& data, OpenFileDescription*);
ErrorOr<size_t> read_bytes(off_t, size_t, UserOrKernelBuffer& buffer, OpenFileDescription*) const;
ErrorOr<size_t> read_until_filled_or_end(off_t, size_t, UserOrKernelBuffer buffer, OpenFileDescription*) const;

using TargetLinkPath = FixedStringBuffer<MAXPATHLEN>;
ErrorOr<TargetLinkPath> read_as_link() const;

ErrorOr<void> truncate(u64);

virtual ErrorOr<void> attach(OpenFileDescription&) { return {}; }
Expand All @@ -69,8 +72,6 @@ class Inode : public ListedRefCounted<Inode, LockType::Spinlock>
virtual ErrorOr<void> chmod(mode_t) = 0;
virtual ErrorOr<void> chown(UserID, GroupID) = 0;

ErrorOr<NonnullRefPtr<Custody>> resolve_as_link(VFSRootContext const&, Credentials const&, CustodyBase const& base, RefPtr<Custody>* out_parent, int options, int symlink_recursion_level) const;

virtual ErrorOr<int> get_block_address(int) { return ENOTSUP; }

LockRefPtr<LocalSocket> bound_socket() const;
Expand Down Expand Up @@ -133,6 +134,8 @@ class Inode : public ListedRefCounted<Inode, LockType::Spinlock>
short type;
};

ErrorOr<size_t> read_until_filled_or_end(off_t, size_t, UserOrKernelBuffer buffer, OpenFileDescription*) const;

bool can_apply_flock_impl(flock const&, Optional<OpenFileDescription const&>, Vector<Flock> const& flocks) const;
ErrorOr<bool> try_apply_flock(Process const&, OpenFileDescription const&, flock const&);

Expand Down
1 change: 0 additions & 1 deletion Kernel/FileSystem/Mount.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ void Mount::delete_mount_from_list(Mount& mount)
dbgln("VirtualFileSystem: Unmounting file system {}...", mount.guest_fs().fsid());
VERIFY(mount.m_vfs_list_node.is_in_list());
mount.m_vfs_list_node.remove();
delete &mount;
}

ErrorOr<NonnullOwnPtr<KString>> Mount::absolute_path() const
Expand Down
5 changes: 2 additions & 3 deletions Kernel/FileSystem/Mount.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

namespace Kernel {

class Mount {
class Mount : public AtomicRefCounted<Mount> {
AK_MAKE_NONCOPYABLE(Mount);
AK_MAKE_NONMOVABLE(Mount);
friend class VFSRootContext;
Expand Down Expand Up @@ -65,7 +65,6 @@ class Mount {

SetOnce m_immutable;

IntrusiveListNode<Mount> m_vfs_list_node;
IntrusiveListNode<Mount, NonnullRefPtr<Mount>> m_vfs_list_node;
};

}
22 changes: 15 additions & 7 deletions Kernel/FileSystem/OpenFileDescription.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,12 @@

namespace Kernel {

ErrorOr<NonnullRefPtr<OpenFileDescription>> OpenFileDescription::try_create(Custody& custody)
ErrorOr<NonnullRefPtr<OpenFileDescription>> OpenFileDescription::try_create(NonnullOwnPtr<Path> path)
{
auto inode_file = TRY(InodeFile::create(custody.inode()));
auto inode_file = TRY(InodeFile::create(path->custody().inode()));
auto description = TRY(adopt_nonnull_ref_or_enomem(new (nothrow) OpenFileDescription(move(inode_file))));

description->m_state.with([&](auto& state) { state.custody = custody; });
description->m_state.with([&](auto& state) { state.path = move(path); });
TRY(description->attach());
return description;
}
Expand Down Expand Up @@ -70,9 +70,9 @@ ErrorOr<void> OpenFileDescription::attach()
return m_file->attach(*this);
}

void OpenFileDescription::set_original_custody(Custody& custody)
void OpenFileDescription::set_original_path(NonnullOwnPtr<Path> path)
{
m_state.with([&](auto& state) { state.custody = custody; });
m_state.with([&](auto& state) { state.path = move(path); });
}

Thread::FileBlocker::BlockFlags OpenFileDescription::should_unblock(Thread::FileBlocker::BlockFlags block_flags) const
Expand Down Expand Up @@ -565,12 +565,20 @@ off_t OpenFileDescription::offset() const

RefPtr<Custody const> OpenFileDescription::custody() const
{
return m_state.with([](auto& state) { return state.custody; });
return m_state.with([](auto& state) -> RefPtr<Custody> {
if (!state.path)
return nullptr;
return state.path->custody();
});
}

RefPtr<Custody> OpenFileDescription::custody()
{
return m_state.with([](auto& state) { return state.custody; });
return m_state.with([](auto& state) -> RefPtr<Custody> {
if (!state.path)
return nullptr;
return state.path->custody();
});
}

}
9 changes: 6 additions & 3 deletions Kernel/FileSystem/OpenFileDescription.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <Kernel/FileSystem/FIFO.h>
#include <Kernel/FileSystem/Inode.h>
#include <Kernel/FileSystem/InodeMetadata.h>
#include <Kernel/FileSystem/Path.h>
#include <Kernel/Forward.h>
#include <Kernel/Library/KBuffer.h>
#include <Kernel/Memory/VirtualAddress.h>
Expand All @@ -25,8 +26,10 @@ class OpenFileDescriptionData {
};

class OpenFileDescription final : public AtomicRefCounted<OpenFileDescription> {
friend class Process;

public:
static ErrorOr<NonnullRefPtr<OpenFileDescription>> try_create(Custody&);
static ErrorOr<NonnullRefPtr<OpenFileDescription>> try_create(NonnullOwnPtr<Path>);
static ErrorOr<NonnullRefPtr<OpenFileDescription>> try_create(File&);
~OpenFileDescription();

Expand Down Expand Up @@ -122,7 +125,7 @@ class OpenFileDescription final : public AtomicRefCounted<OpenFileDescription> {

// NOTE: These methods are (and should be only) called from Kernel/FileSystem/VirtualFileSystem.cpp
void set_original_inode(NonnullRefPtr<Inode> inode) { m_inode = move(inode); }
void set_original_custody(Custody& custody);
void set_original_path(NonnullOwnPtr<Path> path);

ErrorOr<void> truncate(u64);
ErrorOr<void> sync();
Expand Down Expand Up @@ -151,7 +154,7 @@ class OpenFileDescription final : public AtomicRefCounted<OpenFileDescription> {

struct State {
OwnPtr<OpenFileDescriptionData> data;
RefPtr<Custody> custody;
OwnPtr<Path> path;
off_t current_offset { 0 };
u32 file_flags { 0 };
bool readable : 1 { false };
Expand Down
Loading
Loading