mirror of
https://github.com/RGBCube/serenity
synced 2025-05-14 06:14:58 +00:00
LibPartition: Migrate from DeprecatedFile to File
The implemented cloning mechanism should be sound: - If a PartitionTable is passed a File with ShouldCloseFileDescriptor::Yes, then it will keep it alive until the PartitionTable is destroyed. - If a PartitionTable is passed a File with ShouldCloseFileDescriptor::No, then the caller has to ensure that the file descriptor remains alive. If the caller is EBRPartitionTable, the same consideration holds. If the caller is PartitionEditor::PartitionModel, this is satisfied by keeping an OwnPtr<Core::File> around which is the originally opened file. Therefore, we never leak any fds, and never access a Core::File or fd after destroying it.
This commit is contained in:
parent
c197fb4037
commit
3d6b838df3
14 changed files with 221 additions and 177 deletions
|
@ -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
|
||||
)
|
||||
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
|
||||
#include <AK/NumberFormat.h>
|
||||
#include <Applications/PartitionEditor/PartitionModel.h>
|
||||
#include <LibCore/DeprecatedFile.h>
|
||||
#include <LibPartition/EBRPartitionTable.h>
|
||||
#include <LibPartition/GUIDPartitionTable.h>
|
||||
#include <LibPartition/MBRPartitionTable.h>
|
||||
|
@ -68,28 +67,33 @@ GUI::Variant PartitionModel::data(GUI::ModelIndex const& index, GUI::ModelRole r
|
|||
|
||||
ErrorOr<void> 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 {};
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <LibCore/File.h>
|
||||
#include <LibGUI/Model.h>
|
||||
#include <LibPartition/PartitionTable.h>
|
||||
|
||||
|
@ -36,6 +37,7 @@ private:
|
|||
PartitionModel() = default;
|
||||
|
||||
OwnPtr<Partition::PartitionTable> m_partition_table;
|
||||
OwnPtr<Core::File> m_backing_file;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ set(SOURCES
|
|||
EBRPartitionTable.cpp
|
||||
GUIDPartitionTable.cpp
|
||||
MBRPartitionTable.cpp
|
||||
PartitionableDevice.cpp
|
||||
PartitionTable.cpp
|
||||
)
|
||||
|
||||
|
|
|
@ -6,21 +6,11 @@
|
|||
|
||||
#include <LibPartition/EBRPartitionTable.h>
|
||||
|
||||
#ifndef KERNEL
|
||||
# include <LibCore/DeprecatedFile.h>
|
||||
#endif
|
||||
|
||||
namespace Partition {
|
||||
|
||||
#ifdef KERNEL
|
||||
ErrorOr<NonnullOwnPtr<EBRPartitionTable>> EBRPartitionTable::try_to_initialize(Kernel::StorageDevice& device)
|
||||
ErrorOr<NonnullOwnPtr<EBRPartitionTable>> EBRPartitionTable::try_to_initialize(PartitionableDevice device)
|
||||
{
|
||||
auto table = TRY(adopt_nonnull_own_or_enomem(new (nothrow) EBRPartitionTable(device)));
|
||||
#else
|
||||
ErrorOr<NonnullOwnPtr<EBRPartitionTable>> EBRPartitionTable::try_to_initialize(NonnullRefPtr<Core::DeprecatedFile> 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<NonnullOwnPtr<EBRPartitionTable>> 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<Core::DeprecatedFile> 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<Core::Deprecated
|
|||
if (!checked_ebr.contains_ebr())
|
||||
return;
|
||||
current_block_offset += checked_ebr.partition(1).value().start_block();
|
||||
auto next_ebr = MBRPartitionTable::try_to_initialize(device, current_block_offset);
|
||||
auto next_ebr = MBRPartitionTable::try_to_initialize(m_device.clone_unowned(), current_block_offset);
|
||||
if (!next_ebr)
|
||||
return;
|
||||
search_extended_partition(device, *next_ebr, current_block_offset, (limit - 1));
|
||||
// FIXME: Should not rely on TCO here, since this might be called from inside the Kernel, where stack space isn't exactly free.
|
||||
search_extended_partition(*next_ebr, current_block_offset, (limit - 1));
|
||||
}
|
||||
|
||||
#ifdef KERNEL
|
||||
EBRPartitionTable::EBRPartitionTable(Kernel::StorageDevice& device)
|
||||
#else
|
||||
EBRPartitionTable::EBRPartitionTable(NonnullRefPtr<Core::DeprecatedFile> device)
|
||||
#endif
|
||||
: MBRPartitionTable(device)
|
||||
EBRPartitionTable::EBRPartitionTable(PartitionableDevice device)
|
||||
: MBRPartitionTable(move(device))
|
||||
{
|
||||
if (!is_header_valid())
|
||||
return;
|
||||
|
@ -70,11 +54,11 @@ EBRPartitionTable::EBRPartitionTable(NonnullRefPtr<Core::DeprecatedFile> 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;
|
||||
}
|
||||
|
||||
|
|
|
@ -15,13 +15,8 @@ class EBRPartitionTable : public MBRPartitionTable {
|
|||
public:
|
||||
~EBRPartitionTable();
|
||||
|
||||
#ifdef KERNEL
|
||||
static ErrorOr<NonnullOwnPtr<EBRPartitionTable>> try_to_initialize(Kernel::StorageDevice&);
|
||||
explicit EBRPartitionTable(Kernel::StorageDevice&);
|
||||
#else
|
||||
static ErrorOr<NonnullOwnPtr<EBRPartitionTable>> try_to_initialize(NonnullRefPtr<Core::DeprecatedFile>);
|
||||
explicit EBRPartitionTable(NonnullRefPtr<Core::DeprecatedFile>);
|
||||
#endif
|
||||
static ErrorOr<NonnullOwnPtr<EBRPartitionTable>> 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<Core::DeprecatedFile>, MBRPartitionTable&, u64, size_t limit);
|
||||
#endif
|
||||
void search_extended_partition(MBRPartitionTable&, u64, size_t limit);
|
||||
|
||||
bool m_valid { false };
|
||||
};
|
||||
|
|
|
@ -7,10 +7,6 @@
|
|||
#include <AK/Debug.h>
|
||||
#include <LibPartition/GUIDPartitionTable.h>
|
||||
|
||||
#ifndef KERNEL
|
||||
# include <LibCore/DeprecatedFile.h>
|
||||
#endif
|
||||
|
||||
namespace Partition {
|
||||
|
||||
#define GPT_SIGNATURE2 0x54524150
|
||||
|
@ -48,30 +44,19 @@ struct [[gnu::packed]] GUIDPartitionHeader {
|
|||
u32 crc32_entries_array;
|
||||
};
|
||||
|
||||
#ifdef KERNEL
|
||||
ErrorOr<NonnullOwnPtr<GUIDPartitionTable>> GUIDPartitionTable::try_to_initialize(Kernel::StorageDevice& device)
|
||||
ErrorOr<NonnullOwnPtr<GUIDPartitionTable>> GUIDPartitionTable::try_to_initialize(PartitionableDevice device)
|
||||
{
|
||||
auto table = TRY(adopt_nonnull_own_or_enomem(new (nothrow) GUIDPartitionTable(device)));
|
||||
#else
|
||||
ErrorOr<NonnullOwnPtr<GUIDPartitionTable>> GUIDPartitionTable::try_to_initialize(NonnullRefPtr<Core::DeprecatedFile> 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<Core::DeprecatedFile> 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<u8, 16> partition_type {};
|
||||
partition_type.span().overwrite(0, entry.partition_guid, partition_type.size());
|
||||
|
||||
|
|
|
@ -15,13 +15,8 @@ class GUIDPartitionTable final : public MBRPartitionTable {
|
|||
public:
|
||||
virtual ~GUIDPartitionTable() = default;
|
||||
|
||||
#ifdef KERNEL
|
||||
static ErrorOr<NonnullOwnPtr<GUIDPartitionTable>> try_to_initialize(Kernel::StorageDevice&);
|
||||
explicit GUIDPartitionTable(Kernel::StorageDevice&);
|
||||
#else
|
||||
static ErrorOr<NonnullOwnPtr<GUIDPartitionTable>> try_to_initialize(NonnullRefPtr<Core::DeprecatedFile>);
|
||||
explicit GUIDPartitionTable(NonnullRefPtr<Core::DeprecatedFile>);
|
||||
#endif
|
||||
static ErrorOr<NonnullOwnPtr<GUIDPartitionTable>> try_to_initialize(PartitionableDevice);
|
||||
explicit GUIDPartitionTable(PartitionableDevice);
|
||||
|
||||
virtual bool is_valid() const override
|
||||
{
|
||||
|
|
|
@ -7,10 +7,6 @@
|
|||
#include <AK/Debug.h>
|
||||
#include <LibPartition/MBRPartitionTable.h>
|
||||
|
||||
#ifndef KERNEL
|
||||
# include <LibCore/DeprecatedFile.h>
|
||||
#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<NonnullOwnPtr<MBRPartitionTable>> MBRPartitionTable::try_to_initialize(Kernel::StorageDevice& device)
|
||||
ErrorOr<NonnullOwnPtr<MBRPartitionTable>> MBRPartitionTable::try_to_initialize(PartitionableDevice device)
|
||||
{
|
||||
auto table = TRY(adopt_nonnull_own_or_enomem(new (nothrow) MBRPartitionTable(device)));
|
||||
#else
|
||||
ErrorOr<NonnullOwnPtr<MBRPartitionTable>> MBRPartitionTable::try_to_initialize(NonnullRefPtr<Core::DeprecatedFile> 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<NonnullOwnPtr<MBRPartitionTable>> MBRPartitionTable::try_to_initialize(N
|
|||
return table;
|
||||
}
|
||||
|
||||
#ifdef KERNEL
|
||||
OwnPtr<MBRPartitionTable> MBRPartitionTable::try_to_initialize(Kernel::StorageDevice& device, u32 start_lba)
|
||||
OwnPtr<MBRPartitionTable> 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> MBRPartitionTable::try_to_initialize(NonnullRefPtr<Core::DeprecatedFile> 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> MBRPartitionTable::try_to_initialize(NonnullRefPtr<Cor
|
|||
|
||||
bool MBRPartitionTable::read_boot_record()
|
||||
{
|
||||
#ifdef KERNEL
|
||||
auto buffer = UserOrKernelBuffer::for_kernel_buffer(m_cached_header.data());
|
||||
if (!m_device->read_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<Core::DeprecatedFile> 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<Core::DeprecatedFile> device_
|
|||
m_valid = true;
|
||||
}
|
||||
|
||||
#ifdef KERNEL
|
||||
MBRPartitionTable::MBRPartitionTable(Kernel::StorageDevice& device)
|
||||
: PartitionTable(device)
|
||||
#else
|
||||
MBRPartitionTable::MBRPartitionTable(NonnullRefPtr<Core::DeprecatedFile> 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;
|
||||
|
|
|
@ -38,17 +38,10 @@ public:
|
|||
public:
|
||||
~MBRPartitionTable();
|
||||
|
||||
#ifdef KERNEL
|
||||
static ErrorOr<NonnullOwnPtr<MBRPartitionTable>> try_to_initialize(Kernel::StorageDevice&);
|
||||
static OwnPtr<MBRPartitionTable> try_to_initialize(Kernel::StorageDevice&, u32 start_lba);
|
||||
explicit MBRPartitionTable(Kernel::StorageDevice&);
|
||||
MBRPartitionTable(Kernel::StorageDevice&, u32 start_lba);
|
||||
#else
|
||||
static ErrorOr<NonnullOwnPtr<MBRPartitionTable>> try_to_initialize(NonnullRefPtr<Core::DeprecatedFile>);
|
||||
static OwnPtr<MBRPartitionTable> try_to_initialize(NonnullRefPtr<Core::DeprecatedFile>, u32 start_lba);
|
||||
explicit MBRPartitionTable(NonnullRefPtr<Core::DeprecatedFile>);
|
||||
MBRPartitionTable(NonnullRefPtr<Core::DeprecatedFile>, u32 start_lba);
|
||||
#endif
|
||||
static ErrorOr<NonnullOwnPtr<MBRPartitionTable>> try_to_initialize(PartitionableDevice);
|
||||
static OwnPtr<MBRPartitionTable> try_to_initialize(PartitionableDevice, u32 start_lba);
|
||||
explicit MBRPartitionTable(PartitionableDevice);
|
||||
MBRPartitionTable(PartitionableDevice, u32 start_lba);
|
||||
|
||||
bool is_protective_mbr() const;
|
||||
bool contains_ebr() const;
|
||||
|
|
|
@ -7,25 +7,15 @@
|
|||
#include <LibPartition/PartitionTable.h>
|
||||
|
||||
#ifndef KERNEL
|
||||
# include <LibCore/DeprecatedFile.h>
|
||||
# include <sys/ioctl.h>
|
||||
#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<Core::DeprecatedFile> 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<DiskPartitionMetadata> PartitionTable::partition(unsigned index) const
|
||||
{
|
||||
|
|
|
@ -8,12 +8,7 @@
|
|||
|
||||
#include <AK/NonnullRefPtr.h>
|
||||
#include <LibPartition/DiskPartitionMetadata.h>
|
||||
|
||||
#ifdef KERNEL
|
||||
# include <Kernel/Devices/Storage/StorageDevice.h>
|
||||
#else
|
||||
# include <LibCore/Forward.h>
|
||||
#endif
|
||||
#include <LibPartition/PartitionableDevice.h>
|
||||
|
||||
namespace Partition {
|
||||
|
||||
|
@ -25,19 +20,13 @@ public:
|
|||
virtual bool is_valid() const = 0;
|
||||
|
||||
Vector<DiskPartitionMetadata> 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<Kernel::StorageDevice> m_device;
|
||||
#else
|
||||
explicit PartitionTable(NonnullRefPtr<Core::DeprecatedFile>);
|
||||
NonnullRefPtr<Core::DeprecatedFile> m_device_file;
|
||||
#endif
|
||||
explicit PartitionTable(PartitionableDevice&&);
|
||||
PartitionableDevice m_device;
|
||||
|
||||
Vector<DiskPartitionMetadata> m_partitions;
|
||||
size_t m_block_size;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
102
Userland/Libraries/LibPartition/PartitionableDevice.cpp
Normal file
102
Userland/Libraries/LibPartition/PartitionableDevice.cpp
Normal file
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
* Copyright (c) 2023, Ben Wiederhake <BenWiederhake.GitHub@gmx.de>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <LibPartition/PartitionableDevice.h>
|
||||
|
||||
#ifndef KERNEL
|
||||
# include <sys/ioctl.h>
|
||||
#endif
|
||||
|
||||
namespace Partition {
|
||||
|
||||
#ifdef KERNEL
|
||||
ErrorOr<PartitionableDevice> PartitionableDevice::create(Kernel::StorageDevice& device)
|
||||
{
|
||||
return PartitionableDevice(device);
|
||||
}
|
||||
#else
|
||||
ErrorOr<PartitionableDevice> PartitionableDevice::create(MaybeOwned<Core::File> 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<Core::File> 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<Core::File>(*m_device_file), m_block_size);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef KERNEL
|
||||
ErrorOr<PartitionableDevice> PartitionableDevice::clone_owned()
|
||||
{
|
||||
return PartitionableDevice(m_device);
|
||||
}
|
||||
#else
|
||||
ErrorOr<PartitionableDevice> 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<void> 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<void> 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
|
||||
|
||||
}
|
54
Userland/Libraries/LibPartition/PartitionableDevice.h
Normal file
54
Userland/Libraries/LibPartition/PartitionableDevice.h
Normal file
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* Copyright (c) 2023, Ben Wiederhake <BenWiederhake.GitHub@gmx.de>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AK/Noncopyable.h>
|
||||
|
||||
#ifdef KERNEL
|
||||
# include <Kernel/Devices/Storage/StorageDevice.h>
|
||||
#else
|
||||
# include <AK/MaybeOwned.h>
|
||||
# include <LibCore/File.h>
|
||||
#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<PartitionableDevice> create(Kernel::StorageDevice& device);
|
||||
#else
|
||||
static ErrorOr<PartitionableDevice> create(MaybeOwned<Core::File> device_file);
|
||||
#endif
|
||||
~PartitionableDevice() = default;
|
||||
|
||||
PartitionableDevice clone_unowned();
|
||||
ErrorOr<PartitionableDevice> clone_owned();
|
||||
size_t block_size() const;
|
||||
ErrorOr<void> read_block(size_t block_index, Bytes block_buffer);
|
||||
|
||||
private:
|
||||
#ifdef KERNEL
|
||||
Kernel::StorageDevice& m_device;
|
||||
#else
|
||||
explicit PartitionableDevice(MaybeOwned<Core::File>, size_t block_size);
|
||||
MaybeOwned<Core::File> m_device_file;
|
||||
size_t m_block_size;
|
||||
#endif
|
||||
};
|
||||
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue