mirror of
https://github.com/SerenityOS/serenity
synced 2026-04-25 17:15:42 +02:00
That functionality seems to be too much complicated. We shouldn't overengineer how the copy_mount syscall works, so instead of allowing replacement of the root filesystem, let's make the unshare file descriptor to be configured via a special ioctl call before we initialize a new VFSRootContext object. The special ioctl can either set a new root filesystem for the upcoming VFSRootContext object, or remove it (by passing fd of -1). If there's no specified root filesystem, a new RAMFS instance will be created automatically when invoking the unshare_create syscall. This also simplifies the code in the boot process, hence making it much more readable. It should be noted, that we assumed during pivot_root that the first mountpoint in a context is the root mountpoint, which is probably a fair assumption, but we don't assume this anywhere else in the VFSRootContext code. If this functionality ever comes back, we should ensure that we make some effort to not assume this again.
118 lines
4.7 KiB
C++
118 lines
4.7 KiB
C++
/*
|
|
* Copyright (c) 2024, Liav A. <liavalb@hotmail.co.il>
|
|
*
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
*/
|
|
|
|
#include <AK/LexicalPath.h>
|
|
#include <AK/String.h>
|
|
#include <LibCore/System.h>
|
|
#include <LibFileSystem/FileSystem.h>
|
|
|
|
#include "VFSRootContextLayout.h"
|
|
|
|
ErrorOr<void> VFSRootContextLayout::mount_new_filesystem(StringView fstype, StringView source, StringView target_path, int flags)
|
|
{
|
|
auto source_fd = TRY(get_source_fd(source));
|
|
auto actual_path = TRY(generate_path_with_relation_to_preparation_environment_path(target_path));
|
|
|
|
auto target_path_string = TRY(String::from_utf8(target_path));
|
|
auto fstype_string = TRY(String::from_utf8(fstype));
|
|
|
|
TRY(Core::System::mount({}, source_fd, actual_path, fstype, flags));
|
|
|
|
auto mount = Mount { Mount::Type::RegularMount, {}, source_fd, target_path_string, fstype_string };
|
|
TRY(m_mounts.try_append(mount));
|
|
return {};
|
|
}
|
|
|
|
ErrorOr<void> VFSRootContextLayout::chown(StringView path, uid_t uid, gid_t gid)
|
|
{
|
|
auto actual_path = TRY(generate_path_with_relation_to_preparation_environment_path(path));
|
|
return Core::System::chown(actual_path, uid, gid);
|
|
}
|
|
|
|
ErrorOr<void> VFSRootContextLayout::chmod(StringView path, mode_t mode)
|
|
{
|
|
auto actual_path = TRY(generate_path_with_relation_to_preparation_environment_path(path));
|
|
return Core::System::chmod(actual_path, mode);
|
|
}
|
|
|
|
ErrorOr<void> VFSRootContextLayout::symlink(StringView path, StringView target_path)
|
|
{
|
|
auto actual_path = TRY(generate_path_with_relation_to_preparation_environment_path(path));
|
|
return Core::System::symlink(target_path, actual_path);
|
|
}
|
|
|
|
ErrorOr<void> VFSRootContextLayout::copy_as_original(StringView source_path)
|
|
{
|
|
return copy_to_custom_location(source_path, source_path);
|
|
}
|
|
|
|
ErrorOr<void> VFSRootContextLayout::copy_to_custom_location(StringView source_path, StringView target_path)
|
|
{
|
|
auto actual_path = TRY(generate_path_with_relation_to_preparation_environment_path(target_path));
|
|
TRY(FileSystem::copy_file_or_directory(
|
|
actual_path, source_path,
|
|
FileSystem::RecursionMode::Disallowed,
|
|
FileSystem::LinkMode::Disallowed,
|
|
FileSystem::AddDuplicateFileMarker::No,
|
|
FileSystem::PreserveMode::Ownership | FileSystem::PreserveMode::Permissions));
|
|
return {};
|
|
}
|
|
|
|
ErrorOr<void> VFSRootContextLayout::mkdir(StringView target_path)
|
|
{
|
|
auto actual_path = TRY(generate_path_with_relation_to_preparation_environment_path(target_path));
|
|
TRY(Core::System::mkdir(actual_path.bytes_as_string_view(), 0700));
|
|
return {};
|
|
}
|
|
|
|
ErrorOr<String> VFSRootContextLayout::generate_path_with_relation_to_preparation_environment_path(StringView target_path) const
|
|
{
|
|
VERIFY(LexicalPath(target_path).is_canonical());
|
|
auto path = LexicalPath::join(m_preparation_environment_path.bytes_as_string_view(), target_path);
|
|
return String::from_byte_string(path.string());
|
|
}
|
|
|
|
VFSRootContextLayout::VFSRootContextLayout(String preparation_environment_path, unsigned target_vfs_root_context_id)
|
|
: m_preparation_environment_path(move(preparation_environment_path))
|
|
, m_target_vfs_root_context_id(target_vfs_root_context_id)
|
|
{
|
|
}
|
|
|
|
ErrorOr<NonnullOwnPtr<VFSRootContextLayout>> VFSRootContextLayout::create_with_root_mount_point(StringView preparation_environment_path)
|
|
{
|
|
auto vfs_root_context_fd = TRY(Core::System::unshare_open(Kernel::UnshareType::VFSRootContext));
|
|
|
|
// At this point we are expecting this path to be mounted with the actual "root" filesystem for this VFS root context
|
|
auto preparation_environment_path_fd = TRY(Core::System::open(preparation_environment_path, O_DIRECTORY | O_RDONLY));
|
|
TRY(Core::System::ioctl(vfs_root_context_fd, UNSHARE_IOCTL_ATTACH_ROOT_FILESYSTEM_AT_FD, preparation_environment_path_fd));
|
|
close(preparation_environment_path_fd);
|
|
|
|
auto vfs_root_context_index = TRY(Core::System::unshare_create(vfs_root_context_fd));
|
|
|
|
close(vfs_root_context_fd);
|
|
|
|
auto path = TRY(String::from_utf8(preparation_environment_path));
|
|
return adopt_nonnull_own_or_enomem(new (nothrow) VFSRootContextLayout(move(path), vfs_root_context_index));
|
|
}
|
|
|
|
ErrorOr<void> VFSRootContextLayout::apply_mounts_on_vfs_root_context_id()
|
|
{
|
|
for (auto& mount : m_mounts) {
|
|
auto path_on_preparation_environment = TRY(generate_path_with_relation_to_preparation_environment_path(mount.path));
|
|
TRY(Core::System::copy_mount({},
|
|
m_target_vfs_root_context_id,
|
|
path_on_preparation_environment.bytes_as_string_view(),
|
|
mount.path, 0));
|
|
}
|
|
|
|
for (auto& mount : m_mounts.in_reverse()) {
|
|
auto path_on_preparation_environment = TRY(generate_path_with_relation_to_preparation_environment_path(mount.path));
|
|
TRY(Core::System::umount({}, path_on_preparation_environment.bytes_as_string_view()));
|
|
}
|
|
m_mounts.clear();
|
|
return {};
|
|
}
|