mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 14:28:12 +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/EBRPartitionTable.cpp
|
||||||
../Userland/Libraries/LibPartition/GUIDPartitionTable.cpp
|
../Userland/Libraries/LibPartition/GUIDPartitionTable.cpp
|
||||||
../Userland/Libraries/LibPartition/MBRPartitionTable.cpp
|
../Userland/Libraries/LibPartition/MBRPartitionTable.cpp
|
||||||
|
../Userland/Libraries/LibPartition/PartitionableDevice.cpp
|
||||||
../Userland/Libraries/LibPartition/PartitionTable.cpp
|
../Userland/Libraries/LibPartition/PartitionTable.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
|
|
||||||
#include <AK/NumberFormat.h>
|
#include <AK/NumberFormat.h>
|
||||||
#include <Applications/PartitionEditor/PartitionModel.h>
|
#include <Applications/PartitionEditor/PartitionModel.h>
|
||||||
#include <LibCore/DeprecatedFile.h>
|
|
||||||
#include <LibPartition/EBRPartitionTable.h>
|
#include <LibPartition/EBRPartitionTable.h>
|
||||||
#include <LibPartition/GUIDPartitionTable.h>
|
#include <LibPartition/GUIDPartitionTable.h>
|
||||||
#include <LibPartition/MBRPartitionTable.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)
|
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()) {
|
if (!mbr_table_or_error.is_error()) {
|
||||||
dbgln("Found MBR partition table on {}", path);
|
dbgln("Found MBR partition table on {}", path);
|
||||||
m_partition_table = move(mbr_table_or_error.value());
|
m_partition_table = move(mbr_table_or_error.value());
|
||||||
|
m_backing_file = move(strong_file);
|
||||||
invalidate();
|
invalidate();
|
||||||
return {};
|
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()) {
|
if (!ebr_table_or_error.is_error()) {
|
||||||
dbgln("Found EBR partition table on {}", path);
|
dbgln("Found EBR partition table on {}", path);
|
||||||
m_partition_table = move(ebr_table_or_error.value());
|
m_partition_table = move(ebr_table_or_error.value());
|
||||||
|
m_backing_file = move(strong_file);
|
||||||
invalidate();
|
invalidate();
|
||||||
return {};
|
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()) {
|
if (!guid_table_or_error.is_error()) {
|
||||||
dbgln("Found GUID partition table on {}", path);
|
dbgln("Found GUID partition table on {}", path);
|
||||||
m_partition_table = move(guid_table_or_error.value());
|
m_partition_table = move(guid_table_or_error.value());
|
||||||
|
m_backing_file = move(strong_file);
|
||||||
invalidate();
|
invalidate();
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <LibCore/File.h>
|
||||||
#include <LibGUI/Model.h>
|
#include <LibGUI/Model.h>
|
||||||
#include <LibPartition/PartitionTable.h>
|
#include <LibPartition/PartitionTable.h>
|
||||||
|
|
||||||
|
@ -36,6 +37,7 @@ private:
|
||||||
PartitionModel() = default;
|
PartitionModel() = default;
|
||||||
|
|
||||||
OwnPtr<Partition::PartitionTable> m_partition_table;
|
OwnPtr<Partition::PartitionTable> m_partition_table;
|
||||||
|
OwnPtr<Core::File> m_backing_file;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ set(SOURCES
|
||||||
EBRPartitionTable.cpp
|
EBRPartitionTable.cpp
|
||||||
GUIDPartitionTable.cpp
|
GUIDPartitionTable.cpp
|
||||||
MBRPartitionTable.cpp
|
MBRPartitionTable.cpp
|
||||||
|
PartitionableDevice.cpp
|
||||||
PartitionTable.cpp
|
PartitionTable.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -6,21 +6,11 @@
|
||||||
|
|
||||||
#include <LibPartition/EBRPartitionTable.h>
|
#include <LibPartition/EBRPartitionTable.h>
|
||||||
|
|
||||||
#ifndef KERNEL
|
|
||||||
# include <LibCore/DeprecatedFile.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace Partition {
|
namespace Partition {
|
||||||
|
|
||||||
#ifdef KERNEL
|
ErrorOr<NonnullOwnPtr<EBRPartitionTable>> EBRPartitionTable::try_to_initialize(PartitionableDevice device)
|
||||||
ErrorOr<NonnullOwnPtr<EBRPartitionTable>> EBRPartitionTable::try_to_initialize(Kernel::StorageDevice& device)
|
|
||||||
{
|
{
|
||||||
auto table = TRY(adopt_nonnull_own_or_enomem(new (nothrow) EBRPartitionTable(device)));
|
auto table = TRY(adopt_nonnull_own_or_enomem(new (nothrow) EBRPartitionTable(move(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
|
|
||||||
if (table->is_protective_mbr())
|
if (table->is_protective_mbr())
|
||||||
return Error::from_errno(ENOTSUP);
|
return Error::from_errno(ENOTSUP);
|
||||||
if (!table->is_valid())
|
if (!table->is_valid())
|
||||||
|
@ -28,16 +18,13 @@ ErrorOr<NonnullOwnPtr<EBRPartitionTable>> EBRPartitionTable::try_to_initialize(N
|
||||||
return table;
|
return table;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef KERNEL
|
void EBRPartitionTable::search_extended_partition(MBRPartitionTable& checked_ebr, u64 current_block_offset, size_t limit)
|
||||||
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
|
|
||||||
{
|
{
|
||||||
if (limit == 0)
|
if (limit == 0)
|
||||||
return;
|
return;
|
||||||
// EBRs should not carry more than 2 partitions (because they need to form a linked list)
|
// EBRs should not carry more than 2 partitions (because they need to form a linked list)
|
||||||
VERIFY(checked_ebr.partitions_count() <= 2);
|
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);
|
auto checked_logical_partition = checked_ebr.partition(0);
|
||||||
|
|
||||||
// If we are pointed to an invalid logical partition, something is seriously wrong.
|
// 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())
|
if (!checked_ebr.contains_ebr())
|
||||||
return;
|
return;
|
||||||
current_block_offset += checked_ebr.partition(1).value().start_block();
|
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)
|
if (!next_ebr)
|
||||||
return;
|
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(PartitionableDevice device)
|
||||||
EBRPartitionTable::EBRPartitionTable(Kernel::StorageDevice& device)
|
: MBRPartitionTable(move(device))
|
||||||
#else
|
|
||||||
EBRPartitionTable::EBRPartitionTable(NonnullRefPtr<Core::DeprecatedFile> device)
|
|
||||||
#endif
|
|
||||||
: MBRPartitionTable(device)
|
|
||||||
{
|
{
|
||||||
if (!is_header_valid())
|
if (!is_header_valid())
|
||||||
return;
|
return;
|
||||||
|
@ -70,11 +54,11 @@ EBRPartitionTable::EBRPartitionTable(NonnullRefPtr<Core::DeprecatedFile> device)
|
||||||
auto& entry = header.entry[index];
|
auto& entry = header.entry[index];
|
||||||
// Start enumerating all logical partitions
|
// Start enumerating all logical partitions
|
||||||
if (entry.type == 0xf) {
|
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)
|
if (!checked_ebr)
|
||||||
continue;
|
continue;
|
||||||
// It's quite unlikely to see that amount of partitions, so stop at 128 partitions.
|
// 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;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,13 +15,8 @@ class EBRPartitionTable : public MBRPartitionTable {
|
||||||
public:
|
public:
|
||||||
~EBRPartitionTable();
|
~EBRPartitionTable();
|
||||||
|
|
||||||
#ifdef KERNEL
|
static ErrorOr<NonnullOwnPtr<EBRPartitionTable>> try_to_initialize(PartitionableDevice);
|
||||||
static ErrorOr<NonnullOwnPtr<EBRPartitionTable>> try_to_initialize(Kernel::StorageDevice&);
|
explicit EBRPartitionTable(PartitionableDevice);
|
||||||
explicit EBRPartitionTable(Kernel::StorageDevice&);
|
|
||||||
#else
|
|
||||||
static ErrorOr<NonnullOwnPtr<EBRPartitionTable>> try_to_initialize(NonnullRefPtr<Core::DeprecatedFile>);
|
|
||||||
explicit EBRPartitionTable(NonnullRefPtr<Core::DeprecatedFile>);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
virtual bool is_valid() const override
|
virtual bool is_valid() const override
|
||||||
{
|
{
|
||||||
|
@ -29,11 +24,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
#ifdef KERNEL
|
void search_extended_partition(MBRPartitionTable&, u64, size_t limit);
|
||||||
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
|
|
||||||
|
|
||||||
bool m_valid { false };
|
bool m_valid { false };
|
||||||
};
|
};
|
||||||
|
|
|
@ -7,10 +7,6 @@
|
||||||
#include <AK/Debug.h>
|
#include <AK/Debug.h>
|
||||||
#include <LibPartition/GUIDPartitionTable.h>
|
#include <LibPartition/GUIDPartitionTable.h>
|
||||||
|
|
||||||
#ifndef KERNEL
|
|
||||||
# include <LibCore/DeprecatedFile.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace Partition {
|
namespace Partition {
|
||||||
|
|
||||||
#define GPT_SIGNATURE2 0x54524150
|
#define GPT_SIGNATURE2 0x54524150
|
||||||
|
@ -48,30 +44,19 @@ struct [[gnu::packed]] GUIDPartitionHeader {
|
||||||
u32 crc32_entries_array;
|
u32 crc32_entries_array;
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef KERNEL
|
ErrorOr<NonnullOwnPtr<GUIDPartitionTable>> GUIDPartitionTable::try_to_initialize(PartitionableDevice device)
|
||||||
ErrorOr<NonnullOwnPtr<GUIDPartitionTable>> GUIDPartitionTable::try_to_initialize(Kernel::StorageDevice& device)
|
|
||||||
{
|
{
|
||||||
auto table = TRY(adopt_nonnull_own_or_enomem(new (nothrow) GUIDPartitionTable(device)));
|
auto table = TRY(adopt_nonnull_own_or_enomem(new (nothrow) GUIDPartitionTable(move(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
|
|
||||||
if (!table->is_valid())
|
if (!table->is_valid())
|
||||||
return Error::from_errno(EINVAL);
|
return Error::from_errno(EINVAL);
|
||||||
return table;
|
return table;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef KERNEL
|
GUIDPartitionTable::GUIDPartitionTable(PartitionableDevice device)
|
||||||
GUIDPartitionTable::GUIDPartitionTable(Kernel::StorageDevice& device)
|
: MBRPartitionTable(move(device))
|
||||||
: MBRPartitionTable(device)
|
|
||||||
#else
|
|
||||||
GUIDPartitionTable::GUIDPartitionTable(NonnullRefPtr<Core::DeprecatedFile> device_file)
|
|
||||||
: MBRPartitionTable(move(device_file))
|
|
||||||
#endif
|
|
||||||
{
|
{
|
||||||
// FIXME: Handle OOM failure here.
|
// 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);
|
VERIFY(partitions_count() == 0);
|
||||||
if (!initialize())
|
if (!initialize())
|
||||||
m_valid = false;
|
m_valid = false;
|
||||||
|
@ -86,17 +71,11 @@ bool GUIDPartitionTable::initialize()
|
||||||
{
|
{
|
||||||
VERIFY(m_cached_header.data() != nullptr);
|
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 maybe_error = m_device.read_block(first_gpt_block, m_cached_header.bytes());
|
||||||
auto buffer = UserOrKernelBuffer::for_kernel_buffer(m_cached_header.data());
|
if (maybe_error.is_error())
|
||||||
if (!m_device->read_block(first_gpt_block, buffer))
|
|
||||||
return false;
|
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]);
|
dbgln_if(GPT_DEBUG, "GUIDPartitionTable: signature - {:#08x} {:#08x}", header().sig[1], header().sig[0]);
|
||||||
|
|
||||||
|
@ -105,28 +84,19 @@ bool GUIDPartitionTable::initialize()
|
||||||
return false;
|
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()) {
|
if (entries_buffer_result.is_error()) {
|
||||||
dbgln("GUIDPartitionTable: not enough memory for entries buffer");
|
dbgln("GUIDPartitionTable: not enough memory for entries buffer");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
auto entries_buffer = entries_buffer_result.release_value();
|
auto entries_buffer = entries_buffer_result.release_value();
|
||||||
#ifdef KERNEL
|
size_t raw_byte_index = header().partition_array_start_lba * block_size();
|
||||||
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;
|
|
||||||
for (size_t entry_index = 0; entry_index < header().entries_count; entry_index++) {
|
for (size_t entry_index = 0; entry_index < header().entries_count; entry_index++) {
|
||||||
|
maybe_error = m_device.read_block(raw_byte_index / block_size(), entries_buffer.bytes());
|
||||||
#ifdef KERNEL
|
if (maybe_error.is_error())
|
||||||
if (!m_device->read_block((raw_byte_index / m_block_size), raw_entries_buffer))
|
|
||||||
return false;
|
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* 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 {};
|
Array<u8, 16> partition_type {};
|
||||||
partition_type.span().overwrite(0, entry.partition_guid, partition_type.size());
|
partition_type.span().overwrite(0, entry.partition_guid, partition_type.size());
|
||||||
|
|
||||||
|
|
|
@ -15,13 +15,8 @@ class GUIDPartitionTable final : public MBRPartitionTable {
|
||||||
public:
|
public:
|
||||||
virtual ~GUIDPartitionTable() = default;
|
virtual ~GUIDPartitionTable() = default;
|
||||||
|
|
||||||
#ifdef KERNEL
|
static ErrorOr<NonnullOwnPtr<GUIDPartitionTable>> try_to_initialize(PartitionableDevice);
|
||||||
static ErrorOr<NonnullOwnPtr<GUIDPartitionTable>> try_to_initialize(Kernel::StorageDevice&);
|
explicit GUIDPartitionTable(PartitionableDevice);
|
||||||
explicit GUIDPartitionTable(Kernel::StorageDevice&);
|
|
||||||
#else
|
|
||||||
static ErrorOr<NonnullOwnPtr<GUIDPartitionTable>> try_to_initialize(NonnullRefPtr<Core::DeprecatedFile>);
|
|
||||||
explicit GUIDPartitionTable(NonnullRefPtr<Core::DeprecatedFile>);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
virtual bool is_valid() const override
|
virtual bool is_valid() const override
|
||||||
{
|
{
|
||||||
|
|
|
@ -7,10 +7,6 @@
|
||||||
#include <AK/Debug.h>
|
#include <AK/Debug.h>
|
||||||
#include <LibPartition/MBRPartitionTable.h>
|
#include <LibPartition/MBRPartitionTable.h>
|
||||||
|
|
||||||
#ifndef KERNEL
|
|
||||||
# include <LibCore/DeprecatedFile.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace Partition {
|
namespace Partition {
|
||||||
|
|
||||||
#define MBR_SIGNATURE 0xaa55
|
#define MBR_SIGNATURE 0xaa55
|
||||||
|
@ -18,15 +14,9 @@ namespace Partition {
|
||||||
#define EBR_CHS_CONTAINER 0x05
|
#define EBR_CHS_CONTAINER 0x05
|
||||||
#define EBR_LBA_CONTAINER 0x0F
|
#define EBR_LBA_CONTAINER 0x0F
|
||||||
|
|
||||||
#ifdef KERNEL
|
ErrorOr<NonnullOwnPtr<MBRPartitionTable>> MBRPartitionTable::try_to_initialize(PartitionableDevice device)
|
||||||
ErrorOr<NonnullOwnPtr<MBRPartitionTable>> MBRPartitionTable::try_to_initialize(Kernel::StorageDevice& device)
|
|
||||||
{
|
{
|
||||||
auto table = TRY(adopt_nonnull_own_or_enomem(new (nothrow) MBRPartitionTable(device)));
|
auto table = TRY(adopt_nonnull_own_or_enomem(new (nothrow) MBRPartitionTable(move(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
|
|
||||||
if (table->contains_ebr())
|
if (table->contains_ebr())
|
||||||
return Error::from_errno(ENOTSUP);
|
return Error::from_errno(ENOTSUP);
|
||||||
if (table->is_protective_mbr())
|
if (table->is_protective_mbr())
|
||||||
|
@ -36,15 +26,9 @@ ErrorOr<NonnullOwnPtr<MBRPartitionTable>> MBRPartitionTable::try_to_initialize(N
|
||||||
return table;
|
return table;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef KERNEL
|
OwnPtr<MBRPartitionTable> MBRPartitionTable::try_to_initialize(PartitionableDevice device, u32 start_lba)
|
||||||
OwnPtr<MBRPartitionTable> MBRPartitionTable::try_to_initialize(Kernel::StorageDevice& device, u32 start_lba)
|
|
||||||
{
|
{
|
||||||
auto table = adopt_nonnull_own_or_enomem(new (nothrow) MBRPartitionTable(device, start_lba)).release_value_but_fixme_should_propagate_errors();
|
auto table = adopt_nonnull_own_or_enomem(new (nothrow) MBRPartitionTable(move(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
|
|
||||||
if (!table->is_valid())
|
if (!table->is_valid())
|
||||||
return {};
|
return {};
|
||||||
return table;
|
return table;
|
||||||
|
@ -52,28 +36,17 @@ OwnPtr<MBRPartitionTable> MBRPartitionTable::try_to_initialize(NonnullRefPtr<Cor
|
||||||
|
|
||||||
bool MBRPartitionTable::read_boot_record()
|
bool MBRPartitionTable::read_boot_record()
|
||||||
{
|
{
|
||||||
#ifdef KERNEL
|
if (block_size() != 512)
|
||||||
auto buffer = UserOrKernelBuffer::for_kernel_buffer(m_cached_header.data());
|
|
||||||
if (!m_device->read_block(m_start_lba, buffer))
|
|
||||||
return false;
|
return false;
|
||||||
#else
|
auto maybe_error = m_device.read_block(m_start_lba, m_cached_header.bytes());
|
||||||
m_device_file->seek(m_start_lba * m_block_size);
|
m_header_valid = !maybe_error.is_error();
|
||||||
if (m_device_file->read(m_cached_header.data(), m_cached_header.size()) != 512)
|
|
||||||
return false;
|
|
||||||
#endif
|
|
||||||
m_header_valid = true;
|
|
||||||
return m_header_valid;
|
return m_header_valid;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef KERNEL
|
MBRPartitionTable::MBRPartitionTable(PartitionableDevice device, u32 start_lba)
|
||||||
MBRPartitionTable::MBRPartitionTable(Kernel::StorageDevice& device, u32 start_lba)
|
: PartitionTable(move(device))
|
||||||
: PartitionTable(device)
|
|
||||||
#else
|
|
||||||
MBRPartitionTable::MBRPartitionTable(NonnullRefPtr<Core::DeprecatedFile> device_file, u32 start_lba)
|
|
||||||
: PartitionTable(move(device_file))
|
|
||||||
#endif
|
|
||||||
, m_start_lba(start_lba)
|
, 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())
|
if (!read_boot_record() || !initialize())
|
||||||
return;
|
return;
|
||||||
|
@ -91,15 +64,10 @@ MBRPartitionTable::MBRPartitionTable(NonnullRefPtr<Core::DeprecatedFile> device_
|
||||||
m_valid = true;
|
m_valid = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef KERNEL
|
MBRPartitionTable::MBRPartitionTable(PartitionableDevice device)
|
||||||
MBRPartitionTable::MBRPartitionTable(Kernel::StorageDevice& device)
|
: PartitionTable(move(device))
|
||||||
: PartitionTable(device)
|
|
||||||
#else
|
|
||||||
MBRPartitionTable::MBRPartitionTable(NonnullRefPtr<Core::DeprecatedFile> device_file)
|
|
||||||
: PartitionTable(move(device_file))
|
|
||||||
#endif
|
|
||||||
, m_start_lba(0)
|
, 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())
|
if (!read_boot_record() || contains_ebr() || is_protective_mbr() || !initialize())
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -38,17 +38,10 @@ public:
|
||||||
public:
|
public:
|
||||||
~MBRPartitionTable();
|
~MBRPartitionTable();
|
||||||
|
|
||||||
#ifdef KERNEL
|
static ErrorOr<NonnullOwnPtr<MBRPartitionTable>> try_to_initialize(PartitionableDevice);
|
||||||
static ErrorOr<NonnullOwnPtr<MBRPartitionTable>> try_to_initialize(Kernel::StorageDevice&);
|
static OwnPtr<MBRPartitionTable> try_to_initialize(PartitionableDevice, u32 start_lba);
|
||||||
static OwnPtr<MBRPartitionTable> try_to_initialize(Kernel::StorageDevice&, u32 start_lba);
|
explicit MBRPartitionTable(PartitionableDevice);
|
||||||
explicit MBRPartitionTable(Kernel::StorageDevice&);
|
MBRPartitionTable(PartitionableDevice, u32 start_lba);
|
||||||
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
|
|
||||||
|
|
||||||
bool is_protective_mbr() const;
|
bool is_protective_mbr() const;
|
||||||
bool contains_ebr() const;
|
bool contains_ebr() const;
|
||||||
|
|
|
@ -7,25 +7,15 @@
|
||||||
#include <LibPartition/PartitionTable.h>
|
#include <LibPartition/PartitionTable.h>
|
||||||
|
|
||||||
#ifndef KERNEL
|
#ifndef KERNEL
|
||||||
# include <LibCore/DeprecatedFile.h>
|
|
||||||
# include <sys/ioctl.h>
|
# include <sys/ioctl.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace Partition {
|
namespace Partition {
|
||||||
|
|
||||||
#ifdef KERNEL
|
PartitionTable::PartitionTable(PartitionableDevice&& device)
|
||||||
PartitionTable::PartitionTable(Kernel::StorageDevice& device)
|
: m_device(move(device))
|
||||||
: m_device(device)
|
|
||||||
, m_block_size(device.block_size())
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
#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
|
Optional<DiskPartitionMetadata> PartitionTable::partition(unsigned index) const
|
||||||
{
|
{
|
||||||
|
|
|
@ -8,12 +8,7 @@
|
||||||
|
|
||||||
#include <AK/NonnullRefPtr.h>
|
#include <AK/NonnullRefPtr.h>
|
||||||
#include <LibPartition/DiskPartitionMetadata.h>
|
#include <LibPartition/DiskPartitionMetadata.h>
|
||||||
|
#include <LibPartition/PartitionableDevice.h>
|
||||||
#ifdef KERNEL
|
|
||||||
# include <Kernel/Devices/Storage/StorageDevice.h>
|
|
||||||
#else
|
|
||||||
# include <LibCore/Forward.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace Partition {
|
namespace Partition {
|
||||||
|
|
||||||
|
@ -25,19 +20,13 @@ public:
|
||||||
virtual bool is_valid() const = 0;
|
virtual bool is_valid() const = 0;
|
||||||
|
|
||||||
Vector<DiskPartitionMetadata> partitions() const { return m_partitions; }
|
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:
|
protected:
|
||||||
#ifdef KERNEL
|
explicit PartitionTable(PartitionableDevice&&);
|
||||||
explicit PartitionTable(Kernel::StorageDevice&);
|
PartitionableDevice m_device;
|
||||||
NonnullRefPtr<Kernel::StorageDevice> m_device;
|
|
||||||
#else
|
|
||||||
explicit PartitionTable(NonnullRefPtr<Core::DeprecatedFile>);
|
|
||||||
NonnullRefPtr<Core::DeprecatedFile> m_device_file;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
Vector<DiskPartitionMetadata> m_partitions;
|
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