diff --git a/Kernel/CMakeLists.txt b/Kernel/CMakeLists.txt index 9334b7679d..ff516086e4 100644 --- a/Kernel/CMakeLists.txt +++ b/Kernel/CMakeLists.txt @@ -545,6 +545,7 @@ set(PARTITION_SOURCES ../Userland/Libraries/LibPartition/EBRPartitionTable.cpp ../Userland/Libraries/LibPartition/GUIDPartitionTable.cpp ../Userland/Libraries/LibPartition/MBRPartitionTable.cpp + ../Userland/Libraries/LibPartition/PartitionableDevice.cpp ../Userland/Libraries/LibPartition/PartitionTable.cpp ) diff --git a/Userland/Applications/PartitionEditor/PartitionModel.cpp b/Userland/Applications/PartitionEditor/PartitionModel.cpp index 98d2f8a937..4a059cc690 100644 --- a/Userland/Applications/PartitionEditor/PartitionModel.cpp +++ b/Userland/Applications/PartitionEditor/PartitionModel.cpp @@ -6,7 +6,6 @@ #include #include -#include #include #include #include @@ -68,28 +67,33 @@ GUI::Variant PartitionModel::data(GUI::ModelIndex const& index, GUI::ModelRole r ErrorOr PartitionModel::set_device_path(DeprecatedString const& path) { - auto file = TRY(Core::DeprecatedFile::open(path, Core::OpenMode::ReadOnly)); + auto strong_file = TRY(Core::File::open(path, Core::File::OpenMode::Read)); + auto weak_file = TRY(Core::File::adopt_fd(strong_file->fd(), Core::File::OpenMode::Read, Core::File::ShouldCloseFileDescriptor::No)); + auto device = TRY(Partition::PartitionableDevice::create(move(weak_file))); - auto mbr_table_or_error = Partition::MBRPartitionTable::try_to_initialize(file); + auto mbr_table_or_error = Partition::MBRPartitionTable::try_to_initialize(TRY(device.clone_owned())); if (!mbr_table_or_error.is_error()) { dbgln("Found MBR partition table on {}", path); m_partition_table = move(mbr_table_or_error.value()); + m_backing_file = move(strong_file); invalidate(); return {}; } - auto ebr_table_or_error = Partition::EBRPartitionTable::try_to_initialize(file); + auto ebr_table_or_error = Partition::EBRPartitionTable::try_to_initialize(TRY(device.clone_owned())); if (!ebr_table_or_error.is_error()) { dbgln("Found EBR partition table on {}", path); m_partition_table = move(ebr_table_or_error.value()); + m_backing_file = move(strong_file); invalidate(); return {}; } - auto guid_table_or_error = Partition::GUIDPartitionTable::try_to_initialize(file); + auto guid_table_or_error = Partition::GUIDPartitionTable::try_to_initialize(TRY(device.clone_owned())); if (!guid_table_or_error.is_error()) { dbgln("Found GUID partition table on {}", path); m_partition_table = move(guid_table_or_error.value()); + m_backing_file = move(strong_file); invalidate(); return {}; } diff --git a/Userland/Applications/PartitionEditor/PartitionModel.h b/Userland/Applications/PartitionEditor/PartitionModel.h index 7cbdde0793..a66fff5f11 100644 --- a/Userland/Applications/PartitionEditor/PartitionModel.h +++ b/Userland/Applications/PartitionEditor/PartitionModel.h @@ -6,6 +6,7 @@ #pragma once +#include #include #include @@ -36,6 +37,7 @@ private: PartitionModel() = default; OwnPtr m_partition_table; + OwnPtr m_backing_file; }; } diff --git a/Userland/Libraries/LibPartition/CMakeLists.txt b/Userland/Libraries/LibPartition/CMakeLists.txt index 176993ba94..e8afeeb707 100644 --- a/Userland/Libraries/LibPartition/CMakeLists.txt +++ b/Userland/Libraries/LibPartition/CMakeLists.txt @@ -3,6 +3,7 @@ set(SOURCES EBRPartitionTable.cpp GUIDPartitionTable.cpp MBRPartitionTable.cpp + PartitionableDevice.cpp PartitionTable.cpp ) diff --git a/Userland/Libraries/LibPartition/EBRPartitionTable.cpp b/Userland/Libraries/LibPartition/EBRPartitionTable.cpp index dcffd39c40..9011526578 100644 --- a/Userland/Libraries/LibPartition/EBRPartitionTable.cpp +++ b/Userland/Libraries/LibPartition/EBRPartitionTable.cpp @@ -6,21 +6,11 @@ #include -#ifndef KERNEL -# include -#endif - namespace Partition { -#ifdef KERNEL -ErrorOr> EBRPartitionTable::try_to_initialize(Kernel::StorageDevice& device) +ErrorOr> EBRPartitionTable::try_to_initialize(PartitionableDevice device) { - auto table = TRY(adopt_nonnull_own_or_enomem(new (nothrow) EBRPartitionTable(device))); -#else -ErrorOr> EBRPartitionTable::try_to_initialize(NonnullRefPtr device_file) -{ - auto table = TRY(adopt_nonnull_own_or_enomem(new (nothrow) EBRPartitionTable(move(device_file)))); -#endif + auto table = TRY(adopt_nonnull_own_or_enomem(new (nothrow) EBRPartitionTable(move(device)))); if (table->is_protective_mbr()) return Error::from_errno(ENOTSUP); if (!table->is_valid()) @@ -28,16 +18,13 @@ ErrorOr> EBRPartitionTable::try_to_initialize(N return table; } -#ifdef KERNEL -void EBRPartitionTable::search_extended_partition(Kernel::StorageDevice& device, MBRPartitionTable& checked_ebr, u64 current_block_offset, size_t limit) -#else -void EBRPartitionTable::search_extended_partition(NonnullRefPtr device, MBRPartitionTable& checked_ebr, u64 current_block_offset, size_t limit) -#endif +void EBRPartitionTable::search_extended_partition(MBRPartitionTable& checked_ebr, u64 current_block_offset, size_t limit) { if (limit == 0) return; // EBRs should not carry more than 2 partitions (because they need to form a linked list) VERIFY(checked_ebr.partitions_count() <= 2); + // FIXME: We should not crash the Kernel or any apps when the EBR is malformed. auto checked_logical_partition = checked_ebr.partition(0); // If we are pointed to an invalid logical partition, something is seriously wrong. @@ -46,18 +33,15 @@ void EBRPartitionTable::search_extended_partition(NonnullRefPtr device) -#endif - : MBRPartitionTable(device) +EBRPartitionTable::EBRPartitionTable(PartitionableDevice device) + : MBRPartitionTable(move(device)) { if (!is_header_valid()) return; @@ -70,11 +54,11 @@ EBRPartitionTable::EBRPartitionTable(NonnullRefPtr device) auto& entry = header.entry[index]; // Start enumerating all logical partitions if (entry.type == 0xf) { - auto checked_ebr = MBRPartitionTable::try_to_initialize(device, entry.offset); + auto checked_ebr = MBRPartitionTable::try_to_initialize(m_device.clone_unowned(), entry.offset); if (!checked_ebr) continue; // It's quite unlikely to see that amount of partitions, so stop at 128 partitions. - search_extended_partition(device, *checked_ebr, entry.offset, 128); + search_extended_partition(*checked_ebr, entry.offset, 128); continue; } diff --git a/Userland/Libraries/LibPartition/EBRPartitionTable.h b/Userland/Libraries/LibPartition/EBRPartitionTable.h index e88167140c..41a76f5add 100644 --- a/Userland/Libraries/LibPartition/EBRPartitionTable.h +++ b/Userland/Libraries/LibPartition/EBRPartitionTable.h @@ -15,13 +15,8 @@ class EBRPartitionTable : public MBRPartitionTable { public: ~EBRPartitionTable(); -#ifdef KERNEL - static ErrorOr> try_to_initialize(Kernel::StorageDevice&); - explicit EBRPartitionTable(Kernel::StorageDevice&); -#else - static ErrorOr> try_to_initialize(NonnullRefPtr); - explicit EBRPartitionTable(NonnullRefPtr); -#endif + static ErrorOr> try_to_initialize(PartitionableDevice); + explicit EBRPartitionTable(PartitionableDevice); virtual bool is_valid() const override { @@ -29,11 +24,7 @@ public: } private: -#ifdef KERNEL - void search_extended_partition(Kernel::StorageDevice&, MBRPartitionTable&, u64, size_t limit); -#else - void search_extended_partition(NonnullRefPtr, MBRPartitionTable&, u64, size_t limit); -#endif + void search_extended_partition(MBRPartitionTable&, u64, size_t limit); bool m_valid { false }; }; diff --git a/Userland/Libraries/LibPartition/GUIDPartitionTable.cpp b/Userland/Libraries/LibPartition/GUIDPartitionTable.cpp index 1444cd2af2..7ff39051c4 100644 --- a/Userland/Libraries/LibPartition/GUIDPartitionTable.cpp +++ b/Userland/Libraries/LibPartition/GUIDPartitionTable.cpp @@ -7,10 +7,6 @@ #include #include -#ifndef KERNEL -# include -#endif - namespace Partition { #define GPT_SIGNATURE2 0x54524150 @@ -48,30 +44,19 @@ struct [[gnu::packed]] GUIDPartitionHeader { u32 crc32_entries_array; }; -#ifdef KERNEL -ErrorOr> GUIDPartitionTable::try_to_initialize(Kernel::StorageDevice& device) +ErrorOr> GUIDPartitionTable::try_to_initialize(PartitionableDevice device) { - auto table = TRY(adopt_nonnull_own_or_enomem(new (nothrow) GUIDPartitionTable(device))); -#else -ErrorOr> GUIDPartitionTable::try_to_initialize(NonnullRefPtr device_file) -{ - auto table = TRY(adopt_nonnull_own_or_enomem(new (nothrow) GUIDPartitionTable(move(device_file)))); -#endif + auto table = TRY(adopt_nonnull_own_or_enomem(new (nothrow) GUIDPartitionTable(move(device)))); if (!table->is_valid()) return Error::from_errno(EINVAL); return table; } -#ifdef KERNEL -GUIDPartitionTable::GUIDPartitionTable(Kernel::StorageDevice& device) - : MBRPartitionTable(device) -#else -GUIDPartitionTable::GUIDPartitionTable(NonnullRefPtr device_file) - : MBRPartitionTable(move(device_file)) -#endif +GUIDPartitionTable::GUIDPartitionTable(PartitionableDevice device) + : MBRPartitionTable(move(device)) { // FIXME: Handle OOM failure here. - m_cached_header = ByteBuffer::create_zeroed(m_block_size).release_value_but_fixme_should_propagate_errors(); + m_cached_header = ByteBuffer::create_zeroed(block_size()).release_value_but_fixme_should_propagate_errors(); VERIFY(partitions_count() == 0); if (!initialize()) m_valid = false; @@ -86,17 +71,11 @@ bool GUIDPartitionTable::initialize() { VERIFY(m_cached_header.data() != nullptr); - auto first_gpt_block = (m_block_size == 512) ? 1 : 0; + auto first_gpt_block = (block_size() == 512) ? 1 : 0; -#ifdef KERNEL - auto buffer = UserOrKernelBuffer::for_kernel_buffer(m_cached_header.data()); - if (!m_device->read_block(first_gpt_block, buffer)) + auto maybe_error = m_device.read_block(first_gpt_block, m_cached_header.bytes()); + if (maybe_error.is_error()) return false; -#else - m_device_file->seek(first_gpt_block * m_block_size); - if (m_device_file->read(m_cached_header.data(), m_cached_header.size()) != (int)m_block_size) - return false; -#endif dbgln_if(GPT_DEBUG, "GUIDPartitionTable: signature - {:#08x} {:#08x}", header().sig[1], header().sig[0]); @@ -105,28 +84,19 @@ bool GUIDPartitionTable::initialize() return false; } - auto entries_buffer_result = ByteBuffer::create_zeroed(m_block_size); + auto entries_buffer_result = ByteBuffer::create_zeroed(block_size()); if (entries_buffer_result.is_error()) { dbgln("GUIDPartitionTable: not enough memory for entries buffer"); return false; } auto entries_buffer = entries_buffer_result.release_value(); -#ifdef KERNEL - auto raw_entries_buffer = UserOrKernelBuffer::for_kernel_buffer(entries_buffer.data()); -#endif - size_t raw_byte_index = header().partition_array_start_lba * m_block_size; + size_t raw_byte_index = header().partition_array_start_lba * block_size(); for (size_t entry_index = 0; entry_index < header().entries_count; entry_index++) { - -#ifdef KERNEL - if (!m_device->read_block((raw_byte_index / m_block_size), raw_entries_buffer)) + maybe_error = m_device.read_block(raw_byte_index / block_size(), entries_buffer.bytes()); + if (maybe_error.is_error()) return false; -#else - m_device_file->seek(raw_byte_index); - if (m_device_file->read(entries_buffer.data(), entries_buffer.size()) != (int)m_block_size) - return false; -#endif auto* entries = (GPTPartitionEntry const*)entries_buffer.data(); - auto& entry = entries[entry_index % (m_block_size / (size_t)header().partition_entry_size)]; + auto& entry = entries[entry_index % (block_size() / header().partition_entry_size)]; Array partition_type {}; partition_type.span().overwrite(0, entry.partition_guid, partition_type.size()); diff --git a/Userland/Libraries/LibPartition/GUIDPartitionTable.h b/Userland/Libraries/LibPartition/GUIDPartitionTable.h index 55d384cda3..a7e102beb9 100644 --- a/Userland/Libraries/LibPartition/GUIDPartitionTable.h +++ b/Userland/Libraries/LibPartition/GUIDPartitionTable.h @@ -15,13 +15,8 @@ class GUIDPartitionTable final : public MBRPartitionTable { public: virtual ~GUIDPartitionTable() = default; -#ifdef KERNEL - static ErrorOr> try_to_initialize(Kernel::StorageDevice&); - explicit GUIDPartitionTable(Kernel::StorageDevice&); -#else - static ErrorOr> try_to_initialize(NonnullRefPtr); - explicit GUIDPartitionTable(NonnullRefPtr); -#endif + static ErrorOr> try_to_initialize(PartitionableDevice); + explicit GUIDPartitionTable(PartitionableDevice); virtual bool is_valid() const override { diff --git a/Userland/Libraries/LibPartition/MBRPartitionTable.cpp b/Userland/Libraries/LibPartition/MBRPartitionTable.cpp index 3b46dcc654..47331d4d8e 100644 --- a/Userland/Libraries/LibPartition/MBRPartitionTable.cpp +++ b/Userland/Libraries/LibPartition/MBRPartitionTable.cpp @@ -7,10 +7,6 @@ #include #include -#ifndef KERNEL -# include -#endif - namespace Partition { #define MBR_SIGNATURE 0xaa55 @@ -18,15 +14,9 @@ namespace Partition { #define EBR_CHS_CONTAINER 0x05 #define EBR_LBA_CONTAINER 0x0F -#ifdef KERNEL -ErrorOr> MBRPartitionTable::try_to_initialize(Kernel::StorageDevice& device) +ErrorOr> MBRPartitionTable::try_to_initialize(PartitionableDevice device) { - auto table = TRY(adopt_nonnull_own_or_enomem(new (nothrow) MBRPartitionTable(device))); -#else -ErrorOr> MBRPartitionTable::try_to_initialize(NonnullRefPtr device_file) -{ - auto table = TRY(adopt_nonnull_own_or_enomem(new (nothrow) MBRPartitionTable(move(device_file)))); -#endif + auto table = TRY(adopt_nonnull_own_or_enomem(new (nothrow) MBRPartitionTable(move(device)))); if (table->contains_ebr()) return Error::from_errno(ENOTSUP); if (table->is_protective_mbr()) @@ -36,15 +26,9 @@ ErrorOr> MBRPartitionTable::try_to_initialize(N return table; } -#ifdef KERNEL -OwnPtr MBRPartitionTable::try_to_initialize(Kernel::StorageDevice& device, u32 start_lba) +OwnPtr MBRPartitionTable::try_to_initialize(PartitionableDevice device, u32 start_lba) { - auto table = adopt_nonnull_own_or_enomem(new (nothrow) MBRPartitionTable(device, start_lba)).release_value_but_fixme_should_propagate_errors(); -#else -OwnPtr MBRPartitionTable::try_to_initialize(NonnullRefPtr device_file, u32 start_lba) -{ - auto table = adopt_nonnull_own_or_enomem(new (nothrow) MBRPartitionTable(move(device_file), start_lba)).release_value_but_fixme_should_propagate_errors(); -#endif + auto table = adopt_nonnull_own_or_enomem(new (nothrow) MBRPartitionTable(move(device), start_lba)).release_value_but_fixme_should_propagate_errors(); if (!table->is_valid()) return {}; return table; @@ -52,28 +36,17 @@ OwnPtr MBRPartitionTable::try_to_initialize(NonnullRefPtrread_block(m_start_lba, buffer)) + if (block_size() != 512) return false; -#else - m_device_file->seek(m_start_lba * m_block_size); - if (m_device_file->read(m_cached_header.data(), m_cached_header.size()) != 512) - return false; -#endif - m_header_valid = true; + auto maybe_error = m_device.read_block(m_start_lba, m_cached_header.bytes()); + m_header_valid = !maybe_error.is_error(); return m_header_valid; } -#ifdef KERNEL -MBRPartitionTable::MBRPartitionTable(Kernel::StorageDevice& device, u32 start_lba) - : PartitionTable(device) -#else -MBRPartitionTable::MBRPartitionTable(NonnullRefPtr device_file, u32 start_lba) - : PartitionTable(move(device_file)) -#endif +MBRPartitionTable::MBRPartitionTable(PartitionableDevice device, u32 start_lba) + : PartitionTable(move(device)) , m_start_lba(start_lba) - , m_cached_header(ByteBuffer::create_zeroed(m_block_size).release_value_but_fixme_should_propagate_errors()) // FIXME: Do something sensible if this fails because of OOM. + , m_cached_header(ByteBuffer::create_zeroed(block_size()).release_value_but_fixme_should_propagate_errors()) // FIXME: Do something sensible if this fails because of OOM. { if (!read_boot_record() || !initialize()) return; @@ -91,15 +64,10 @@ MBRPartitionTable::MBRPartitionTable(NonnullRefPtr device_ m_valid = true; } -#ifdef KERNEL -MBRPartitionTable::MBRPartitionTable(Kernel::StorageDevice& device) - : PartitionTable(device) -#else -MBRPartitionTable::MBRPartitionTable(NonnullRefPtr device_file) - : PartitionTable(move(device_file)) -#endif +MBRPartitionTable::MBRPartitionTable(PartitionableDevice device) + : PartitionTable(move(device)) , m_start_lba(0) - , m_cached_header(ByteBuffer::create_zeroed(m_block_size).release_value_but_fixme_should_propagate_errors()) // FIXME: Do something sensible if this fails because of OOM. + , m_cached_header(ByteBuffer::create_zeroed(block_size()).release_value_but_fixme_should_propagate_errors()) // FIXME: Do something sensible if this fails because of OOM. { if (!read_boot_record() || contains_ebr() || is_protective_mbr() || !initialize()) return; diff --git a/Userland/Libraries/LibPartition/MBRPartitionTable.h b/Userland/Libraries/LibPartition/MBRPartitionTable.h index 269c23d342..a12e307ff9 100644 --- a/Userland/Libraries/LibPartition/MBRPartitionTable.h +++ b/Userland/Libraries/LibPartition/MBRPartitionTable.h @@ -38,17 +38,10 @@ public: public: ~MBRPartitionTable(); -#ifdef KERNEL - static ErrorOr> try_to_initialize(Kernel::StorageDevice&); - static OwnPtr try_to_initialize(Kernel::StorageDevice&, u32 start_lba); - explicit MBRPartitionTable(Kernel::StorageDevice&); - MBRPartitionTable(Kernel::StorageDevice&, u32 start_lba); -#else - static ErrorOr> try_to_initialize(NonnullRefPtr); - static OwnPtr try_to_initialize(NonnullRefPtr, u32 start_lba); - explicit MBRPartitionTable(NonnullRefPtr); - MBRPartitionTable(NonnullRefPtr, u32 start_lba); -#endif + static ErrorOr> try_to_initialize(PartitionableDevice); + static OwnPtr try_to_initialize(PartitionableDevice, u32 start_lba); + explicit MBRPartitionTable(PartitionableDevice); + MBRPartitionTable(PartitionableDevice, u32 start_lba); bool is_protective_mbr() const; bool contains_ebr() const; diff --git a/Userland/Libraries/LibPartition/PartitionTable.cpp b/Userland/Libraries/LibPartition/PartitionTable.cpp index 0be1ece644..f7ab34df2b 100644 --- a/Userland/Libraries/LibPartition/PartitionTable.cpp +++ b/Userland/Libraries/LibPartition/PartitionTable.cpp @@ -7,25 +7,15 @@ #include #ifndef KERNEL -# include # include #endif namespace Partition { -#ifdef KERNEL -PartitionTable::PartitionTable(Kernel::StorageDevice& device) - : m_device(device) - , m_block_size(device.block_size()) +PartitionTable::PartitionTable(PartitionableDevice&& device) + : m_device(move(device)) { } -#else -PartitionTable::PartitionTable(NonnullRefPtr device_file) - : m_device_file(device_file) -{ - VERIFY(ioctl(m_device_file->leak_fd(), STORAGE_DEVICE_GET_BLOCK_SIZE, &m_block_size) >= 0); -} -#endif Optional PartitionTable::partition(unsigned index) const { diff --git a/Userland/Libraries/LibPartition/PartitionTable.h b/Userland/Libraries/LibPartition/PartitionTable.h index 58590c6ced..e35be0cae2 100644 --- a/Userland/Libraries/LibPartition/PartitionTable.h +++ b/Userland/Libraries/LibPartition/PartitionTable.h @@ -8,12 +8,7 @@ #include #include - -#ifdef KERNEL -# include -#else -# include -#endif +#include namespace Partition { @@ -25,19 +20,13 @@ public: virtual bool is_valid() const = 0; Vector partitions() const { return m_partitions; } - size_t block_size() const { return m_block_size; } + size_t block_size() const { return m_device.block_size(); } protected: -#ifdef KERNEL - explicit PartitionTable(Kernel::StorageDevice&); - NonnullRefPtr m_device; -#else - explicit PartitionTable(NonnullRefPtr); - NonnullRefPtr m_device_file; -#endif + explicit PartitionTable(PartitionableDevice&&); + PartitionableDevice m_device; Vector m_partitions; - size_t m_block_size; }; } diff --git a/Userland/Libraries/LibPartition/PartitionableDevice.cpp b/Userland/Libraries/LibPartition/PartitionableDevice.cpp new file mode 100644 index 0000000000..d23edbc921 --- /dev/null +++ b/Userland/Libraries/LibPartition/PartitionableDevice.cpp @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2023, Ben Wiederhake + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include + +#ifndef KERNEL +# include +#endif + +namespace Partition { + +#ifdef KERNEL +ErrorOr PartitionableDevice::create(Kernel::StorageDevice& device) +{ + return PartitionableDevice(device); +} +#else +ErrorOr PartitionableDevice::create(MaybeOwned device_file) +{ + VERIFY(device_file.ptr() != nullptr); + size_t block_size; + int rc = ioctl(device_file->fd(), STORAGE_DEVICE_GET_BLOCK_SIZE, &block_size); + if (rc < 0) + return Error::from_string_view("ioctl on device failed"sv); + return PartitionableDevice(move(device_file), block_size); +} +#endif + +#ifdef KERNEL +PartitionableDevice::PartitionableDevice(Kernel::StorageDevice& device) + : m_device(device) +{ +} +#else +PartitionableDevice::PartitionableDevice(MaybeOwned device_file, size_t block_size) + : m_device_file(move(device_file)) + , m_block_size(block_size) +{ +} +#endif + +#ifdef KERNEL +PartitionableDevice PartitionableDevice::clone_unowned() +{ + return PartitionableDevice(m_device); +} +#else +PartitionableDevice PartitionableDevice::clone_unowned() +{ + return PartitionableDevice(MaybeOwned(*m_device_file), m_block_size); +} +#endif + +#ifdef KERNEL +ErrorOr PartitionableDevice::clone_owned() +{ + return PartitionableDevice(m_device); +} +#else +ErrorOr PartitionableDevice::clone_owned() +{ + auto cloned_file = TRY(Core::File::adopt_fd(m_device_file->fd(), Core::File::OpenMode::Read, Core::File::ShouldCloseFileDescriptor::No)); + return PartitionableDevice(move(cloned_file), m_block_size); +} +#endif + +#ifdef KERNEL +size_t PartitionableDevice::block_size() const +{ + return m_device.block_size(); +} +#else +size_t PartitionableDevice::block_size() const +{ + return m_block_size; +} +#endif + +#ifdef KERNEL +ErrorOr PartitionableDevice::read_block(size_t block_index, Bytes block_buffer) +{ + VERIFY(block_buffer.size() == block_size()); + auto buffer = UserOrKernelBuffer::for_kernel_buffer(block_buffer.data()); + bool read_successful = m_device.read_block(block_index, buffer); + if (!read_successful) + return Error::from_errno(EIO); + return {}; +} +#else +ErrorOr PartitionableDevice::read_block(size_t block_index, Bytes block_buffer) +{ + VERIFY(block_buffer.size() == block_size()); + TRY(m_device_file->seek(block_index * block_size(), SeekMode::SetPosition)); + TRY(m_device_file->read_until_filled(block_buffer)); + return {}; +} +#endif + +} diff --git a/Userland/Libraries/LibPartition/PartitionableDevice.h b/Userland/Libraries/LibPartition/PartitionableDevice.h new file mode 100644 index 0000000000..d557b5ef71 --- /dev/null +++ b/Userland/Libraries/LibPartition/PartitionableDevice.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2023, Ben Wiederhake + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include + +#ifdef KERNEL +# include +#else +# include +# include +#endif + +namespace Partition { + +class PartitionableDevice { + AK_MAKE_NONCOPYABLE(PartitionableDevice); + +public: +#ifdef KERNEL + PartitionableDevice(Kernel::StorageDevice&); + // Userland doesn't get an implicit constructor. +#endif + PartitionableDevice(PartitionableDevice&&) = default; + // Unused, and "move out of reference" isn't well-defined anyway: + PartitionableDevice& operator=(PartitionableDevice&&) = delete; + +#ifdef KERNEL + static ErrorOr create(Kernel::StorageDevice& device); +#else + static ErrorOr create(MaybeOwned device_file); +#endif + ~PartitionableDevice() = default; + + PartitionableDevice clone_unowned(); + ErrorOr clone_owned(); + size_t block_size() const; + ErrorOr read_block(size_t block_index, Bytes block_buffer); + +private: +#ifdef KERNEL + Kernel::StorageDevice& m_device; +#else + explicit PartitionableDevice(MaybeOwned, size_t block_size); + MaybeOwned m_device_file; + size_t m_block_size; +#endif +}; + +}