From fc2e994b72cf183577ec407d3712d8e787805f1d Mon Sep 17 00:00:00 2001 From: Maschell Date: Mon, 11 Oct 2021 22:02:35 +0200 Subject: [PATCH] Use shared_ptr/unique_ptr in combination with std::optional instead of raw pointers --- source/ApplicationState.cpp | 59 +++--- source/WUD/DefaultNUSDataProcessor.cpp | 38 ++-- source/WUD/DefaultNUSDataProcessor.h | 10 +- source/WUD/DiscReaderDiscDrive.cpp | 11 + source/WUD/DiscReaderDiscDrive.h | 2 + source/WUD/NUSDataProcessor.h | 4 +- source/WUD/NUSDataProvider.h | 12 +- source/WUD/NUSDataProviderWUD.cpp | 78 +++---- source/WUD/NUSDataProviderWUD.h | 22 +- source/WUD/NUSDecryption.cpp | 15 +- source/WUD/NUSDecryption.h | 7 +- source/WUD/NUSTitle.cpp | 107 +++++----- source/WUD/NUSTitle.h | 26 ++- source/WUD/Ticket.cpp | 43 +++- source/WUD/Ticket.h | 12 +- .../WUD/content/WiiUContentsInformation.cpp | 33 ++- source/WUD/content/WiiUContentsInformation.h | 16 +- source/WUD/content/WiiUDiscContentsHeader.cpp | 42 ++-- source/WUD/content/WiiUDiscContentsHeader.h | 17 +- .../content/partitions/WiiUDataPartition.cpp | 18 +- .../content/partitions/WiiUDataPartition.h | 8 +- .../content/partitions/WiiUGMPartition.cpp | 26 +-- .../WUD/content/partitions/WiiUGMPartition.h | 21 +- .../WUD/content/partitions/WiiUPartition.cpp | 67 +++--- source/WUD/content/partitions/WiiUPartition.h | 29 +-- .../WUD/content/partitions/WiiUPartitions.cpp | 191 ++++++++++-------- .../WUD/content/partitions/WiiUPartitions.h | 21 +- .../partitions/volumes/H3HashArray.cpp | 2 +- .../partitions/volumes/VolumeHeader.cpp | 137 ++++++++----- .../content/partitions/volumes/VolumeHeader.h | 29 ++- source/WUD/entities/FST/FST.cpp | 81 ++++++-- source/WUD/entities/FST/FST.h | 23 ++- source/WUD/entities/FST/header/FSTHeader.cpp | 31 ++- source/WUD/entities/FST/header/FSTHeader.h | 12 +- .../entities/FST/nodeentry/DirectoryEntry.cpp | 81 +++++--- .../entities/FST/nodeentry/DirectoryEntry.h | 31 ++- .../WUD/entities/FST/nodeentry/FileEntry.cpp | 52 +++-- source/WUD/entities/FST/nodeentry/FileEntry.h | 16 +- .../entities/FST/nodeentry/NodeEntries.cpp | 65 +++--- .../WUD/entities/FST/nodeentry/NodeEntries.h | 32 ++- .../WUD/entities/FST/nodeentry/NodeEntry.cpp | 104 +++++++--- source/WUD/entities/FST/nodeentry/NodeEntry.h | 39 ++-- .../entities/FST/nodeentry/NodeEntryParam.h | 2 +- .../WUD/entities/FST/nodeentry/RootEntry.cpp | 47 +++-- source/WUD/entities/FST/nodeentry/RootEntry.h | 14 +- .../FST/sectionentry/SectionEntries.cpp | 34 +++- .../FST/sectionentry/SectionEntries.h | 18 +- .../FST/sectionentry/SectionEntry.cpp | 4 +- .../entities/FST/sectionentry/SectionEntry.h | 5 +- .../entities/FST/stringtable/StringEntry.cpp | 9 +- .../entities/FST/stringtable/StringEntry.h | 8 +- .../entities/FST/stringtable/StringTable.cpp | 35 +++- .../entities/FST/stringtable/StringTable.h | 23 +-- source/WUD/entities/TMD/Content.cpp | 25 ++- source/WUD/entities/TMD/Content.h | 15 +- source/WUD/entities/TMD/TitleMetaData.cpp | 49 +++-- source/WUD/entities/TMD/TitleMetaData.h | 12 +- source/WUD/header/WiiUDiscHeader.cpp | 56 +++-- source/WUD/header/WiiUDiscHeader.h | 24 ++- source/WUD/header/WiiUDiscId.cpp | 54 +++++ .../WUD/header/{WiiUDiscID.h => WiiUDiscId.h} | 18 +- source/WUD/header/WiiUManufactorDiscID.cpp | 26 --- ...iiUDiscID.cpp => WiiUManufactorDiscId.cpp} | 36 ++-- ...ufactorDiscID.h => WiiUManufactorDiscId.h} | 13 +- source/utils/FSTUtils.cpp | 40 ++-- source/utils/FSTUtils.h | 22 +- source/utils/blocksize/AddressInBlocks.h | 4 +- 67 files changed, 1410 insertions(+), 853 deletions(-) create mode 100644 source/WUD/header/WiiUDiscId.cpp rename source/WUD/header/{WiiUDiscID.h => WiiUDiscId.h} (71%) delete mode 100644 source/WUD/header/WiiUManufactorDiscID.cpp rename source/WUD/header/{WiiUDiscID.cpp => WiiUManufactorDiscId.cpp} (54%) rename source/WUD/header/{WiiUManufactorDiscID.h => WiiUManufactorDiscId.h} (69%) diff --git a/source/ApplicationState.cpp b/source/ApplicationState.cpp index 352b839..557e21a 100644 --- a/source/ApplicationState.cpp +++ b/source/ApplicationState.cpp @@ -22,6 +22,7 @@ #include #include #include +#include extern ntfs_md *ntfs_mounts; extern int ntfs_mount_count; @@ -704,32 +705,36 @@ void ApplicationState::printDumpState(const char *fmt, ...) { void ApplicationState::dumpAppFiles() { uint8_t opt[0x400]; IOSUHAX_read_otp(opt, 0x400); - uint8_t cKey[0x10]; - memcpy(cKey, opt + 0xE0, 0x10); + std::array cKey{}; + memcpy(cKey.data(), opt + 0xE0, 0x10); DEBUG_FUNCTION_LINE("Reading Partitions"); printDumpState("Reading Partitions..."); - auto discReader = new DiscReaderDiscDrive(); + auto discReader = std::make_shared(); if (!discReader->IsReady()) { DEBUG_FUNCTION_LINE("!IsReady"); this->setError(ERROR_OPEN_ODD1); - delete discReader; return; } DEBUG_FUNCTION_LINE("Read DiscHeader"); - auto *discHeader = new WiiUDiscHeader(discReader); + auto discHeader = WiiUDiscHeader::make_unique(discReader); + if (!discHeader.has_value()) { + DEBUG_FUNCTION_LINE("Failed to read discheader"); + return; + } bool forceExit = false; - for (auto &partition: discHeader->wiiUContentsInformation->partitions->partitions) { - auto gmPartition = dynamic_cast(partition); + for (auto &partition: discHeader.value()->wiiUContentsInformation->partitions->partitions) { + auto gmPartition = std::dynamic_pointer_cast(partition); if (gmPartition != nullptr) { - auto *nusTitle = NUSTitle::loadTitleFromGMPartition(gmPartition, discReader, cKey); - if (nusTitle == nullptr) { + auto nusTitleOpt = NUSTitle::loadTitleFromGMPartition(gmPartition, discReader, cKey); + if (!nusTitleOpt.has_value()) { DEBUG_FUNCTION_LINE("nusTitle was null"); continue; } - auto *dataProvider = nusTitle->dataProcessor->getDataProvider(); + auto nusTitle = nusTitleOpt.value(); + auto dataProvider = nusTitle->dataProcessor->getDataProvider(); uint64_t partitionSize = 0; uint64_t partitionSizeWritten = 0; @@ -745,26 +750,26 @@ void ApplicationState::dumpAppFiles() { snprintf(buffer, 500, "%swudump/%s/%s", target.c_str(), this->discId, gmPartition->getVolumeId().c_str()); FSUtils::CreateSubfolder(buffer); - uint8_t *wBuffer = nullptr; - uint32_t wBufferLen = 0; - if (dataProvider->getRawTMD(&wBuffer, &wBufferLen)) { + std::vector wBuffer; + if (dataProvider->getRawTMD(wBuffer)) { std::string fileName = std::string(buffer).append("/").append(WUD_TMD_FILENAME); printDumpState("%s\nSaving %s", partitionDumpInfo.c_str(), WUD_TMD_FILENAME); - FSUtils::saveBufferToFile(fileName.c_str(), wBuffer, wBufferLen); - free(wBuffer); + FSUtils::saveBufferToFile(fileName.c_str(), wBuffer.data(), wBuffer.size()); + wBuffer.clear(); } - if (dataProvider->getRawTicket(&wBuffer, &wBufferLen)) { + if (dataProvider->getRawTicket(wBuffer)) { std::string fileName = std::string(buffer).append("/").append(WUD_TICKET_FILENAME); printDumpState("%s\nSaving %s", partitionDumpInfo.c_str(), WUD_TICKET_FILENAME); - FSUtils::saveBufferToFile(fileName.c_str(), wBuffer, wBufferLen); - free(wBuffer); + FSUtils::saveBufferToFile(fileName.c_str(), wBuffer.data(), wBuffer.size()); + wBuffer.clear(); } - if (dataProvider->getRawCert(&wBuffer, &wBufferLen)) { + + if (dataProvider->getRawCert(wBuffer)) { std::string fileName = std::string(buffer).append("/").append(WUD_TICKET_FILENAME); printDumpState("%s\nSaving %s", partitionDumpInfo.c_str(), WUD_CERT_FILENAME); - FSUtils::saveBufferToFile(fileName.c_str(), wBuffer, wBufferLen); - free(wBuffer); + FSUtils::saveBufferToFile(fileName.c_str(), wBuffer.data(), wBuffer.size()); + wBuffer.clear(); } auto contentCount = nusTitle->tmd->contentList.size(); @@ -836,26 +841,20 @@ void ApplicationState::dumpAppFiles() { break; } - uint8_t *h3Data = nullptr; - uint32_t h3Length = 0; - if (dataProvider->getContentH3Hash(content, &h3Data, &h3Length)) { + std::vector h3Data; + if (dataProvider->getContentH3Hash(content, h3Data)) { char bufh3[32]; snprintf(bufh3, 31, "%08X.h3", content->ID); std::string h3FileName = std::string(buffer) + "/" + bufh3; printDumpState("%s\n%s", partitionDumpInfo.c_str(), contentDumpInfo.c_str()); - FSUtils::saveBufferToFile(h3FileName.c_str(), h3Data, h3Length); + FSUtils::saveBufferToFile(h3FileName.c_str(), h3Data.data(), h3Data.size()); } contentI++; } - - delete nusTitle; - if (forceExit) { exit(0); break; } } } - delete discHeader; - delete discReader; } diff --git a/source/WUD/DefaultNUSDataProcessor.cpp b/source/WUD/DefaultNUSDataProcessor.cpp index 8f61974..9ec0f66 100644 --- a/source/WUD/DefaultNUSDataProcessor.cpp +++ b/source/WUD/DefaultNUSDataProcessor.cpp @@ -16,45 +16,45 @@ ****************************************************************************/ #include "DefaultNUSDataProcessor.h" -bool DefaultNUSDataProcessor::readPlainDecryptedContent(Content *pContent, uint8_t **data, uint32_t *length) { - if (pContent == nullptr || data == nullptr || length == nullptr) { - return false; - } +bool DefaultNUSDataProcessor::readPlainDecryptedContent(const std::shared_ptr &pContent, std::vector &out_data) { if ((pContent->type & 0x0002) == 0x0002) { DEBUG_FUNCTION_LINE("Hashed content not supported yet"); return false; } + auto contentSize = ROUNDUP(pContent->encryptedFileSize, 16); + out_data.resize(contentSize); - *length = ROUNDUP(pContent->encryptedFileSize, 16); - *data = (uint8_t *) malloc(*length); - if (*data == nullptr) { + auto *inData = (uint8_t *) malloc(contentSize); + if (inData == nullptr) { + DEBUG_FUNCTION_LINE("Failed to alloc"); return false; } - auto *inData = (uint8_t *) malloc(*length); - - if (!dataProvider->readRawContent(pContent, inData, 0, *length)) { - free(*data); + if (!dataProvider->readRawContent(pContent, inData, 0, contentSize)) { + DEBUG_FUNCTION_LINE("Failed tor read content"); free(inData); return false; } - uint8_t IV[16]; - memset(IV, 0, 16); + std::array IV{}; + memset(IV.data(), 0, 16); uint16_t content_index = pContent->index; - memcpy(IV, &content_index, 2); + memcpy(IV.data(), &content_index, 2); - nusDecryption->decryptData(IV, inData, *data, *length); + nusDecryption->decryptData(IV, inData, out_data.data(), contentSize); free(inData); return true; } -NUSDataProvider *DefaultNUSDataProcessor::getDataProvider() { +std::shared_ptr DefaultNUSDataProcessor::getDataProvider() { return dataProvider; } -DefaultNUSDataProcessor::DefaultNUSDataProcessor(NUSDataProvider *pDataProvider, NUSDecryption *pNUSDecryption) { - dataProvider = pDataProvider; - nusDecryption = pNUSDecryption; +DefaultNUSDataProcessor::DefaultNUSDataProcessor( + std::shared_ptr pDataProvider, + std::shared_ptr pNUSDecryption) : + dataProvider(std::move(pDataProvider)), + nusDecryption(std::move(pNUSDecryption)) { + DEBUG_FUNCTION_LINE(); } diff --git a/source/WUD/DefaultNUSDataProcessor.h b/source/WUD/DefaultNUSDataProcessor.h index f2f8197..94b9ff8 100644 --- a/source/WUD/DefaultNUSDataProcessor.h +++ b/source/WUD/DefaultNUSDataProcessor.h @@ -21,15 +21,15 @@ class DefaultNUSDataProcessor : public NUSDataProcessor { public: - DefaultNUSDataProcessor(NUSDataProvider *pDataProvider, NUSDecryption *pNUSDecryption); + DefaultNUSDataProcessor(std::shared_ptr pDataProvider, std::shared_ptr pNUSDecryption); ~DefaultNUSDataProcessor() override = default; - bool readPlainDecryptedContent(Content *pContent, uint8_t **data, uint32_t *length) override; + bool readPlainDecryptedContent(const std::shared_ptr &pContent, std::vector &out_data) override; - NUSDataProvider *getDataProvider() override; + std::shared_ptr getDataProvider() override; private: - NUSDataProvider *dataProvider; - NUSDecryption *nusDecryption; + std::shared_ptr dataProvider; + std::shared_ptr nusDecryption; }; diff --git a/source/WUD/DiscReaderDiscDrive.cpp b/source/WUD/DiscReaderDiscDrive.cpp index 811d262..07e8983 100644 --- a/source/WUD/DiscReaderDiscDrive.cpp +++ b/source/WUD/DiscReaderDiscDrive.cpp @@ -24,6 +24,7 @@ DiscReaderDiscDrive::DiscReaderDiscDrive() : DiscReader() { + DEBUG_FUNCTION_LINE(); auto *sector_buf = (uint8_t *) malloc(READ_SECTOR_SIZE); if (sector_buf == nullptr) { return; @@ -75,6 +76,7 @@ bool DiscReaderDiscDrive::IsReady() { } DiscReaderDiscDrive::~DiscReaderDiscDrive() { + DEBUG_FUNCTION_LINE(); if (device_handle != -1) { IOSUHAX_FSA_RawOpen(gFSAfd, "/dev/odd01", &device_handle); } @@ -95,3 +97,12 @@ bool DiscReaderDiscDrive::readEncrypted(uint8_t *buf, uint64_t offset, uint32_t } return true; } + +std::optional DiscReaderDiscDrive::Create() { + auto discReader = new DiscReaderDiscDrive(); + if (!discReader->IsReady()) { + delete discReader; + return {}; + } + return discReader; +} diff --git a/source/WUD/DiscReaderDiscDrive.h b/source/WUD/DiscReaderDiscDrive.h index 02f1242..3dc4d8c 100644 --- a/source/WUD/DiscReaderDiscDrive.h +++ b/source/WUD/DiscReaderDiscDrive.h @@ -25,6 +25,8 @@ public: ~DiscReaderDiscDrive() override; + static std::optional Create(); + bool readEncryptedSector(uint8_t *buffer, uint32_t block_cnt, uint64_t offset_in_sector) const override; bool IsReady() override; diff --git a/source/WUD/NUSDataProcessor.h b/source/WUD/NUSDataProcessor.h index 7985de2..5ce9c01 100644 --- a/source/WUD/NUSDataProcessor.h +++ b/source/WUD/NUSDataProcessor.h @@ -10,7 +10,7 @@ protected: public: virtual ~NUSDataProcessor() = default; - virtual NUSDataProvider *getDataProvider() = 0; + virtual std::shared_ptr getDataProvider() = 0; - virtual bool readPlainDecryptedContent(Content *pContent, uint8_t **data, uint32_t *length) = 0; + virtual bool readPlainDecryptedContent(const std::shared_ptr &pContent, std::vector &out_data) = 0; }; \ No newline at end of file diff --git a/source/WUD/NUSDataProvider.h b/source/WUD/NUSDataProvider.h index 9d484bc..2e2be7a 100644 --- a/source/WUD/NUSDataProvider.h +++ b/source/WUD/NUSDataProvider.h @@ -25,17 +25,17 @@ class NUSDataProvider { public: virtual ~NUSDataProvider() = default; - virtual bool readRawContent(Content *content, uint8_t *buffer, uint64_t offset, uint32_t size) = 0; + virtual bool readRawContent(const std::shared_ptr &content, uint8_t *buffer, uint64_t offset, uint32_t size) = 0; - virtual bool getContentH3Hash(Content *content, uint8_t **data, uint32_t *size) = 0; + virtual bool getContentH3Hash(const std::shared_ptr &content, std::vector &out_data) = 0; - virtual bool getRawTMD(uint8_t **data, uint32_t *size) = 0; + virtual bool getRawTMD(std::vector &out_data) = 0; - virtual bool getRawTicket(uint8_t **data, uint32_t *size) = 0; + virtual bool getRawTicket(std::vector &out_data) = 0; - virtual bool getRawCert(uint8_t **data, uint32_t *size) = 0; + virtual bool getRawCert(std::vector &out_data) = 0; - virtual void setFST(FST *fst) { + virtual void setFST(const std::shared_ptr &fst) { } }; \ No newline at end of file diff --git a/source/WUD/NUSDataProviderWUD.cpp b/source/WUD/NUSDataProviderWUD.cpp index 0427e4f..81a81ea 100644 --- a/source/WUD/NUSDataProviderWUD.cpp +++ b/source/WUD/NUSDataProviderWUD.cpp @@ -16,41 +16,40 @@ ****************************************************************************/ #include "NUSDataProviderWUD.h" -NUSDataProviderWUD::NUSDataProviderWUD(WiiUGMPartition *pGamePartition, DiscReader *pDiscReader) { +NUSDataProviderWUD::NUSDataProviderWUD(const std::shared_ptr &pGamePartition, const std::shared_ptr &pDiscReader) { + DEBUG_FUNCTION_LINE(); gamePartition = pGamePartition; discReader = pDiscReader; } NUSDataProviderWUD::~NUSDataProviderWUD() { - delete fst; + DEBUG_FUNCTION_LINE(); } -bool NUSDataProviderWUD::readRawContent(Content *content, uint8_t *buffer, uint64_t offset, uint32_t size) { +bool NUSDataProviderWUD::readRawContent(const std::shared_ptr &content, uint8_t *buffer, uint64_t offset, uint32_t size) { if (buffer == nullptr) { - DEBUG_FUNCTION_LINE(); return false; } - auto offsetInWUD = getOffsetInWUD(content) + offset; + auto offsetInWUDOpt = getOffsetInWUD(content); + if (!offsetInWUDOpt.has_value()) { + return false; + } + auto offsetInWUD = offsetInWUDOpt.value() + offset; return discReader->readEncrypted(buffer, offsetInWUD, size); } -bool NUSDataProviderWUD::getContentH3Hash(Content *content, uint8_t **data, uint32_t *size) { - if (content == nullptr || data == nullptr || size == nullptr) { - DEBUG_FUNCTION_LINE(); - return false; - } +bool NUSDataProviderWUD::getContentH3Hash(const std::shared_ptr &content, std::vector &out_data) { auto cur = gamePartition->getVolumes().begin()->second->h3HashArrayList[content->index]; if (cur == nullptr || cur->size == 0) { DEBUG_FUNCTION_LINE(); return false; } - *data = (uint8_t *) malloc(cur->size); - *size = cur->size; - memcpy(*data, cur->data, *size); + out_data.resize(cur->size); + memcpy(out_data.data(), cur->data, cur->size); return true; } -void NUSDataProviderWUD::setFST(FST *pFST) { +void NUSDataProviderWUD::setFST(const std::shared_ptr &pFST) { // We need to set the correct blocksizes auto blockSize = gamePartition->getVolumes().begin()->second->blockSize; for (const auto &e: pFST->sectionEntries->getSections()) { @@ -60,55 +59,30 @@ void NUSDataProviderWUD::setFST(FST *pFST) { fst = pFST; } -bool NUSDataProviderWUD::getRawCert(uint8_t **data, uint32_t *size) { - if (data == nullptr || size == nullptr) { - return false; - } - *data = (uint8_t *) malloc(gamePartition->certLen); - if (*data == nullptr) { - return false; - } - *size = gamePartition->certLen; - memcpy(*data, gamePartition->rawCert, gamePartition->certLen); +bool NUSDataProviderWUD::getRawCert(std::vector &out_data) { + out_data = gamePartition->rawCert; return true; } -bool NUSDataProviderWUD::getRawTicket(uint8_t **data, uint32_t *size) { - if (data == nullptr || size == nullptr) { - return false; - } - *data = (uint8_t *) malloc(gamePartition->tikLen); - if (*data == nullptr) { - return false; - } - *size = gamePartition->tikLen; - memcpy(*data, gamePartition->rawTicket, gamePartition->tikLen); +bool NUSDataProviderWUD::getRawTicket(std::vector &out_data) { + out_data = gamePartition->rawTicket; return true; } -bool NUSDataProviderWUD::getRawTMD(uint8_t **data, uint32_t *size) { - if (data == nullptr || size == nullptr) { - DEBUG_FUNCTION_LINE("input was null"); - return false; - } - *data = (uint8_t *) malloc(gamePartition->TMDLen); - if (*data == nullptr) { - DEBUG_FUNCTION_LINE("Failed to alloc memory"); - return false; - } - *size = gamePartition->TMDLen; - memcpy(*data, gamePartition->rawTMD, gamePartition->TMDLen); +bool NUSDataProviderWUD::getRawTMD(std::vector &out_data) { + out_data = gamePartition->rawTMD; return true; } -uint64_t NUSDataProviderWUD::getOffsetInWUD(Content *content) const { +std::optional NUSDataProviderWUD::getOffsetInWUD(const std::shared_ptr &content) const { if (content->index == 0) { // Index 0 is the FST which is at the beginning of the partition; - auto *vh = gamePartition->getVolumes().begin()->second; + auto vh = gamePartition->getVolumes().begin()->second; return gamePartition->getSectionOffsetOnDefaultPartition() + vh->FSTAddress.getAddressInBytes(); } - auto *info = FSTUtils::getSectionEntryForIndex(fst, content->index); - if (info == nullptr) { - OSFatal("Failed to get section for Content"); + auto info = FSTUtils::getSectionEntryForIndex(fst, content->index); + if (!info.has_value()) { + DEBUG_FUNCTION_LINE("Failed to get section for Content"); + return {}; } - return gamePartition->getSectionOffsetOnDefaultPartition() + info->address.getAddressInBytes(); + return gamePartition->getSectionOffsetOnDefaultPartition() + info.value()->address.getAddressInBytes(); } diff --git a/source/WUD/NUSDataProviderWUD.h b/source/WUD/NUSDataProviderWUD.h index 9a0b7cd..d5dc49c 100644 --- a/source/WUD/NUSDataProviderWUD.h +++ b/source/WUD/NUSDataProviderWUD.h @@ -25,26 +25,26 @@ class NUSDataProviderWUD : public NUSDataProvider { public: - NUSDataProviderWUD(WiiUGMPartition *pGamePartition, DiscReader *pDiscReader); + NUSDataProviderWUD(const std::shared_ptr &pPartition, const std::shared_ptr &pDrive); ~NUSDataProviderWUD() override; - bool readRawContent(Content *content, uint8_t *buffer, uint64_t offset, uint32_t size) override; + bool readRawContent(const std::shared_ptr &content, uint8_t *buffer, uint64_t offset, uint32_t size) override; - bool getContentH3Hash(Content *content, uint8_t **data, uint32_t *size) override; + bool getContentH3Hash(const std::shared_ptr &content, std::vector &out_data) override; - void setFST(FST *pFST) override; + void setFST(const std::shared_ptr &pFST) override; - bool getRawCert(uint8_t **data, uint32_t *size) override; + bool getRawCert(std::vector &out_data) override; - bool getRawTicket(uint8_t **data, uint32_t *size) override; + bool getRawTicket(std::vector &data) override; - bool getRawTMD(uint8_t **data, uint32_t *size) override; + bool getRawTMD(std::vector &out_data) override; - FST *fst{}; - WiiUGMPartition *gamePartition; - DiscReader *discReader; + std::shared_ptr fst; + std::shared_ptr gamePartition; + std::shared_ptr discReader; private: - uint64_t getOffsetInWUD(Content *content) const; + [[nodiscard]] std::optional getOffsetInWUD(const std::shared_ptr &content) const; }; \ No newline at end of file diff --git a/source/WUD/NUSDecryption.cpp b/source/WUD/NUSDecryption.cpp index a6aa7e6..83b772b 100644 --- a/source/WUD/NUSDecryption.cpp +++ b/source/WUD/NUSDecryption.cpp @@ -16,11 +16,14 @@ ****************************************************************************/ #include "NUSDecryption.h" -void NUSDecryption::decryptData(uint8_t *IV, uint8_t *inData, uint8_t *outData, uint32_t size) const { - aes_set_key(ticket->ticketKeyDec); - aes_decrypt(IV, inData, outData, size); +#include +#include + +void NUSDecryption::decryptData(const std::array &IV, uint8_t *inData, uint8_t *outData, uint32_t size) const { + aes_set_key(ticket->ticketKeyDec.data()); + aes_decrypt((uint8_t *) IV.data(), inData, outData, size); } -NUSDecryption::NUSDecryption(Ticket *pTicket) { - ticket = pTicket; -} +NUSDecryption::NUSDecryption(std::shared_ptr pTicket) : ticket(std::move(pTicket)) { + DEBUG_FUNCTION_LINE(); +} \ No newline at end of file diff --git a/source/WUD/NUSDecryption.h b/source/WUD/NUSDecryption.h index b1354e9..a23bbea 100644 --- a/source/WUD/NUSDecryption.h +++ b/source/WUD/NUSDecryption.h @@ -17,12 +17,13 @@ #pragma once #include "Ticket.h" +#include class NUSDecryption { public: - explicit NUSDecryption(Ticket *pTicket); + explicit NUSDecryption(std::shared_ptr pTicket); - void decryptData(uint8_t *IV, uint8_t *inData, uint8_t *outData, uint32_t size) const; + void decryptData(const std::array &IV, uint8_t *inData, uint8_t *outData, uint32_t size) const; - Ticket *ticket; + std::shared_ptr ticket; }; diff --git a/source/WUD/NUSTitle.cpp b/source/WUD/NUSTitle.cpp index 580d94d..fc45306 100644 --- a/source/WUD/NUSTitle.cpp +++ b/source/WUD/NUSTitle.cpp @@ -16,68 +16,81 @@ ****************************************************************************/ #include "NUSTitle.h" -NUSTitle *NUSTitle::loadTitle(NUSDataProvider *dataProvider, uint8_t *commonKey) { - uint8_t *data = nullptr; - uint32_t dataLen = 0; - if (!dataProvider->getRawTMD(&data, &dataLen)) { +#include + +std::optional> NUSTitle::loadTitle(const std::shared_ptr &dataProvider, const std::array &commonKey) { + std::vector dataBuffer; + if (!dataProvider->getRawTMD(dataBuffer)) { DEBUG_FUNCTION_LINE("Failed to read TMD"); - delete dataProvider; - return nullptr; + return {}; } - auto *tmd = new TitleMetaData(data); - free(data); + auto tmdOpt = TitleMetaData::make_shared(dataBuffer); + if (!tmdOpt.has_value()) { + DEBUG_FUNCTION_LINE("Failed to parse TMD"); + return {}; + } + dataBuffer.clear(); - if (!dataProvider->getRawTicket(&data, &dataLen)) { - DEBUG_FUNCTION_LINE("Failed to read ticket"); - delete tmd; - delete dataProvider; - return nullptr; + if (!dataProvider->getRawTicket(dataBuffer)) { + DEBUG_FUNCTION_LINE("Failed to read ticket data"); + return {}; } - auto *ticket = new Ticket(data, commonKey); - free(data); - auto *decryption = new NUSDecryption(ticket); - auto *dpp = new DefaultNUSDataProcessor(dataProvider, decryption); + auto ticketOpt = Ticket::make_shared(dataBuffer, commonKey); + if (!ticketOpt.has_value()) { + DEBUG_FUNCTION_LINE("Failed to parse ticket"); + return {}; + } + + dataBuffer.clear(); + auto decryption = std::make_shared(std::move(ticketOpt.value())); + auto dpp = std::shared_ptr(new DefaultNUSDataProcessor(dataProvider, decryption)); // If we have more than one content, the index 0 is the FST. - Content *fstContent = tmd->getContentByIndex(0); - - if (!dpp->readPlainDecryptedContent(fstContent, &data, &dataLen)) { - DEBUG_FUNCTION_LINE("Failed to read decrypted content"); - delete dataProvider; - delete dpp; - delete decryption; - delete ticket; - delete tmd; - return nullptr; + auto fstContentOpt = tmdOpt.value()->getContentByIndex(0); + if (!fstContentOpt.has_value()) { + DEBUG_FUNCTION_LINE("Failed to get content for index 0"); + return {}; + } + + if (!dpp->readPlainDecryptedContent(fstContentOpt.value(), dataBuffer)) { + DEBUG_FUNCTION_LINE("Failed to read decrypted content"); + return {}; + } + auto fstOpt = FST::make_shared(dataBuffer, 0, VolumeBlockSize(1)); + + if (!fstOpt.has_value()) { + DEBUG_FUNCTION_LINE(); + return {}; } - FST *fst = new FST(data, dataLen, 0, VolumeBlockSize(1)); // The dataprovider may need the FST to calculate the offset of a content // on the partition. - dataProvider->setFST(fst); - - return new NUSTitle(tmd, dpp, dataProvider, decryption, ticket, fst); + dataProvider->setFST(fstOpt.value()); + return std::shared_ptr(new NUSTitle(tmdOpt.value(), dpp, dataProvider, decryption, ticketOpt.value(), fstOpt.value())); } -NUSTitle::NUSTitle(TitleMetaData *pTMD, NUSDataProcessor *pProcessor, NUSDataProvider *pDataProvider, NUSDecryption *pDecryption, Ticket *pTicket, FST *pFST) { - tmd = pTMD; - dataProcessor = pProcessor; - ticket = pTicket; - fst = pFST; - decryption = pDecryption; - dataProvider = pDataProvider; +NUSTitle::NUSTitle(std::shared_ptr pTMD, + std::shared_ptr pProcessor, + std::shared_ptr pDataProvider, + std::shared_ptr pDecryption, + std::shared_ptr pTicket, + std::shared_ptr pFST) : + + dataProcessor(std::move(pProcessor)), + tmd(std::move(pTMD)), + ticket(std::move(pTicket)), + fst(std::move(pFST)), + decryption(std::move(pDecryption)), + dataProvider(std::move(pDataProvider)) { + } -NUSTitle::~NUSTitle() { - delete dataProvider; - delete dataProcessor; - delete decryption; - delete ticket; - delete tmd; +std::optional> +NUSTitle::loadTitleFromGMPartition(const std::shared_ptr &pPartition, const std::shared_ptr &pDrive, const std::array &commonKey) { + DEBUG_FUNCTION_LINE(); + return loadTitle(std::shared_ptr(new NUSDataProviderWUD(pPartition, pDrive)), commonKey); } -NUSTitle *NUSTitle::loadTitleFromGMPartition(WiiUGMPartition *pPartition, DiscReaderDiscDrive *pDrive, uint8_t *commonKey) { - return loadTitle(new NUSDataProviderWUD(pPartition, pDrive), commonKey); -} +NUSTitle::~NUSTitle() = default; diff --git a/source/WUD/NUSTitle.h b/source/WUD/NUSTitle.h index 5b304d5..43eef28 100644 --- a/source/WUD/NUSTitle.h +++ b/source/WUD/NUSTitle.h @@ -31,18 +31,26 @@ class NUSTitle { public: ~NUSTitle(); - NUSDataProcessor *dataProcessor; - TitleMetaData *tmd; - Ticket *ticket; - FST *fst; - NUSDecryption *decryption; - NUSDataProvider *dataProvider; + std::shared_ptr dataProcessor; + std::shared_ptr tmd; + std::shared_ptr ticket; + std::shared_ptr fst; + std::shared_ptr decryption; + std::shared_ptr dataProvider; - static NUSTitle *loadTitleFromGMPartition(WiiUGMPartition *pPartition, DiscReaderDiscDrive *pDrive, uint8_t commonKey[16]); + static std::optional> loadTitleFromGMPartition( + const std::shared_ptr &pPartition, + const std::shared_ptr &pDrive, + const std::array &commonKey); private: - static NUSTitle *loadTitle(NUSDataProvider *dataProvider, uint8_t commonKey[16]); + static std::optional> loadTitle(const std::shared_ptr &dataProvider, const std::array &commonKey); - NUSTitle(TitleMetaData *pTMD, NUSDataProcessor *pProcessor, NUSDataProvider *pDataProvider, NUSDecryption *pDecryption, Ticket *pTicket, FST *pFST); + NUSTitle(std::shared_ptr pTMD, + std::shared_ptr pProcessor, + std::shared_ptr pDataProvider, + std::shared_ptr pDecryption, + std::shared_ptr pTicket, + std::shared_ptr pFST); }; \ No newline at end of file diff --git a/source/WUD/Ticket.cpp b/source/WUD/Ticket.cpp index 842a3d0..4877558 100644 --- a/source/WUD/Ticket.cpp +++ b/source/WUD/Ticket.cpp @@ -15,19 +15,40 @@ * along with this program. If not, see . ****************************************************************************/ #include "Ticket.h" +#include +#include -Ticket::Ticket(uint8_t *data, uint8_t *commonKey) { - uint8_t *tikKeyEnc = data + 0x1BF; - uint8_t *title_id = data + 0x1DC; - uint8_t IV[0x10]; +Ticket::Ticket(const std::array &pEncryptedKey, const std::array &pDecryptedKey) : + ticketKeyEnc(pEncryptedKey), + ticketKeyDec(pDecryptedKey) { + DEBUG_FUNCTION_LINE(); - int k; - for (k = 0; k < 8; k++) { - IV[k] = title_id[k]; - IV[k + 8] = 0x00; +} + +std::optional> Ticket::make_shared(const std::vector &data, std::optional> commonKey) { + if (data.size() <= 0x1DC + 0x10) { + DEBUG_FUNCTION_LINE("Not enough data to parse a ticket"); + return {}; } - aes_set_key(commonKey); - aes_decrypt(IV, tikKeyEnc, ticketKeyDec, 16); - memcpy(ticketKeyEnc, tikKeyEnc, 16); + std::array title_id{}; + std::array decryptedKey{}; + std::array encryptedKey{}; + + std::copy_n(data.begin() + 0x1BF, 0x10, decryptedKey.begin()); + std::copy_n(data.begin() + 0x1BF, 0x10, encryptedKey.begin()); + std::copy_n(data.begin() + 0x1DC, 0x10, title_id.begin()); + + uint8_t IV[0x10]; + for (int i = 0; i < 8; i++) { + IV[i] = title_id[i]; + IV[i + 8] = 0x00; + } + + if (commonKey.has_value()) { + aes_set_key((uint8_t *) commonKey.value().data()); + aes_decrypt(IV, encryptedKey.data(), decryptedKey.data(), 16); + } + + return std::shared_ptr(new Ticket(encryptedKey, decryptedKey)); } diff --git a/source/WUD/Ticket.h b/source/WUD/Ticket.h index d4dbd7f..d8dd624 100644 --- a/source/WUD/Ticket.h +++ b/source/WUD/Ticket.h @@ -19,11 +19,17 @@ #include #include #include +#include +#include +#include class Ticket { public: - Ticket(uint8_t *data, uint8_t commonKey[16]); + std::array ticketKeyEnc; + std::array ticketKeyDec; - uint8_t ticketKeyEnc[16]{}; - uint8_t ticketKeyDec[16]{}; + static std::optional> make_shared(const std::vector &data, std::optional> commonKey); + +private: + Ticket(const std::array &encryptedKey, const std::array &decryptedKey); }; \ No newline at end of file diff --git a/source/WUD/content/WiiUContentsInformation.cpp b/source/WUD/content/WiiUContentsInformation.cpp index 77108ff..26b1b6d 100644 --- a/source/WUD/content/WiiUContentsInformation.cpp +++ b/source/WUD/content/WiiUContentsInformation.cpp @@ -19,20 +19,37 @@ uint32_t WiiUContentsInformation::LENGTH = 32768; -WiiUContentsInformation::WiiUContentsInformation(DiscReader *reader, uint32_t offset) { +std::optional> WiiUContentsInformation::make_unique(const std::shared_ptr &discReader, uint32_t offset) { uint32_t curOffset = offset; - discContentHeader = new WiiUDiscContentsHeader(reader, curOffset); + auto discContentHeaderOpt = WiiUDiscContentsHeader::make_unique(discReader, curOffset); + if (!discContentHeaderOpt.has_value()) { + DEBUG_FUNCTION_LINE("Failed to read WiiUDiscContentsHeader"); + return {}; + } curOffset += WiiUDiscContentsHeader::LENGTH; - partitions = new WiiUPartitions(reader, curOffset, discContentHeader->numberOfPartition, discContentHeader->blockSize); + auto partitionsOpt = WiiUPartitions::make_unique(discReader, curOffset, discContentHeaderOpt.value()->numberOfPartition, discContentHeaderOpt.value()->blockSize); + if (!partitionsOpt.has_value()) { + DEBUG_FUNCTION_LINE("Failed to read Partitions"); + return {}; + } curOffset += WiiUPartitions::LENGTH; if (curOffset - offset != LENGTH) { - OSFatal("Length mismatch"); + DEBUG_FUNCTION_LINE("Unexpected offset"); + return {}; } + + return std::unique_ptr(new WiiUContentsInformation( + std::move(discContentHeaderOpt.value()), + std::move(partitionsOpt.value()))); } -WiiUContentsInformation::~WiiUContentsInformation() { - delete partitions; - delete discContentHeader; -} + +WiiUContentsInformation::WiiUContentsInformation(std::unique_ptr pDiscContentHeader, + std::unique_ptr pPartitions) : + discContentHeader(std::move(pDiscContentHeader)), + partitions(std::move(pPartitions)) { + +}; + diff --git a/source/WUD/content/WiiUContentsInformation.h b/source/WUD/content/WiiUContentsInformation.h index 18b7360..2e44bd8 100644 --- a/source/WUD/content/WiiUContentsInformation.h +++ b/source/WUD/content/WiiUContentsInformation.h @@ -16,20 +16,22 @@ ****************************************************************************/ #pragma once -#include "../DiscReader.h" +#include +#include #include "WiiUDiscContentsHeader.h" #include "partitions/WiiUPartitions.h" class WiiUContentsInformation { public: - WiiUContentsInformation(DiscReader *reader, uint32_t offset); + std::unique_ptr discContentHeader; - ~WiiUContentsInformation(); - - WiiUDiscContentsHeader *discContentHeader; - - WiiUPartitions *partitions; + std::unique_ptr partitions; static uint32_t LENGTH; + + static std::optional> make_unique(const std::shared_ptr &discReader, uint32_t offset); + +private: + WiiUContentsInformation(std::unique_ptr pDiscContentsHeader, std::unique_ptr pPartitions); }; diff --git a/source/WUD/content/WiiUDiscContentsHeader.cpp b/source/WUD/content/WiiUDiscContentsHeader.cpp index 19d1c24..886a349 100644 --- a/source/WUD/content/WiiUDiscContentsHeader.cpp +++ b/source/WUD/content/WiiUDiscContentsHeader.cpp @@ -16,29 +16,43 @@ ****************************************************************************/ #include #include -#include #include "WiiUDiscContentsHeader.h" -uint32_t WiiUDiscContentsHeader::LENGTH = 2048; -uint32_t WiiUDiscContentsHeader::MAGIC = 0xCCA6E67B; - -WiiUDiscContentsHeader::WiiUDiscContentsHeader(DiscReader *reader, uint32_t offset) { +std::optional> WiiUDiscContentsHeader::make_unique(const std::shared_ptr &discReader, uint32_t offset) { auto *buffer = (uint8_t *) malloc(LENGTH); - if (!reader->hasDiscKey) { - if (!reader->readEncrypted(buffer, offset, LENGTH)) { - OSFatal("WiiUDiscContentsHeader: Failed to read encrypted"); + if (!buffer) { + DEBUG_FUNCTION_LINE("Failed to alloc buffer"); + return {}; + } + if (!discReader->hasDiscKey) { + if (!discReader->readEncrypted(buffer, offset, LENGTH)) { + DEBUG_FUNCTION_LINE("Failed to read data"); + return {}; } } else { - if (!reader->readDecrypted(buffer, offset, 0, LENGTH, reader->discKey, nullptr, true)) { - OSFatal("WiiUDiscContentsHeader: Failed to read decrypted"); + if (!discReader->readDecrypted(buffer, offset, 0, LENGTH, discReader->discKey, nullptr, true)) { + DEBUG_FUNCTION_LINE("Failed to read data"); + return {}; } } if (((uint32_t *) buffer)[0] != MAGIC) { - OSFatal("WiiUDiscContentsHeader MAGIC mismatch."); + DEBUG_FUNCTION_LINE("MAGIC mismatch"); + return {}; } - blockSize = DiscBlockSize(((uint32_t *) buffer)[1]); - memcpy(tocHash, &buffer[8], 20); - numberOfPartition = ((uint32_t *) buffer)[7]; + auto blockSize = DiscBlockSize(((uint32_t *) buffer)[1]); + std::array tocHash{}; + memcpy(tocHash.data(), &buffer[8], 20); + auto numberOfPartition = ((uint32_t *) buffer)[7]; free(buffer); + + return std::unique_ptr(new WiiUDiscContentsHeader(blockSize, tocHash, numberOfPartition)); } + +WiiUDiscContentsHeader::WiiUDiscContentsHeader(DiscBlockSize pSize, const std::array &pTocHash, uint32_t pNumberOfPartitions) : + blockSize(pSize), + numberOfPartition(pNumberOfPartitions), + tocHash(pTocHash) { + +} + diff --git a/source/WUD/content/WiiUDiscContentsHeader.h b/source/WUD/content/WiiUDiscContentsHeader.h index 26ad6a3..4eecef2 100644 --- a/source/WUD/content/WiiUDiscContentsHeader.h +++ b/source/WUD/content/WiiUDiscContentsHeader.h @@ -16,21 +16,24 @@ ****************************************************************************/ #pragma once +#include +#include #include #include +#include class WiiUDiscContentsHeader { public: - WiiUDiscContentsHeader(DiscReader *reader, uint32_t offset); - - ~WiiUDiscContentsHeader() = default; - DiscBlockSize blockSize{}; - uint8_t tocHash[20]{}; uint32_t numberOfPartition; + std::array tocHash; - static uint32_t LENGTH; + static constexpr uint32_t LENGTH = 2048; + static constexpr uint32_t MAGIC = 0xCCA6E67B; - static uint32_t MAGIC; + static std::optional> make_unique(const std::shared_ptr &discReader, uint32_t offset); + +private: + WiiUDiscContentsHeader(DiscBlockSize pSize, const std::array &pTocHash, uint32_t pNumberOfPartitions); }; diff --git a/source/WUD/content/partitions/WiiUDataPartition.cpp b/source/WUD/content/partitions/WiiUDataPartition.cpp index 5d8d426..b507eb2 100644 --- a/source/WUD/content/partitions/WiiUDataPartition.cpp +++ b/source/WUD/content/partitions/WiiUDataPartition.cpp @@ -16,21 +16,23 @@ ****************************************************************************/ #include "WiiUDataPartition.h" -WiiUDataPartition::~WiiUDataPartition() { - delete basePartition; - delete fst; -} +#include + +WiiUDataPartition::~WiiUDataPartition() = default; + +WiiUDataPartition::WiiUDataPartition( + std::shared_ptr pPartition, + std::shared_ptr pFST) : + fst(std::move(pFST)), + basePartition(std::move(pPartition)) { -WiiUDataPartition::WiiUDataPartition(WiiUPartition *partition, FST *pFST) { - basePartition = partition; - fst = pFST; } std::string WiiUDataPartition::getVolumeId() const &{ return basePartition->getVolumeId(); } -std::map WiiUDataPartition::getVolumes() const &{ +std::map> WiiUDataPartition::getVolumes() const &{ return basePartition->getVolumes(); } diff --git a/source/WUD/content/partitions/WiiUDataPartition.h b/source/WUD/content/partitions/WiiUDataPartition.h index ad8d823..b4c9b8f 100644 --- a/source/WUD/content/partitions/WiiUDataPartition.h +++ b/source/WUD/content/partitions/WiiUDataPartition.h @@ -25,22 +25,22 @@ class WiiUDataPartition : public WiiUPartition { public: - WiiUDataPartition(WiiUPartition *partition, FST *pFST); + WiiUDataPartition(std::shared_ptr pPartition, std::shared_ptr pFST); ~WiiUDataPartition() override; [[nodiscard]] std::string getVolumeId() const & override; - [[nodiscard]] std::map getVolumes() const & override; + [[nodiscard]] std::map> getVolumes() const & override; [[nodiscard]] uint16_t getFileSystemDescriptor() const override; [[nodiscard]] uint64_t getSectionOffsetOnDefaultPartition() override; - FST *fst{}; + std::shared_ptr fst; private: - WiiUPartition *basePartition; + std::shared_ptr basePartition; }; diff --git a/source/WUD/content/partitions/WiiUGMPartition.cpp b/source/WUD/content/partitions/WiiUGMPartition.cpp index d2b17ec..5c46782 100644 --- a/source/WUD/content/partitions/WiiUGMPartition.cpp +++ b/source/WUD/content/partitions/WiiUGMPartition.cpp @@ -16,28 +16,22 @@ ****************************************************************************/ #include "WiiUGMPartition.h" -WiiUGMPartition::~WiiUGMPartition() { - free(rawCert); - free(rawTMD); - free(rawTicket); - delete basePartition; -} - -WiiUGMPartition::WiiUGMPartition(WiiUPartition *partition, uint8_t *pRawTIK, uint32_t pTikLen, uint8_t *pRawTMD, uint32_t pTMDLen, uint8_t *pRawCert, uint32_t pCertLen) { - basePartition = partition; - rawCert = pRawCert; - rawTMD = pRawTMD; - rawTicket = pRawTIK; - tikLen = pTikLen; - TMDLen = pTMDLen; - certLen = pCertLen; +WiiUGMPartition::WiiUGMPartition(std::shared_ptr partition, + std::vector pRawTicket, + std::vector pRawTMD, + std::vector pRawCert) + : WiiUPartition(), + rawTicket(std::move(pRawTicket)), + rawTMD(std::move(pRawTMD)), + rawCert(std::move(pRawCert)), + basePartition(std::move(partition)) { } std::string WiiUGMPartition::getVolumeId() const &{ return basePartition->getVolumeId(); } -std::map WiiUGMPartition::getVolumes() const &{ +std::map> WiiUGMPartition::getVolumes() const &{ return basePartition->getVolumes(); } diff --git a/source/WUD/content/partitions/WiiUGMPartition.h b/source/WUD/content/partitions/WiiUGMPartition.h index 3645985..307b948 100644 --- a/source/WUD/content/partitions/WiiUGMPartition.h +++ b/source/WUD/content/partitions/WiiUGMPartition.h @@ -16,32 +16,31 @@ ****************************************************************************/ #pragma once +#include #include #include #include "WiiUPartition.h" class WiiUGMPartition : public WiiUPartition { public: - WiiUGMPartition(WiiUPartition *partition, uint8_t *pRawTIK, uint32_t pTikLen, uint8_t *pRawTMD, uint32_t pTMDLen, uint8_t *pRawCert, uint32_t pCertLen); - - ~WiiUGMPartition() override; + WiiUGMPartition(std::shared_ptr partition, + std::vector pRawTicket, + std::vector pRawTMD, + std::vector pRawCert); [[nodiscard]] std::string getVolumeId() const & override; - [[nodiscard]] std::map getVolumes() const & override; + [[nodiscard]] std::map> getVolumes() const & override; [[nodiscard]] uint16_t getFileSystemDescriptor() const override; [[nodiscard]] uint64_t getSectionOffsetOnDefaultPartition() override; - uint8_t *rawTicket; - uint8_t *rawTMD; - uint8_t *rawCert; - uint32_t tikLen; - uint32_t TMDLen; - uint32_t certLen; + std::vector rawTicket; + std::vector rawTMD; + std::vector rawCert; private: - WiiUPartition *basePartition; + std::shared_ptr basePartition; }; diff --git a/source/WUD/content/partitions/WiiUPartition.cpp b/source/WUD/content/partitions/WiiUPartition.cpp index 83d87be..a7206d3 100644 --- a/source/WUD/content/partitions/WiiUPartition.cpp +++ b/source/WUD/content/partitions/WiiUPartition.cpp @@ -14,36 +14,33 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . ****************************************************************************/ +#include #include #include "WiiUPartition.h" -uint32_t WiiUPartition::LENGTH = 128; - -WiiUPartition::WiiUPartition() = default; - -WiiUPartition::~WiiUPartition() { - for (auto const&[key, val]: volumes) { - delete val; +uint64_t WiiUPartition::getSectionOffsetOnDefaultPartition() { + if (volumes.size() != 1) { + OSFatal("We have more or less than 1 volume header."); } - volumes.clear(); + return volumes.begin()->first.getAddressInBytes(); } -WiiUPartition::WiiUPartition(DiscReader *reader, uint32_t offset, const DiscBlockSize &blockSize) { +std::optional> WiiUPartition::make_shared(const std::shared_ptr &discReader, uint32_t offset, const DiscBlockSize &blockSize) { auto buffer = (uint8_t *) malloc(LENGTH); if (buffer == nullptr) { - OSFatal("WiiUPartition: alloc buffer failed"); + return {}; } - if (!reader->hasDiscKey) { - if (!reader->readEncrypted(buffer, offset, LENGTH)) { - OSFatal("WiiUPartition: Failed to read encrypted"); + if (!discReader->hasDiscKey) { + if (!discReader->readEncrypted(buffer, offset, LENGTH)) { + return {}; } } else { auto bufferBigger = (uint8_t *) malloc(LENGTH + 0x10); if (bufferBigger == nullptr) { - OSFatal("WiiUPartition: alloc bufferBigger failed"); + return {}; } - if (!reader->readDecrypted(bufferBigger, offset - 0x10, 0, LENGTH + 0x10, reader->discKey, nullptr, true)) { - OSFatal("WiiUPartition: Failed to read encrypted"); + if (!discReader->readDecrypted(bufferBigger, offset - 0x10, 0, LENGTH + 0x10, discReader->discKey, nullptr, true)) { + return {}; } memcpy(buffer, bufferBigger + 0x10, LENGTH); @@ -54,26 +51,46 @@ WiiUPartition::WiiUPartition(DiscReader *reader, uint32_t offset, const DiscBloc char name[32]; memset(name, 0, sizeof(name)); memcpy(name, buffer, 31); - volumeId = name; + auto volumeId = name; uint8_t num = buffer[31]; + std::map> volumes; + for (int i = 0; i < num; i++) { auto address = *((uint32_t *) &buffer[32 + (i * 4)]); AddressInDiscBlocks discLbaAddress = AddressInDiscBlocks(blockSize, address); - auto vh = new VolumeHeader(reader, discLbaAddress.getAddressInBytes()); - volumes[discLbaAddress] = vh; + auto vh = VolumeHeader::make_shared(discReader, discLbaAddress.getAddressInBytes()); + if (!vh.has_value()) { + free(buffer); + return {}; + } + volumes[discLbaAddress] = vh.value(); } - fileSystemDescriptor = ((uint16_t *) &buffer[64])[0]; + auto fileSystemDescriptor = ((uint16_t *) &buffer[64])[0]; free(buffer); + + return std::unique_ptr(new WiiUPartition( + volumeId, + volumes, + fileSystemDescriptor)); } -uint64_t WiiUPartition::getSectionOffsetOnDefaultPartition() { - if (volumes.size() != 1) { - OSFatal("We have more or less than 1 volume header."); - } - return volumes.begin()->first.getAddressInBytes(); +std::string WiiUPartition::getVolumeId() const &{ + return volumeId; } +std::map> WiiUPartition::getVolumes() const &{ + return volumes; +} + +uint16_t WiiUPartition::getFileSystemDescriptor() const { + return fileSystemDescriptor; +} + +WiiUPartition::~WiiUPartition() = default; + + + diff --git a/source/WUD/content/partitions/WiiUPartition.h b/source/WUD/content/partitions/WiiUPartition.h index 686e3e0..21240a4 100644 --- a/source/WUD/content/partitions/WiiUPartition.h +++ b/source/WUD/content/partitions/WiiUPartition.h @@ -17,6 +17,7 @@ #pragma once #include +#include #include #include #include "volumes/VolumeHeader.h" @@ -24,29 +25,29 @@ class WiiUPartition { public: - WiiUPartition(); + virtual ~WiiUPartition(); - explicit WiiUPartition(DiscReader *reader, uint32_t offset, const DiscBlockSize &blockSize); + static constexpr uint32_t LENGTH = 128; virtual uint64_t getSectionOffsetOnDefaultPartition(); - virtual ~WiiUPartition(); + [[nodiscard]] virtual std::string getVolumeId() const &; - [[nodiscard]] virtual std::string getVolumeId() const &{ - return volumeId; - } + [[nodiscard]] virtual std::map> getVolumes() const &; - [[nodiscard]] virtual std::map getVolumes() const &{ - return volumes; - } + [[nodiscard]] virtual uint16_t getFileSystemDescriptor() const; - [[nodiscard]] virtual uint16_t getFileSystemDescriptor() const { - return fileSystemDescriptor; - } + static std::optional> make_shared(const std::shared_ptr &discReader, uint32_t offset, const DiscBlockSize &blockSize); + +protected: + WiiUPartition() = default; private: + WiiUPartition(char *pVolumeId, std::map> pVolumes, uint16_t pFileSystemDescriptor) + : volumeId(pVolumeId), volumes(std::move(pVolumes)), fileSystemDescriptor(pFileSystemDescriptor) { + } + std::string volumeId; - std::map volumes; + std::map> volumes; uint16_t fileSystemDescriptor{}; - static uint32_t LENGTH; }; \ No newline at end of file diff --git a/source/WUD/content/partitions/WiiUPartitions.cpp b/source/WUD/content/partitions/WiiUPartitions.cpp index 0d5a9a8..b234ee3 100644 --- a/source/WUD/content/partitions/WiiUPartitions.cpp +++ b/source/WUD/content/partitions/WiiUPartitions.cpp @@ -16,94 +16,140 @@ ****************************************************************************/ #include #include + +#include #include "WiiUPartitions.h" #include "WiiUGMPartition.h" #include "WiiUDataPartition.h" -uint32_t WiiUPartitions::LENGTH = 30720; +bool WiiUPartitions::getFSTEntryAsByte(std::string &filePath, + const std::shared_ptr &fst, + const AddressInDiscBlocks &volumeAddress, + const std::shared_ptr &discReader, + std::vector &out_data) { + auto entryOpt = FSTUtils::getFSTEntryByFullPath(fst->getRootEntry(), filePath); + if (!entryOpt.has_value()) { + return false; + } -WiiUPartitions::WiiUPartitions(DiscReader *reader, uint32_t offset, uint32_t numberOfPartitions, const DiscBlockSize &blockSize) { - std::vector tmp; + auto asFileEntry = std::dynamic_pointer_cast(entryOpt.value()); + if (asFileEntry == nullptr) { + return false; + } + + auto info = asFileEntry->getSectionEntry(); + uint64_t sectionOffsetOnDisc = volumeAddress.getAddressInBytes() + info->address.getAddressInBytes(); + + out_data.resize(asFileEntry->getSize()); + + if (!discReader->hasDiscKey) { + return discReader->readEncrypted(out_data.data(), sectionOffsetOnDisc + asFileEntry->getOffset(), asFileEntry->getSize()); + } + + // Calculating the IV + uint8_t IV[16]; + memset(IV, 0, 16); + uint64_t ivTemp = asFileEntry->getOffset() >> 16; + memcpy(IV + 8, &ivTemp, 8); + + return discReader->readDecrypted(out_data.data(), sectionOffsetOnDisc, asFileEntry->getOffset(), asFileEntry->getSize(), discReader->discKey, IV, false); +} + +std::optional> +WiiUPartitions::make_unique(const std::shared_ptr &discReader, uint32_t offset, uint32_t numberOfPartitions, const DiscBlockSize &blockSize) { + std::vector> tmp; + std::vector> partitions; + partitions.reserve(numberOfPartitions); tmp.reserve(numberOfPartitions); for (uint32_t i = 0; i < numberOfPartitions; i++) { - tmp.push_back(new WiiUPartition(reader, offset + (i * 128), blockSize)); + auto partitionOpt = WiiUPartition::make_shared(discReader, offset + (i * 128), blockSize); + if (!partitionOpt.has_value()) { + DEBUG_FUNCTION_LINE("Failed to read partition"); + return {}; + } + tmp.push_back(partitionOpt.value()); } - WiiUPartition *SIPartition = nullptr; + std::optional> SIPartition; for (auto &partition: tmp) { if (partition->getVolumeId().starts_with("SI")) { SIPartition = partition; + break; } } - if (SIPartition != nullptr) { - for (auto const&[key, val]: SIPartition->getVolumes()) { + if (SIPartition.has_value()) { + for (auto const&[key, val]: SIPartition.value()->getVolumes()) { auto volumeAddress = key; auto volumeAddressInBytes = volumeAddress.getAddressInBytes(); auto volumeHeader = val; - auto fst = (uint8_t *) malloc(volumeHeader->FSTSize); - if (fst == nullptr) { - OSFatal("WiiUPartitions: Failed to alloc FST buffer"); - } + std::vector fstData; + fstData.resize(volumeHeader->FSTSize); - if (!reader->hasDiscKey) { - if (!reader->readEncrypted(fst, volumeAddressInBytes + volumeHeader->FSTAddress.getAddressInBytes(), - volumeHeader->FSTSize)) { - OSFatal("WiiUPartitions: Failed to read encrypted"); + if (!discReader->hasDiscKey) { + if (!discReader->readEncrypted(fstData.data(), volumeAddressInBytes + volumeHeader->FSTAddress.getAddressInBytes(), + volumeHeader->FSTSize)) { + DEBUG_FUNCTION_LINE("Failed to read FST"); + return {}; } } else { - if (!reader->readDecrypted(fst, volumeAddressInBytes + volumeHeader->FSTAddress.getAddressInBytes(), 0, volumeHeader->FSTSize, - reader->discKey, nullptr, true)) { - OSFatal("WiiUPartitions: Failed to read decrypted"); + if (!discReader->readDecrypted(fstData.data(), volumeAddressInBytes + volumeHeader->FSTAddress.getAddressInBytes(), 0, volumeHeader->FSTSize, + discReader->discKey, nullptr, true)) { + DEBUG_FUNCTION_LINE("Failed to read FST"); + return {}; } } - FST *siFST = new FST(fst, volumeHeader->FSTSize, 0, volumeHeader->blockSize); - free(fst); + auto siFST = FST::make_shared(fstData, 0, volumeHeader->blockSize); + if (!siFST.has_value()) { + DEBUG_FUNCTION_LINE("Failed to parse FST"); + return {}; + } - for (auto &child: siFST->getRootEntry()->getDirChildren()) { - uint8_t *tikRaw = nullptr; - uint32_t tikRawLen = 0; + for (auto &child: siFST.value()->getRootEntry()->getDirChildren()) { + std::vector bufferTicket; std::string tikFilePath = std::string(child->getFullPath() + '/' + WUD_TICKET_FILENAME); - if (!getFSTEntryAsByte(&tikRaw, &tikRawLen, tikFilePath, siFST, volumeAddress, reader)) { - OSFatal("tikRaw"); + if (!getFSTEntryAsByte(tikFilePath, siFST.value(), volumeAddress, discReader, bufferTicket)) { + DEBUG_FUNCTION_LINE("Failted to read FSTEntry"); + return {}; } - uint8_t *tmdRaw = nullptr; - uint32_t tmdRawLen = 0; + std::vector bufferTMD; std::string tmdFilePath = std::string(child->getFullPath() + '/' + WUD_TMD_FILENAME); - if (!getFSTEntryAsByte(&tmdRaw, &tmdRawLen, tmdFilePath, siFST, volumeAddress, reader)) { - OSFatal("tmdRaw"); + if (!getFSTEntryAsByte(tmdFilePath, siFST.value(), volumeAddress, discReader, bufferTMD)) { + DEBUG_FUNCTION_LINE("Failted to read FSTEntry"); + return {}; } - uint8_t *certRaw = nullptr; - uint32_t certRawLen = 0; + std::vector bufferCert; std::string certFilePath = std::string(child->getFullPath() + '/' + WUD_CERT_FILENAME); - if (!getFSTEntryAsByte(&certRaw, &certRawLen, certFilePath, siFST, volumeAddress, reader)) { - OSFatal("certRaw"); + if (!getFSTEntryAsByte(certFilePath, siFST.value(), volumeAddress, discReader, bufferCert)) { + DEBUG_FUNCTION_LINE("Failted to read FSTEntry"); + return {}; } char partitionNameRaw[0x12]; memset(partitionNameRaw, 0, 0x12); - snprintf(partitionNameRaw, 0x11, "%016llX", *((uint64_t *) &tikRaw[0x1DC])); + snprintf(partitionNameRaw, 0x11, "%016llX", *((uint64_t *) &bufferTicket[0x1DC])); std::string partitionName = std::string("GM") + partitionNameRaw; - WiiUPartition *curPartition = nullptr; + std::optional> curPartition; for (auto &partition: tmp) { if (partition->getVolumeId().starts_with(partitionName)) { curPartition = partition; + break; } } - if (curPartition == nullptr) { - OSFatal("Failed to get partition"); + if (!curPartition.has_value()) { + DEBUG_FUNCTION_LINE("Failed to find partition"); + return {}; } - auto *gmPartition = new WiiUGMPartition(curPartition, tikRaw, tikRawLen, tmdRaw, tmdRawLen, certRaw, certRawLen); + auto gmPartition = std::shared_ptr(new WiiUGMPartition(curPartition.value(), bufferTicket, bufferTMD, bufferCert)); partitions.push_back(gmPartition); } - delete siFST; } } @@ -117,65 +163,32 @@ WiiUPartitions::WiiUPartitions(DiscReader *reader, uint32_t offset, uint32_t num } auto volumeAddress = partition->getVolumes().begin()->first; auto vh = partition->getVolumes().begin()->second; - auto *rawFST = (uint8_t *) malloc(vh->FSTSize); - if (rawFST == nullptr) { - OSFatal("Failed to alloc rawFST"); - } - if (!reader->hasDiscKey) { - if (!reader->readEncrypted(rawFST, volumeAddress.getAddressInBytes() + vh->FSTAddress.getAddressInBytes(), vh->FSTSize)) { + + std::vector fstData; + fstData.resize(vh->FSTSize); + + if (!discReader->hasDiscKey) { + if (!discReader->readEncrypted(fstData.data(), volumeAddress.getAddressInBytes() + vh->FSTAddress.getAddressInBytes(), vh->FSTSize)) { OSFatal("WiiUPartition: Failed to read encrypted"); } } else { - if (!reader->readDecrypted(rawFST, volumeAddress.getAddressInBytes() + vh->FSTAddress.getAddressInBytes(), 0, vh->FSTSize, - reader->discKey, nullptr, true)) { + if (!discReader->readDecrypted(fstData.data(), volumeAddress.getAddressInBytes() + vh->FSTAddress.getAddressInBytes(), 0, vh->FSTSize, + discReader->discKey, nullptr, true)) { OSFatal("WiiUPartition: Failed to read encrypted"); } } - FST *fst = new FST(rawFST, vh->FSTSize, 0, vh->blockSize); - free(rawFST); - partitions.push_back(new WiiUDataPartition(partition, fst)); + auto fstOpt = FST::make_shared(fstData, 0, vh->blockSize); + if (!fstOpt.has_value()) { + DEBUG_FUNCTION_LINE("Failed to parse FST"); + return {}; + } + partitions.push_back(std::shared_ptr(new WiiUDataPartition(partition, fstOpt.value()))); } + return std::unique_ptr(new WiiUPartitions(partitions)); } -WiiUPartitions::~WiiUPartitions() { - for (auto &partition: partitions) { - delete partition; - } -} - -bool WiiUPartitions::getFSTEntryAsByte(uint8_t **buffer_out, uint32_t *outSize, std::string &filePath, FST *fst, const AddressInDiscBlocks &volumeAddress, DiscReader *discReader) { - NodeEntry *entry = FSTUtils::getFSTEntryByFullPath(fst->nodeEntries->rootEntry, filePath); - - auto asFileEntry = dynamic_cast(entry); - if (asFileEntry == nullptr) { - return false; - } - - SectionEntry *info = asFileEntry->getSectionEntry(); - if (info == nullptr) { - OSFatal("WiiUPartitions::getFSTEntryAsByte, section info was null"); - } - - uint64_t sectionOffsetOnDisc = volumeAddress.getAddressInBytes() + info->address.getAddressInBytes(); - - auto *buffer = (uint8_t *) malloc(asFileEntry->getSize()); - if (buffer == nullptr) { - return false; - } - *buffer_out = buffer; - *outSize = asFileEntry->getSize(); - - if (!discReader->hasDiscKey) { - return discReader->readEncrypted(buffer, sectionOffsetOnDisc + asFileEntry->getOffset(), asFileEntry->getSize()); - } - - // Calculating the IV - uint8_t IV[16]; - memset(IV, 0, 16); - uint64_t ivTemp = asFileEntry->getOffset() >> 16; - memcpy(IV + 8, &ivTemp, 8); - - return discReader->readDecrypted(buffer, sectionOffsetOnDisc, asFileEntry->getOffset(), asFileEntry->getSize(), discReader->discKey, IV, false); +WiiUPartitions::WiiUPartitions(std::vector> pPartitions) : partitions(std::move(pPartitions)) { + DEBUG_FUNCTION_LINE(); } diff --git a/source/WUD/content/partitions/WiiUPartitions.h b/source/WUD/content/partitions/WiiUPartitions.h index 31badc1..4137d17 100644 --- a/source/WUD/content/partitions/WiiUPartitions.h +++ b/source/WUD/content/partitions/WiiUPartitions.h @@ -16,6 +16,7 @@ ****************************************************************************/ #pragma once +#include #include #include #include @@ -30,13 +31,21 @@ class WiiUPartitions { public: - static bool getFSTEntryAsByte(uint8_t **buffer_out, uint32_t *outSize, std::string &filePath, FST *fst, const AddressInDiscBlocks &volumeAddress, DiscReader *discReader); + static bool getFSTEntryAsByte(std::string &filePath, + const std::shared_ptr &fst, + const AddressInDiscBlocks &volumeAddress, + const std::shared_ptr &discReader, + std::vector &out_data); - WiiUPartitions(DiscReader *reader, uint32_t offset, uint32_t numberOfPartitions, const DiscBlockSize &blockSize); + std::vector> partitions; + static constexpr uint32_t LENGTH = 30720; - ~WiiUPartitions(); - - std::vector partitions; - static uint32_t LENGTH; + static std::optional> make_unique( + const std::shared_ptr &discReader, + uint32_t offset, + uint32_t numberOfPartitions, + const DiscBlockSize &blockSize); +private: + explicit WiiUPartitions(std::vector> pPartitions); }; \ No newline at end of file diff --git a/source/WUD/content/partitions/volumes/H3HashArray.cpp b/source/WUD/content/partitions/volumes/H3HashArray.cpp index a7e940d..7a90924 100644 --- a/source/WUD/content/partitions/volumes/H3HashArray.cpp +++ b/source/WUD/content/partitions/volumes/H3HashArray.cpp @@ -34,4 +34,4 @@ H3HashArray::~H3HashArray() { if (data) { free(data); } -} +} \ No newline at end of file diff --git a/source/WUD/content/partitions/volumes/VolumeHeader.cpp b/source/WUD/content/partitions/volumes/VolumeHeader.cpp index 9286e43..43deb62 100644 --- a/source/WUD/content/partitions/volumes/VolumeHeader.cpp +++ b/source/WUD/content/partitions/volumes/VolumeHeader.cpp @@ -15,58 +15,15 @@ * along with this program. If not, see . ****************************************************************************/ +#include #include "VolumeHeader.h" -#include #include +#include uint32_t VolumeHeader::MAGIC = 0xCC93A4F5; -VolumeHeader::VolumeHeader(DiscReader *reader, uint64_t offset) { - auto buffer = (uint8_t *) malloc(64); - if (buffer == nullptr) { - OSFatal("VolumeHeader: failed to alloc buffer"); - } - - if (!reader->readEncrypted(buffer, offset, 64)) { - OSFatal("VolumeHeader: failed to read"); - } - - auto *bufferUint = (uint32_t *) buffer; - - if (bufferUint[0] != MAGIC) { - OSFatal("VolumeHeader MAGIC mismatch."); - } - - blockSize = VolumeBlockSize(bufferUint[1]); - volumeSize = SizeInVolumeBlocks(blockSize, bufferUint[2]); - h3HashArrayListSize = bufferUint[3]; - numberOfH3HashArray = bufferUint[4]; - FSTSize = bufferUint[5]; - FSTAddress = AddressInVolumeBlocks(blockSize, bufferUint[6]); - FSTHashMode = buffer[36]; - encryptType = buffer[37]; - majorVersion = buffer[38]; - minorVersion = buffer[39]; - expiringMajorVersion = buffer[40]; - - free(buffer); - - auto bufferH3 = (uint8_t *) malloc(ROUNDUP(h3HashArrayListSize, 16)); - if (bufferH3 == nullptr) { - OSFatal("VolumeHeader: failed to alloc h3 buffer"); - } - - if (!reader->readEncrypted(bufferH3, offset + 64, ROUNDUP(h3HashArrayListSize, 16))) { - OSFatal("VolumeHeader: failed to read h3"); - } - - h3HashArrayList = getH3HashArray(bufferH3, numberOfH3HashArray, h3HashArrayListSize); - - free(bufferH3); -} - -std::vector VolumeHeader::getH3HashArray(uint8_t *h3Data, uint32_t pNumberOfH3HashArray, uint32_t pH3HashArrayListSize) { - std::vector arrayList; +std::vector> VolumeHeader::getH3HashArray(uint8_t *h3Data, uint32_t pNumberOfH3HashArray, uint32_t pH3HashArrayListSize) { + std::vector> arrayList; if (pNumberOfH3HashArray == 0) { return arrayList; } @@ -80,15 +37,93 @@ std::vector VolumeHeader::getH3HashArray(uint8_t *h3Data, uint32_ curEnd = offsetPtr[1]; } - arrayList.push_back(new H3HashArray(h3Data + curOffset, curEnd - curOffset)); + arrayList.push_back(std::make_shared(h3Data + curOffset, curEnd - curOffset)); } return arrayList; } -VolumeHeader::~VolumeHeader() { - for (auto &h3: h3HashArrayList) { - delete h3; +std::optional> VolumeHeader::make_shared(const std::shared_ptr &discReader, uint64_t offset) { + auto buffer = (uint8_t *) malloc(64); + if (buffer == nullptr) { + DEBUG_FUNCTION_LINE("Failed to alloc buffer"); + return {}; } + + if (!discReader->readEncrypted(buffer, offset, 64)) { + free(buffer); + DEBUG_FUNCTION_LINE("Failed to read data"); + return {}; + } + + auto *bufferUint = (uint32_t *) buffer; + + if (bufferUint[0] != MAGIC) { + DEBUG_FUNCTION_LINE("MAGIC mismatch"); + free(buffer); + return {}; + } + + auto blockSize = VolumeBlockSize(bufferUint[1]); + auto volumeSize = SizeInVolumeBlocks(blockSize, bufferUint[2]); + auto h3HashArrayListSize = bufferUint[3]; + auto numberOfH3HashArray = bufferUint[4]; + auto FSTSize = bufferUint[5]; + auto FSTAddress = AddressInVolumeBlocks(blockSize, bufferUint[6]); + auto FSTHashMode = buffer[36]; + auto encryptType = buffer[37]; + auto majorVersion = buffer[38]; + auto minorVersion = buffer[39]; + auto expiringMajorVersion = buffer[40]; + + DEBUG_FUNCTION_LINE("FSTSize: %08X", FSTSize); + + free(buffer); + + auto bufferH3 = (uint8_t *) malloc(ROUNDUP(h3HashArrayListSize, 16)); + if (bufferH3 == nullptr) { + DEBUG_FUNCTION_LINE("Failed to alloc h3 buffer"); + return {}; + } + + if (!discReader->readEncrypted(bufferH3, offset + 64, ROUNDUP(h3HashArrayListSize, 16))) { + DEBUG_FUNCTION_LINE("Failed to read h3 data"); + free(bufferH3); + return {}; + } + + auto h3HashArrayList = getH3HashArray(bufferH3, numberOfH3HashArray, h3HashArrayListSize); + + free(bufferH3); + + return std::unique_ptr( + new VolumeHeader(blockSize, volumeSize, FSTSize, FSTAddress, FSTHashMode, encryptType, majorVersion, minorVersion, expiringMajorVersion, h3HashArrayList, h3HashArrayListSize, + numberOfH3HashArray)); } +VolumeHeader::VolumeHeader(const VolumeBlockSize &pBlockSize, + SizeInVolumeBlocks pVolumeSize, + uint32_t pFSTSize, + AddressInVolumeBlocks pFSTAddress, + uint8_t pFSTHashMode, + uint8_t pEncryptType, + uint8_t pMajorVersion, + uint8_t pMinorVersion, + uint8_t pExpiringMajorVersion, + std::vector> pH3HashArrayList, + uint32_t pH3HashArrayListSize, + uint32_t pNumberOfH3HashArray) : blockSize(pBlockSize), + volumeSize(std::move(pVolumeSize)), + FSTSize(pFSTSize), + FSTAddress(std::move(pFSTAddress)), + FSTHashMode(pFSTHashMode), + encryptType(pEncryptType), + majorVersion(pMajorVersion), + minorVersion(pMinorVersion), + expiringMajorVersion(pExpiringMajorVersion), + h3HashArrayList(std::move(pH3HashArrayList)), + h3HashArrayListSize(pH3HashArrayListSize), + numberOfH3HashArray(pNumberOfH3HashArray) { +} + + diff --git a/source/WUD/content/partitions/volumes/VolumeHeader.h b/source/WUD/content/partitions/volumes/VolumeHeader.h index 6b6656c..907fa04 100644 --- a/source/WUD/content/partitions/volumes/VolumeHeader.h +++ b/source/WUD/content/partitions/volumes/VolumeHeader.h @@ -16,22 +16,21 @@ ****************************************************************************/ #pragma once +#include #include #include #include #include #include #include +#include +#include #include "H3HashArray.h" class VolumeHeader { public: - static std::vector getH3HashArray(uint8_t *h3Data, uint32_t numberOfH3HashArray, uint32_t h3HashArrayListSize); - - VolumeHeader(DiscReader *reader, uint64_t offset); - - ~VolumeHeader(); + static std::vector> getH3HashArray(uint8_t *h3Data, uint32_t numberOfH3HashArray, uint32_t h3HashArrayListSize); static uint32_t MAGIC; VolumeBlockSize blockSize; @@ -43,8 +42,26 @@ public: uint8_t majorVersion; uint8_t minorVersion; uint8_t expiringMajorVersion; - std::vector h3HashArrayList; + std::vector> h3HashArrayList; uint32_t h3HashArrayListSize; uint32_t numberOfH3HashArray; + + static std::optional> make_shared(const std::shared_ptr &discReader, uint64_t offset); + +private: + VolumeHeader( + const VolumeBlockSize &pBlockSize, + SizeInVolumeBlocks pVolumeSize, + uint32_t pFSTSize, + AddressInVolumeBlocks pFSTAddress, + uint8_t pFSTHashMode, + uint8_t pEncryptType, + uint8_t pMajorVersion, + uint8_t pMinorVersion, + uint8_t pExpiringMajorVersion, + std::vector> pH3HashArrayList, + uint32_t pH3HashArrayListSize, + uint32_t pNumberOfH3HashArray); + }; \ No newline at end of file diff --git a/source/WUD/entities/FST/FST.cpp b/source/WUD/entities/FST/FST.cpp index 1d07054..57a153a 100644 --- a/source/WUD/entities/FST/FST.cpp +++ b/source/WUD/entities/FST/FST.cpp @@ -15,33 +15,80 @@ * along with this program. If not, see . ****************************************************************************/ #include "FST.h" +#include -FST::FST(uint8_t *data, uint32_t fstSize, uint32_t offset, const VolumeBlockSize &blockSize) { +std::shared_ptr FST::getRootEntry() const { + return nodeEntries->getRootEntry(); +} + +std::optional> FST::make_shared(const std::vector &data, uint32_t offset, const VolumeBlockSize &blockSize) { uint32_t curOffset = offset; - header = new FSTHeader(data + curOffset); - curOffset += header->LENGTH; + if (curOffset + FSTHeader::LENGTH > data.size()) { + DEBUG_FUNCTION_LINE("Not enough data to parse the FSTHeader"); + return {}; + } - sectionEntries = new SectionEntries(data + curOffset, header->numberOfSections, blockSize); - curOffset += sectionEntries->getSizeInBytes(); + std::array fstData{}; + std::copy_n(data.begin() + (int) curOffset, FSTHeader::LENGTH, fstData.begin()); - uint32_t lastEntryNumber = RootEntry::parseLastEntryNumber(data, curOffset); + auto headerOpt = FSTHeader::make_unique(fstData); + if (!headerOpt.has_value()) { + DEBUG_FUNCTION_LINE("Failed to parse FSTHeader"); + return {}; + } + curOffset += FSTHeader::LENGTH; + + uint32_t sectionEntriesDataSize = headerOpt.value()->numberOfSections * SectionEntry::LENGTH; + if (curOffset + sectionEntriesDataSize > data.size()) { + DEBUG_FUNCTION_LINE("Not enough data to parse the SectionEntries"); + return {}; + } + + std::vector sectionEntriesData; + sectionEntriesData.resize(sectionEntriesDataSize); + std::copy_n(data.begin() + (int) curOffset, sectionEntriesDataSize, sectionEntriesData.begin()); + + auto sectionEntriesOpt = SectionEntries::make_shared(sectionEntriesData, headerOpt.value()->numberOfSections, blockSize); + if (!sectionEntriesOpt.has_value()) { + DEBUG_FUNCTION_LINE("Failed to parse FSTHeader"); + return {}; + } + curOffset += sectionEntriesOpt.value()->getSizeInBytes(); + + std::array rootEntry{}; + std::copy_n(data.begin() + (int) curOffset, NodeEntry::LENGTH, rootEntry.begin()); + + uint32_t lastEntryNumber = RootEntry::parseLastEntryNumber(rootEntry); auto stringTableOffset = curOffset + (lastEntryNumber * 16); - stringTable = StringTable::parseData(data, fstSize - stringTableOffset, stringTableOffset, lastEntryNumber); + auto stringTableOpt = StringTable::make_shared(data, stringTableOffset, lastEntryNumber); + if (!stringTableOpt.has_value()) { + DEBUG_FUNCTION_LINE("Failed to parse StringTable"); + return {}; + } - nodeEntries = NodeEntries::parseData(data, curOffset, sectionEntries, stringTable, header->blockSize); + auto nodeEntriesOpt = NodeEntries::make_unique(data, curOffset, sectionEntriesOpt.value(), stringTableOpt.value(), headerOpt.value()->blockSize); + if (!nodeEntriesOpt.has_value()) { + DEBUG_FUNCTION_LINE("Failed to parse NodeEntries"); + return {}; + } + + return std::shared_ptr(new FST( + std::move(headerOpt.value()), + std::move(sectionEntriesOpt.value()), + std::move(stringTableOpt.value()), + std::move(nodeEntriesOpt.value()))); } -FST::~FST() { - delete nodeEntries; - delete stringTable; - delete sectionEntries; - delete header; -} +FST::FST(std::unique_ptr pHeader, + std::shared_ptr pSectionEntries, + std::shared_ptr pStringTable, + std::unique_ptr pNodeEntries) : + sectionEntries(std::move(pSectionEntries)), + stringTable(std::move(pStringTable)), + nodeEntries(std::move(pNodeEntries)), + header(std::move(pHeader)) { -RootEntry *FST::getRootEntry() const { - return nodeEntries->rootEntry; } - diff --git a/source/WUD/entities/FST/FST.h b/source/WUD/entities/FST/FST.h index 934ff4d..270a7f9 100644 --- a/source/WUD/entities/FST/FST.h +++ b/source/WUD/entities/FST/FST.h @@ -16,7 +16,10 @@ ****************************************************************************/ #pragma once +#include +#include #include +#include #include #include #include @@ -24,16 +27,20 @@ #include class FST { - public: - FST(uint8_t *data, uint32_t fstSize, uint32_t offset, const VolumeBlockSize &blockSize); + [[nodiscard]] std::shared_ptr getRootEntry() const; - ~FST(); + static std::optional> make_shared(const std::vector &data, uint32_t offset, const VolumeBlockSize &blockSize); - FSTHeader *header; - SectionEntries *sectionEntries; - StringTable *stringTable; - NodeEntries *nodeEntries; + std::shared_ptr sectionEntries; +private: + FST(std::unique_ptr pHeader, + std::shared_ptr pSectionEntries, + std::shared_ptr pStringTable, + std::unique_ptr pNodeEntries + ); - [[nodiscard]] RootEntry *getRootEntry() const; + std::shared_ptr stringTable; + std::unique_ptr nodeEntries; + std::unique_ptr header; }; \ No newline at end of file diff --git a/source/WUD/entities/FST/header/FSTHeader.cpp b/source/WUD/entities/FST/header/FSTHeader.cpp index d6e6075..e3b45d3 100644 --- a/source/WUD/entities/FST/header/FSTHeader.cpp +++ b/source/WUD/entities/FST/header/FSTHeader.cpp @@ -15,16 +15,31 @@ * along with this program. If not, see . ****************************************************************************/ #include -#include +#include #include "FSTHeader.h" -FSTHeader::FSTHeader(uint8_t *data) { - auto *dataAsUint = (uint32_t *) data; +std::optional> FSTHeader::make_unique(const std::array &data) { + auto *dataAsUint = (uint32_t *) data.data(); if ((dataAsUint[0] & 0xFFFFFF00) != 0x46535400) { - OSFatal("FST Header magic was wrong"); + DEBUG_FUNCTION_LINE("FST Header magic was wrong"); + return {}; } - FSTVersion = data[3]; - blockSize = SectionBlockSize(dataAsUint[1]); - numberOfSections = dataAsUint[2]; - hashDisabled = data[12]; + auto FSTVersion = data[3]; + auto blockSize = SectionBlockSize(dataAsUint[1]); + auto numberOfSections = dataAsUint[2]; + auto hashDisabled = data[12]; + + return std::unique_ptr(new FSTHeader( + FSTVersion, + blockSize, + numberOfSections, + hashDisabled + )); +} + +FSTHeader::FSTHeader(uint8_t pFSTVersion, SectionBlockSize pBlockSize, uint32_t pNumberOfSections, uint8_t pHashDisabled) : FSTVersion(pFSTVersion), + blockSize(pBlockSize), + numberOfSections(pNumberOfSections), + hashDisabled(pHashDisabled) { + } diff --git a/source/WUD/entities/FST/header/FSTHeader.h b/source/WUD/entities/FST/header/FSTHeader.h index f0e8d24..3c6aa63 100644 --- a/source/WUD/entities/FST/header/FSTHeader.h +++ b/source/WUD/entities/FST/header/FSTHeader.h @@ -16,20 +16,24 @@ ****************************************************************************/ #pragma once +#include +#include #include #include class FSTHeader { public: - explicit FSTHeader(uint8_t *data); + static constexpr uint32_t LENGTH = 32; - ~FSTHeader() = default; + static std::optional> make_unique(const std::array &data); uint8_t FSTVersion; SectionBlockSize blockSize; - uint8_t hashDisabled; uint32_t numberOfSections; - uint32_t LENGTH = 32; + uint8_t hashDisabled; + +private: + FSTHeader(uint8_t pFSTVersion, SectionBlockSize pBlockSize, uint32_t pNumberOfSections, uint8_t pHashDisabled); }; diff --git a/source/WUD/entities/FST/nodeentry/DirectoryEntry.cpp b/source/WUD/entities/FST/nodeentry/DirectoryEntry.cpp index a7c7a86..b9135ea 100644 --- a/source/WUD/entities/FST/nodeentry/DirectoryEntry.cpp +++ b/source/WUD/entities/FST/nodeentry/DirectoryEntry.cpp @@ -17,56 +17,48 @@ #include #include "DirectoryEntry.h" -DirectoryEntry *DirectoryEntry::parseData(const uint8_t *data, NodeEntryParam param, SectionEntries *sectionEntries, StringTable *stringTable) { - auto *directoryEntry = new DirectoryEntry(); - directoryEntry->entryNumber = param.entryNumber; - directoryEntry->parent = param.parent; - directoryEntry->entryType = param.type; - directoryEntry->nameString = stringTable->getStringEntry(param.uint24); - if (directoryEntry->nameString == nullptr) { - OSFatal("Failed to find string for offset"); +std::optional> +DirectoryEntry::parseData(const std::array &data, const NodeEntryParam ¶m, const std::shared_ptr §ionEntries, + const std::shared_ptr &stringTable) { + auto parentEntryNumber = ((uint32_t *) &data[4])[0]; + auto lastEntryNumber = ((uint32_t *) &data[8])[0]; + auto stringNameOpt = stringTable->getStringEntry(param.uint24); + if (!stringNameOpt.has_value()) { + DEBUG_FUNCTION_LINE("Failed to get string name"); + return {}; } - directoryEntry->parentEntryNumber = ((uint32_t *) &data[4])[0]; - directoryEntry->lastEntryNumber = ((uint32_t *) &data[8])[0]; - - directoryEntry->permission = param.permission; - - if (param.sectionNumber > sectionEntries->size()) { - OSFatal("section number does not match"); + auto sectionEntryOpt = sectionEntries->getSection(param.sectionNumber); + if (!sectionEntryOpt.has_value()) { + DEBUG_FUNCTION_LINE("Failed to get section entry"); + return {}; } - directoryEntry->sectionEntry = sectionEntries->getSection(param.sectionNumber); - return directoryEntry; + + return std::unique_ptr(new DirectoryEntry(param, stringNameOpt.value(), sectionEntryOpt.value(), parentEntryNumber, lastEntryNumber)); } -DirectoryEntry::~DirectoryEntry() { - for (auto &child: children) { - delete child; - } -} - -std::vector DirectoryEntry::getDirChildren() const { - std::vector res; +std::vector> DirectoryEntry::getDirChildren() const { + std::vector> res; for (auto &cur: children) { if (cur->isDirectory()) { - res.push_back(dynamic_cast(cur)); + res.push_back(std::dynamic_pointer_cast(cur)); } } return res; } -std::vector DirectoryEntry::getFileChildren() const { - std::vector res; +std::vector> DirectoryEntry::getFileChildren() const { + std::vector> res; for (auto &cur: children) { if (cur->isFile()) { - res.push_back(dynamic_cast(cur)); + res.push_back(std::dynamic_pointer_cast(cur)); } } return res; } -std::vector DirectoryEntry::getChildren() const { +std::vector> DirectoryEntry::getChildren() const { return children; } @@ -77,6 +69,33 @@ void DirectoryEntry::printPathRecursive() { } } -void DirectoryEntry::addChild(NodeEntry *entry) { +void DirectoryEntry::addChild(const std::shared_ptr &entry) { children.push_back(entry); } + +DirectoryEntry::DirectoryEntry(const NodeEntryParam ¶m, + const std::shared_ptr &pStringEntry, + const std::shared_ptr &pSectionEntry, + uint32_t pParentEntryNumber, + uint32_t pLastEntryNumber) : + NodeEntry(param.permission, + pStringEntry, + pSectionEntry, + param.parent, + param.type, + param.entryNumber), + parentEntryNumber(pParentEntryNumber), + lastEntryNumber(pLastEntryNumber) { +} + +DirectoryEntry::DirectoryEntry(const std::shared_ptr &input) : + NodeEntry(input->permission, + input->nameString, + input->sectionEntry, + input->parent, + input->entryType, + input->entryNumber), + parentEntryNumber(input->parentEntryNumber), + lastEntryNumber(input->lastEntryNumber) { + +} diff --git a/source/WUD/entities/FST/nodeentry/DirectoryEntry.h b/source/WUD/entities/FST/nodeentry/DirectoryEntry.h index 74495f4..38ad879 100644 --- a/source/WUD/entities/FST/nodeentry/DirectoryEntry.h +++ b/source/WUD/entities/FST/nodeentry/DirectoryEntry.h @@ -23,24 +23,35 @@ #include "FileEntry.h" class DirectoryEntry : public NodeEntry { - - public: - ~DirectoryEntry() override; - - static DirectoryEntry *parseData(const uint8_t *data, NodeEntryParam param, SectionEntries *sectionEntries, StringTable *stringTable); + static std::optional> + parseData(const std::array &data, + const NodeEntryParam ¶m, + const std::shared_ptr §ionEntries, + const std::shared_ptr &stringTable); uint32_t parentEntryNumber{}; uint32_t lastEntryNumber{}; - std::vector children; + std::vector> children; - void addChild(NodeEntry *entry); + void addChild(const std::shared_ptr &entry); - [[nodiscard]] std::vector getDirChildren() const; + [[nodiscard]] std::vector> getDirChildren() const; - [[nodiscard]] std::vector getFileChildren() const; + [[nodiscard]] std::vector> getFileChildren() const; - [[nodiscard]] std::vector getChildren() const; + [[nodiscard]] std::vector> getChildren() const; void printPathRecursive() override; + +protected: + explicit DirectoryEntry(const std::shared_ptr &input); + +private: + DirectoryEntry( + const NodeEntryParam ¶m, + const std::shared_ptr &stringEntry, + const std::shared_ptr §ionEntry, + uint32_t parentEntryNumber, + uint32_t lastEntryNumber); }; \ No newline at end of file diff --git a/source/WUD/entities/FST/nodeentry/FileEntry.cpp b/source/WUD/entities/FST/nodeentry/FileEntry.cpp index a75eb42..88f4413 100644 --- a/source/WUD/entities/FST/nodeentry/FileEntry.cpp +++ b/source/WUD/entities/FST/nodeentry/FileEntry.cpp @@ -20,30 +20,32 @@ #include -FileEntry::FileEntry(SectionAddress address) : address(std::move(address)) { -} +std::optional> +FileEntry::parseData(const std::array &data, + const NodeEntryParam ¶m, + const std::shared_ptr §ionEntries, + const std::shared_ptr &stringTable, + const SectionBlockSize &blockSize) { + auto size = ((uint32_t *) &data[8])[0]; + auto offset = SectionAddress(blockSize, ((uint32_t *) &data[4])[0]); -NodeEntry *FileEntry::parseData(uint8_t *data, NodeEntryParam param, SectionEntries *sectionEntries, StringTable *stringTable, const SectionBlockSize &blockSize) { - auto *entry = new FileEntry(SectionAddress(blockSize, ((uint32_t *) &data[4])[0])); - - entry->entryNumber = param.entryNumber; - entry->parent = param.parent; - entry->entryType = param.type; - entry->nameString = stringTable->getStringEntry(param.uint24); - if (entry->nameString == nullptr) { - OSFatal("Failed to find string for offset"); + auto stringNameOpt = stringTable->getStringEntry(param.uint24); + if (!stringNameOpt.has_value()) { + DEBUG_FUNCTION_LINE("Failed to get string name"); + return {}; } - entry->size = ((uint32_t *) &data[8])[0]; + auto sectionEntryOpt = sectionEntries->getSection(param.sectionNumber); + if (!sectionEntryOpt.has_value()) { + DEBUG_FUNCTION_LINE("Failed to get section entry"); + return {}; + } - entry->permission = param.permission; - entry->sectionEntry = sectionEntries->getSection(param.sectionNumber); - - return entry; + return std::shared_ptr(new FileEntry(param, stringNameOpt.value(), sectionEntryOpt.value(), size, offset)); } -SectionEntry *FileEntry::getSectionEntry() { +std::shared_ptr FileEntry::getSectionEntry() { return sectionEntry; } @@ -54,3 +56,19 @@ uint64_t FileEntry::getOffset() const { uint32_t FileEntry::getSize() const { return size; } + +FileEntry::FileEntry( + const NodeEntryParam ¶m, + const std::shared_ptr &pStringEntry, + const std::shared_ptr &pSectionEntry, + uint32_t pSize, SectionAddress pAddress) : + NodeEntry(param.permission, + pStringEntry, + pSectionEntry, + param.parent, + param.type, + param.entryNumber), + address(std::move(pAddress)), + size(pSize) { + +} \ No newline at end of file diff --git a/source/WUD/entities/FST/nodeentry/FileEntry.h b/source/WUD/entities/FST/nodeentry/FileEntry.h index 163b1b9..656190c 100644 --- a/source/WUD/entities/FST/nodeentry/FileEntry.h +++ b/source/WUD/entities/FST/nodeentry/FileEntry.h @@ -23,19 +23,29 @@ class FileEntry : public NodeEntry { public: - explicit FileEntry(SectionAddress address); - static NodeEntry *parseData(uint8_t *data, NodeEntryParam param, SectionEntries *sectionEntries, StringTable *stringTable, const SectionBlockSize &blockSize); + static std::optional> + parseData(const std::array &data, + const NodeEntryParam ¶m, + const std::shared_ptr §ionEntries, + const std::shared_ptr &stringTable, + const SectionBlockSize &blockSize); ~FileEntry() override = default; - SectionEntry *getSectionEntry(); + std::shared_ptr getSectionEntry(); [[nodiscard]] uint64_t getOffset() const; [[nodiscard]] uint32_t getSize() const; private: + FileEntry(const NodeEntryParam ¶m, + const std::shared_ptr &pStringEntry, + const std::shared_ptr &pSectionEntry, + uint32_t pSize, + SectionAddress offset); + SectionAddress address; uint32_t size{}; }; \ No newline at end of file diff --git a/source/WUD/entities/FST/nodeentry/NodeEntries.cpp b/source/WUD/entities/FST/nodeentry/NodeEntries.cpp index 29cf926..69d0a3a 100644 --- a/source/WUD/entities/FST/nodeentry/NodeEntries.cpp +++ b/source/WUD/entities/FST/nodeentry/NodeEntries.cpp @@ -17,25 +17,30 @@ #include #include "NodeEntries.h" -NodeEntries::NodeEntries(RootEntry *pEntry) { - rootEntry = pEntry; -} - -NodeEntries::~NodeEntries() { - delete rootEntry; -} - -NodeEntry *NodeEntries::DeserializeImpl(uint8_t *data, uint32_t offset, DirectoryEntry *parent, uint32_t entryNumber, SectionEntries *sectionEntries, StringTable *stringTable, - const SectionBlockSize &blockSize) { - NodeEntry *nodeEntry = NodeEntry::AutoDeserialize(data, offset, parent, entryNumber, sectionEntries, stringTable, blockSize); - auto asDirEntry = dynamic_cast(nodeEntry); +std::optional> NodeEntries::DeserializeImpl(const std::vector &pData, + uint32_t pOffset, + const std::optional> &pParent, + uint32_t pEntryNumber, + const std::shared_ptr &pSectionEntries, + const std::shared_ptr &pStringTable, + const SectionBlockSize &pBlockSize) { + auto nodeEntry = NodeEntry::AutoDeserialize(pData, pOffset, pParent, pEntryNumber, pSectionEntries, pStringTable, pBlockSize); + if (!nodeEntry.has_value()) { + DEBUG_FUNCTION_LINE("Failed to AutoDeserialize NodeEntry"); + return {}; + } + auto asDirEntry = std::dynamic_pointer_cast(nodeEntry.value()); if (asDirEntry != nullptr) { uint32_t curEntryNumber = asDirEntry->entryNumber + 1; while (curEntryNumber < asDirEntry->lastEntryNumber) { - NodeEntry *entry = NodeEntries::DeserializeImpl(data, offset + (curEntryNumber - asDirEntry->entryNumber) * NodeEntry::LENGTH, - asDirEntry, curEntryNumber, sectionEntries, stringTable, blockSize); - asDirEntry->addChild(entry); - auto *childAsDir = dynamic_cast(entry); + auto entry = NodeEntries::DeserializeImpl(pData, pOffset + (curEntryNumber - asDirEntry->entryNumber) * NodeEntry::LENGTH, + asDirEntry, curEntryNumber, pSectionEntries, pStringTable, pBlockSize); + if (!entry.has_value()) { + DEBUG_FUNCTION_LINE("Failed to Deserialize child of NodeEntry"); + return {}; + } + asDirEntry->addChild(entry.value()); + auto childAsDir = std::dynamic_pointer_cast(entry.value()); if (childAsDir != nullptr) { curEntryNumber = childAsDir->lastEntryNumber; } else { @@ -46,12 +51,26 @@ NodeEntry *NodeEntries::DeserializeImpl(uint8_t *data, uint32_t offset, Director return nodeEntry; } -NodeEntries *NodeEntries::parseData(unsigned char *data, uint32_t offset, SectionEntries *sectionEntries, StringTable *stringTable, const SectionBlockSize &blockSize) { - NodeEntry *rootEntry = NodeEntries::DeserializeImpl(data, offset, (DirectoryEntry *) nullptr, 0, sectionEntries, stringTable, blockSize); - auto rootEntryCasted = dynamic_cast(rootEntry); - if (rootEntryCasted != nullptr) { - return new NodeEntries(rootEntryCasted); +std::optional> +NodeEntries::make_unique(const std::vector &data, uint32_t offset, const std::shared_ptr &pSectionEntries, const std::shared_ptr &pStringTable, + const SectionBlockSize &blockSize) { + auto rootEntry = NodeEntries::DeserializeImpl(data, offset, std::nullopt, 0, pSectionEntries, pStringTable, blockSize); + if (!rootEntry.has_value()) { + DEBUG_FUNCTION_LINE("DeserializeImpl for root entry has failed"); + return {}; } - OSFatal("Failed to parse Root"); - return nullptr; + auto rootEntryCasted = std::dynamic_pointer_cast(rootEntry.value()); + if (rootEntryCasted != nullptr) { + return std::unique_ptr(new NodeEntries(rootEntryCasted)); + } + DEBUG_FUNCTION_LINE("Failed to parse Root"); + return {}; +} + +std::shared_ptr NodeEntries::getRootEntry() const { + return rootEntry; +} + +NodeEntries::NodeEntries(const std::shared_ptr &pEntry) { + rootEntry = pEntry; } diff --git a/source/WUD/entities/FST/nodeentry/NodeEntries.h b/source/WUD/entities/FST/nodeentry/NodeEntries.h index aff7041..509077d 100644 --- a/source/WUD/entities/FST/nodeentry/NodeEntries.h +++ b/source/WUD/entities/FST/nodeentry/NodeEntries.h @@ -19,6 +19,8 @@ #include #include #include + +#include #include "DirectoryEntry.h" #include "RootEntry.h" #include "NodeEntry.h" @@ -27,14 +29,32 @@ class NodeEntries { public: - explicit NodeEntries(RootEntry *pEntry); - ~NodeEntries(); + virtual ~NodeEntries() { + DEBUG_FUNCTION_LINE("Bye"); + } - static NodeEntry * - DeserializeImpl(unsigned char *data, uint32_t offset, DirectoryEntry *parent, uint32_t entryNumber, SectionEntries *sectionEntries, StringTable *stringTable, const SectionBlockSize &blockSize); + static std::optional> + DeserializeImpl(const std::vector &data, + uint32_t offset, + const std::optional> &pParent, + uint32_t entryNumber, + const std::shared_ptr §ionEntries, + const std::shared_ptr &stringTable, + const SectionBlockSize &blockSize); - static NodeEntries *parseData(unsigned char *data, uint32_t offset, SectionEntries *sectionEntries, StringTable *stringTable, const SectionBlockSize &blockSize); + static std::optional> + make_unique(const std::vector &data, + uint32_t offset, + const std::shared_ptr §ionEntries, + const std::shared_ptr &stringTable, + const SectionBlockSize &blockSize); - RootEntry *rootEntry; + [[nodiscard]] std::shared_ptr getRootEntry() const; + +private: + explicit NodeEntries(const std::shared_ptr &pEntry); + + + std::shared_ptr rootEntry; }; diff --git a/source/WUD/entities/FST/nodeentry/NodeEntry.cpp b/source/WUD/entities/FST/nodeentry/NodeEntry.cpp index e0261b6..7a76bbc 100644 --- a/source/WUD/entities/FST/nodeentry/NodeEntry.cpp +++ b/source/WUD/entities/FST/nodeentry/NodeEntry.cpp @@ -17,16 +17,26 @@ #include #include #include -#include + +#include +#include #include "NodeEntry.h" #include "DirectoryEntry.h" #include "RootEntry.h" -uint32_t NodeEntry::LENGTH = 16; - -NodeEntry *NodeEntry::AutoDeserialize(uint8_t *data, uint32_t offset, DirectoryEntry *pParent, uint32_t eEntryNumber, SectionEntries *sectionEntries, - StringTable *stringTable, const SectionBlockSize &blockSize) { - uint8_t *curEntryData = &data[offset]; +std::optional> +NodeEntry::AutoDeserialize(const std::vector &data, + uint32_t offset, + const std::optional> &pParent, + uint32_t eEntryNumber, + const std::shared_ptr §ionEntries, + const std::shared_ptr &stringTable, + const SectionBlockSize &blockSize) { + if (offset + NodeEntry::LENGTH >= data.size()) { + return {}; + } + std::array curEntryData{}; + std::copy_n(data.begin() + (int) offset, NodeEntry::LENGTH, curEntryData.begin()); NodeEntryParam param{}; param.permission = ((uint16_t *) &curEntryData[12])[0]; @@ -34,41 +44,68 @@ NodeEntry *NodeEntry::AutoDeserialize(uint8_t *data, uint32_t offset, DirectoryE param.entryNumber = eEntryNumber; param.parent = pParent; param.type = curEntryData[0]; - param.uint24 = ((uint32_t *) curEntryData)[0] & 0x00FFFFFF; + param.uint24 = ((uint32_t *) &curEntryData[0])[0] & 0x00FFFFFF; if ((param.type & ENTRY_TYPE_Directory) == ENTRY_TYPE_Directory && param.uint24 == 0) { // Root - return (NodeEntry *) RootEntry::parseData(curEntryData, param, sectionEntries, stringTable); + auto res = RootEntry::parseData(curEntryData, param, sectionEntries, stringTable); + if (!res.has_value()) { + DEBUG_FUNCTION_LINE("Failed to parse node"); + return {}; + } + return res; } else if ((param.type & ENTRY_TYPE_Directory) == ENTRY_TYPE_Directory) { - return (NodeEntry *) DirectoryEntry::parseData(curEntryData, param, sectionEntries, stringTable); + auto res = DirectoryEntry::parseData(curEntryData, param, sectionEntries, stringTable); + if (!res.has_value()) { + DEBUG_FUNCTION_LINE("Failed to parse node"); + return {}; + } + auto resAsNodeEntry = std::dynamic_pointer_cast(res.value()); + if (resAsNodeEntry == nullptr) { + DEBUG_FUNCTION_LINE("Failed to cast to NodeEntry"); + return {}; + } + return resAsNodeEntry; } else if ((param.type & ENTRY_TYPE_File) == ENTRY_TYPE_File) { - return (NodeEntry *) FileEntry::parseData(curEntryData, param, sectionEntries, stringTable, blockSize); + auto res = FileEntry::parseData(curEntryData, param, sectionEntries, stringTable, blockSize); + + if (!res.has_value()) { + DEBUG_FUNCTION_LINE("Failed to parse node"); + return {}; + } + auto resAsNodeEntry = std::dynamic_pointer_cast(res.value()); + if (resAsNodeEntry == nullptr) { + DEBUG_FUNCTION_LINE("Failed to cast to NodeEntry"); + return {}; + } + return resAsNodeEntry; } - OSFatal("FST Unknown Node Type"); - return nullptr; + DEBUG_FUNCTION_LINE("FST Unknown Node Type"); + return {}; } -std::string NodeEntry::getName() const &{ - if (nameString != nullptr) { - return nameString->toString(); +std::string NodeEntry::getName() { + auto res = nameString->toString(); + if (res.has_value()) { + return res.value(); } - return "ERROR"; + return "[ERROR]"; } -std::string NodeEntry::getFullPathInternal() const &{ - if (parent != nullptr) { - return parent->getFullPathInternal().append("/").append(getName()); +std::string NodeEntry::getFullPathInternal() { + if (parent.has_value()) { + return parent.value()->getFullPathInternal().append("/").append(getName()); } return getName(); } -std::string NodeEntry::getFullPath() const &{ +std::string NodeEntry::getFullPath() { return getFullPathInternal(); } -std::string NodeEntry::getPath() const &{ - if (parent != nullptr) { - return parent->getFullPath().append("/"); +std::string NodeEntry::getPath() { + if (parent.has_value()) { + return parent.value()->getFullPath().append("/"); } return "/"; } @@ -80,4 +117,23 @@ bool NodeEntry::isDirectory() const { bool NodeEntry::isFile() const { return (entryType & ENTRY_TYPE_File) == ENTRY_TYPE_File; -} \ No newline at end of file +} + +NodeEntry::NodeEntry(const uint16_t pPermission, + std::shared_ptr pNameString, + std::shared_ptr pSectionEntry, + std::optional> pParent, + const uint8_t pType, const uint32_t pEntryNumber) : + permission(pPermission), + nameString(std::move(pNameString)), + sectionEntry(std::move(pSectionEntry)), + parent(std::move(pParent)), + entryType(pType), + entryNumber(pEntryNumber) { + +} + +void NodeEntry::printPathRecursive() { + DEBUG_FUNCTION_LINE("%s", getFullPath().c_str()); +} + diff --git a/source/WUD/entities/FST/nodeentry/NodeEntry.h b/source/WUD/entities/FST/nodeentry/NodeEntry.h index e299793..346a3ca 100644 --- a/source/WUD/entities/FST/nodeentry/NodeEntry.h +++ b/source/WUD/entities/FST/nodeentry/NodeEntry.h @@ -34,32 +34,43 @@ class NodeEntry { public: uint16_t permission{}; - StringEntry *nameString{}; - SectionEntry *sectionEntry{}; - DirectoryEntry *parent{}; + std::shared_ptr nameString; + std::shared_ptr sectionEntry; + std::optional> parent; uint8_t entryType{}; uint32_t entryNumber{}; - static NodeEntry *AutoDeserialize(uint8_t *data, uint32_t offset, DirectoryEntry *pParent, uint32_t eEntryNumber, SectionEntries *sectionEntries, - StringTable *stringTable, const SectionBlockSize &blockSize); + static std::optional> + AutoDeserialize(const std::vector &data, + uint32_t offset, + const std::optional> &pParent, + uint32_t eEntryNumber, + const std::shared_ptr §ionEntries, + const std::shared_ptr &stringTable, const SectionBlockSize &blockSize); virtual ~NodeEntry() = default; - virtual void printPathRecursive() { - DEBUG_FUNCTION_LINE("%s", getFullPath().c_str()); - } + virtual void printPathRecursive(); - [[nodiscard]] std::string getFullPath() const &; + [[nodiscard]] std::string getFullPath(); - [[nodiscard]] std::string getPath() const &; + [[nodiscard]] std::string getPath(); - [[nodiscard]] std::string getName() const &; + [[nodiscard]] std::string getName(); [[nodiscard]] bool isDirectory() const; [[nodiscard]] bool isFile() const; - static uint32_t LENGTH; -private: - [[nodiscard]] std::string getFullPathInternal() const &; + static constexpr uint32_t LENGTH = 16; + + [[nodiscard]] std::string getFullPathInternal(); + +protected: + NodeEntry(uint16_t pPermission, + std::shared_ptr pNameString, + std::shared_ptr pSectionEntry, + std::optional> pParent, + uint8_t pType, + uint32_t pEntryNumber); }; \ No newline at end of file diff --git a/source/WUD/entities/FST/nodeentry/NodeEntryParam.h b/source/WUD/entities/FST/nodeentry/NodeEntryParam.h index c61cccf..8012e4d 100644 --- a/source/WUD/entities/FST/nodeentry/NodeEntryParam.h +++ b/source/WUD/entities/FST/nodeentry/NodeEntryParam.h @@ -24,7 +24,7 @@ class NodeEntryParam { public: uint16_t sectionNumber; uint32_t entryNumber; - DirectoryEntry *parent; + std::optional> parent; uint16_t permission; uint8_t type; uint32_t uint24; diff --git a/source/WUD/entities/FST/nodeentry/RootEntry.cpp b/source/WUD/entities/FST/nodeentry/RootEntry.cpp index b935d5f..1d6594c 100644 --- a/source/WUD/entities/FST/nodeentry/RootEntry.cpp +++ b/source/WUD/entities/FST/nodeentry/RootEntry.cpp @@ -17,29 +17,28 @@ #include #include "RootEntry.h" -RootEntry::RootEntry(DirectoryEntry *input) { - if ((input->entryType & ENTRY_TYPE_Directory) != ENTRY_TYPE_Directory || input->entryNumber != 0) { - OSFatal("Input is no root entry."); +RootEntry::RootEntry(const std::shared_ptr &input) : DirectoryEntry(input) { + +} + +uint32_t RootEntry::parseLastEntryNumber(const std::array &data) { + return ((uint32_t *) &data[8])[0]; +} + +std::optional> +RootEntry::parseData + (const std::array &data, + const NodeEntryParam ¶m, + const std::shared_ptr §ionEntries, + const std::shared_ptr &stringTable) { + auto dir = DirectoryEntry::parseData(data, param, sectionEntries, stringTable); + if (dir.has_value()) { + if ((dir.value()->entryType & ENTRY_TYPE_Directory) != ENTRY_TYPE_Directory || dir.value()->entryNumber != 0) { + DEBUG_FUNCTION_LINE("Input is no root entry."); + return {}; + } + return std::shared_ptr(new RootEntry(dir.value())); } - - entryNumber = input->entryNumber; - parent = input->parent; - nameString = input->nameString; - if (nameString == nullptr) { - OSFatal("nameString was null"); - } - entryType = input->entryType; - - parentEntryNumber = input->parentEntryNumber; - lastEntryNumber = input->lastEntryNumber; - permission = input->permission; - sectionEntry = input->sectionEntry; -} - -uint32_t RootEntry::parseLastEntryNumber(uint8_t *data, uint32_t offset) { - return ((uint32_t *) &data[8 + offset])[0]; -} - -RootEntry *RootEntry::parseData(uint8_t *data, NodeEntryParam param, SectionEntries *sectionEntries, StringTable *stringTable) { - return new RootEntry(DirectoryEntry::parseData(data, param, sectionEntries, stringTable)); + DEBUG_FUNCTION_LINE("Failed to parse dir"); + return {}; } diff --git a/source/WUD/entities/FST/nodeentry/RootEntry.h b/source/WUD/entities/FST/nodeentry/RootEntry.h index 6977d98..eeafa4d 100644 --- a/source/WUD/entities/FST/nodeentry/RootEntry.h +++ b/source/WUD/entities/FST/nodeentry/RootEntry.h @@ -24,13 +24,17 @@ class RootEntry : public DirectoryEntry { - explicit RootEntry(DirectoryEntry *input); - public: - ~RootEntry() override = default; - static RootEntry *parseData(uint8_t *data, NodeEntryParam param, SectionEntries *sectionEntries, StringTable *stringTable); + static std::optional> + parseData(const std::array &data, + const NodeEntryParam ¶m, + const std::shared_ptr §ionEntries, + const std::shared_ptr &stringTable); - static uint32_t parseLastEntryNumber(uint8_t *data, uint32_t offset); + static uint32_t parseLastEntryNumber(const std::array &data); + +private: + explicit RootEntry(const std::shared_ptr &input); }; \ No newline at end of file diff --git a/source/WUD/entities/FST/sectionentry/SectionEntries.cpp b/source/WUD/entities/FST/sectionentry/SectionEntries.cpp index 3179fd1..2144062 100644 --- a/source/WUD/entities/FST/sectionentry/SectionEntries.cpp +++ b/source/WUD/entities/FST/sectionentry/SectionEntries.cpp @@ -16,25 +16,41 @@ ****************************************************************************/ #include "SectionEntries.h" -SectionEntries::SectionEntries(uint8_t *data, uint32_t numberOfSections, const VolumeBlockSize &pBlockSize) { - for (uint32_t i = 0; i < numberOfSections; i++) { - list.push_back(new SectionEntry(data + (i * 32), i, pBlockSize)); - } -} - -SectionEntry *SectionEntries::getSection(uint16_t sectionNumber) const { +std::optional> SectionEntries::getSection(uint16_t sectionNumber) const { for (auto const &e: list) { if (e->sectionNumber == sectionNumber) { return e; } } - return nullptr; + return {}; } uint32_t SectionEntries::getSizeInBytes() const { - return list.size() * 32; + return list.size() * SectionEntry::LENGTH; } uint32_t SectionEntries::size() const { return list.size(); } + +std::optional> SectionEntries::make_shared(const std::vector &data, uint32_t numberOfSections, const VolumeBlockSize &pBlockSize) { + std::vector> list; + for (uint32_t i = 0; i < numberOfSections; i++) { + if (data.size() < (i + 1) * SectionEntry::LENGTH) { + DEBUG_FUNCTION_LINE("Failed to parse SectionEntries"); + return {}; + } + std::array sectionEntryData{}; + memcpy(sectionEntryData.data(), data.data() + (i * SectionEntry::LENGTH), SectionEntry::LENGTH); + list.push_back(std::make_shared(sectionEntryData, i, pBlockSize));; + } + return std::shared_ptr(new SectionEntries(list)); +} + +std::vector> SectionEntries::getSections() const &{ + return list; +} + +SectionEntries::SectionEntries(std::vector> pList) : list(std::move(pList)) { + +} diff --git a/source/WUD/entities/FST/sectionentry/SectionEntries.h b/source/WUD/entities/FST/sectionentry/SectionEntries.h index e4299b9..91c2942 100644 --- a/source/WUD/entities/FST/sectionentry/SectionEntries.h +++ b/source/WUD/entities/FST/sectionentry/SectionEntries.h @@ -16,26 +16,30 @@ ****************************************************************************/ #pragma once +#include +#include #include +#include #include #include +#include #include "SectionEntry.h" class SectionEntries { public: - SectionEntries(uint8_t *data, uint32_t numberOfSections, const VolumeBlockSize &pBlockSize); - [[nodiscard]] uint32_t getSizeInBytes() const; [[nodiscard]] uint32_t size() const; - [[nodiscard]] SectionEntry *getSection(uint16_t sectionNumber) const; + [[nodiscard]] std::optional> getSection(uint16_t sectionNumber) const; - [[nodiscard]] std::vector getSections() const &{ - return list; - } + [[nodiscard]] std::vector> getSections() const &; + + static std::optional> make_shared(const std::vector &data, uint32_t numberOfSections, const VolumeBlockSize &pBlockSize); private: - std::vector list; + explicit SectionEntries(std::vector> pList); + + std::vector> list; }; \ No newline at end of file diff --git a/source/WUD/entities/FST/sectionentry/SectionEntry.cpp b/source/WUD/entities/FST/sectionentry/SectionEntry.cpp index fe2018b..921e508 100644 --- a/source/WUD/entities/FST/sectionentry/SectionEntry.cpp +++ b/source/WUD/entities/FST/sectionentry/SectionEntry.cpp @@ -16,8 +16,8 @@ ****************************************************************************/ #include "SectionEntry.h" -SectionEntry::SectionEntry(uint8_t *data, uint32_t pSectionNumber, const VolumeBlockSize &pBlockSize) { - auto *dataAsUint = (uint32_t *) data; +SectionEntry::SectionEntry(const std::array &data, uint32_t pSectionNumber, const VolumeBlockSize &pBlockSize) { + auto *dataAsUint = (uint32_t *) data.data(); address = AddressInVolumeBlocks(pBlockSize, dataAsUint[0]); size = SizeInVolumeBlocks(pBlockSize, dataAsUint[1]); diff --git a/source/WUD/entities/FST/sectionentry/SectionEntry.h b/source/WUD/entities/FST/sectionentry/SectionEntry.h index 2a79063..b5a31b3 100644 --- a/source/WUD/entities/FST/sectionentry/SectionEntry.h +++ b/source/WUD/entities/FST/sectionentry/SectionEntry.h @@ -18,12 +18,15 @@ #include #include +#include #include #include class SectionEntry { public: - SectionEntry(uint8_t *data, uint32_t pSectionNumber, const VolumeBlockSize &pBlockSize); + static constexpr uint32_t LENGTH = 32; + + SectionEntry(const std::array &data, uint32_t pSectionNumber, const VolumeBlockSize &pBlockSize); ~SectionEntry() = default; diff --git a/source/WUD/entities/FST/stringtable/StringEntry.cpp b/source/WUD/entities/FST/stringtable/StringEntry.cpp index d54967c..362bf64 100644 --- a/source/WUD/entities/FST/stringtable/StringEntry.cpp +++ b/source/WUD/entities/FST/stringtable/StringEntry.cpp @@ -15,13 +15,14 @@ * along with this program. If not, see . ****************************************************************************/ #include "StringEntry.h" + +#include +#include #include "StringTable.h" -std::string StringEntry::toString() const { +std::optional StringEntry::toString() const { return stringTable->getByAddress(offset); } -StringEntry::StringEntry(StringTable *pTable, uint32_t pOffset) { - stringTable = pTable; - offset = pOffset; +StringEntry::StringEntry(std::shared_ptr pTable, uint32_t pOffset) : stringTable(std::move(pTable)), offset(pOffset) { } diff --git a/source/WUD/entities/FST/stringtable/StringEntry.h b/source/WUD/entities/FST/stringtable/StringEntry.h index 0569d7e..f6963dd 100644 --- a/source/WUD/entities/FST/stringtable/StringEntry.h +++ b/source/WUD/entities/FST/stringtable/StringEntry.h @@ -18,16 +18,18 @@ #include #include +#include +#include class StringTable; class StringEntry { public: - StringEntry(StringTable *pTable, uint32_t pOffset); + StringEntry(std::shared_ptr pTable, uint32_t pOffset); - [[nodiscard]] std::string toString() const; + [[nodiscard]] std::optional toString() const; - StringTable *stringTable; + std::shared_ptr stringTable; uint32_t offset; }; diff --git a/source/WUD/entities/FST/stringtable/StringTable.cpp b/source/WUD/entities/FST/stringtable/StringTable.cpp index a81f7dd..633b5dd 100644 --- a/source/WUD/entities/FST/stringtable/StringTable.cpp +++ b/source/WUD/entities/FST/stringtable/StringTable.cpp @@ -16,26 +16,33 @@ ****************************************************************************/ #include #include +#include #include "StringTable.h" -StringTable *StringTable::parseData(uint8_t *data, uint32_t dataLength, uint32_t offset, uint32_t stringCount) { - auto *stringTable = new StringTable(); + +std::optional> StringTable::make_shared(const std::vector &data, uint32_t offset, uint32_t stringCount) { + if (offset >= data.size()) { + DEBUG_FUNCTION_LINE("Invalid offset for reading StringTable"); + return {}; + } + auto stringTable = std::shared_ptr(new StringTable()); uint32_t curOffset = 0; uint32_t i; - for (i = 0; curOffset < dataLength && i < stringCount; ++curOffset) { + for (i = 0; curOffset < data.size() && i < stringCount; ++curOffset) { if (data[offset + curOffset] == (uint8_t) 0) { ++i; } } if (i < stringCount) { - OSFatal("stringtable is broken"); + DEBUG_FUNCTION_LINE("stringtable is broken"); + return {}; } uint32_t curLength = 0; for (i = 0; i < stringCount; ++i) { curOffset = offset + curLength; - stringTable->stringMap[curLength] = new StringEntry(stringTable, curLength); + stringTable->stringMap[curLength] = std::make_shared(stringTable, curLength); stringTable->strings[curLength] = (char *) &data[curOffset]; curLength += strlen((char *) &data[curOffset]) + 1; @@ -44,12 +51,18 @@ StringTable *StringTable::parseData(uint8_t *data, uint32_t dataLength, uint32_t return stringTable; } -std::string StringTable::getByAddress(uint32_t address) { - return strings[address]; +std::optional StringTable::getByAddress(uint32_t address) { + if (strings.count(address) > 0) { + return strings[address]; + } + return {}; } -StringEntry *StringTable::getStringEntry(uint32_t address) { - return stringMap[address]; +std::optional> StringTable::getStringEntry(uint32_t address) { + if (stringMap.count(address) > 0) { + return stringMap[address]; + } + return {}; } uint32_t StringTable::getSize() { @@ -60,12 +73,12 @@ uint32_t StringTable::getSize() { return capacity; } -StringEntry *StringTable::getEntry(std::string &str) { +std::optional> StringTable::getEntry(std::string &str) { for (auto &cur: strings) { if (cur.second == str) { return stringMap[cur.first]; } } - return nullptr; + return {}; } diff --git a/source/WUD/entities/FST/stringtable/StringTable.h b/source/WUD/entities/FST/stringtable/StringTable.h index f9f85ef..7efc304 100644 --- a/source/WUD/entities/FST/stringtable/StringTable.h +++ b/source/WUD/entities/FST/stringtable/StringTable.h @@ -16,6 +16,9 @@ ****************************************************************************/ #pragma once +#include +#include +#include #include #include #include "StringEntry.h" @@ -23,25 +26,19 @@ class StringTable { public: - ~StringTable() { - for (auto &cur: stringMap) { - delete cur.second; - } - stringMap.clear(); - strings.clear(); - } + static std::optional> make_shared(const std::vector &data, uint32_t offset, uint32_t stringCount); - static StringTable *parseData(uint8_t *data, uint32_t dataLength, uint32_t offset, uint32_t stringCount); + std::optional getByAddress(uint32_t address); - std::string getByAddress(uint32_t address); - - StringEntry *getStringEntry(uint32_t address); + std::optional> getStringEntry(uint32_t address); uint32_t getSize(); - StringEntry *getEntry(std::string &str); + std::optional> getEntry(std::string &str); private: - std::map stringMap; + StringTable() = default; + + std::map> stringMap; std::map strings; }; \ No newline at end of file diff --git a/source/WUD/entities/TMD/Content.cpp b/source/WUD/entities/TMD/Content.cpp index c08c643..4584103 100644 --- a/source/WUD/entities/TMD/Content.cpp +++ b/source/WUD/entities/TMD/Content.cpp @@ -17,12 +17,21 @@ #include #include "Content.h" -uint32_t Content::LENGTH = 0x30; - -Content::Content(uint8_t *data) { - ID = ((uint32_t *) &data[0x00])[0]; - index = ((uint16_t *) &data[0x04])[0]; - type = ((uint16_t *) &data[0x06])[0]; - encryptedFileSize = ((uint64_t *) &data[0x08])[0]; - memcpy(hash, &data[0x10], 0x14); +Content::Content(uint32_t pId, uint16_t pIndex, uint16_t pType, uint64_t pEncryptedFileSize, const std::array &pHash) : + ID(pId), + index(pIndex), + type(pType), + encryptedFileSize(pEncryptedFileSize), + hash(pHash) { +} + +std::optional> Content::make_shared(const std::array &data) { + auto id = ((uint32_t *) &data[0x00])[0]; + auto index = ((uint16_t *) &data[0x04])[0]; + auto type = ((uint16_t *) &data[0x06])[0]; + auto encryptedFileSize = ((uint64_t *) &data[0x08])[0]; + std::array hash{}; + memcpy(hash.data(), &data[0x10], 0x14); + + return std::shared_ptr(new Content(id, index, type, encryptedFileSize, hash)); } diff --git a/source/WUD/entities/TMD/Content.h b/source/WUD/entities/TMD/Content.h index 1d3c3fc..16a7521 100644 --- a/source/WUD/entities/TMD/Content.h +++ b/source/WUD/entities/TMD/Content.h @@ -17,16 +17,21 @@ #pragma once #include +#include +#include class Content { public: - static uint32_t LENGTH; + static constexpr uint32_t LENGTH = 0x30; - explicit Content(uint8_t *data); - - uint16_t index; uint32_t ID; + uint16_t index; uint16_t type; uint64_t encryptedFileSize; - uint8_t hash[0x14]{}; + std::array hash; + + static std::optional> make_shared(const std::array &data); + +private: + explicit Content(uint32_t pId, uint16_t pIndex, uint16_t pType, uint64_t pEncryptedFileSize, const std::array &pHash); }; diff --git a/source/WUD/entities/TMD/TitleMetaData.cpp b/source/WUD/entities/TMD/TitleMetaData.cpp index 9d94e8b..1e1e943 100644 --- a/source/WUD/entities/TMD/TitleMetaData.cpp +++ b/source/WUD/entities/TMD/TitleMetaData.cpp @@ -16,27 +16,46 @@ ****************************************************************************/ #include "TitleMetaData.h" -TitleMetaData::TitleMetaData(uint8_t *data) { - contentCount = ((uint16_t *) &data[0x1DE])[0]; +#include +#include + +TitleMetaData::TitleMetaData(std::vector> pContentList) : contentList(std::move(pContentList)) { + // Get Contents - for (uint16_t i = 0; i < contentCount; i++) { - auto curOffset = 0xB04 + (i * Content::LENGTH); - auto *c = new Content((uint8_t *) &data[curOffset]); - contentList.push_back(c); - } + } -TitleMetaData::~TitleMetaData() { - for (auto &content: contentList) { - delete content; - } -} - -Content *TitleMetaData::getContentByIndex(uint16_t i) { +std::optional> TitleMetaData::getContentByIndex(uint16_t i) { for (auto &content: contentList) { if (content->index == i) { return content; } } - return nullptr; + return {}; +} + +std::optional> TitleMetaData::make_shared(const std::vector &data) { + if (data.empty() || data.size() <= 0xB04) { + return {}; + } + std::vector> contentList; + auto contentCount = ((uint16_t *) &data[0x1DE])[0]; + for (uint16_t i = 0; i < contentCount; i++) { + auto curOffset = 0xB04 + (i * Content::LENGTH); + if (data.size() < curOffset + Content::LENGTH) { + DEBUG_FUNCTION_LINE("Failed to parse TitleMetaData"); + return {}; + } + std::array contentData{}; + std::copy(data.begin() + (int) curOffset, data.begin() + (int) curOffset + Content::LENGTH, contentData.begin()); + + auto curContentOpt = Content::make_shared(contentData); + if (!curContentOpt.has_value()) { + DEBUG_FUNCTION_LINE("Failed to parse Content"); + return {}; + } + contentList.push_back(curContentOpt.value()); + } + + return std::shared_ptr(new TitleMetaData(contentList)); } diff --git a/source/WUD/entities/TMD/TitleMetaData.h b/source/WUD/entities/TMD/TitleMetaData.h index c4667b5..2ecb926 100644 --- a/source/WUD/entities/TMD/TitleMetaData.h +++ b/source/WUD/entities/TMD/TitleMetaData.h @@ -16,20 +16,20 @@ ****************************************************************************/ #pragma once +#include +#include #include #include #include "Content.h" class TitleMetaData { public: - explicit TitleMetaData(uint8_t *data); + std::vector> contentList; - ~TitleMetaData(); + std::optional> getContentByIndex(uint16_t index); - std::vector contentList; - - Content *getContentByIndex(uint16_t index); + static std::optional> make_shared(const std::vector &data); private: - uint16_t contentCount; + explicit TitleMetaData(std::vector> pContentList); }; diff --git a/source/WUD/header/WiiUDiscHeader.cpp b/source/WUD/header/WiiUDiscHeader.cpp index e0bd46d..1b626b9 100644 --- a/source/WUD/header/WiiUDiscHeader.cpp +++ b/source/WUD/header/WiiUDiscHeader.cpp @@ -19,26 +19,48 @@ uint32_t WiiUDiscHeader::LENGTH = 131072L; -WiiUDiscHeader::WiiUDiscHeader(DiscReader *reader, uint32_t offset) { +WiiUDiscHeader::WiiUDiscHeader(std::unique_ptr pManufactorDiscId, + std::unique_ptr pDiscId, + std::unique_ptr pWiiUContentsInformation) : + manufactorDiscId(std::move(pManufactorDiscId)), + discId(std::move(pDiscId)), + wiiUContentsInformation(std::move(pWiiUContentsInformation)) { +} + +std::optional> WiiUDiscHeader::make_unique(const std::shared_ptr &discReader) { + if (!discReader->IsReady()) { + DEBUG_FUNCTION_LINE("DiscReader is not ready"); + return {}; + } + uint32_t offset = 0; uint32_t curOffset = offset; - manufactorDiscID = new WiiUManufactorDiscID(reader, 0); - curOffset += WiiUManufactorDiscID::LENGTH; - discId = new WiiUDiscID(reader, curOffset); - curOffset += WiiUDiscID::LENGTH; - wiiUContentsInformation = new WiiUContentsInformation(reader, curOffset); + auto manufactorDiscIDOpt = WiiUManufactorDiscId::make_unique(discReader); + if (!manufactorDiscIDOpt.has_value()) { + DEBUG_FUNCTION_LINE("Failed to read ManufactorDiscId"); + return {}; + } + + curOffset += WiiUManufactorDiscId::LENGTH; + auto discIdOpt = WiiUDiscId::make_unique(discReader, curOffset); + if (!discIdOpt.has_value()) { + DEBUG_FUNCTION_LINE("Failed to read DiscId"); + return {}; + } + curOffset += WiiUDiscId::LENGTH; + auto wiiUContentsInformationOpt = WiiUContentsInformation::make_unique(discReader, curOffset); + if (!wiiUContentsInformationOpt.has_value()) { + DEBUG_FUNCTION_LINE("Failed to read WiiUContentsInformation"); + return {}; + } curOffset += WiiUContentsInformation::LENGTH; if (curOffset - offset != LENGTH) { - OSFatal("Length mismatch"); + DEBUG_FUNCTION_LINE("Unexpected offset"); + return {}; } -} - -WiiUDiscHeader::~WiiUDiscHeader() { - delete manufactorDiscID; - delete discId; - delete wiiUContentsInformation; -} - -WiiUDiscHeader::WiiUDiscHeader(DiscReaderDiscDrive *pDrive) : WiiUDiscHeader(pDrive, 0) { - + DEBUG_FUNCTION_LINE(); + return std::unique_ptr(new WiiUDiscHeader( + std::move(manufactorDiscIDOpt.value()), + std::move(discIdOpt.value()), + std::move(wiiUContentsInformationOpt.value()))); } diff --git a/source/WUD/header/WiiUDiscHeader.h b/source/WUD/header/WiiUDiscHeader.h index f3ac758..dd4e56e 100644 --- a/source/WUD/header/WiiUDiscHeader.h +++ b/source/WUD/header/WiiUDiscHeader.h @@ -20,21 +20,25 @@ #include #include #include -#include "WiiUManufactorDiscID.h" -#include "WiiUDiscID.h" +#include +#include "WiiUManufactorDiscId.h" +#include "WiiUDiscId.h" class WiiUDiscHeader { - public: - explicit WiiUDiscHeader(DiscReaderDiscDrive *pDrive); - WiiUDiscHeader(DiscReader *reader, uint32_t offset); + static std::optional> make_unique(const std::shared_ptr &discReader); - ~WiiUDiscHeader(); - - WiiUManufactorDiscID *manufactorDiscID = nullptr; - WiiUDiscID *discId = nullptr; - WiiUContentsInformation *wiiUContentsInformation = nullptr; + std::unique_ptr manufactorDiscId; + std::unique_ptr discId; + std::unique_ptr wiiUContentsInformation; static uint32_t LENGTH; + +private: + explicit WiiUDiscHeader( + std::unique_ptr pManufactorDiscId, + std::unique_ptr pDiscId, + std::unique_ptr pWiiUContentsInformation + ); }; \ No newline at end of file diff --git a/source/WUD/header/WiiUDiscId.cpp b/source/WUD/header/WiiUDiscId.cpp new file mode 100644 index 0000000..052d4bf --- /dev/null +++ b/source/WUD/header/WiiUDiscId.cpp @@ -0,0 +1,54 @@ +/**************************************************************************** + * Copyright (C) 2016-2021 Maschell + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + ****************************************************************************/ +#include "WiiUDiscId.h" +#include +#include +#include + +std::optional> WiiUDiscId::make_unique(const std::shared_ptr &discReader, uint32_t offset) { + auto data = (uint8_t *) malloc(WiiUDiscId::LENGTH); + if (data == nullptr) { + DEBUG_FUNCTION_LINE("Failed to alloc memory"); + return {}; + } + + if (!discReader->readEncrypted(data, offset, WiiUDiscId::LENGTH)) { + DEBUG_FUNCTION_LINE("Failed to read data"); + return {}; + } + + if (((uint32_t *) data)[0] != WiiUDiscId::MAGIC) { + DEBUG_FUNCTION_LINE("MAGIC mismatch"); + return {}; + } + + auto majorVersion = data[5]; + auto minorVersion = data[6]; + + auto footprint = std::string((char *) &data[32]); + + free(data); + + return std::unique_ptr(new WiiUDiscId(minorVersion, majorVersion, footprint)); +} + +WiiUDiscId::WiiUDiscId(uint8_t pMinorVersion, uint8_t pMajorVersion, const std::string &pFootprint) : + minorVersion(pMinorVersion), + majorVersion(pMajorVersion), + footprint(pFootprint) { + +} diff --git a/source/WUD/header/WiiUDiscID.h b/source/WUD/header/WiiUDiscId.h similarity index 71% rename from source/WUD/header/WiiUDiscID.h rename to source/WUD/header/WiiUDiscId.h index 3e7b54c..57e5985 100644 --- a/source/WUD/header/WiiUDiscID.h +++ b/source/WUD/header/WiiUDiscId.h @@ -16,17 +16,23 @@ ****************************************************************************/ #pragma once +#include #include #include +#include +#include -class WiiUDiscID { +class WiiUDiscId { public: - WiiUDiscID(DiscReader *reader, uint32_t offset); - - static uint32_t LENGTH; - static uint32_t MAGIC; - uint8_t majorVersion; + static constexpr uint32_t LENGTH = 32768; + static constexpr uint32_t MAGIC = 0xCC549EB9; uint8_t minorVersion; + uint8_t majorVersion; std::string footprint; + + static std::optional> make_unique(const std::shared_ptr &discReader, uint32_t offset); + +private: + WiiUDiscId(uint8_t pMinorVersion, uint8_t pMajorVersion, const std::string &pFootprint); }; diff --git a/source/WUD/header/WiiUManufactorDiscID.cpp b/source/WUD/header/WiiUManufactorDiscID.cpp deleted file mode 100644 index 75500df..0000000 --- a/source/WUD/header/WiiUManufactorDiscID.cpp +++ /dev/null @@ -1,26 +0,0 @@ -/**************************************************************************** - * Copyright (C) 2016-2021 Maschell - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - ****************************************************************************/ -#include "WiiUManufactorDiscID.h" -#include - -uint32_t WiiUManufactorDiscID::LENGTH = 65536; - -WiiUManufactorDiscID::WiiUManufactorDiscID(DiscReader *reader, uint32_t offset) { - if (!reader->readEncrypted(data, offset, LENGTH)) { - OSFatal("WiiUManufactorDiscID: read failed"); - } -} diff --git a/source/WUD/header/WiiUDiscID.cpp b/source/WUD/header/WiiUManufactorDiscId.cpp similarity index 54% rename from source/WUD/header/WiiUDiscID.cpp rename to source/WUD/header/WiiUManufactorDiscId.cpp index ea585bf..5fabbe0 100644 --- a/source/WUD/header/WiiUDiscID.cpp +++ b/source/WUD/header/WiiUManufactorDiscId.cpp @@ -14,30 +14,24 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . ****************************************************************************/ -#include "WiiUDiscID.h" +#include "WiiUManufactorDiscId.h" #include +#include -uint32_t WiiUDiscID::LENGTH = 32768; -uint32_t WiiUDiscID::MAGIC = 0xCC549EB9; - -WiiUDiscID::WiiUDiscID(DiscReader *reader, uint32_t offset) { - auto data = (uint8_t *) malloc(LENGTH); - if (data == nullptr) { - OSFatal("Failed to alloc for WiiUDiscID"); +std::optional> WiiUManufactorDiscId::make_unique(const std::shared_ptr &discReader) { + if (!discReader->IsReady()) { + DEBUG_FUNCTION_LINE("DiscReader is not ready"); + return {}; } + std::array data{}; - if (!reader->readEncrypted(data, offset, LENGTH)) { - OSFatal("Failed to read data"); + if (!discReader->readEncrypted(data.data(), 0, WiiUManufactorDiscId::LENGTH)) { + DEBUG_FUNCTION_LINE("Failed to read data"); + return {}; } - - if (((uint32_t *) data)[0] != MAGIC) { - OSFatal("MAGIC FAIL"); - } - - majorVersion = data[5]; - minorVersion = data[6]; - - footprint = std::string((char *) &data[32]); - - free(data); + return std::unique_ptr(new WiiUManufactorDiscId(data)); } + +WiiUManufactorDiscId::WiiUManufactorDiscId(const std::array &pData) : data(pData) { + this->data = pData; +} \ No newline at end of file diff --git a/source/WUD/header/WiiUManufactorDiscID.h b/source/WUD/header/WiiUManufactorDiscId.h similarity index 69% rename from source/WUD/header/WiiUManufactorDiscID.h rename to source/WUD/header/WiiUManufactorDiscId.h index f729124..c0d9338 100644 --- a/source/WUD/header/WiiUManufactorDiscID.h +++ b/source/WUD/header/WiiUManufactorDiscId.h @@ -16,15 +16,20 @@ ****************************************************************************/ #pragma once +#include #include #include +#include -class WiiUManufactorDiscID { +class WiiUManufactorDiscId { public: - WiiUManufactorDiscID(DiscReader *reader, uint32_t offset); + static std::optional> make_unique(const std::shared_ptr &discReader); + + static constexpr uint32_t LENGTH = 65536; + + std::array data; - static uint32_t LENGTH; private: - uint8_t data[65536]{}; + explicit WiiUManufactorDiscId(const std::array &pData); }; diff --git a/source/utils/FSTUtils.cpp b/source/utils/FSTUtils.cpp index fbdaa38..1eb48d1 100644 --- a/source/utils/FSTUtils.cpp +++ b/source/utils/FSTUtils.cpp @@ -1,33 +1,49 @@ +/**************************************************************************** + * Copyright (C) 2016-2021 Maschell + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + ****************************************************************************/ #include "FSTUtils.h" #include "logger.h" #include -NodeEntry *FSTUtils::getFSTEntryByFullPath(DirectoryEntry *root, std::string &givenFullPath) { +std::optional> FSTUtils::getFSTEntryByFullPath(const std::shared_ptr &root, std::string &givenFullPath) { std::string fullPath = givenFullPath; if (strncmp(fullPath.c_str(), "/", 1) != 0) { fullPath = "/" + fullPath; } - DirectoryEntry *pathOpt = root; + auto pathOpt = std::optional(root); std::filesystem::path asPath = fullPath; std::string dirPath = asPath.parent_path().string(); if (dirPath != "/") { pathOpt = getFileEntryDir(root, dirPath); } - if (pathOpt == nullptr) { - return nullptr; + if (!pathOpt.has_value()) { + return {}; } - for (auto &child: pathOpt->getChildren()) { + for (auto &child: pathOpt.value()->getChildren()) { if (child->getFullPath() == fullPath) { return child; } } - return nullptr; + return {}; } -DirectoryEntry *FSTUtils::getFileEntryDir(DirectoryEntry *curEntry, std::string &string) { +std::optional> FSTUtils::getFileEntryDir(const std::shared_ptr &curEntry, std::string &string) { // We add the "/" at the end so we don't get false results when using the "startWith" function. if (!string.ends_with("/")) { string += "/"; @@ -44,18 +60,14 @@ DirectoryEntry *FSTUtils::getFileEntryDir(DirectoryEntry *curEntry, std::string return getFileEntryDir(curChild, string); } } - return nullptr; + return {}; } -SectionEntry *FSTUtils::getSectionEntryForIndex(FST *pFst, uint16_t index) { - if (pFst == nullptr || pFst->sectionEntries == nullptr) { - return nullptr; - } - +std::optional> FSTUtils::getSectionEntryForIndex(const std::shared_ptr &pFst, uint16_t index) { for (const auto &entry: pFst->sectionEntries->getSections()) { if (entry->sectionNumber == index) { return entry; } } - return nullptr; + return {}; } diff --git a/source/utils/FSTUtils.h b/source/utils/FSTUtils.h index 6390c6b..f459490 100644 --- a/source/utils/FSTUtils.h +++ b/source/utils/FSTUtils.h @@ -1,3 +1,19 @@ +/**************************************************************************** + * Copyright (C) 2016-2021 Maschell + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + ****************************************************************************/ #pragma once #include @@ -7,10 +23,10 @@ class FSTUtils { public: - static NodeEntry *getFSTEntryByFullPath(DirectoryEntry *root, std::string &givenFullPath); + static std::optional> getFSTEntryByFullPath(const std::shared_ptr &root, std::string &givenFullPath); - static DirectoryEntry *getFileEntryDir(DirectoryEntry *curEntry, std::string &string); + static std::optional> getFileEntryDir(const std::shared_ptr &curEntry, std::string &string); - static SectionEntry *getSectionEntryForIndex(FST *pFst, uint16_t index); + static std::optional> getSectionEntryForIndex(const std::shared_ptr &pFst, uint16_t index); }; diff --git a/source/utils/blocksize/AddressInBlocks.h b/source/utils/blocksize/AddressInBlocks.h index 18917bf..f92c526 100644 --- a/source/utils/blocksize/AddressInBlocks.h +++ b/source/utils/blocksize/AddressInBlocks.h @@ -21,8 +21,8 @@ class AddressInBlocks { public: - explicit AddressInBlocks(const BlockSize &blockSize, uint32_t pValue) : blockSize(blockSize) { - value = pValue; + explicit AddressInBlocks(const BlockSize &pBlockSize, uint32_t pValue) : blockSize(pBlockSize), value(pValue) { + } AddressInBlocks() = default;