diff --git a/src/common/scope_exit.h b/src/common/scope_exit.h index 1176a72..e2ce9b3 100644 --- a/src/common/scope_exit.h +++ b/src/common/scope_exit.h @@ -41,4 +41,5 @@ ScopeExitHelper ScopeExit(Func&& func) { * } * \endcode */ -#define SCOPE_EXIT(body) auto CONCAT2(scope_exit_helper_, __LINE__) = detail::ScopeExit([&]() body) +#define SCOPE_EXIT(body) \ + auto CONCAT2(scope_exit_helper_, __LINE__) = ::detail::ScopeExit([&]() body) diff --git a/src/core/importer.cpp b/src/core/importer.cpp index e52528c..fe782cc 100644 --- a/src/core/importer.cpp +++ b/src/core/importer.cpp @@ -6,6 +6,7 @@ #include "common/assert.h" #include "common/common_paths.h" #include "common/file_util.h" +#include "common/scope_exit.h" #include "common/string_util.h" #include "core/data_container.h" #include "core/decryptor.h" @@ -60,7 +61,6 @@ bool SDMCImporter::Init() { } decryptor = std::make_unique(config.sdmc_path); - cia_builder = std::make_unique(); // Load SDMC Title DB { @@ -694,6 +694,15 @@ bool SDMCImporter::BuildCIA(CIABuildType type, const ContentSpecifier& specifier } } + { + std::lock_guard lock{cia_builder_mutex}; + cia_builder = std::make_unique(); + } + SCOPE_EXIT({ + std::lock_guard lock{cia_builder_mutex}; + cia_builder.reset(); // To release file handles, etc + }); + const bool ret = cia_builder->Init(type, destination, tmd, config, FileUtil::GetDirectoryTreeSize(physical_path), callback); if (!ret) { @@ -752,7 +761,10 @@ bool SDMCImporter::BuildCIA(CIABuildType type, const ContentSpecifier& specifier } void SDMCImporter::AbortBuildCIA() { - cia_builder->Abort(); + std::lock_guard lock{cia_builder_mutex}; + if (cia_builder) { + cia_builder->Abort(); + } } void SDMCImporter::ListTitle(std::vector& out) const { diff --git a/src/core/importer.h b/src/core/importer.h index ff5bd25..3fc308b 100644 --- a/src/core/importer.h +++ b/src/core/importer.h @@ -6,6 +6,7 @@ #include #include +#include #include #include #include "common/common_types.h" @@ -199,7 +200,9 @@ private: bool is_good{}; Config config; std::unique_ptr decryptor; + std::unique_ptr cia_builder; + std::mutex cia_builder_mutex; // The NCCH used to dump CXIs. std::unique_ptr dump_cxi_ncch; diff --git a/src/core/ncch/cia_builder.cpp b/src/core/ncch/cia_builder.cpp index d28f4a5..f0ea10f 100644 --- a/src/core/ncch/cia_builder.cpp +++ b/src/core/ncch/cia_builder.cpp @@ -67,7 +67,6 @@ bool CIABuilder::Init(CIABuildType type_, const std::string& destination, TitleM file = std::make_shared(destination, "wb"); if (!*file) { LOG_ERROR(Core, "Could not open file {}", destination); - file.reset(); return false; } @@ -82,7 +81,6 @@ bool CIABuilder::Init(CIABuildType type_, const std::string& destination, TitleM // Check for legit TMD if (!tmd.VerifyHashes() || !tmd.ValidateSignature()) { LOG_ERROR(Core, "TMD is not legit"); - file.reset(); return false; } } @@ -95,14 +93,12 @@ bool CIABuilder::Init(CIABuildType type_, const std::string& destination, TitleM header.cert_size = CIA_CERT_SIZE; if (!WriteCert(config.certs_db_path)) { LOG_ERROR(Core, "Could not write cert to file {}", destination); - file.reset(); return false; } // Ticket ticket_offset = Common::AlignUp(cert_offset + header.cert_size, CIA_ALIGNMENT); if (!WriteTicket(config.ticket_db_path, config.enc_title_keys_bin_path)) { - file.reset(); return false; } @@ -219,7 +215,6 @@ bool CIABuilder::WriteTicket(const std::string& ticket_db_path, file->Seek(ticket_offset, SEEK_SET); if (!ticket.Save(*file)) { LOG_ERROR(Core, "Could not write ticket"); - file.reset(); return false; } return true; @@ -273,7 +268,6 @@ bool CIABuilder::AddContent(u16 content_id, NCCHContainer& ncch) { } if (ret != ResultStatus::Success) { - file.reset(); return false; } file->GetHash(tmd_chunk.hash.data()); @@ -300,7 +294,6 @@ bool CIABuilder::AddContent(u16 content_id, NCCHContainer& ncch) { if (!decryptor.CryptAndWriteFile(ncch.file, ncch.file->GetSize(), file, progress_callback)) { - file.reset(); return false; } @@ -314,7 +307,6 @@ bool CIABuilder::AddContent(u16 content_id, NCCHContainer& ncch) { } if (!verified) { LOG_ERROR(Core, "Hash dismatch for content {}", content_id); - file.reset(); return false; } } @@ -355,7 +347,6 @@ bool CIABuilder::Finalize() { file->Seek(0, SEEK_SET); if (file->WriteBytes(&header, sizeof(header)) != sizeof(header)) { LOG_ERROR(Core, "Failed to write header"); - file.reset(); return false; } @@ -365,7 +356,6 @@ bool CIABuilder::Finalize() { } file->Seek(tmd_offset, SEEK_SET); if (tmd.Save(*file) != ResultStatus::Success) { - file.reset(); return false; } @@ -374,13 +364,11 @@ bool CIABuilder::Finalize() { file->Seek(written, SEEK_SET); if (file->WriteBytes(&meta, sizeof(meta)) != sizeof(meta)) { LOG_ERROR(Core, "Failed to write meta"); - file.reset(); return false; } } callback(total_size, total_size); - file.reset(); return true; }