/* * Copyright (c) 2024, the SerenityOS developers. * * SPDX-License-Identifier: BSD-2-Clause */ #include #include #include #include #include #include namespace Kernel { static constexpr StringView rootmode_flag = "rootmode"sv; static constexpr StringView gid_flag = "gid"sv; static constexpr StringView uid_flag = "uid"sv; static constexpr StringView fd_flag = "fd"sv; ErrorOr> FUSE::try_create(FileSystemSpecificOptions const& filesystem_specific_options) { int device_inode = parse_unsigned_filesystem_specific_option(filesystem_specific_options, fd_flag).value_or(-1); auto description = TRY(Process::current().open_file_description(device_inode)); auto connection = TRY(FUSEConnection::try_create(description)); u64 rootmode = parse_unsigned_filesystem_specific_option(filesystem_specific_options, rootmode_flag).value_or(0); u64 gid = parse_unsigned_filesystem_specific_option(filesystem_specific_options, gid_flag).value_or(0); u64 uid = parse_unsigned_filesystem_specific_option(filesystem_specific_options, uid_flag).value_or(0); return TRY(adopt_nonnull_ref_or_enomem(new (nothrow) FUSE(connection, rootmode, uid, gid))); } ErrorOr FUSE::validate_mount_unsigned_integer_flag(StringView flag_name, u64) { if (flag_name == rootmode_flag) return {}; if (flag_name == gid_flag) return {}; if (flag_name == uid_flag) return {}; if (flag_name == fd_flag) return {}; return EINVAL; } FUSE::FUSE(NonnullRefPtr connection, u64 rootmode, u64 gid, u64 uid) : m_connection(connection) , m_rootmode(rootmode) , m_gid(gid) , m_uid(uid) { } FUSE::~FUSE() = default; ErrorOr FUSE::initialize() { m_root_inode = TRY(adopt_nonnull_ref_or_enomem(new (nothrow) FUSEInode(*this))); m_root_inode->m_metadata.mode = m_rootmode; m_root_inode->m_metadata.uid = m_gid; m_root_inode->m_metadata.gid = m_uid; m_root_inode->m_metadata.size = 0; m_root_inode->m_metadata.mtime = TimeManagement::boot_time(); return {}; } Inode& FUSE::root_inode() { return *m_root_inode; } ErrorOr FUSE::rename(Inode& old_parent_inode, StringView old_basename, Inode& new_parent_inode, StringView new_basename) { auto payload = TRY(KBuffer::try_create_with_size("FUSE: Lookup name string"sv, sizeof(fuse_rename_in) + old_basename.length() + new_basename.length() + 2)); memset(payload->data(), 0, payload->size()); fuse_rename_in* rename_in = bit_cast(payload->data()); rename_in->newdir = new_parent_inode.identifier().index().value(); memcpy(rename_in->data, old_basename.characters_without_null_termination(), old_basename.length()); memcpy(rename_in->data + old_basename.length() + 1, new_basename.characters_without_null_termination(), new_basename.length()); auto response = TRY(m_connection->send_request_and_wait_for_a_reply(FUSEOpcode::FUSE_RENAME, old_parent_inode.identifier().index().value(), payload->bytes())); fuse_out_header* header = bit_cast(response->data()); if (header->error) return Error::from_errno(-header->error); return {}; } u8 FUSE::internal_file_type_to_directory_entry_type(DirectoryEntryView const& entry) const { return ram_backed_file_type_to_directory_entry_type(entry); } }