From 217f0473750b960bd072128118ec1cbbd361520a Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Wed, 30 Oct 2024 00:18:04 -0700 Subject: [PATCH] hac2l: support extracting pfs contents to directory --- source/hactool_options.cpp | 2 ++ source/hactool_options.hpp | 1 + source/hactool_processor.hpp | 1 + source/hactool_processor.pfs.cpp | 36 ++++++++++++++++++++++++++++++++ 4 files changed, 40 insertions(+) diff --git a/source/hactool_options.cpp b/source/hactool_options.cpp index 629e6cb..3f08af6 100644 --- a/source/hactool_options.cpp +++ b/source/hactool_options.cpp @@ -176,6 +176,8 @@ namespace ams::hactool { MakeOptionHandler("updatedir", "[xci] Specify xci update hfs0 directory path.", [] (Options &options, const char *arg) { return CreateFilePath(std::addressof(options.update_partition_out_dir), arg); }), MakeOptionHandler("logodir", "[xci] Specify xci logo hfs0 directory path.", [] (Options &options, const char *arg) { return CreateFilePath(std::addressof(options.logo_partition_out_dir), arg); }), MakeOptionHandler("listupdate", "[xci] List update details.", [] (Options &options) { options.list_update = true; }), + MakeOptionHandler("pfsdir", "[pfs] Specify pfs directory path.", [] (Options &options, const char *arg) { return CreateFilePath(std::addressof(options.nsp_out_dir_path), arg); }), + MakeOptionHandler("nspdir", "[pfs] Specify nsp directory path. Synonym for pfsdir.", [] (Options &options, const char *arg) { return CreateFilePath(std::addressof(options.nsp_out_dir_path), arg); }), MakeOptionHandler("ciphertext", "[unused] Specify ciphertext output path.", [] (Options &options, const char *arg) { return CreateFilePath(std::addressof(options.ciphertext_out_path), arg); }), }; diff --git a/source/hactool_options.hpp b/source/hactool_options.hpp index 1781220..a7baa7c 100644 --- a/source/hactool_options.hpp +++ b/source/hactool_options.hpp @@ -62,6 +62,7 @@ namespace ams::hactool { const char *romfs_out_file_path = nullptr; const char *romfs_out_dir_path = nullptr; const char *ini_out_dir_path = nullptr; + const char *nsp_out_dir_path = nullptr; const char *default_out_dir_path = nullptr; const char *default_out_file_path = nullptr; const char *plaintext_out_path = nullptr; diff --git a/source/hactool_processor.hpp b/source/hactool_processor.hpp index bc64306..bb7d774 100644 --- a/source/hactool_processor.hpp +++ b/source/hactool_processor.hpp @@ -130,6 +130,7 @@ namespace ams::hactool { std::shared_ptr storage; std::shared_ptr fs; + u32 magic; bool is_exefs; ProcessAsNpdmContext npdm_ctx; diff --git a/source/hactool_processor.pfs.cpp b/source/hactool_processor.pfs.cpp index a3b3292..aafaa7b 100644 --- a/source/hactool_processor.pfs.cpp +++ b/source/hactool_processor.pfs.cpp @@ -29,6 +29,9 @@ namespace ams::hactool { /* Set the fs. */ ctx->storage = std::move(storage); + /* Read the magic. */ + R_TRY(ctx->storage->Read(0, std::addressof(ctx->magic), sizeof(ctx->magic))); + /* Mount the partition filesystem. */ { /* Allocate the fs. */ @@ -87,6 +90,20 @@ namespace ams::hactool { } void Processor::PrintAsPfs(ProcessAsPfsContext &ctx) { + { + auto _ = this->PrintHeader("PartitionFileSystem"); + this->PrintMagic(ctx.magic); + { + auto _ = this->PrintHeader("Files"); + + char print_prefix[1_KB + 5]; + std::memset(print_prefix, ' ', WidthToPrintFieldValue); + util::TSNPrintf(print_prefix, sizeof(print_prefix), "%s%s", m_indent_buffer, "pfs:"); + + PrintDirectory(ctx.fs, print_prefix, "/"); + } + } + if (ctx.is_exefs) { this->PrintAsNpdm(ctx.npdm_ctx); } else { @@ -95,6 +112,25 @@ namespace ams::hactool { } void Processor::SaveAsPfs(ProcessAsPfsContext &ctx) { + /* Save pfs contents. */ + { + /* Determine path to extract to. */ + const char *dir_path = nullptr; + if (dir_path == nullptr && ctx.is_exefs && m_options.exefs_out_dir_path != nullptr) { + dir_path = m_options.exefs_out_dir_path; + } + if (dir_path == nullptr && m_options.nsp_out_dir_path != nullptr) { + dir_path = m_options.nsp_out_dir_path; + } + if (dir_path == nullptr && m_options.default_out_dir_path != nullptr) { + dir_path = m_options.default_out_dir_path; + } + + /* If we have a path, extract to it. */ + if (dir_path != nullptr) { + ExtractDirectory(m_local_fs, ctx.fs, "pfs:", dir_path, "/"); + } + } if (ctx.is_exefs) { this->SaveAsNpdm(ctx.npdm_ctx); } else {