Migrate to new extract system (incomplete) + submodule update.

This commit is contained in:
jakcron 2022-02-01 13:16:17 +08:00
parent 71452fcf50
commit 162452655b
23 changed files with 367 additions and 79 deletions

2
deps/libfmt vendored

@ -1 +1 @@
Subproject commit 53d084cc0c6ea61bbb535a873299b0ae5ff9a05d Subproject commit ae6df0aead2fdaae8a0b117524a6eb036c8fa075

@ -1 +1 @@
Subproject commit e93b71a2d2cebf060df00891fd8268f14288af63 Subproject commit 64adf7e5ee46355270e370231ea933ed82509915

2
deps/libtoolchain vendored

@ -1 +1 @@
Subproject commit d7b48027a93ef69b9c6b0d78fe392abc0bce5e68 Subproject commit ec4144330589b96c53adc10dac36f654821327a0

View file

@ -48,6 +48,11 @@ void nstool::AssetProcess::setRomfsShowFsTree(bool show_fs_tree)
mRomfs.setShowFsTree(show_fs_tree); mRomfs.setShowFsTree(show_fs_tree);
} }
void nstool::AssetProcess::setRomfsArchiveJobs(const std::vector<nstool::ArchiveJob>& jobs)
{
mRomfs.setArchiveJobs(jobs);
}
void nstool::AssetProcess::setRomfsExtractJobs(const std::vector<nstool::ExtractJob>& extract_jobs) void nstool::AssetProcess::setRomfsExtractJobs(const std::vector<nstool::ExtractJob>& extract_jobs)
{ {
mRomfs.setExtractJobs(extract_jobs); mRomfs.setExtractJobs(extract_jobs);

View file

@ -21,6 +21,7 @@ public:
void setIconExtractPath(const tc::io::Path& path); void setIconExtractPath(const tc::io::Path& path);
void setNacpExtractPath(const tc::io::Path& path); void setNacpExtractPath(const tc::io::Path& path);
void setRomfsArchiveJobs(const std::vector<nstool::ArchiveJob>& jobs);
void setRomfsShowFsTree(bool show_fs_tree); void setRomfsShowFsTree(bool show_fs_tree);
void setRomfsExtractJobs(const std::vector<nstool::ExtractJob>& extract_jobs); void setRomfsExtractJobs(const std::vector<nstool::ExtractJob>& extract_jobs);
private: private:

View file

@ -14,6 +14,7 @@ nstool::FsProcess::FsProcess() :
mShowFsTree(false), mShowFsTree(false),
mFsRootLabel(), mFsRootLabel(),
mExtractJobs(), mExtractJobs(),
mArchiveJobs(),
mDataCache(0x10000) mDataCache(0x10000)
{ {
@ -26,6 +27,8 @@ void nstool::FsProcess::process()
throw tc::InvalidOperationException(mModuleLabel, "No input filesystem"); throw tc::InvalidOperationException(mModuleLabel, "No input filesystem");
} }
processArchiveJobs();
if (mShowFsInfo) if (mShowFsInfo)
{ {
fmt::print("[{:s}]\n", mFsFormatName.isSet() ? mFsFormatName.get() : "FileSystem/Info"); fmt::print("[{:s}]\n", mFsFormatName.isSet() ? mFsFormatName.get() : "FileSystem/Info");
@ -81,6 +84,115 @@ void nstool::FsProcess::setExtractJobs(const std::vector<nstool::ExtractJob>& ex
mExtractJobs = extract_jobs; mExtractJobs = extract_jobs;
} }
void nstool::FsProcess::setArchiveJobs(const std::vector<nstool::ArchiveJob>& archive_jobs)
{
mArchiveJobs = archive_jobs;
}
void nstool::FsProcess::processArchiveJobs()
{
for (auto itr = mArchiveJobs.begin(); itr != mArchiveJobs.end(); itr++)
{
/*
std::string archive_path_str, extract_base_path_str;
tc::io::PathUtil::pathToUnixUTF8(itr->archive_path, archive_path_str);
tc::io::PathUtil::pathToUnixUTF8(itr->extract_base_path, extract_base_path_str);
*/
// Qualify Archive Path
tc::io::Path qualified_archive_path;
bool is_dir = false, is_file = false;
if (!qualifyArchivePath(itr->archive_path, qualified_archive_path, is_dir, is_file))
{
std::string archive_path_str;
tc::io::PathUtil::pathToUnixUTF8(itr->archive_path, archive_path_str);
fmt::print("Path \"{}\" did not exist for this archive.\n", archive_path_str);
continue;
}
// print
{
std::string qualified_archive_path_str;
tc::io::PathUtil::pathToUnixUTF8(qualified_archive_path, qualified_archive_path_str);
fmt::print("Path \"{}\" was valid, is_dir={}, is_file={}.\n", qualified_archive_path_str, is_dir, is_file);
}
if (itr->job_action == ArchiveJob::JobAction::DoNothing)
{
fmt::print("DoNothing\n");
continue;
}
else if (itr->job_action == ArchiveJob::JobAction::ListFileTree)
{
fmt::print("ListFileTree\n");
}
else if (itr->job_action == ArchiveJob::JobAction::Extract)
{
fmt::print("Extract\n");
}
else
{
fmt::print("Unsupported ArchiveJob::JobAction\n");
}
}
}
bool nstool::FsProcess::qualifyArchivePath(const tc::io::Path& path, tc::io::Path& qualified_path, bool& is_dir, bool& is_file)
{
// test if the path is for a directory
try {
tc::io::sDirectoryListing dir_listing;
// getDirectoryListing will throw if this is not a directory
mInputFs->getDirectoryListing(path, dir_listing);
// set state and return
qualified_path = dir_listing.abs_path;
is_dir = true;
is_file = false;
return true;
} catch (tc::io::DirectoryNotFoundException&) {
// acceptable exception, just means directory didn't exist
}
// test if the path is for a file
try {
// opening the file will throw if the file doesn't exist
std::shared_ptr<tc::io::IStream> file_stream;
mInputFs->openFile(path, tc::io::FileMode::Open, tc::io::FileAccess::Read, file_stream);
// breakup the path into the parent directory path and file name
tc::io::Path parent_dir_path = path;
parent_dir_path.pop_back(); // remove the last element, which should be the file name (which should exist because opening the file worked)
std::string file_name = path.back();
// get the qualified file path
tc::io::sDirectoryListing dir_listing;
// getDirectoryListing will throw if this is not a directory
mInputFs->getDirectoryListing(parent_dir_path, dir_listing);
// set state
qualified_path = dir_listing.abs_path + file_name;
is_dir = false;
is_file = true;
return true;
} catch (tc::io::FileNotFoundException&) {
// acceptable exception, just means file didn't exist
}
qualified_path = tc::io::Path();
is_dir = false;
is_file = false;
return false;
}
void nstool::FsProcess::printFs() void nstool::FsProcess::printFs()
{ {
fmt::print("[{:s}/Tree]\n", (mFsFormatName.isSet() ? mFsFormatName.get() : "FileSystem")); fmt::print("[{:s}/Tree]\n", (mFsFormatName.isSet() ? mFsFormatName.get() : "FileSystem"));

View file

@ -21,6 +21,7 @@ public:
void setShowFsTree(bool show_fs_tree); void setShowFsTree(bool show_fs_tree);
void setFsRootLabel(const std::string& root_label); void setFsRootLabel(const std::string& root_label);
void setExtractJobs(const std::vector<nstool::ExtractJob>& extract_jobs); void setExtractJobs(const std::vector<nstool::ExtractJob>& extract_jobs);
void setArchiveJobs(const std::vector<nstool::ArchiveJob>& archive_jobs);
private: private:
std::string mModuleLabel; std::string mModuleLabel;
@ -37,10 +38,15 @@ private:
// extract jobs // extract jobs
std::vector<nstool::ExtractJob> mExtractJobs; std::vector<nstool::ExtractJob> mExtractJobs;
std::vector<nstool::ArchiveJob> mArchiveJobs;
// cache for file extract // cache for file extract
tc::ByteData mDataCache; tc::ByteData mDataCache;
void processArchiveJobs();
bool qualifyArchivePath(const tc::io::Path& path, tc::io::Path& qualified_path, bool& is_dir, bool& is_file);
void printFs(); void printFs();
void extractFs(); void extractFs();

View file

@ -16,10 +16,12 @@ nstool::GameCardProcess::GameCardProcess() :
mFile(), mFile(),
mCliOutputMode(true, false, false, false), mCliOutputMode(true, false, false, false),
mVerify(false), mVerify(false),
mListFs(false), mIsTrueSdkXci(false),
mIsSdkXciEncrypted(false),
mGcHeaderOffset(0),
mProccessExtendedHeader(false), mProccessExtendedHeader(false),
mRootPfs(), mFileSystem(),
mExtractJobs() mFsProcess()
{ {
} }
@ -59,14 +61,19 @@ void nstool::GameCardProcess::setVerifyMode(bool verify)
mVerify = verify; mVerify = verify;
} }
void nstool::GameCardProcess::setExtractJobs(const std::vector<nstool::ExtractJob> extract_jobs) void nstool::GameCardProcess::setArchiveJobs(const std::vector<nstool::ArchiveJob>& jobs)
{ {
mExtractJobs = extract_jobs; mFsProcess.setArchiveJobs(jobs);
} }
void nstool::GameCardProcess::setShowFsTree(bool show_fs_tree) void nstool::GameCardProcess::setShowFsTree(bool show_fs_tree)
{ {
mListFs = show_fs_tree; mFsProcess.setShowFsTree(show_fs_tree);
}
void nstool::GameCardProcess::setExtractJobs(const std::vector<nstool::ExtractJob> extract_jobs)
{
mFsProcess.setExtractJobs(extract_jobs);
} }
void nstool::GameCardProcess::importHeader() void nstool::GameCardProcess::importHeader()
@ -266,21 +273,16 @@ void nstool::GameCardProcess::processRootPfs()
std::shared_ptr<tc::io::IStream> gc_fs_raw = std::make_shared<tc::io::SubStream>(tc::io::SubStream(mFile, mHdr.getPartitionFsAddress(), nn::hac::GameCardUtil::blockToAddr(mHdr.getValidDataEndPage()+1) - mHdr.getPartitionFsAddress())); std::shared_ptr<tc::io::IStream> gc_fs_raw = std::make_shared<tc::io::SubStream>(tc::io::SubStream(mFile, mHdr.getPartitionFsAddress(), nn::hac::GameCardUtil::blockToAddr(mHdr.getValidDataEndPage()+1) - mHdr.getPartitionFsAddress()));
auto gc_vfs_meta = nn::hac::GameCardFsMetaGenerator(gc_fs_raw, mHdr.getPartitionFsSize(), mVerify ? nn::hac::GameCardFsMetaGenerator::ValidationMode_Warn : nn::hac::GameCardFsMetaGenerator::ValidationMode_None); auto gc_vfs_meta = nn::hac::GameCardFsMetaGenerator(gc_fs_raw, mHdr.getPartitionFsSize(), mVerify ? nn::hac::GameCardFsMetaGenerator::ValidationMode_Warn : nn::hac::GameCardFsMetaGenerator::ValidationMode_None);
std::shared_ptr<tc::io::IStorage> gc_vfs = std::make_shared<tc::io::VirtualFileSystem>(tc::io::VirtualFileSystem(gc_vfs_meta) ); mFileSystem = std::make_shared<tc::io::VirtualFileSystem>(tc::io::VirtualFileSystem(gc_vfs_meta) );
FsProcess fs_proc; mFsProcess.setInputFileSystem(mFileSystem);
mFsProcess.setFsFormatName("PartitionFs");
fs_proc.setInputFileSystem(gc_vfs); mFsProcess.setFsProperties({
fs_proc.setFsFormatName("PartitionFs");
fs_proc.setFsProperties({
fmt::format("Type: Nested HFS0"), fmt::format("Type: Nested HFS0"),
fmt::format("DirNum: {:d}", gc_vfs_meta.dir_entries.empty() ? 0 : gc_vfs_meta.dir_entries.size() - 1), // -1 to not include root directory fmt::format("DirNum: {:d}", gc_vfs_meta.dir_entries.empty() ? 0 : gc_vfs_meta.dir_entries.size() - 1), // -1 to not include root directory
fmt::format("FileNum: {:d}", gc_vfs_meta.file_entries.size()) fmt::format("FileNum: {:d}", gc_vfs_meta.file_entries.size())
}); });
fs_proc.setShowFsInfo(mCliOutputMode.show_basic_info); mFsProcess.setShowFsInfo(mCliOutputMode.show_basic_info);
fs_proc.setShowFsTree(mListFs); mFsProcess.setFsRootLabel(kXciMountPointName);
fs_proc.setFsRootLabel(kXciMountPointName); mFsProcess.process();
fs_proc.setExtractJobs(mExtractJobs);
fs_proc.process();
} }

View file

@ -21,6 +21,7 @@ public:
void setVerifyMode(bool verify); void setVerifyMode(bool verify);
// fs specific // fs specific
void setArchiveJobs(const std::vector<nstool::ArchiveJob>& jobs);
void setShowFsTree(bool show_fs_tree); void setShowFsTree(bool show_fs_tree);
void setExtractJobs(const std::vector<nstool::ExtractJob> extract_jobs); void setExtractJobs(const std::vector<nstool::ExtractJob> extract_jobs);
private: private:
@ -32,7 +33,6 @@ private:
KeyBag mKeyCfg; KeyBag mKeyCfg;
CliOutputMode mCliOutputMode; CliOutputMode mCliOutputMode;
bool mVerify; bool mVerify;
bool mListFs;
bool mIsTrueSdkXci; bool mIsTrueSdkXci;
bool mIsSdkXciEncrypted; bool mIsSdkXciEncrypted;
@ -42,8 +42,9 @@ private:
nn::hac::detail::sha256_hash_t mHdrHash; nn::hac::detail::sha256_hash_t mHdrHash;
nn::hac::GameCardHeader mHdr; nn::hac::GameCardHeader mHdr;
PfsProcess mRootPfs; // fs processing
std::vector<nstool::ExtractJob> mExtractJobs; std::shared_ptr<tc::io::IStorage> mFileSystem;
FsProcess mFsProcess;
void importHeader(); void importHeader();
void displayHeader(); void displayHeader();

View file

@ -243,7 +243,7 @@ void nstool::KipProcess::displayKernelCap(const nn::hac::KernelCapabilityControl
} }
if (kern.getMiscParams().isSet()) if (kern.getMiscParams().isSet())
{ {
fmt::print(" ProgramType: {:s} ({:d})\n", nn::hac::KernelCapabilityUtil::getProgramTypeAsString(kern.getMiscParams().getProgramType()), kern.getMiscParams().getProgramType()); fmt::print(" ProgramType: {:s} ({:d})\n", nn::hac::KernelCapabilityUtil::getProgramTypeAsString(kern.getMiscParams().getProgramType()), (uint32_t)kern.getMiscParams().getProgramType());
} }
if (kern.getKernelVersion().isSet()) if (kern.getKernelVersion().isSet())
{ {

View file

@ -169,7 +169,7 @@ void nstool::MetaProcess::validateAciFromAcid(const nn::hac::AccessControlInfo&
if (rightFound == false) if (rightFound == false)
{ {
fmt::print("[WARNING] ACI/FAC SaveDataOwnerId: FAIL (0x{:016x} ({:d}) not permitted)\n", aci.getFileSystemAccessControl().getSaveDataOwnerIdList()[i].id, aci.getFileSystemAccessControl().getSaveDataOwnerIdList()[i].access_type); fmt::print("[WARNING] ACI/FAC SaveDataOwnerId: FAIL (0x{:016x} ({:d}) not permitted)\n", aci.getFileSystemAccessControl().getSaveDataOwnerIdList()[i].id, (uint32_t)aci.getFileSystemAccessControl().getSaveDataOwnerIdList()[i].access_type);
} }
} }
@ -268,7 +268,7 @@ void nstool::MetaProcess::validateAciFromAcid(const nn::hac::AccessControlInfo&
// check misc params // check misc params
if (aci.getKernelCapabilities().getMiscParams().getProgramType() != acid.getKernelCapabilities().getMiscParams().getProgramType()) if (aci.getKernelCapabilities().getMiscParams().getProgramType() != acid.getKernelCapabilities().getMiscParams().getProgramType())
{ {
fmt::print("[WARNING] ACI/KC ProgramType: FAIL ({:d} not permitted)\n", aci.getKernelCapabilities().getMiscParams().getProgramType()); fmt::print("[WARNING] ACI/KC ProgramType: FAIL ({:d} not permitted)\n", (uint32_t)aci.getKernelCapabilities().getMiscParams().getProgramType());
} }
// check kernel version // check kernel version
uint32_t aciKernelVersion = (uint32_t)aci.getKernelCapabilities().getKernelVersion().getVerMajor() << 16 | (uint32_t)aci.getKernelCapabilities().getKernelVersion().getVerMinor(); uint32_t aciKernelVersion = (uint32_t)aci.getKernelCapabilities().getKernelVersion().getVerMajor() << 16 | (uint32_t)aci.getKernelCapabilities().getKernelVersion().getVerMinor();
@ -328,7 +328,7 @@ void nstool::MetaProcess::displayAciDescHdr(const nn::hac::AccessControlInfoDesc
fmt::print(" Flags: \n"); fmt::print(" Flags: \n");
fmt::print(" Production: {}\n", acid.getProductionFlag()); fmt::print(" Production: {}\n", acid.getProductionFlag());
fmt::print(" Unqualified Approval: {}\n", acid.getUnqualifiedApprovalFlag()); fmt::print(" Unqualified Approval: {}\n", acid.getUnqualifiedApprovalFlag());
fmt::print(" Memory Region: {:s} ({:d})\n", nn::hac::AccessControlInfoUtil::getMemoryRegionAsString(acid.getMemoryRegion()), acid.getMemoryRegion()); fmt::print(" Memory Region: {:s} ({:d})\n", nn::hac::AccessControlInfoUtil::getMemoryRegionAsString(acid.getMemoryRegion()), (uint32_t)acid.getMemoryRegion());
fmt::print(" ProgramID Restriction\n"); fmt::print(" ProgramID Restriction\n");
fmt::print(" Min: 0x{:016x}\n", acid.getProgramIdRestrict().min); fmt::print(" Min: 0x{:016x}\n", acid.getProgramIdRestrict().min);
fmt::print(" Max: 0x{:016x}\n", acid.getProgramIdRestrict().max); fmt::print(" Max: 0x{:016x}\n", acid.getProgramIdRestrict().max);
@ -347,7 +347,7 @@ void nstool::MetaProcess::displayFac(const nn::hac::FileSystemAccessControl& fac
std::string flag_string = nn::hac::FileSystemAccessUtil::getFsAccessFlagAsString(nn::hac::fac::FsAccessFlag(*itr)); std::string flag_string = nn::hac::FileSystemAccessUtil::getFsAccessFlagAsString(nn::hac::fac::FsAccessFlag(*itr));
if (mCliOutputMode.show_extended_info) if (mCliOutputMode.show_extended_info)
{ {
fs_access_str_list.push_back(fmt::format("{:s} (bit {:d})", flag_string, *itr)); fs_access_str_list.push_back(fmt::format("{:s} (bit {:d})", flag_string, (uint32_t)*itr));
} }
else else
{ {
@ -445,7 +445,7 @@ void nstool::MetaProcess::displayKernelCap(const nn::hac::KernelCapabilityContro
} }
if (kern.getMiscParams().isSet()) if (kern.getMiscParams().isSet())
{ {
fmt::print(" ProgramType: {:s} ({:d})\n", nn::hac::KernelCapabilityUtil::getProgramTypeAsString(kern.getMiscParams().getProgramType()), kern.getMiscParams().getProgramType()); fmt::print(" ProgramType: {:s} ({:d})\n", nn::hac::KernelCapabilityUtil::getProgramTypeAsString(kern.getMiscParams().getProgramType()), (uint32_t)kern.getMiscParams().getProgramType());
} }
if (kern.getKernelVersion().isSet()) if (kern.getKernelVersion().isSet())
{ {

View file

@ -69,6 +69,11 @@ void nstool::NcaProcess::setVerifyMode(bool verify)
mVerify = verify; mVerify = verify;
} }
void nstool::NcaProcess::setArchiveJobs(const std::vector<nstool::ArchiveJob>& jobs)
{
mFsProcess.setArchiveJobs(jobs);
}
void nstool::NcaProcess::setShowFsTree(bool show_fs_tree) void nstool::NcaProcess::setShowFsTree(bool show_fs_tree)
{ {
mFsProcess.setShowFsTree(show_fs_tree); mFsProcess.setShowFsTree(show_fs_tree);

View file

@ -23,6 +23,7 @@ public:
void setVerifyMode(bool verify); void setVerifyMode(bool verify);
// fs specific // fs specific
void setArchiveJobs(const std::vector<nstool::ArchiveJob>& jobs);
void setShowFsTree(bool show_fs_tree); void setShowFsTree(bool show_fs_tree);
void setFsRootLabel(const std::string& root_label); void setFsRootLabel(const std::string& root_label);
void setExtractJobs(const std::vector<nstool::ExtractJob>& extract_jobs); void setExtractJobs(const std::vector<nstool::ExtractJob>& extract_jobs);

View file

@ -64,6 +64,11 @@ void nstool::NroProcess::setAssetNacpExtractPath(const tc::io::Path& path)
mAssetProc.setNacpExtractPath(path); mAssetProc.setNacpExtractPath(path);
} }
void nstool::NroProcess::setAssetRomfsArchiveJobs(const std::vector<nstool::ArchiveJob>& jobs)
{
mAssetProc.setRomfsArchiveJobs(jobs);
}
void nstool::NroProcess::setAssetRomfsShowFsTree(bool show_fs_tree) void nstool::NroProcess::setAssetRomfsShowFsTree(bool show_fs_tree)
{ {
mAssetProc.setRomfsShowFsTree(show_fs_tree); mAssetProc.setRomfsShowFsTree(show_fs_tree);

View file

@ -25,6 +25,7 @@ public:
// for homebrew NROs with Asset blobs appended // for homebrew NROs with Asset blobs appended
void setAssetIconExtractPath(const tc::io::Path& path); void setAssetIconExtractPath(const tc::io::Path& path);
void setAssetNacpExtractPath(const tc::io::Path& path); void setAssetNacpExtractPath(const tc::io::Path& path);
void setAssetRomfsArchiveJobs(const std::vector<nstool::ArchiveJob>& jobs);
void setAssetRomfsShowFsTree(bool show_fs_tree); void setAssetRomfsShowFsTree(bool show_fs_tree);
void setAssetRomfsExtractJobs(const std::vector<nstool::ExtractJob>& extract_jobs); void setAssetRomfsExtractJobs(const std::vector<nstool::ExtractJob>& extract_jobs);

View file

@ -90,6 +90,11 @@ void nstool::PfsProcess::setVerifyMode(bool verify)
mVerify = verify; mVerify = verify;
} }
void nstool::PfsProcess::setArchiveJobs(const std::vector<nstool::ArchiveJob>& jobs)
{
mFsProcess.setArchiveJobs(jobs);
}
void nstool::PfsProcess::setShowFsTree(bool show_fs_tree) void nstool::PfsProcess::setShowFsTree(bool show_fs_tree)
{ {
mFsProcess.setShowFsTree(show_fs_tree); mFsProcess.setShowFsTree(show_fs_tree);

View file

@ -19,6 +19,7 @@ public:
void setVerifyMode(bool verify); void setVerifyMode(bool verify);
// fs specific // fs specific
void setArchiveJobs(const std::vector<nstool::ArchiveJob>& jobs);
void setShowFsTree(bool show_fs_tree); void setShowFsTree(bool show_fs_tree);
void setFsRootLabel(const std::string& root_label); void setFsRootLabel(const std::string& root_label);
void setExtractJobs(const std::vector<nstool::ExtractJob>& extract_jobs); void setExtractJobs(const std::vector<nstool::ExtractJob>& extract_jobs);

View file

@ -112,6 +112,11 @@ void nstool::RomfsProcess::setVerifyMode(bool verify)
mVerify = verify; mVerify = verify;
} }
void nstool::RomfsProcess::setArchiveJobs(const std::vector<nstool::ArchiveJob>& jobs)
{
mFsProcess.setArchiveJobs(jobs);
}
void nstool::RomfsProcess::setFsRootLabel(const std::string& root_label) void nstool::RomfsProcess::setFsRootLabel(const std::string& root_label)
{ {
mFsProcess.setFsRootLabel(root_label); mFsProcess.setFsRootLabel(root_label);

View file

@ -19,6 +19,7 @@ public:
void setVerifyMode(bool verify); void setVerifyMode(bool verify);
// fs specific // fs specific
void setArchiveJobs(const std::vector<nstool::ArchiveJob>& jobs);
void setFsRootLabel(const std::string& root_label); void setFsRootLabel(const std::string& root_label);
void setExtractJobs(const std::vector<nstool::ExtractJob>& extract_jobs); void setExtractJobs(const std::vector<nstool::ExtractJob>& extract_jobs);
void setShowFsTree(bool show_fs_tree); void setShowFsTree(bool show_fs_tree);

View file

@ -9,8 +9,6 @@
#include <tc/io/FileStream.h> #include <tc/io/FileStream.h>
#include <tc/io/StreamSource.h> #include <tc/io/StreamSource.h>
#include <nn/hac/ContentArchiveUtil.h> #include <nn/hac/ContentArchiveUtil.h>
#include <nn/hac/AesKeygen.h> #include <nn/hac/AesKeygen.h>
#include <nn/hac/define/gc.h> #include <nn/hac/define/gc.h>
@ -42,6 +40,11 @@ public:
throw tc::InvalidOperationException("getOptionStrings() not defined for UnkOptionHandler."); throw tc::InvalidOperationException("getOptionStrings() not defined for UnkOptionHandler.");
} }
const std::vector<std::string>& getOptionRegexPatterns() const
{
throw tc::InvalidOperationException("getOptionRegexPatterns() not defined for UnkOptionHandler.");
}
void processOption(const std::string& option, const std::vector<std::string>& params) void processOption(const std::string& option, const std::vector<std::string>& params)
{ {
throw tc::Exception(mModuleLabel, "Unrecognized option: \"" + option + "\""); throw tc::Exception(mModuleLabel, "Unrecognized option: \"" + option + "\"");
@ -55,7 +58,8 @@ class DeprecatedOptionHandler : public tc::cli::OptionParser::IOptionHandler
public: public:
DeprecatedOptionHandler(const std::string& warn_message, const std::vector<std::string>& opts) : DeprecatedOptionHandler(const std::string& warn_message, const std::vector<std::string>& opts) :
mWarnMessage(warn_message), mWarnMessage(warn_message),
mOptStrings(opts) mOptStrings(opts),
mOptRegex()
{} {}
const std::vector<std::string>& getOptionStrings() const const std::vector<std::string>& getOptionStrings() const
@ -63,6 +67,11 @@ public:
return mOptStrings; return mOptStrings;
} }
const std::vector<std::string>& getOptionRegexPatterns() const
{
return mOptRegex;
}
void processOption(const std::string& option, const std::vector<std::string>& params) void processOption(const std::string& option, const std::vector<std::string>& params)
{ {
fmt::print("[WARNING] Option \"{}\" is deprecated.{}{}\n", option, (mWarnMessage.empty() ? "" : " "), mWarnMessage); fmt::print("[WARNING] Option \"{}\" is deprecated.{}{}\n", option, (mWarnMessage.empty() ? "" : " "), mWarnMessage);
@ -70,6 +79,7 @@ public:
private: private:
std::string mWarnMessage; std::string mWarnMessage;
std::vector<std::string> mOptStrings; std::vector<std::string> mOptStrings;
std::vector<std::string> mOptRegex;
}; };
class FlagOptionHandler : public tc::cli::OptionParser::IOptionHandler class FlagOptionHandler : public tc::cli::OptionParser::IOptionHandler
@ -77,7 +87,8 @@ class FlagOptionHandler : public tc::cli::OptionParser::IOptionHandler
public: public:
FlagOptionHandler(bool& flag, const std::vector<std::string>& opts) : FlagOptionHandler(bool& flag, const std::vector<std::string>& opts) :
mFlag(flag), mFlag(flag),
mOptStrings(opts) mOptStrings(opts),
mOptRegex()
{} {}
const std::vector<std::string>& getOptionStrings() const const std::vector<std::string>& getOptionStrings() const
@ -85,6 +96,11 @@ public:
return mOptStrings; return mOptStrings;
} }
const std::vector<std::string>& getOptionRegexPatterns() const
{
return mOptRegex;
}
void processOption(const std::string& option, const std::vector<std::string>& params) void processOption(const std::string& option, const std::vector<std::string>& params)
{ {
if (params.size() != 0) if (params.size() != 0)
@ -97,6 +113,7 @@ public:
private: private:
bool& mFlag; bool& mFlag;
std::vector<std::string> mOptStrings; std::vector<std::string> mOptStrings;
std::vector<std::string> mOptRegex;
}; };
class SingleParamStringOptionHandler : public tc::cli::OptionParser::IOptionHandler class SingleParamStringOptionHandler : public tc::cli::OptionParser::IOptionHandler
@ -104,7 +121,8 @@ class SingleParamStringOptionHandler : public tc::cli::OptionParser::IOptionHand
public: public:
SingleParamStringOptionHandler(tc::Optional<std::string>& param, const std::vector<std::string>& opts) : SingleParamStringOptionHandler(tc::Optional<std::string>& param, const std::vector<std::string>& opts) :
mParam(param), mParam(param),
mOptStrings(opts) mOptStrings(opts),
mOptRegex()
{} {}
const std::vector<std::string>& getOptionStrings() const const std::vector<std::string>& getOptionStrings() const
@ -112,6 +130,11 @@ public:
return mOptStrings; return mOptStrings;
} }
const std::vector<std::string>& getOptionRegexPatterns() const
{
return mOptRegex;
}
void processOption(const std::string& option, const std::vector<std::string>& params) void processOption(const std::string& option, const std::vector<std::string>& params)
{ {
if (params.size() != 1) if (params.size() != 1)
@ -124,6 +147,7 @@ public:
private: private:
tc::Optional<std::string>& mParam; tc::Optional<std::string>& mParam;
std::vector<std::string> mOptStrings; std::vector<std::string> mOptStrings;
std::vector<std::string> mOptRegex;
}; };
class SingleParamPathOptionHandler : public tc::cli::OptionParser::IOptionHandler class SingleParamPathOptionHandler : public tc::cli::OptionParser::IOptionHandler
@ -131,7 +155,8 @@ class SingleParamPathOptionHandler : public tc::cli::OptionParser::IOptionHandle
public: public:
SingleParamPathOptionHandler(tc::Optional<tc::io::Path>& param, const std::vector<std::string>& opts) : SingleParamPathOptionHandler(tc::Optional<tc::io::Path>& param, const std::vector<std::string>& opts) :
mParam(param), mParam(param),
mOptStrings(opts) mOptStrings(opts),
mOptRegex()
{} {}
const std::vector<std::string>& getOptionStrings() const const std::vector<std::string>& getOptionStrings() const
@ -139,6 +164,11 @@ public:
return mOptStrings; return mOptStrings;
} }
const std::vector<std::string>& getOptionRegexPatterns() const
{
return mOptRegex;
}
void processOption(const std::string& option, const std::vector<std::string>& params) void processOption(const std::string& option, const std::vector<std::string>& params)
{ {
if (params.size() != 1) if (params.size() != 1)
@ -151,6 +181,7 @@ public:
private: private:
tc::Optional<tc::io::Path>& mParam; tc::Optional<tc::io::Path>& mParam;
std::vector<std::string> mOptStrings; std::vector<std::string> mOptStrings;
std::vector<std::string> mOptRegex;
}; };
class SingleParamSizetOptionHandler : public tc::cli::OptionParser::IOptionHandler class SingleParamSizetOptionHandler : public tc::cli::OptionParser::IOptionHandler
@ -158,7 +189,8 @@ class SingleParamSizetOptionHandler : public tc::cli::OptionParser::IOptionHandl
public: public:
SingleParamSizetOptionHandler(size_t& param, const std::vector<std::string>& opts) : SingleParamSizetOptionHandler(size_t& param, const std::vector<std::string>& opts) :
mParam(param), mParam(param),
mOptStrings(opts) mOptStrings(opts),
mOptRegex()
{} {}
const std::vector<std::string>& getOptionStrings() const const std::vector<std::string>& getOptionStrings() const
@ -166,6 +198,11 @@ public:
return mOptStrings; return mOptStrings;
} }
const std::vector<std::string>& getOptionRegexPatterns() const
{
return mOptRegex;
}
void processOption(const std::string& option, const std::vector<std::string>& params) void processOption(const std::string& option, const std::vector<std::string>& params)
{ {
if (params.size() != 1) if (params.size() != 1)
@ -178,6 +215,7 @@ public:
private: private:
size_t& mParam; size_t& mParam;
std::vector<std::string> mOptStrings; std::vector<std::string> mOptStrings;
std::vector<std::string> mOptRegex;
}; };
class SingleParamAesKeyOptionHandler : public tc::cli::OptionParser::IOptionHandler class SingleParamAesKeyOptionHandler : public tc::cli::OptionParser::IOptionHandler
@ -185,7 +223,8 @@ class SingleParamAesKeyOptionHandler : public tc::cli::OptionParser::IOptionHand
public: public:
SingleParamAesKeyOptionHandler(tc::Optional<nstool::KeyBag::aes128_key_t>& param, const std::vector<std::string>& opts) : SingleParamAesKeyOptionHandler(tc::Optional<nstool::KeyBag::aes128_key_t>& param, const std::vector<std::string>& opts) :
mParam(param), mParam(param),
mOptStrings(opts) mOptStrings(opts),
mOptRegex()
{} {}
const std::vector<std::string>& getOptionStrings() const const std::vector<std::string>& getOptionStrings() const
@ -193,6 +232,11 @@ public:
return mOptStrings; return mOptStrings;
} }
const std::vector<std::string>& getOptionRegexPatterns() const
{
return mOptRegex;
}
void processOption(const std::string& option, const std::vector<std::string>& params) void processOption(const std::string& option, const std::vector<std::string>& params)
{ {
if (params.size() != 1) if (params.size() != 1)
@ -214,6 +258,7 @@ public:
private: private:
tc::Optional<nstool::KeyBag::aes128_key_t>& mParam; tc::Optional<nstool::KeyBag::aes128_key_t>& mParam;
std::vector<std::string> mOptStrings; std::vector<std::string> mOptStrings;
std::vector<std::string> mOptRegex;
}; };
class FileTypeOptionHandler : public tc::cli::OptionParser::IOptionHandler class FileTypeOptionHandler : public tc::cli::OptionParser::IOptionHandler
@ -221,7 +266,8 @@ class FileTypeOptionHandler : public tc::cli::OptionParser::IOptionHandler
public: public:
FileTypeOptionHandler(nstool::Settings::FileType& param, const std::vector<std::string>& opts) : FileTypeOptionHandler(nstool::Settings::FileType& param, const std::vector<std::string>& opts) :
mParam(param), mParam(param),
mOptStrings(opts) mOptStrings(opts),
mOptRegex()
{} {}
const std::vector<std::string>& getOptionStrings() const const std::vector<std::string>& getOptionStrings() const
@ -229,6 +275,11 @@ public:
return mOptStrings; return mOptStrings;
} }
const std::vector<std::string>& getOptionRegexPatterns() const
{
return mOptRegex;
}
void processOption(const std::string& option, const std::vector<std::string>& params) void processOption(const std::string& option, const std::vector<std::string>& params)
{ {
if (params.size() != 1) if (params.size() != 1)
@ -310,6 +361,7 @@ public:
private: private:
nstool::Settings::FileType& mParam; nstool::Settings::FileType& mParam;
std::vector<std::string> mOptStrings; std::vector<std::string> mOptStrings;
std::vector<std::string> mOptRegex;
}; };
class InstructionTypeOptionHandler : public tc::cli::OptionParser::IOptionHandler class InstructionTypeOptionHandler : public tc::cli::OptionParser::IOptionHandler
@ -317,7 +369,8 @@ class InstructionTypeOptionHandler : public tc::cli::OptionParser::IOptionHandle
public: public:
InstructionTypeOptionHandler(bool& param, const std::vector<std::string>& opts) : InstructionTypeOptionHandler(bool& param, const std::vector<std::string>& opts) :
mParam(param), mParam(param),
mOptStrings(opts) mOptStrings(opts),
mOptRegex()
{} {}
const std::vector<std::string>& getOptionStrings() const const std::vector<std::string>& getOptionStrings() const
@ -325,6 +378,11 @@ public:
return mOptStrings; return mOptStrings;
} }
const std::vector<std::string>& getOptionRegexPatterns() const
{
return mOptRegex;
}
void processOption(const std::string& option, const std::vector<std::string>& params) void processOption(const std::string& option, const std::vector<std::string>& params)
{ {
if (params.size() != 1) if (params.size() != 1)
@ -348,14 +406,16 @@ public:
private: private:
bool& mParam; bool& mParam;
std::vector<std::string> mOptStrings; std::vector<std::string> mOptStrings;
std::vector<std::string> mOptRegex;
}; };
class ExtractDataPathOptionHandler : public tc::cli::OptionParser::IOptionHandler class ListArchiveJobPathOptionHandler : public tc::cli::OptionParser::IOptionHandler
{ {
public: public:
ExtractDataPathOptionHandler(std::vector<nstool::ExtractJob>& jobs, const std::vector<std::string>& opts) : ListArchiveJobPathOptionHandler(std::vector<nstool::ArchiveJob>& jobs, const std::vector<std::string>& opts) :
mJobs(jobs), mJobs(jobs),
mOptStrings(opts) mOptStrings(opts),
mOptRegex()
{} {}
const std::vector<std::string>& getOptionStrings() const const std::vector<std::string>& getOptionStrings() const
@ -363,15 +423,60 @@ public:
return mOptStrings; return mOptStrings;
} }
const std::vector<std::string>& getOptionRegexPatterns() const
{
return mOptRegex;
}
void processOption(const std::string& option, const std::vector<std::string>& params)
{
if (params.size() == 0)
{
mJobs.push_back({nstool::ArchiveJob::JobAction::ListFileTree, tc::io::Path("/"), tc::io::Path(), false});
}
else if (params.size() == 1)
{
mJobs.push_back({nstool::ArchiveJob::JobAction::ListFileTree, tc::io::Path(params[0]), tc::io::Path(), false});
}
else
{
throw tc::ArgumentOutOfRangeException(fmt::format("Option \"{:s}\" requires one parameter in the format \"{:s} [<internal path>]\".", option, option));
}
}
private:
std::vector<nstool::ArchiveJob>& mJobs;
std::vector<std::string> mOptStrings;
std::vector<std::string> mOptRegex;
};
class ExtractArchiveJobPathOptionHandler : public tc::cli::OptionParser::IOptionHandler
{
public:
ExtractArchiveJobPathOptionHandler(std::vector<nstool::ArchiveJob>& jobs, const std::vector<std::string>& opts) :
mJobs(jobs),
mOptStrings(opts),
mOptRegex()
{}
const std::vector<std::string>& getOptionStrings() const
{
return mOptStrings;
}
const std::vector<std::string>& getOptionRegexPatterns() const
{
return mOptRegex;
}
void processOption(const std::string& option, const std::vector<std::string>& params) void processOption(const std::string& option, const std::vector<std::string>& params)
{ {
if (params.size() == 1) if (params.size() == 1)
{ {
mJobs.push_back({tc::io::Path("/"), tc::io::Path(params[0])}); mJobs.push_back({nstool::ArchiveJob::JobAction::Extract, tc::io::Path("/"), tc::io::Path(params[0]), false});
} }
else if (params.size() == 2) else if (params.size() == 2)
{ {
mJobs.push_back({tc::io::Path(params[0]), tc::io::Path(params[1])}); mJobs.push_back({nstool::ArchiveJob::JobAction::Extract, tc::io::Path(params[0]), tc::io::Path(params[1]), false});
} }
else else
{ {
@ -379,16 +484,18 @@ public:
} }
} }
private: private:
std::vector<nstool::ExtractJob>& mJobs; std::vector<nstool::ArchiveJob>& mJobs;
std::vector<std::string> mOptStrings; std::vector<std::string> mOptStrings;
std::vector<std::string> mOptRegex;
}; };
class CustomExtractDataPathOptionHandler : public tc::cli::OptionParser::IOptionHandler class CustomExtractArchiveJobPathOptionHandler : public tc::cli::OptionParser::IOptionHandler
{ {
public: public:
CustomExtractDataPathOptionHandler(std::vector<nstool::ExtractJob>& jobs, const std::vector<std::string>& opts, const tc::io::Path& custom_path) : CustomExtractArchiveJobPathOptionHandler(std::vector<nstool::ArchiveJob>& jobs, const std::vector<std::string>& opts, const tc::io::Path& custom_path) :
mJobs(jobs), mJobs(jobs),
mOptStrings(opts), mOptStrings(opts),
mOptRegex(),
mCustomPath(custom_path) mCustomPath(custom_path)
{} {}
@ -397,6 +504,11 @@ public:
return mOptStrings; return mOptStrings;
} }
const std::vector<std::string>& getOptionRegexPatterns() const
{
return mOptRegex;
}
void processOption(const std::string& option, const std::vector<std::string>& params) void processOption(const std::string& option, const std::vector<std::string>& params)
{ {
if (params.size() != 1) if (params.size() != 1)
@ -417,13 +529,13 @@ public:
{ {
fmt::print("Consider using \"-x {:s} {:s}\" instead.\n", custom_path_str, params[0]); fmt::print("Consider using \"-x {:s} {:s}\" instead.\n", custom_path_str, params[0]);
} }
mJobs.push_back({mCustomPath, tc::io::Path(params[0])}); mJobs.push_back({nstool::ArchiveJob::JobAction::Extract, mCustomPath, tc::io::Path(params[0]), false});
} }
private: private:
std::vector<nstool::ExtractJob>& mJobs; std::vector<nstool::ArchiveJob>& mJobs;
std::vector<std::string> mOptStrings; std::vector<std::string> mOptStrings;
std::vector<std::string> mOptRegex;
tc::io::Path mCustomPath; tc::io::Path mCustomPath;
}; };
@ -536,6 +648,7 @@ void nstool::SettingsInitializer::parse_args(const std::vector<std::string>& arg
// register handler for deprecated options DeprecatedOptionHandler // register handler for deprecated options DeprecatedOptionHandler
// none just yet // none just yet
//opts.registerOptionHandler(std::shared_ptr<DeprecatedOptionHandler>(new DeprecatedOptionHandler("warning message here", {"--dep-option"})));
// get option flags // get option flags
opts.registerOptionHandler(std::shared_ptr<FlagOptionHandler>(new FlagOptionHandler(mShowLayout, {"--showlayout"}))); opts.registerOptionHandler(std::shared_ptr<FlagOptionHandler>(new FlagOptionHandler(mShowLayout, {"--showlayout"})));
@ -560,21 +673,21 @@ void nstool::SettingsInitializer::parse_args(const std::vector<std::string>& arg
opts.registerOptionHandler(std::shared_ptr<InstructionTypeOptionHandler>(new InstructionTypeOptionHandler(code.is_64bit_instruction, { "--insttype" }))); opts.registerOptionHandler(std::shared_ptr<InstructionTypeOptionHandler>(new InstructionTypeOptionHandler(code.is_64bit_instruction, { "--insttype" })));
// fs options // fs options
opts.registerOptionHandler(std::shared_ptr<FlagOptionHandler>(new FlagOptionHandler(fs.show_fs_tree, { "--fstree", "--listfs" }))); opts.registerOptionHandler(std::shared_ptr<ListArchiveJobPathOptionHandler>(new ListArchiveJobPathOptionHandler(fs.archive_jobs, { "--fstree", "--listfs" })));
opts.registerOptionHandler(std::shared_ptr<ExtractDataPathOptionHandler>(new ExtractDataPathOptionHandler(fs.extract_jobs, { "-x", "--extract" }))); opts.registerOptionHandler(std::shared_ptr<ExtractArchiveJobPathOptionHandler>(new ExtractArchiveJobPathOptionHandler(fs.archive_jobs, { "-x", "--extract" })));
opts.registerOptionHandler(std::shared_ptr<CustomExtractDataPathOptionHandler>(new CustomExtractDataPathOptionHandler(fs.extract_jobs, { "--fsdir" }, tc::io::Path("/")))); opts.registerOptionHandler(std::shared_ptr<CustomExtractArchiveJobPathOptionHandler>(new CustomExtractArchiveJobPathOptionHandler(fs.archive_jobs, { "--fsdir" }, tc::io::Path("/"))));
// xci options // xci options
opts.registerOptionHandler(std::shared_ptr<CustomExtractDataPathOptionHandler>(new CustomExtractDataPathOptionHandler(fs.extract_jobs, { "--update" }, tc::io::Path("/update/")))); opts.registerOptionHandler(std::shared_ptr<CustomExtractArchiveJobPathOptionHandler>(new CustomExtractArchiveJobPathOptionHandler(fs.archive_jobs, { "--update" }, tc::io::Path("/update/"))));
opts.registerOptionHandler(std::shared_ptr<CustomExtractDataPathOptionHandler>(new CustomExtractDataPathOptionHandler(fs.extract_jobs, { "--normal" }, tc::io::Path("/normal/")))); opts.registerOptionHandler(std::shared_ptr<CustomExtractArchiveJobPathOptionHandler>(new CustomExtractArchiveJobPathOptionHandler(fs.archive_jobs, { "--normal" }, tc::io::Path("/normal/"))));
opts.registerOptionHandler(std::shared_ptr<CustomExtractDataPathOptionHandler>(new CustomExtractDataPathOptionHandler(fs.extract_jobs, { "--secure" }, tc::io::Path("/secure/")))); opts.registerOptionHandler(std::shared_ptr<CustomExtractArchiveJobPathOptionHandler>(new CustomExtractArchiveJobPathOptionHandler(fs.archive_jobs, { "--secure" }, tc::io::Path("/secure/"))));
opts.registerOptionHandler(std::shared_ptr<CustomExtractDataPathOptionHandler>(new CustomExtractDataPathOptionHandler(fs.extract_jobs, { "--logo" }, tc::io::Path("/logo/")))); opts.registerOptionHandler(std::shared_ptr<CustomExtractArchiveJobPathOptionHandler>(new CustomExtractArchiveJobPathOptionHandler(fs.archive_jobs, { "--logo" }, tc::io::Path("/logo/"))));
// nca options // nca options
opts.registerOptionHandler(std::shared_ptr<CustomExtractDataPathOptionHandler>(new CustomExtractDataPathOptionHandler(fs.extract_jobs, { "--part0" }, tc::io::Path("/0/")))); opts.registerOptionHandler(std::shared_ptr<CustomExtractArchiveJobPathOptionHandler>(new CustomExtractArchiveJobPathOptionHandler(fs.archive_jobs, { "--part0" }, tc::io::Path("/0/"))));
opts.registerOptionHandler(std::shared_ptr<CustomExtractDataPathOptionHandler>(new CustomExtractDataPathOptionHandler(fs.extract_jobs, { "--part1" }, tc::io::Path("/1/")))); opts.registerOptionHandler(std::shared_ptr<CustomExtractArchiveJobPathOptionHandler>(new CustomExtractArchiveJobPathOptionHandler(fs.archive_jobs, { "--part1" }, tc::io::Path("/1/"))));
opts.registerOptionHandler(std::shared_ptr<CustomExtractDataPathOptionHandler>(new CustomExtractDataPathOptionHandler(fs.extract_jobs, { "--part2" }, tc::io::Path("/2/")))); opts.registerOptionHandler(std::shared_ptr<CustomExtractArchiveJobPathOptionHandler>(new CustomExtractArchiveJobPathOptionHandler(fs.archive_jobs, { "--part2" }, tc::io::Path("/2/"))));
opts.registerOptionHandler(std::shared_ptr<CustomExtractDataPathOptionHandler>(new CustomExtractDataPathOptionHandler(fs.extract_jobs, { "--part3" }, tc::io::Path("/3/")))); opts.registerOptionHandler(std::shared_ptr<CustomExtractArchiveJobPathOptionHandler>(new CustomExtractArchiveJobPathOptionHandler(fs.archive_jobs, { "--part3" }, tc::io::Path("/3/"))));
// kip options // kip options
opts.registerOptionHandler(std::shared_ptr<SingleParamPathOptionHandler>(new SingleParamPathOptionHandler(kip.extract_path, { "--kipdir" }))); opts.registerOptionHandler(std::shared_ptr<SingleParamPathOptionHandler>(new SingleParamPathOptionHandler(kip.extract_path, { "--kipdir" })));

View file

@ -56,27 +56,14 @@ struct Settings
// Generic FS options // Generic FS options
struct FsOptions struct FsOptions
{ {
// legacy
bool show_fs_tree; bool show_fs_tree;
std::vector<ExtractJob> extract_jobs; std::vector<ExtractJob> extract_jobs;
// new
std::vector<ArchiveJob> archive_jobs;
} fs; } fs;
// XCI options
struct XciOptions
{
tc::Optional<tc::io::Path> update_extract_path;
tc::Optional<tc::io::Path> logo_extract_path;
tc::Optional<tc::io::Path> normal_extract_path;
tc::Optional<tc::io::Path> secure_extract_path;
} xci;
// NCA options
struct NcaOptions
{
tc::Optional<tc::io::Path> part0_extract_path;
tc::Optional<tc::io::Path> part1_extract_path;
tc::Optional<tc::io::Path> part2_extract_path;
tc::Optional<tc::io::Path> part3_extract_path;
} nca;
// KIP options // KIP options
struct KipOptions struct KipOptions
@ -107,6 +94,7 @@ struct Settings
fs.show_fs_tree = false; fs.show_fs_tree = false;
fs.extract_jobs = std::vector<ExtractJob>(); fs.extract_jobs = std::vector<ExtractJob>();
fs.archive_jobs = std::vector<ArchiveJob>();
kip.extract_path = tc::Optional<tc::io::Path>(); kip.extract_path = tc::Optional<tc::io::Path>();

View file

@ -37,6 +37,8 @@ int umain(const std::vector<std::string>& args, const std::vector<std::string>&
obj.setCliOutputMode(set.opt.cli_output_mode); obj.setCliOutputMode(set.opt.cli_output_mode);
obj.setVerifyMode(set.opt.verify); obj.setVerifyMode(set.opt.verify);
obj.setArchiveJobs(set.fs.archive_jobs);
obj.setShowFsTree(set.fs.show_fs_tree); obj.setShowFsTree(set.fs.show_fs_tree);
obj.setExtractJobs(set.fs.extract_jobs); obj.setExtractJobs(set.fs.extract_jobs);
@ -51,6 +53,8 @@ int umain(const std::vector<std::string>& args, const std::vector<std::string>&
obj.setCliOutputMode(set.opt.cli_output_mode); obj.setCliOutputMode(set.opt.cli_output_mode);
obj.setVerifyMode(set.opt.verify); obj.setVerifyMode(set.opt.verify);
obj.setArchiveJobs(set.fs.archive_jobs);
obj.setShowFsTree(set.fs.show_fs_tree); obj.setShowFsTree(set.fs.show_fs_tree);
obj.setExtractJobs(set.fs.extract_jobs); obj.setExtractJobs(set.fs.extract_jobs);
@ -65,6 +69,8 @@ int umain(const std::vector<std::string>& args, const std::vector<std::string>&
obj.setCliOutputMode(set.opt.cli_output_mode); obj.setCliOutputMode(set.opt.cli_output_mode);
obj.setVerifyMode(set.opt.verify); obj.setVerifyMode(set.opt.verify);
obj.setArchiveJobs(set.fs.archive_jobs);
obj.setShowFsTree(set.fs.show_fs_tree); obj.setShowFsTree(set.fs.show_fs_tree);
obj.setExtractJobs(set.fs.extract_jobs); obj.setExtractJobs(set.fs.extract_jobs);
@ -79,6 +85,8 @@ int umain(const std::vector<std::string>& args, const std::vector<std::string>&
obj.setCliOutputMode(set.opt.cli_output_mode); obj.setCliOutputMode(set.opt.cli_output_mode);
obj.setVerifyMode(set.opt.verify); obj.setVerifyMode(set.opt.verify);
obj.setArchiveJobs(set.fs.archive_jobs);
obj.setShowFsTree(set.fs.show_fs_tree); obj.setShowFsTree(set.fs.show_fs_tree);
obj.setExtractJobs(set.fs.extract_jobs); obj.setExtractJobs(set.fs.extract_jobs);
@ -136,6 +144,8 @@ int umain(const std::vector<std::string>& args, const std::vector<std::string>&
if (set.aset.nacp_extract_path.isSet()) if (set.aset.nacp_extract_path.isSet())
obj.setAssetNacpExtractPath(set.aset.nacp_extract_path.get()); obj.setAssetNacpExtractPath(set.aset.nacp_extract_path.get());
obj.setAssetRomfsArchiveJobs(set.fs.archive_jobs);
obj.setAssetRomfsShowFsTree(set.fs.show_fs_tree); obj.setAssetRomfsShowFsTree(set.fs.show_fs_tree);
obj.setAssetRomfsExtractJobs(set.fs.extract_jobs); obj.setAssetRomfsExtractJobs(set.fs.extract_jobs);

View file

@ -24,6 +24,32 @@ struct CliOutputMode
{} {}
}; };
struct ArchiveJob
{
/* Common Job Properties */
enum class JobAction {
DoNothing,
ListFileTree,
Extract
};
JobAction job_action; // action taken by job processor
tc::io::Path archive_path; // path within archive to process
/* Extract Job Properties */
tc::io::Path extract_base_path; // path to base directory to extract
bool preserve_archive_path; // recreate archive path when extracting
ArchiveJob() : job_action(JobAction::DoNothing), archive_path(), extract_base_path(), preserve_archive_path(false)
{}
ArchiveJob(JobAction job_action, const tc::io::Path& archive_path, const tc::io::Path& extract_base_path, bool preserve_archive_path) :
job_action(job_action),
archive_path(archive_path),
extract_base_path(extract_base_path),
preserve_archive_path(preserve_archive_path)
{}
};
struct ExtractJob { struct ExtractJob {
tc::io::Path virtual_path; tc::io::Path virtual_path;
tc::io::Path extract_path; tc::io::Path extract_path;