From d3f13b091eb05bdae9b89515cbfcc0005e2c194a Mon Sep 17 00:00:00 2001 From: koolkdev Date: Wed, 14 Feb 2024 00:43:21 +0200 Subject: [PATCH 01/17] refactor error handling --- CMakeLists.txt | 3 +- include/wfslib/directory.h | 15 +++-- include/wfslib/directory_items_iterator.h | 7 +- include/wfslib/errors.h | 39 +++++++++++ include/wfslib/wfs_item.h | 3 - src/area.cpp | 72 +++++++++++--------- src/area.h | 37 ++++++----- src/block.cpp | 5 +- src/block.h | 2 +- src/data_block.cpp | 18 ++--- src/data_block.h | 17 +++-- src/directory.cpp | 81 ++++++++++++++--------- src/directory_items_iterator.cpp | 17 +++-- src/errors.cpp | 26 ++++++++ src/file.cpp | 10 ++- src/free_blocks_allocator.cpp | 6 +- src/free_blocks_allocator.h | 9 ++- src/metadata_block.cpp | 14 ++-- src/metadata_block.h | 14 ++-- src/structs.cpp | 17 +++++ src/structs.h | 2 + src/wfs.cpp | 53 ++++++++++----- src/wfs_item.cpp | 17 ----- 23 files changed, 314 insertions(+), 170 deletions(-) create mode 100644 include/wfslib/errors.h create mode 100644 src/errors.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index c0a2bf5..2647225 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,6 +28,7 @@ add_library(${PROJECT_NAME} src/device_encryption.cpp src/directory.cpp src/directory_items_iterator.cpp + src/errors.cpp src/file.cpp src/file_device.cpp src/free_blocks_allocator.cpp @@ -44,7 +45,7 @@ if(BUILD_STATIC AND MSVC) MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") endif() -target_compile_features(${PROJECT_NAME} PRIVATE cxx_std_20) +target_compile_features(${PROJECT_NAME} PRIVATE cxx_std_23) target_compile_options(${PROJECT_NAME} PRIVATE $<$:/W4 /WX> $<$>:-Wall -Wextra -Wpedantic -Werror> diff --git a/include/wfslib/directory.h b/include/wfslib/directory.h index 6980e81..84f8937 100644 --- a/include/wfslib/directory.h +++ b/include/wfslib/directory.h @@ -7,9 +7,12 @@ #pragma once +#include #include #include + #include "directory_items_iterator.h" +#include "errors.h" #include "wfs_item.h" class Area; @@ -26,9 +29,9 @@ class Directory : public WfsItem, public std::enable_shared_from_this const std::shared_ptr& block) : WfsItem(name, attributes), area_(area), block_(block) {} - std::shared_ptr GetObject(const std::string& name) const; - std::shared_ptr GetDirectory(const std::string& name) const; - std::shared_ptr GetFile(const std::string& name) const; + std::expected, WfsError> GetObject(const std::string& name) const; + std::expected, WfsError> GetDirectory(const std::string& name) const; + std::expected, WfsError> GetFile(const std::string& name) const; size_t Size() const; DirectoryItemsIterator begin() const; @@ -44,6 +47,8 @@ class Directory : public WfsItem, public std::enable_shared_from_this std::shared_ptr block_; - std::shared_ptr Create(const std::string& name, const AttributesBlock& attributes) const; - AttributesBlock GetObjectAttributes(const std::shared_ptr& block, const std::string& name) const; + std::expected, WfsError> GetObjectInternal(const std::string& name, + const AttributesBlock& attributes) const; + std::expected GetObjectAttributes(const std::shared_ptr& block, + const std::string& name) const; }; diff --git a/include/wfslib/directory_items_iterator.h b/include/wfslib/directory_items_iterator.h index c29d4b1..41e762d 100644 --- a/include/wfslib/directory_items_iterator.h +++ b/include/wfslib/directory_items_iterator.h @@ -7,10 +7,13 @@ #pragma once +#include #include #include #include +#include "errors.h" + class Directory; class WfsItem; class MetadataBlock; @@ -21,7 +24,7 @@ class DirectoryItemsIterator { public: using iterator_category = std::input_iterator_tag; using difference_type = std::ptrdiff_t; - using value_type = std::shared_ptr; + using value_type = std::tuple, WfsError>>; struct NodeState { std::shared_ptr block; @@ -39,7 +42,7 @@ class DirectoryItemsIterator { DirectoryItemsIterator operator++(int); bool operator==(const DirectoryItemsIterator& rhs) const; bool operator!=(const DirectoryItemsIterator& rhs) const; - std::shared_ptr operator*(); + value_type operator*(); private: std::shared_ptr directory_; diff --git a/include/wfslib/errors.h b/include/wfslib/errors.h new file mode 100644 index 0000000..a6aa52f --- /dev/null +++ b/include/wfslib/errors.h @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2024 koolkdev + * + * This software may be modified and distributed under the terms + * of the MIT license. See the LICENSE file for details. + */ + +#pragma once + +#include +#include + +enum WfsError { + kItemNotFound, + kNotDirectory, + kNotFile, + kBlockBadHash, + kAreaHeaderCorrupted, + kDirectoryCorrupted, + kFreeBlocksAllocatorCorrupted, + kFileDataCorrupted, + kFileMetadataCorrupted, +}; + +class WfsException : public std::exception { + public: + WfsException(WfsError error) : error_(error) {} + virtual char const* what() const noexcept override; + + private: + WfsError error_; +}; + +template +T throw_if_error(std::expected res) { + if (!res.has_value()) + throw WfsException(res.error()); + return *res; +} diff --git a/include/wfslib/wfs_item.h b/include/wfslib/wfs_item.h index e47b6f1..bbd67a2 100644 --- a/include/wfslib/wfs_item.h +++ b/include/wfslib/wfs_item.h @@ -18,8 +18,6 @@ struct AttributesBlock { std::shared_ptr block; size_t attributes_offset; - operator bool() const { return !!block; } - ::Attributes* Attributes(); const ::Attributes* Attributes() const; }; @@ -29,7 +27,6 @@ class WfsItem { WfsItem(const std::string& name, const AttributesBlock& block); virtual ~WfsItem() {} const std::string& GetName() const { return name_; } - std::string GetRealName() const; virtual bool IsDirectory() const; virtual bool IsFile() const; virtual bool IsLink() const; diff --git a/src/area.cpp b/src/area.cpp index 1d84db1..8096024 100644 --- a/src/area.cpp +++ b/src/area.cpp @@ -27,39 +27,44 @@ Area::Area(const std::shared_ptr& device, root_directory_name_(root_directory_name), root_directory_attributes_(root_directory_attributes) {} -std::shared_ptr Area::LoadRootArea(const std::shared_ptr& device) { - std::shared_ptr block; - try { - block = MetadataBlock::LoadBlock(device, 0, Block::BlockSize::Basic, 0); - } catch (const Block::BadHash&) { +std::expected, WfsError> Area::LoadRootArea(const std::shared_ptr& device) { + auto block = MetadataBlock::LoadBlock(device, 0, Block::BlockSize::Basic, 0); + if (!block.has_value()) { block = MetadataBlock::LoadBlock(device, 0, Block::BlockSize::Regular, 0); + if (!block.has_value()) + return std::unexpected(WfsError::kAreaHeaderCorrupted); } return std::make_shared( - device, nullptr, block, "", - AttributesBlock{block, sizeof(MetadataBlockHeader) + offsetof(WfsHeader, root_area_attributes)}); + device, nullptr, *block, "", + AttributesBlock{*block, sizeof(MetadataBlockHeader) + offsetof(WfsHeader, root_area_attributes)}); } -std::shared_ptr Area::GetDirectory(uint32_t block_number, - const std::string& name, - const AttributesBlock& attributes) { - // TODO: Cache - return std::make_shared(name, attributes, shared_from_this(), GetMetadataBlock(block_number)); +std::expected, WfsError> Area::GetDirectory(uint32_t block_number, + const std::string& name, + const AttributesBlock& attributes) { + auto block = GetMetadataBlock(block_number); + if (!block.has_value()) + return std::unexpected(WfsError::kDirectoryCorrupted); + return std::make_shared(name, attributes, shared_from_this(), std::move(*block)); } -std::shared_ptr Area::GetRootDirectory() { +std::expected, WfsError> Area::GetRootDirectory() { return GetDirectory(as_const(this)->header()->root_directory_block_number.value(), root_directory_name_, root_directory_attributes_); } -std::shared_ptr Area::GetArea(uint32_t block_number, - const std::string& root_directory_name, - const AttributesBlock& root_directory_attributes, - Block::BlockSize size) { - return std::make_shared(device_, root_area_ ? root_area_ : shared_from_this(), - GetMetadataBlock(block_number, size), root_directory_name, root_directory_attributes); +std::expected, WfsError> Area::GetArea(uint32_t block_number, + const std::string& root_directory_name, + const AttributesBlock& root_directory_attributes, + Block::BlockSize size) { + auto area_metadata_block = GetMetadataBlock(block_number, size); + if (!area_metadata_block.has_value()) + return std::unexpected(WfsError::kAreaHeaderCorrupted); + return std::make_shared(device_, root_area_ ? root_area_ : shared_from_this(), std::move(*area_metadata_block), + root_directory_name, root_directory_attributes); } -std::shared_ptr Area::GetMetadataBlock(uint32_t block_number) const { +std::expected, WfsError> Area::GetMetadataBlock(uint32_t block_number) const { return GetMetadataBlock(block_number, static_cast(header()->log2_block_size.value())); } @@ -68,16 +73,17 @@ uint32_t Area::IV(uint32_t block_number) const { (ToBasicBlockNumber(block_number) << (Block::BlockSize::Basic - device_->device()->Log2SectorSize())); } -std::shared_ptr Area::GetMetadataBlock(uint32_t block_number, Block::BlockSize size) const { +std::expected, WfsError> Area::GetMetadataBlock(uint32_t block_number, + Block::BlockSize size) const { return MetadataBlock::LoadBlock(device_, header_block_->BlockNumber() + ToBasicBlockNumber(block_number), size, IV(block_number)); } -std::shared_ptr Area::GetDataBlock(uint32_t block_number, - Block::BlockSize size, - uint32_t data_size, - const DataBlock::DataBlockHash& data_hash, - bool encrypted) const { +std::expected, WfsError> Area::GetDataBlock(uint32_t block_number, + Block::BlockSize size, + uint32_t data_size, + const DataBlock::DataBlockHash& data_hash, + bool encrypted) const { return DataBlock::LoadBlock(device_, header_block_->BlockNumber() + ToBasicBlockNumber(block_number), size, data_size, IV(block_number), data_hash, encrypted); } @@ -106,10 +112,16 @@ uint32_t Area::BlocksCount() const { return root_directory_attributes_.Attributes()->blocks_count.value(); } -std::shared_ptr Area::GetFreeBlocksAllocator() const { - return std::make_unique(shared_from_this(), FreeBlocksAllocatorBlockNumber); +std::expected, WfsError> Area::GetFreeBlocksAllocator() const { + auto metadata_block = GetMetadataBlock(FreeBlocksAllocatorBlockNumber); + if (!metadata_block.has_value()) + return std::unexpected(WfsError::kFreeBlocksAllocatorCorrupted); + return std::make_unique(shared_from_this(), std::move(*metadata_block)); } -std::shared_ptr Area::GetFreeBlocksAllocator() { - return std::make_unique(shared_from_this(), FreeBlocksAllocatorBlockNumber); +std::expected, WfsError> Area::GetFreeBlocksAllocator() { + auto res = as_const(this)->GetFreeBlocksAllocator(); + if (!res.has_value()) + return std::unexpected(res.error()); + return std::const_pointer_cast(*res); } diff --git a/src/area.h b/src/area.h index 4569cfb..0133c5b 100644 --- a/src/area.h +++ b/src/area.h @@ -29,27 +29,28 @@ class Area : public std::enable_shared_from_this { const std::string& root_directory_name, const AttributesBlock& root_directory_attributes); - static std::shared_ptr LoadRootArea(const std::shared_ptr& device); + static std::expected, WfsError> LoadRootArea(const std::shared_ptr& device); - std::shared_ptr GetArea(uint32_t block_number, - const std::string& root_directory_name, - const AttributesBlock& root_directory_attributes, - Block::BlockSize size); + std::expected, WfsError> GetArea(uint32_t block_number, + const std::string& root_directory_name, + const AttributesBlock& root_directory_attributes, + Block::BlockSize size); - std::shared_ptr GetRootDirectory(); + std::expected, WfsError> GetRootDirectory(); - std::shared_ptr GetDirectory(uint32_t block_number, - const std::string& name, - const AttributesBlock& attributes); + std::expected, WfsError> GetDirectory(uint32_t block_number, + const std::string& name, + const AttributesBlock& attributes); - std::shared_ptr GetMetadataBlock(uint32_t block_number) const; - std::shared_ptr GetMetadataBlock(uint32_t block_number, Block::BlockSize size) const; + std::expected, WfsError> GetMetadataBlock(uint32_t block_number) const; + std::expected, WfsError> GetMetadataBlock(uint32_t block_number, + Block::BlockSize size) const; - std::shared_ptr GetDataBlock(uint32_t block_number, - Block::BlockSize size, - uint32_t data_size, - const DataBlock::DataBlockHash& data_hash, - bool encrypted) const; + std::expected, WfsError> GetDataBlock(uint32_t block_number, + Block::BlockSize size, + uint32_t data_size, + const DataBlock::DataBlockHash& data_hash, + bool encrypted) const; uint32_t RelativeBlockNumber(uint32_t block_number) const; uint32_t AbsoluteBlockNumber(uint32_t block_number) const; @@ -59,8 +60,8 @@ class Area : public std::enable_shared_from_this { uint32_t BlockNumber() const; uint32_t BlocksCount() const; - std::shared_ptr GetFreeBlocksAllocator() const; - std::shared_ptr GetFreeBlocksAllocator(); + std::expected, WfsError> GetFreeBlocksAllocator() const; + std::expected, WfsError> GetFreeBlocksAllocator(); private: static constexpr uint32_t FreeBlocksAllocatorBlockNumber = 1; diff --git a/src/block.cpp b/src/block.cpp index 0cbbddc..eca7ea8 100644 --- a/src/block.cpp +++ b/src/block.cpp @@ -49,10 +49,9 @@ void Block::Resize(uint32_t data_size) { } } -void Block::Fetch(bool check_hash) { +bool Block::Fetch(bool check_hash) { device_->ReadBlock(ToDeviceSector(block_number_), data_, iv_, encrypted_); - if (check_hash && !device_->CheckHash(data_, as_const(this)->Hash())) - throw Block::BadHash(block_number_); + return !check_hash || device_->CheckHash(data_, as_const(this)->Hash()); } void Block::Flush() { diff --git a/src/block.h b/src/block.h index f0f9860..68d7817 100644 --- a/src/block.h +++ b/src/block.h @@ -24,7 +24,7 @@ class Block { MegaRegular = 16, }; - void Fetch(bool check_hash = true); + bool Fetch(bool check_hash = true); void Flush(); // Actual used size, always equal to capacity in metadata blocks. diff --git a/src/data_block.cpp b/src/data_block.cpp index 3557586..907aa39 100644 --- a/src/data_block.cpp +++ b/src/data_block.cpp @@ -24,13 +24,14 @@ DataBlock::~DataBlock() { Flush(); } -std::shared_ptr DataBlock::LoadBlock(const std::shared_ptr& device, - uint32_t block_number, - Block::BlockSize size_category, - uint32_t data_size, - uint32_t iv, - const DataBlockHash& data_hash, - bool encrypted) { +std::expected, WfsError> DataBlock::LoadBlock( + const std::shared_ptr& device, + uint32_t block_number, + Block::BlockSize size_category, + uint32_t data_size, + uint32_t iv, + const DataBlockHash& data_hash, + bool encrypted) { auto cached_block = device->GetFromCache(block_number); if (cached_block) { assert(cached_block->BlockNumber() == block_number); @@ -45,7 +46,8 @@ std::shared_ptr DataBlock::LoadBlock(const std::shared_ptrAddToCache(block_number, block); if (data_size) { // Fetch block only if have data - block->Fetch(); + if (!block->Fetch()) + return std::unexpected(WfsError::kBlockBadHash); } return block; } diff --git a/src/data_block.h b/src/data_block.h index 4c1f09d..592bc84 100644 --- a/src/data_block.h +++ b/src/data_block.h @@ -7,8 +7,11 @@ #pragma once +#include #include + #include "block.h" +#include "errors.h" class MetadataBlock; @@ -28,13 +31,13 @@ class DataBlock : public Block { bool encrypted); ~DataBlock() override; - static std::shared_ptr LoadBlock(const std::shared_ptr& device, - uint32_t block_number, - Block::BlockSize size_category, - uint32_t data_size, - uint32_t iv, - const DataBlockHash& data_hash, - bool encrypted); + static std::expected, WfsError> LoadBlock(const std::shared_ptr& device, + uint32_t block_number, + Block::BlockSize size_category, + uint32_t data_size, + uint32_t iv, + const DataBlockHash& data_hash, + bool encrypted); protected: std::span Hash() override; diff --git a/src/directory.cpp b/src/directory.cpp index a98e2c2..8a07c5c 100644 --- a/src/directory.cpp +++ b/src/directory.cpp @@ -17,42 +17,48 @@ using NodeState = DirectoryItemsIterator::NodeState; using DirectoryTree = SubBlockAllocator; -std::shared_ptr Directory::GetObject(const std::string& name) const { - AttributesBlock attributes_block = GetObjectAttributes(block_, name); - if (!attributes_block) - return nullptr; - return Create(name, attributes_block); +std::expected, WfsError> Directory::GetObject(const std::string& name) const { + auto attributes_block = GetObjectAttributes(block_, name); + if (!attributes_block.has_value()) + return std::unexpected(attributes_block.error()); + return GetObjectInternal(name, *attributes_block); } -std::shared_ptr Directory::GetDirectory(const std::string& name) const { - AttributesBlock attributes_block = GetObjectAttributes(block_, name); - if (!attributes_block) { - // Not found - return nullptr; +std::expected, WfsError> Directory::GetDirectory(const std::string& name) const { + auto attributes_block = GetObjectAttributes(block_, name); + if (!attributes_block.has_value()) { + return std::unexpected(attributes_block.error()); } - auto attributes = attributes_block.Attributes(); + auto attributes = attributes_block->Attributes(); if (attributes->IsLink() || !attributes->IsDirectory()) { // Not a directory - return nullptr; + return std::unexpected(kNotDirectory); } - return std::dynamic_pointer_cast(Create(name, attributes_block)); + auto obj = GetObjectInternal(attributes->GetCaseSensitiveName(name), *attributes_block); + if (!obj.has_value()) + return std::unexpected(obj.error()); + return std::dynamic_pointer_cast(*obj); } -std::shared_ptr Directory::GetFile(const std::string& name) const { - AttributesBlock attributes_block = GetObjectAttributes(block_, name); - auto attributes = attributes_block.Attributes(); - if (!attributes_block) { - // Not found - return nullptr; +std::expected, WfsError> Directory::GetFile(const std::string& name) const { + auto attributes_block = GetObjectAttributes(block_, name); + if (!attributes_block.has_value()) { + return std::unexpected(attributes_block.error()); } + auto attributes = attributes_block->Attributes(); if (attributes->IsLink() || attributes->IsDirectory()) { // Not a file - return nullptr; + return std::unexpected(kNotFile); } - return std::dynamic_pointer_cast(Create(name, attributes_block)); + auto obj = GetObjectInternal(name, *attributes_block); + if (!obj.has_value()) + return std::unexpected(obj.error()); + return std::dynamic_pointer_cast(*obj); } -std::shared_ptr Directory::Create(const std::string& name, const AttributesBlock& attributes_block) const { +std::expected, WfsError> Directory::GetObjectInternal( + const std::string& name, + const AttributesBlock& attributes_block) const { auto attributes = attributes_block.Attributes(); if (attributes->IsLink()) { // TODO, I think that the link info is in the attributes metadata @@ -65,7 +71,9 @@ std::shared_ptr Directory::Create(const std::string& name, const Attrib (attributes->flags.value() & attributes->Flags::AREA_SIZE_REGULAR)) block_size = Block::BlockSize::Regular; auto new_area = area_->GetArea(attributes->directory_block_number.value(), name, attributes_block, block_size); - return new_area->GetRootDirectory(); + if (!new_area.has_value()) + return std::unexpected(new_area.error()); + return (*new_area)->GetRootDirectory(); } else { return area_->GetDirectory(attributes->directory_block_number.value(), name, attributes_block); } @@ -75,8 +83,8 @@ std::shared_ptr Directory::Create(const std::string& name, const Attrib } } -AttributesBlock Directory::GetObjectAttributes(const std::shared_ptr& block, - const std::string& name) const { +std::expected Directory::GetObjectAttributes(const std::shared_ptr& block, + const std::string& name) const { DirectoryTree dir_tree{block}; auto current_node = as_const(block.get())->get_object(std::as_const(dir_tree).extra_header()->root.value()); @@ -84,19 +92,23 @@ AttributesBlock Directory::GetObjectAttributes(const std::shared_ptr(current_node); - if (current_node->prefix_length.value() > static_cast(std::distance(pos_in_path, name.end()))) { + auto prefix_length = current_node->prefix_length.value(); + if (prefix_length > static_cast(std::distance(pos_in_path, name.end()))) { // not equal.. path too long - return {}; + return std::unexpected(kItemNotFound); } - if (current_node->prefix_length.value() && - std::strncmp(&*pos_in_path, current_node->prefix().data(), current_node->prefix_length.value())) { + if (prefix_length && + !std::equal(pos_in_path, pos_in_path + prefix_length, current_node->prefix().begin(), + current_node->prefix().begin() + prefix_length, [](char expected_char, char prefix_char) { + return std::tolower(expected_char) == prefix_char; + })) { // not equal.. not found - return {}; + return std::unexpected(kItemNotFound); } pos_in_path += current_node->prefix_length.value(); char next_expected_char = 0; if (pos_in_path < name.end()) - next_expected_char = *pos_in_path; + next_expected_char = static_cast(std::tolower(*pos_in_path)); auto choices = current_node->choices(); // This is sorted list, so we can find it with lower_bound auto res = std::lower_bound(choices.begin(), choices.end(), std::byte{(uint8_t)next_expected_char}); @@ -107,7 +119,7 @@ AttributesBlock Directory::GetObjectAttributes(const std::shared_ptrget_item(res - choices.begin()).value(); if (pos_in_path == name.end()) { // We found the attribute! - return {block, value_offset}; + return AttributesBlock{block, value_offset}; } pos_in_path++; // Go to next node @@ -154,7 +166,10 @@ AttributesBlock Directory::GetObjectAttributes(const std::shared_ptrGetMetadataBlock(last_block_number), name); + auto next_block = area_->GetMetadataBlock(last_block_number); + if (!next_block.has_value()) + return std::unexpected(kDirectoryCorrupted); + return GetObjectAttributes(std::move(*next_block), name); } } diff --git a/src/directory_items_iterator.cpp b/src/directory_items_iterator.cpp index 0aefb7d..309e048 100644 --- a/src/directory_items_iterator.cpp +++ b/src/directory_items_iterator.cpp @@ -55,11 +55,13 @@ DirectoryItemsIterator& DirectoryItemsIterator::operator++() { // This is just internal node (in the directories trees tree), it just point to another tree auto block = directory_->area()->GetMetadataBlock( static_cast(node_state_->node)->get_next_allocator_block_number().value()); - DirectoryTree dir_tree{block}; + if (!block.has_value()) + throw WfsException(WfsError::kDirectoryCorrupted); + DirectoryTree dir_tree{*block}; auto current_node = - as_const(block.get())->get_object(std::as_const(dir_tree).extra_header()->root.value()); + as_const(block->get())->get_object(std::as_const(dir_tree).extra_header()->root.value()); node_state_ = - std::make_shared(NodeState{block, current_node, std::move(node_state_), 0, current_node->prefix()}); + std::make_shared(NodeState{*block, current_node, std::move(node_state_), 0, current_node->prefix()}); // -- because it will be advanced immedialty to 0 when we do ++ --node_state_->current_index; // Go to the first node in this directory block @@ -87,15 +89,16 @@ bool DirectoryItemsIterator::operator!=(const DirectoryItemsIterator& rhs) const return !operator==(rhs); } -std::shared_ptr DirectoryItemsIterator::operator*() { +DirectoryItemsIterator::value_type DirectoryItemsIterator::operator*() { if (!node_state_) - return nullptr; + return {{}, nullptr}; if (node_state_->block->Header()->block_flags.value() & node_state_->block->Header()->Flags::EXTERNAL_DIRECTORY_TREE) { auto block = node_state_->block; auto external_node = static_cast(node_state_->node); - return directory_->Create(node_state_->path, - AttributesBlock{block, external_node->get_item(node_state_->current_index).value()}); + const AttributesBlock attributes{block, external_node->get_item(node_state_->current_index).value()}; + auto name = attributes.Attributes()->GetCaseSensitiveName(node_state_->path); + return {name, directory_->GetObjectInternal(name, attributes)}; } else { // Should not happen (can't happen, the iterator should stop only at external trees) throw std::logic_error("Should not happen!"); diff --git a/src/errors.cpp b/src/errors.cpp new file mode 100644 index 0000000..7953c72 --- /dev/null +++ b/src/errors.cpp @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2017 koolkdev + * + * This software may be modified and distributed under the terms + * of the MIT license. See the LICENSE file for details. + */ + +#include "errors.h" + +char const* WfsException::what() const noexcept { + switch (error_) { + case WfsError::kItemNotFound: + return "Item not found"; + case WfsError::kNotDirectory: + return "Not a directory"; + case WfsError::kNotFile: + return "Not a file"; + case WfsError::kBlockBadHash: + return "Block bad hash"; + case WfsError::kAreaHeaderCorrupted: + return "Area header corrupted"; + case WfsError::kDirectoryCorrupted: + return "Directory corrupted"; + } + return ""; +} diff --git a/src/file.cpp b/src/file.cpp index 5f8927b..ed3fee7 100644 --- a/src/file.cpp +++ b/src/file.cpp @@ -172,9 +172,12 @@ class File::RegularDataCategoryReader : public File::DataCategoryReader { void LoadDataBlock(uint32_t block_number, uint32_t data_size, const DataBlock::DataBlockHash& data_hash) { if (current_data_block && file_->area()->RelativeBlockNumber(current_data_block->BlockNumber()) == block_number) return; - current_data_block = file_->area()->GetDataBlock( + auto block = file_->area()->GetDataBlock( block_number, GetDataBlockSize(), data_size, data_hash, !(as_const(file_.get())->attributes_data().Attributes()->flags.value() & Attributes::UNENCRYPTED_FILE)); + if (!block.has_value()) + throw WfsException(WfsError::kFileDataCorrupted); + current_data_block = std::move(*block); } }; @@ -283,7 +286,10 @@ class File::DataCategory4Reader : public File::DataCategory3Reader { if (current_metadata_block && file_->area()->RelativeBlockNumber(current_metadata_block->BlockNumber()) == block_number) return; - current_metadata_block = file_->area()->GetMetadataBlock(block_number); + auto metadata_block = file_->area()->GetMetadataBlock(block_number); + if (!metadata_block.has_value()) + throw WfsException(WfsError::kFileMetadataCorrupted); + current_metadata_block = std::move(*metadata_block); } size_t ClustersInBlock() const { diff --git a/src/free_blocks_allocator.cpp b/src/free_blocks_allocator.cpp index 2c45c0c..c39683c 100644 --- a/src/free_blocks_allocator.cpp +++ b/src/free_blocks_allocator.cpp @@ -7,7 +7,5 @@ #include "free_blocks_allocator.h" -FreeBlocksAllocator::FreeBlocksAllocator(std::shared_ptr area, uint32_t block_number) - : area_(area), tree_{Adapter{area}, block_number} { - root_block_ = area_->GetMetadataBlock(block_number); -} +FreeBlocksAllocator::FreeBlocksAllocator(std::shared_ptr area, std::shared_ptr root_block) + : area_(area), tree_{Adapter{area}, root_block->BlockNumber()}, root_block_(std::move(root_block)) {} diff --git a/src/free_blocks_allocator.h b/src/free_blocks_allocator.h index 40c0994..333bd19 100644 --- a/src/free_blocks_allocator.h +++ b/src/free_blocks_allocator.h @@ -15,7 +15,12 @@ class FreeBlocksAllocator { class Adapter { public: Adapter(std::shared_ptr area) : area_(area) {} - MetadataBlock::Adapter get_block(int32_t block_number) const { return {area_->GetMetadataBlock(block_number)}; } + MetadataBlock::Adapter get_block(int32_t block_number) const { + auto block = area_->GetMetadataBlock(block_number); + if (!block.has_value()) + throw WfsException(WfsError::kFreeBlocksAllocatorCorrupted); + return {std::move(*block)}; + } private: std::shared_ptr area_; @@ -23,7 +28,7 @@ class FreeBlocksAllocator { using Tree = EPTree; - FreeBlocksAllocator(std::shared_ptr area, uint32_t block_number); + FreeBlocksAllocator(std::shared_ptr area, std::shared_ptr root_block); FreeBlocksAllocatorHeader* header() { return root_block()->get_object(header_offset()); } const FreeBlocksAllocatorHeader* header() const { diff --git a/src/metadata_block.cpp b/src/metadata_block.cpp index 1896516..813f573 100644 --- a/src/metadata_block.cpp +++ b/src/metadata_block.cpp @@ -20,11 +20,12 @@ MetadataBlock::~MetadataBlock() { Flush(); } -std::shared_ptr MetadataBlock::LoadBlock(const std::shared_ptr& device, - uint32_t block_number, - Block::BlockSize size_category, - uint32_t iv, - bool check_hash) { +std::expected, WfsError> MetadataBlock::LoadBlock( + const std::shared_ptr& device, + uint32_t block_number, + Block::BlockSize size_category, + uint32_t iv, + bool check_hash) { auto cached_block = device->GetFromCache(block_number); if (cached_block) { assert(cached_block->BlockNumber() == block_number); @@ -35,7 +36,8 @@ std::shared_ptr MetadataBlock::LoadBlock(const std::shared_ptr(device, block_number, size_category, iv); device->AddToCache(block_number, block); - block->Fetch(check_hash); + if (!block->Fetch(check_hash)) + return std::unexpected(WfsError::kBlockBadHash); return block; } diff --git a/src/metadata_block.h b/src/metadata_block.h index b591ff0..506f0dc 100644 --- a/src/metadata_block.h +++ b/src/metadata_block.h @@ -7,8 +7,11 @@ #pragma once +#include #include + #include "block.h" +#include "errors.h" #include "utils.h" struct MetadataBlockHeader; @@ -31,11 +34,12 @@ class MetadataBlock : public Block { uint32_t iv); ~MetadataBlock() override; - static std::shared_ptr LoadBlock(const std::shared_ptr& device, - uint32_t block_number, - Block::BlockSize size_category, - uint32_t iv, - bool check_hash = true); + static std::expected, WfsError> LoadBlock( + const std::shared_ptr& device, + uint32_t block_number, + Block::BlockSize size_category, + uint32_t iv, + bool check_hash = true); MetadataBlockHeader* Header(); const MetadataBlockHeader* Header() const; diff --git a/src/structs.cpp b/src/structs.cpp index cb40f2c..dcced1e 100644 --- a/src/structs.cpp +++ b/src/structs.cpp @@ -5,6 +5,9 @@ * of the MIT license. See the LICENSE file for details. */ +#include +#include + #include "structs.h" #include "utils.h" @@ -12,6 +15,20 @@ size_t Attributes::DataOffset() const { return offsetof(Attributes, case_bitmap) + div_ceil(filename_length.value(), 8); } +std::string Attributes::GetCaseSensitiveName(const std::string& name) const { + std::string real_filename = ""; + if (filename_length.value() != name.size()) { + throw std::runtime_error("Unexepected filename length"); + } + boost::dynamic_bitset bits(name.size()); + boost::from_block_range(reinterpret_cast(&case_bitmap), + reinterpret_cast(&case_bitmap) + (name.size() / 8), bits); + std::string final_name; + std::ranges::transform(std::ranges::iota_view(0ull, name.size()), std::back_inserter(final_name), + [&](auto i) { return bits[i] ? std::toupper(name[i]) : std::tolower(name[i]); }); + return final_name; +} + size_t ExternalDirectoryTreeNode::size() const { size_t total_size = sizeof(DirectoryTreeNode) + prefix_length.value() + choices_count.value() + choices_count.value() * sizeof(boost::endian::big_uint16_buf_t); diff --git a/src/structs.h b/src/structs.h index f7cd88e..91858b2 100644 --- a/src/structs.h +++ b/src/structs.h @@ -85,6 +85,8 @@ struct Attributes { bool IsLink() const { return !!(flags.value() & Flags::LINK); } size_t DataOffset() const; + + std::string GetCaseSensitiveName(const std::string& name) const; }; static_assert(sizeof(Attributes) == 0x2C, "Incorrect sizeof Attributes"); diff --git a/src/wfs.cpp b/src/wfs.cpp index 3e9635f..a44f72e 100644 --- a/src/wfs.cpp +++ b/src/wfs.cpp @@ -19,7 +19,7 @@ Wfs::Wfs(const std::shared_ptr& device, const std::span& key) : device_(std::make_shared(device, key)) { // Read first area - root_area_ = Area::LoadRootArea(device_); + root_area_ = throw_if_error(Area::LoadRootArea(device_)); } Wfs::~Wfs() { @@ -32,31 +32,55 @@ std::shared_ptr Wfs::GetObject(const std::string& filename) { std::filesystem::path path(filename); auto dir = GetDirectory(path.parent_path().string()); if (!dir) - return nullptr; - return dir->GetObject(path.filename().string()); + throw nullptr; + auto obj = dir->GetObject(path.filename().string()); + if (!obj.has_value()) { + if (obj.error() == WfsError::kItemNotFound) + return nullptr; + else + throw WfsException(obj.error()); + } + return *obj; } std::shared_ptr Wfs::GetFile(const std::string& filename) { std::filesystem::path path(filename); auto dir = GetDirectory(path.parent_path().string()); if (!dir) - return nullptr; - return dir->GetFile(path.filename().string()); + throw nullptr; + auto file = dir->GetFile(path.filename().string()); + if (!file.has_value()) { + if (file.error() == WfsError::kItemNotFound) + return nullptr; + else + throw WfsException(file.error()); + } + return *file; } std::shared_ptr Wfs::GetDirectory(const std::string& filename) { std::filesystem::path path(filename); - std::shared_ptr current_directory = root_area_->GetRootDirectory(); + auto current_directory = root_area_->GetRootDirectory(); + if (!current_directory.has_value()) { + if (current_directory.error() == WfsError::kItemNotFound) + return nullptr; + else + throw WfsException(current_directory.error()); + } for (const auto& part : path) { // the first part is "/" if (part == "/") continue; - current_directory = current_directory->GetDirectory(part.string()); - if (!current_directory) - return current_directory; + current_directory = (*current_directory)->GetDirectory(part.string()); + if (!current_directory.has_value()) { + if (current_directory.error() == WfsError::kItemNotFound) + return nullptr; + else + throw WfsException(current_directory.error()); + } } - return current_directory; + return *current_directory; } void Wfs::Flush() { @@ -76,7 +100,7 @@ void Wfs::DetectDeviceSectorSizeAndCount(const std::shared_ptr& devi device->SetLog2SectorSize(9); auto enc_device = std::make_shared(device, key); std::shared_ptr block = - MetadataBlock::LoadBlock(enc_device, 0, Block::BlockSize::Basic, 0, false); + *MetadataBlock::LoadBlock(enc_device, 0, Block::BlockSize::Basic, 0, false); auto wfs_header = reinterpret_cast(&block->data()[sizeof(MetadataBlockHeader)]); if (wfs_header->version.value() != 0x01010800) throw std::runtime_error("Unexpected WFS version (bad key?)"); @@ -86,7 +110,7 @@ void Wfs::DetectDeviceSectorSizeAndCount(const std::shared_ptr& devi block_size = Block::BlockSize::Regular; block.reset(); // Now lets read it again, this time with the correct block size - block = MetadataBlock::LoadBlock(enc_device, 0, block_size, 0, false); + block = *MetadataBlock::LoadBlock(enc_device, 0, block_size, 0, false); uint32_t xored_sectors_count, xored_sector_size; // The two last dwords of the IV is the sectors count and sector size, right now it is xored with our fake sector size // and sector count, and with the hash @@ -110,9 +134,6 @@ void Wfs::DetectDeviceSectorSizeAndCount(const std::shared_ptr& devi device->SetSectorsCount(xored_sectors_count); block.reset(); // Now try to fetch block again, this time check the hash, it will raise exception - try { - block = MetadataBlock::LoadBlock(enc_device, 0, block_size, 0, true); - } catch (const Block::BadHash&) { + if (!MetadataBlock::LoadBlock(enc_device, 0, block_size, 0, true).has_value()) throw std::runtime_error("Wfs: Failed to detect sector size and sectors count"); - } } diff --git a/src/wfs_item.cpp b/src/wfs_item.cpp index 61eacd7..557cde4 100644 --- a/src/wfs_item.cpp +++ b/src/wfs_item.cpp @@ -7,9 +7,7 @@ #include "wfs_item.h" -#include #include -#include #include "metadata_block.h" #include "structs.h" #include "utils.h" @@ -38,18 +36,3 @@ bool WfsItem::IsLink() const { auto attributes = attributes_data().Attributes(); return attributes->IsLink(); } - -std::string WfsItem::GetRealName() const { - auto attributes = attributes_data().Attributes(); - std::string real_filename = ""; - if (attributes->filename_length.value() != name_.size()) { - throw std::runtime_error("Unexepected filename length"); - } - boost::dynamic_bitset bits(name_.size()); - boost::from_block_range(reinterpret_cast(&attributes->case_bitmap), - reinterpret_cast(&attributes->case_bitmap) + (name_.size() / 8), bits); - std::string real_name; - std::ranges::transform(std::ranges::iota_view(0ull, name_.size()), std::back_inserter(real_name), - [&](auto i) { return bits[i] ? std::toupper(name_[i]) : name_[i]; }); - return real_name; -} From 39b01715217841af1b8c7ddab8a9d149a18bde58 Mon Sep 17 00:00:00 2001 From: koolkdev Date: Wed, 14 Feb 2024 00:45:51 +0200 Subject: [PATCH 02/17] fixes --- src/file.cpp | 2 +- src/structs.cpp | 1 + src/wfs.cpp | 4 ++-- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/file.cpp b/src/file.cpp index ed3fee7..5b14f7f 100644 --- a/src/file.cpp +++ b/src/file.cpp @@ -313,7 +313,7 @@ std::shared_ptr File::CreateReader(const std::shared_p case 4: return std::make_shared(file); default: - throw std::runtime_error("Unexpected file category"); + throw std::runtime_error("Unexpected file category"); // TODO: Change to WfsError } } diff --git a/src/structs.cpp b/src/structs.cpp index dcced1e..0ff65e9 100644 --- a/src/structs.cpp +++ b/src/structs.cpp @@ -18,6 +18,7 @@ size_t Attributes::DataOffset() const { std::string Attributes::GetCaseSensitiveName(const std::string& name) const { std::string real_filename = ""; if (filename_length.value() != name.size()) { + // TODO: return WfsError throw std::runtime_error("Unexepected filename length"); } boost::dynamic_bitset bits(name.size()); diff --git a/src/wfs.cpp b/src/wfs.cpp index a44f72e..c2d09f9 100644 --- a/src/wfs.cpp +++ b/src/wfs.cpp @@ -32,7 +32,7 @@ std::shared_ptr Wfs::GetObject(const std::string& filename) { std::filesystem::path path(filename); auto dir = GetDirectory(path.parent_path().string()); if (!dir) - throw nullptr; + return nullptr; auto obj = dir->GetObject(path.filename().string()); if (!obj.has_value()) { if (obj.error() == WfsError::kItemNotFound) @@ -47,7 +47,7 @@ std::shared_ptr Wfs::GetFile(const std::string& filename) { std::filesystem::path path(filename); auto dir = GetDirectory(path.parent_path().string()); if (!dir) - throw nullptr; + return nullptr; auto file = dir->GetFile(path.filename().string()); if (!file.has_value()) { if (file.error() == WfsError::kItemNotFound) From 1f8ae112fa17ca21b7edb68776cb137aecbd4502 Mon Sep 17 00:00:00 2001 From: koolkdev Date: Wed, 14 Feb 2024 00:47:59 +0200 Subject: [PATCH 03/17] add missing pragma once --- src/free_blocks_allocator.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/free_blocks_allocator.h b/src/free_blocks_allocator.h index 333bd19..42f6cb8 100644 --- a/src/free_blocks_allocator.h +++ b/src/free_blocks_allocator.h @@ -5,6 +5,8 @@ * of the MIT license. See the LICENSE file for details. */ +#pragma once + #include "area.h" #include "free_blocks_allocator_tree.h" From 3109cbd72bfd029a6166223125fe80d12fcbffe1 Mon Sep 17 00:00:00 2001 From: koolkdev Date: Wed, 14 Feb 2024 00:49:05 +0200 Subject: [PATCH 04/17] add missing errors strings --- src/errors.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/errors.cpp b/src/errors.cpp index 7953c72..7272a3c 100644 --- a/src/errors.cpp +++ b/src/errors.cpp @@ -21,6 +21,12 @@ char const* WfsException::what() const noexcept { return "Area header corrupted"; case WfsError::kDirectoryCorrupted: return "Directory corrupted"; + case WfsError::kFreeBlocksAllocatorCorrupted: + return "Free blocks allocator corrupted"; + case WfsError::kFileDataCorrupted: + return "File data corrupted"; + case WfsError::kFileMetadataCorrupted: + return "File metadata corrupted"; } return ""; } From 0103f6a97d86c2c80003075c3bc032c82ca6e461 Mon Sep 17 00:00:00 2001 From: koolkdev Date: Wed, 14 Feb 2024 01:48:44 +0200 Subject: [PATCH 05/17] remove uncessary header --- src/wfs_item.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/wfs_item.cpp b/src/wfs_item.cpp index 557cde4..c01816c 100644 --- a/src/wfs_item.cpp +++ b/src/wfs_item.cpp @@ -7,7 +7,6 @@ #include "wfs_item.h" -#include #include "metadata_block.h" #include "structs.h" #include "utils.h" From 871943894a5b15e230475fba7a7df927c1a8f106 Mon Sep 17 00:00:00 2001 From: koolkdev Date: Wed, 14 Feb 2024 02:04:49 +0200 Subject: [PATCH 06/17] when compiling with llvm use libc++ --- .github/workflows/build.yml | 63 +++++++++++++++++++------------------ CMakeLists.txt | 1 + 2 files changed, 33 insertions(+), 31 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a4f237e..860aefc 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -22,44 +22,45 @@ jobs: runs-on: ${{matrix.platform}} steps: - - uses: actions/checkout@v2 - with: - submodules: 'true' + - uses: actions/checkout@v2 + with: + submodules: "true" - - uses: lukka/get-cmake@latest + - uses: lukka/get-cmake@latest - - name: Run vcpkg - uses: lukka/run-vcpkg@v10 + - name: Run vcpkg + uses: lukka/run-vcpkg@v10 - - name: Set llvm (Ubuntu) - run: | + - name: Set llvm (Ubuntu) + run: | wget https://apt.llvm.org/llvm.sh chmod +x llvm.sh sudo ./llvm.sh 16 + sudo apt install libc++-16-dev echo "CC=clang-16" >> $GITHUB_ENV echo "CXX=clang++-16" >> $GITHUB_ENV - shell: bash - if: matrix.platform == 'ubuntu-latest' && matrix.compiler == 'llvm' + shell: bash + if: matrix.platform == 'ubuntu-latest' && matrix.compiler == 'llvm' - - name: Set llvm (MacOS) - run: | - brew update - # Temporary fix, see https://github.com/actions/setup-python/issues/577 - rm /usr/local/bin/2to3 || true - rm /usr/local/bin/idle3 || true - rm /usr/local/bin/pydoc3 || true - rm /usr/local/bin/python3 || true - rm /usr/local/bin/python3-config || true - brew install llvm - echo "CC=/usr/local/opt/llvm/bin/clang" >> $GITHUB_ENV - echo "CXX=/usr/local/opt/llvm/bin/clang++" >> $GITHUB_ENV - echo "LDFLAGS=-L/usr/local/opt/llvm/lib" >> $GITHUB_ENV - echo "CXXFLAGS=-isystem /usr/local/opt/llvm/include" >> $GITHUB_ENV - shell: bash - if: matrix.platform == 'macos-latest' + - name: Set llvm (MacOS) + run: | + brew update + # Temporary fix, see https://github.com/actions/setup-python/issues/577 + rm /usr/local/bin/2to3 || true + rm /usr/local/bin/idle3 || true + rm /usr/local/bin/pydoc3 || true + rm /usr/local/bin/python3 || true + rm /usr/local/bin/python3-config || true + brew install llvm + echo "CC=/usr/local/opt/llvm/bin/clang" >> $GITHUB_ENV + echo "CXX=/usr/local/opt/llvm/bin/clang++" >> $GITHUB_ENV + echo "LDFLAGS=-L/usr/local/opt/llvm/lib" >> $GITHUB_ENV + echo "CXXFLAGS=-isystem /usr/local/opt/llvm/include" >> $GITHUB_ENV + shell: bash + if: matrix.platform == 'macos-latest' - - name: Run cmake - uses: lukka/run-cmake@v10 - with: - configurePreset: 'default' - buildPreset: 'release' + - name: Run cmake + uses: lukka/run-cmake@v10 + with: + configurePreset: "default" + buildPreset: "release" diff --git a/CMakeLists.txt b/CMakeLists.txt index 2647225..de1bd7e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -49,6 +49,7 @@ target_compile_features(${PROJECT_NAME} PRIVATE cxx_std_23) target_compile_options(${PROJECT_NAME} PRIVATE $<$:/W4 /WX> $<$>:-Wall -Wextra -Wpedantic -Werror> + $<$:-stdlib=libc++> ) target_include_directories(${PROJECT_NAME} From 8b351fd9c141cef50dfab176381027835bb7d2f1 Mon Sep 17 00:00:00 2001 From: koolkdev Date: Wed, 14 Feb 2024 02:12:10 +0200 Subject: [PATCH 07/17] update to gcc 12 --- .github/workflows/build.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 860aefc..1fad68d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -31,6 +31,15 @@ jobs: - name: Run vcpkg uses: lukka/run-vcpkg@v10 + - name: Update gcc + run: | + sudo apt update + sudo apt install gcc-12 g++-12 + echo "CC=gcc-12" >> $GITHUB_ENV + echo "CXX=g++-12" >> $GITHUB_ENV + shell: bash + if: matrix.platform == 'ubuntu-latest' + - name: Set llvm (Ubuntu) run: | wget https://apt.llvm.org/llvm.sh From 124e6539814bc031ad0bcfc977f045268ab546c2 Mon Sep 17 00:00:00 2001 From: koolkdev Date: Wed, 14 Feb 2024 02:15:32 +0200 Subject: [PATCH 08/17] fix yml --- .github/workflows/build.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 1fad68d..37f4069 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -31,14 +31,12 @@ jobs: - name: Run vcpkg uses: lukka/run-vcpkg@v10 - - name: Update gcc + - name: Set gcc run: | - sudo apt update - sudo apt install gcc-12 g++-12 echo "CC=gcc-12" >> $GITHUB_ENV echo "CXX=g++-12" >> $GITHUB_ENV shell: bash - if: matrix.platform == 'ubuntu-latest' + if: matrix.platform == 'ubuntu-latest' && matrix.compiler == 'gcc' - name: Set llvm (Ubuntu) run: | From d43e0b23e3ef7250d00b0437a92620d59edc0bb3 Mon Sep 17 00:00:00 2001 From: koolkdev Date: Wed, 14 Feb 2024 02:19:26 +0200 Subject: [PATCH 09/17] fix includes --- src/directory.cpp | 2 ++ src/directory_items_iterator.cpp | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/directory.cpp b/src/directory.cpp index 8a07c5c..b1007d2 100644 --- a/src/directory.cpp +++ b/src/directory.cpp @@ -7,6 +7,8 @@ #include "directory.h" +#include + #include "area.h" #include "file.h" #include "link.h" diff --git a/src/directory_items_iterator.cpp b/src/directory_items_iterator.cpp index 309e048..943c7b4 100644 --- a/src/directory_items_iterator.cpp +++ b/src/directory_items_iterator.cpp @@ -8,6 +8,8 @@ #include "directory_items_iterator.h" #include +#include + #include "area.h" #include "directory.h" #include "metadata_block.h" From a707840514e0754263d8309b84a688b269951c88 Mon Sep 17 00:00:00 2001 From: koolkdev Date: Wed, 14 Feb 2024 02:25:36 +0200 Subject: [PATCH 10/17] fix --- src/directory_items_iterator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/directory_items_iterator.cpp b/src/directory_items_iterator.cpp index 943c7b4..fac3ba0 100644 --- a/src/directory_items_iterator.cpp +++ b/src/directory_items_iterator.cpp @@ -93,7 +93,7 @@ bool DirectoryItemsIterator::operator!=(const DirectoryItemsIterator& rhs) const DirectoryItemsIterator::value_type DirectoryItemsIterator::operator*() { if (!node_state_) - return {{}, nullptr}; + throw std::runtime_error("Out of bounds"); if (node_state_->block->Header()->block_flags.value() & node_state_->block->Header()->Flags::EXTERNAL_DIRECTORY_TREE) { auto block = node_state_->block; From a518db51e83db4f729e99cd75366cf28f8f94764 Mon Sep 17 00:00:00 2001 From: koolkdev Date: Wed, 14 Feb 2024 02:36:23 +0200 Subject: [PATCH 11/17] make libc++ public dep --- CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index de1bd7e..3679260 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -49,6 +49,9 @@ target_compile_features(${PROJECT_NAME} PRIVATE cxx_std_23) target_compile_options(${PROJECT_NAME} PRIVATE $<$:/W4 /WX> $<$>:-Wall -Wextra -Wpedantic -Werror> +) + +target_compile_options(${PROJECT_NAME} PUBLIC $<$:-stdlib=libc++> ) From 67e7f3681876f6c87d50ddf3adfa8fdbc6e03d09 Mon Sep 17 00:00:00 2001 From: koolkdev Date: Wed, 14 Feb 2024 10:50:57 +0200 Subject: [PATCH 12/17] update requirement to gcc 13 and llvm 17 --- .github/workflows/build.yml | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 37f4069..300fd0b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -33,8 +33,10 @@ jobs: - name: Set gcc run: | - echo "CC=gcc-12" >> $GITHUB_ENV - echo "CXX=g++-12" >> $GITHUB_ENV + sudo apt update + sudo apt install gcc-13 g++-13 + echo "CC=gcc-13" >> $GITHUB_ENV + echo "CXX=g++-13" >> $GITHUB_ENV shell: bash if: matrix.platform == 'ubuntu-latest' && matrix.compiler == 'gcc' @@ -42,10 +44,10 @@ jobs: run: | wget https://apt.llvm.org/llvm.sh chmod +x llvm.sh - sudo ./llvm.sh 16 - sudo apt install libc++-16-dev - echo "CC=clang-16" >> $GITHUB_ENV - echo "CXX=clang++-16" >> $GITHUB_ENV + sudo ./llvm.sh 17 + sudo apt install libc++-17-dev + echo "CC=clang-17" >> $GITHUB_ENV + echo "CXX=clang++-17" >> $GITHUB_ENV shell: bash if: matrix.platform == 'ubuntu-latest' && matrix.compiler == 'llvm' From 8f1d0cf00beccb657317de32dda6eded3008a582 Mon Sep 17 00:00:00 2001 From: koolkdev Date: Wed, 14 Feb 2024 19:30:54 +0200 Subject: [PATCH 13/17] remove libc++ forced usage, cause link issues --- CMakeLists.txt | 4 ---- 1 file changed, 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3679260..2647225 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -51,10 +51,6 @@ target_compile_options(${PROJECT_NAME} PRIVATE $<$>:-Wall -Wextra -Wpedantic -Werror> ) -target_compile_options(${PROJECT_NAME} PUBLIC - $<$:-stdlib=libc++> -) - target_include_directories(${PROJECT_NAME} PUBLIC $ From 097d3f4596d5b2707b39ce33d550859eba8a0983 Mon Sep 17 00:00:00 2001 From: koolkdev Date: Wed, 14 Feb 2024 19:36:14 +0200 Subject: [PATCH 14/17] debug --- .github/workflows/build.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 300fd0b..8b5f308 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -48,6 +48,8 @@ jobs: sudo apt install libc++-17-dev echo "CC=clang-17" >> $GITHUB_ENV echo "CXX=clang++-17" >> $GITHUB_ENV + clang-17 -v + clang++-17 -v shell: bash if: matrix.platform == 'ubuntu-latest' && matrix.compiler == 'llvm' From f4a2f271b7a1ca412acacd8fd34c84b16055e17b Mon Sep 17 00:00:00 2001 From: koolkdev Date: Wed, 14 Feb 2024 20:39:34 +0200 Subject: [PATCH 15/17] temporarly disable build on ubuntu with llvm --- .github/workflows/build.yml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8b5f308..be69459 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -15,6 +15,9 @@ jobs: compiler: llvm - platform: ubuntu-latest compiler: msvc + # llvm doesn't work with libstd++ until P2493R0 is done + - platform: ubuntu-latest + compiler: llvm - platform: macos-latest compiler: msvc - platform: macos-latest @@ -33,8 +36,6 @@ jobs: - name: Set gcc run: | - sudo apt update - sudo apt install gcc-13 g++-13 echo "CC=gcc-13" >> $GITHUB_ENV echo "CXX=g++-13" >> $GITHUB_ENV shell: bash @@ -48,8 +49,6 @@ jobs: sudo apt install libc++-17-dev echo "CC=clang-17" >> $GITHUB_ENV echo "CXX=clang++-17" >> $GITHUB_ENV - clang-17 -v - clang++-17 -v shell: bash if: matrix.platform == 'ubuntu-latest' && matrix.compiler == 'llvm' From 328b5ef124fb2f7c85743c6534a45b8b006da5bb Mon Sep 17 00:00:00 2001 From: koolkdev Date: Wed, 14 Feb 2024 23:52:58 +0200 Subject: [PATCH 16/17] remove dependency in boost-format --- src/block.cpp | 7 ------- src/block.h | 11 ----------- vcpkg.json | 1 - 3 files changed, 19 deletions(-) diff --git a/src/block.cpp b/src/block.cpp index eca7ea8..99d4a70 100644 --- a/src/block.cpp +++ b/src/block.cpp @@ -7,17 +7,10 @@ #include "block.h" -#include #include "device.h" #include "device_encryption.h" #include "utils.h" -Block::BadHash::BadHash(uint32_t block_number) - : block_number_(block_number), msg_((boost::format("Bad hash for block 0x%08X") % block_number_).str()) {} -char const* Block::BadHash::what() const noexcept { - return msg_.c_str(); -} - Block::Block(const std::shared_ptr& device, uint32_t block_number, Block::BlockSize size_category, diff --git a/src/block.h b/src/block.h index 68d7817..69fc79c 100644 --- a/src/block.h +++ b/src/block.h @@ -9,7 +9,6 @@ #include #include -#include #include #include @@ -52,16 +51,6 @@ class Block { bool encrypted() const { return encrypted_; } - class BadHash : public std::exception { - public: - BadHash(uint32_t block_number); - virtual char const* what() const noexcept override; - - private: - uint32_t block_number_; - std::string msg_; - }; - virtual void Resize(uint32_t data_size); private: diff --git a/vcpkg.json b/vcpkg.json index d038b25..bac0b6c 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -4,7 +4,6 @@ "dependencies": [ "boost-dynamic-bitset", "boost-endian", - "boost-format", "boost-iostreams", "cryptopp" ] From 2f55e43bcba5354dcf46f51d1d978351570f5612 Mon Sep 17 00:00:00 2001 From: koolkdev Date: Wed, 14 Feb 2024 23:53:34 +0200 Subject: [PATCH 17/17] use macos-13 instead of latest --- .github/workflows/build.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index be69459..c3906fe 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -6,7 +6,7 @@ jobs: build: strategy: matrix: - platform: [ubuntu-latest, windows-latest, macos-latest] + platform: [ubuntu-latest, windows-latest, macos-13] compiler: [msvc, gcc, llvm] exclude: - platform: windows-latest @@ -18,9 +18,9 @@ jobs: # llvm doesn't work with libstd++ until P2493R0 is done - platform: ubuntu-latest compiler: llvm - - platform: macos-latest + - platform: macos-13 compiler: msvc - - platform: macos-latest + - platform: macos-13 compiler: gcc runs-on: ${{matrix.platform}} @@ -67,7 +67,7 @@ jobs: echo "LDFLAGS=-L/usr/local/opt/llvm/lib" >> $GITHUB_ENV echo "CXXFLAGS=-isystem /usr/local/opt/llvm/include" >> $GITHUB_ENV shell: bash - if: matrix.platform == 'macos-latest' + if: matrix.platform == 'macos-13' - name: Run cmake uses: lukka/run-cmake@v10