diff --git a/include/wfslib/blocks_device.h b/include/wfslib/blocks_device.h index aedcb6b..4c08203 100644 --- a/include/wfslib/blocks_device.h +++ b/include/wfslib/blocks_device.h @@ -22,16 +22,19 @@ class BlocksDevice { BlocksDevice(const std::shared_ptr& device, const std::span& key); virtual void WriteBlock(uint32_t block_number, + uint32_t size_in_blocks, const std::span& data, const std::span& hash, uint32_t iv, - bool encrypt); + bool encrypt, + bool recalculate_hash); virtual bool ReadBlock(uint32_t block_number, + uint32_t size_in_blocks, const std::span& data, const std::span& hash, uint32_t iv, bool encrypt, - bool check_hash) const; + bool check_hash); const Device* device() const { return device_.get(); } diff --git a/include/wfslib/file_device.h b/include/wfslib/file_device.h index 8ecd377..8b9180a 100644 --- a/include/wfslib/file_device.h +++ b/include/wfslib/file_device.h @@ -16,7 +16,11 @@ class Wfs; class FileDevice : public Device { public: - FileDevice(const std::string& path, uint32_t log2_sector_size = 9 /* 512 */, bool read_only = true); + FileDevice(const std::string& path, + uint32_t log2_sector_size = 9 /* 512 */, + uint32_t sectors_count = 0, + bool read_only = true, + bool create = false); void ReadSectors(const std::span& data, uint32_t sector_address, uint32_t sectors_count) override; void WriteSectors(const std::span& data, uint32_t sector_address, uint32_t sectors_count) override; uint32_t SectorsCount() const override { return sectors_count_; } diff --git a/include/wfslib/wfs.h b/include/wfslib/wfs.h index ff91dcb..c1f538b 100644 --- a/include/wfslib/wfs.h +++ b/include/wfslib/wfs.h @@ -19,10 +19,12 @@ class Area; class WfsItem; class File; class Directory; +class BlocksDevice; class Wfs { public: Wfs(const std::shared_ptr& device, const std::span& key); + Wfs(const std::shared_ptr& device); ~Wfs(); const std::shared_ptr& GetDevice() { return device_; } diff --git a/include/wfslib/wfs_item.h b/include/wfslib/wfs_item.h index bbd67a2..11f5ebe 100644 --- a/include/wfslib/wfs_item.h +++ b/include/wfslib/wfs_item.h @@ -30,6 +30,7 @@ class WfsItem { virtual bool IsDirectory() const; virtual bool IsFile() const; virtual bool IsLink() const; + virtual bool IsQuota() const; protected: AttributesBlock& attributes_data() { return attributes_; } diff --git a/src/area.cpp b/src/area.cpp index 9c74805..31ffd9c 100644 --- a/src/area.cpp +++ b/src/area.cpp @@ -16,7 +16,6 @@ #include "utils.h" #include "wfs.h" - Area::Area(const std::shared_ptr& device, const std::shared_ptr& root_area, const std::shared_ptr& block, @@ -54,6 +53,14 @@ std::expected, WfsError> Area::GetRootDirectory() { root_directory_attributes_); } +std::expected, WfsError> Area::GetShadowDirectory1() { + return GetDirectory(as_const(this)->header()->shadow_directory_block_number_1.value(), ".shadow_dir_1", {}); +} + +std::expected, WfsError> Area::GetShadowDirectory2() { + return GetDirectory(as_const(this)->header()->shadow_directory_block_number_2.value(), ".shadow_dir_1", {}); +} + std::expected, WfsError> Area::GetArea(uint32_t block_number, const std::string& root_directory_name, const AttributesBlock& root_directory_attributes, diff --git a/src/area.h b/src/area.h index af13f06..7d0caa9 100644 --- a/src/area.h +++ b/src/area.h @@ -38,6 +38,9 @@ class Area : public std::enable_shared_from_this { std::expected, WfsError> GetRootDirectory(); + std::expected, WfsError> GetShadowDirectory1(); + std::expected, WfsError> GetShadowDirectory2(); + std::expected, WfsError> GetDirectory(uint32_t block_number, const std::string& name, const AttributesBlock& attributes); diff --git a/src/block.cpp b/src/block.cpp index db1a24c..5d042f9 100644 --- a/src/block.cpp +++ b/src/block.cpp @@ -43,13 +43,15 @@ void Block::Resize(uint32_t data_size) { } bool Block::Fetch(bool check_hash) { - return device_->ReadBlock(block_number_, data_, as_const(this)->Hash(), iv_, encrypted_, check_hash); + return device_->ReadBlock(block_number_, 1 << (size_category_ - BlockSize::Basic), data_, as_const(this)->Hash(), iv_, + encrypted_, check_hash); } void Block::Flush() { if (!dirty_) return; - device_->WriteBlock(block_number_, data_, Hash(), iv_, encrypted_); + device_->WriteBlock(block_number_, 1 << (size_category_ - BlockSize::Basic), data_, Hash(), iv_, encrypted_, + /*recalculate_hash=*/true); dirty_ = false; } diff --git a/src/blocks_device.cpp b/src/blocks_device.cpp index 490c30b..3c26981 100644 --- a/src/blocks_device.cpp +++ b/src/blocks_device.cpp @@ -16,20 +16,24 @@ BlocksDevice::BlocksDevice(const std::shared_ptr& device, const std::spa : device_(device), device_encryption_(std::make_unique(device, key)) {} void BlocksDevice::WriteBlock(uint32_t block_number, + uint32_t /*size_in_blocks*/, const std::span& data, const std::span& hash, uint32_t iv, - bool encrypt) { - device_encryption_->CalculateHash(data, hash); + bool encrypt, + bool recalculate_hash) { + if (recalculate_hash) + device_encryption_->CalculateHash(data, hash); device_encryption_->WriteBlock(ToDeviceSector(block_number), data, iv, encrypt); } bool BlocksDevice::ReadBlock(uint32_t block_number, + uint32_t /*size_in_blocks*/, const std::span& data, const std::span& hash, uint32_t iv, bool encrypt, - bool check_hash) const { + bool check_hash) { device_encryption_->ReadBlock(ToDeviceSector(block_number), data, iv, encrypt); return !check_hash || device_encryption_->CheckHash(data, hash); } diff --git a/src/file_device.cpp b/src/file_device.cpp index 282b21c..2e6935d 100644 --- a/src/file_device.cpp +++ b/src/file_device.cpp @@ -10,9 +10,16 @@ #include #include -FileDevice::FileDevice(const std::string& path, uint32_t log2_sector_size, bool read_only) - : file_(new std::fstream(path, std::ios::binary | (!read_only ? (std::ios::out | std::ios::in) : std::ios::in))), +FileDevice::FileDevice(const std::string& path, + uint32_t log2_sector_size, + uint32_t sectors_count, + bool read_only, + bool create) + : file_(new std::fstream( + path, + std::ios::binary | (!create ? std::ios::in : 0) | ((create || !read_only) ? std::ios::out : 0))), log2_sector_size_(log2_sector_size), + sectors_count_(sectors_count), read_only_(read_only) { if (file_->fail()) { throw std::runtime_error("FileDevice: Failed to open file"); @@ -29,8 +36,9 @@ FileDevice::FileDevice(const std::string& path, uint32_t log2_sector_size, bool sector size)"); } sectors_count_ = static_cast(file->tellg() >> log2_sector_size);*/ - sectors_count_ = 0x10; // we will find the exact sectors count later with - // Wfs::DetectSectorsCount + if (sectors_count_ == 0) + sectors_count_ = 0x10; // we will find the exact sectors count later with + // Wfs::DetectSectorsCount } void FileDevice::ReadSectors(const std::span& data, uint32_t sector_address, uint32_t sectors_count) { diff --git a/src/structs.h b/src/structs.h index 91858b2..40fbacc 100644 --- a/src/structs.h +++ b/src/structs.h @@ -83,6 +83,7 @@ struct Attributes { bool IsDirectory() const { return !!(flags.value() & Flags::DIRECTORY); } bool IsFile() const { return !IsDirectory(); } bool IsLink() const { return !!(flags.value() & Flags::LINK); } + bool IsQuota() const { return !!(flags.value() & Flags::QUOTA); } size_t DataOffset() const; diff --git a/src/wfs.cpp b/src/wfs.cpp index d99fa1c..6b56ee9 100644 --- a/src/wfs.cpp +++ b/src/wfs.cpp @@ -19,7 +19,9 @@ #include "structs.h" Wfs::Wfs(const std::shared_ptr& device, const std::span& key) - : device_(std::make_shared(device, key)) { + : Wfs(std::make_shared(device, key)) {} + +Wfs::Wfs(const std::shared_ptr& device) : device_(device) { // Read first area root_area_ = throw_if_error(Area::LoadRootArea(device_)); } diff --git a/src/wfs_item.cpp b/src/wfs_item.cpp index c01816c..1956df8 100644 --- a/src/wfs_item.cpp +++ b/src/wfs_item.cpp @@ -32,6 +32,10 @@ bool WfsItem::IsFile() const { } bool WfsItem::IsLink() const { + return attributes_data().Attributes()->IsLink(); +} + +bool WfsItem::IsQuota() const { auto attributes = attributes_data().Attributes(); - return attributes->IsLink(); + return attributes->IsDirectory() && attributes->IsQuota(); }