diff --git a/driver/main.cpp b/driver/main.cpp index 60d9bf3..2bb31f8 100644 --- a/driver/main.cpp +++ b/driver/main.cpp @@ -29,13 +29,19 @@ int main(int argc, char* argv[]) /* Enable logging to console */ LogVisor::RegisterConsoleLogger(); + NOD::ExtractionContext ctx = { true, true, [&](const std::string& str){ + fprintf(stderr, "%s\n", str.c_str()); + }}; const NOD::SystemChar* inDir = nullptr; const NOD::SystemChar* outDir = _S("."); - bool force = false; + for (int a=2 ; aextractToDirectory(outDir, force)) + if (!dataPart->extractToDirectory(outDir, ctx)) return -1; } else if (!strcasecmp(argv[1], _S("make"))) diff --git a/include/NOD/DiscBase.hpp b/include/NOD/DiscBase.hpp index c541b83..d393745 100644 --- a/include/NOD/DiscBase.hpp +++ b/include/NOD/DiscBase.hpp @@ -13,6 +13,7 @@ namespace NOD { +class ExtractionContext; class DiscBase { public: @@ -163,7 +164,7 @@ public: return end(); } - bool extractToDirectory(const SystemString& basePath, bool force=false) const; + bool extractToDirectory(const SystemString& basePath, const ExtractionContext& ctx) const; }; protected: uint64_t m_dolOff; @@ -193,7 +194,7 @@ public: {return beginReadStream(0x2440 + offset);} inline const Node& getFSTRoot() const {return m_nodes[0];} inline Node& getFSTRoot() {return m_nodes[0];} - bool extractToDirectory(const SystemString& path, bool force=false); + bool extractToDirectory(const SystemString& path, const ExtractionContext& ctx); inline uint64_t getDOLSize() const {return m_dolSz;} inline std::unique_ptr getDOLBuf() const @@ -245,10 +246,10 @@ public: return part.get(); return nullptr; } - inline void extractToDirectory(const SystemString& path, bool force=false) + inline void extractToDirectory(const SystemString& path, const ExtractionContext& ctx) { for (std::unique_ptr& part : m_partitions) - part->extractToDirectory(path, force); + part->extractToDirectory(path, ctx); } }; diff --git a/include/NOD/NOD.hpp b/include/NOD/NOD.hpp index 6b431c5..d878785 100644 --- a/include/NOD/NOD.hpp +++ b/include/NOD/NOD.hpp @@ -2,6 +2,7 @@ #define __NOD_LIB__ #include +#include #include #include "Util.hpp" @@ -10,6 +11,13 @@ namespace NOD class DiscBase; +struct ExtractionContext final +{ + bool verbose : 1; + bool force : 1; + std::function progressCB; +}; + std::unique_ptr OpenDiscFromImage(const SystemChar* path); std::unique_ptr OpenDiscFromImage(const SystemChar* path, bool& isWii); diff --git a/lib/DiscBase.cpp b/lib/DiscBase.cpp index a2ce21d..e9a4c96 100644 --- a/lib/DiscBase.cpp +++ b/lib/DiscBase.cpp @@ -1,5 +1,6 @@ #include "NOD/DiscBase.hpp" #include "NOD/IFileIO.hpp" +#include "NOD/NOD.hpp" #include #ifndef _WIN32 @@ -60,25 +61,33 @@ void DiscBase::IPartition::parseDOL(IPartReadStream& s) m_dolSz = dolSize; } -bool DiscBase::IPartition::Node::extractToDirectory(const SystemString& basePath, bool force) const +bool DiscBase::IPartition::Node::extractToDirectory(const SystemString& basePath, const ExtractionContext& ctx) const { SystemStringView nameView(getName()); SystemString path = basePath + _S("/") + nameView.sys_str(); + if (m_kind == NODE_DIRECTORY) { + if (ctx.verbose && ctx.progressCB && !getName().empty()) + ctx.progressCB(getName()); if (Mkdir(path.c_str(), 0755) && errno != EEXIST) { LogModule.report(LogVisor::Error, _S("unable to mkdir '%s'"), path.c_str()); return false; } for (Node& subnode : *this) - if (!subnode.extractToDirectory(path, force)) + if (!subnode.extractToDirectory(path, ctx)) return false; + if (ctx.verbose && ctx.progressCB) + ctx.progressCB(getName()); } else if (m_kind == NODE_FILE) { Sstat theStat; - if (force || Stat(path.c_str(), &theStat)) + if (ctx.verbose && ctx.progressCB) + ctx.progressCB(getName()); + + if (ctx.force || Stat(path.c_str(), &theStat)) { std::unique_ptr rs = beginReadStream(); std::unique_ptr ws = NewFileIO(path)->beginWriteStream(); @@ -88,7 +97,7 @@ bool DiscBase::IPartition::Node::extractToDirectory(const SystemString& basePath return true; } -bool DiscBase::IPartition::extractToDirectory(const SystemString& path, bool force) +bool DiscBase::IPartition::extractToDirectory(const SystemString& path, const ExtractionContext& ctx) { Sstat theStat; if (Mkdir(path.c_str(), 0755) && errno != EEXIST) @@ -99,22 +108,26 @@ bool DiscBase::IPartition::extractToDirectory(const SystemString& path, bool for /* Extract Apploader */ SystemString apploaderPath = path + _S("/apploader.bin"); - if (force || Stat(apploaderPath.c_str(), &theStat)) + if (ctx.force || Stat(apploaderPath.c_str(), &theStat)) { + if (ctx.verbose && ctx.progressCB) + ctx.progressCB("apploader.bin"); std::unique_ptr buf = getApploaderBuf(); NewFileIO(apploaderPath)->beginWriteStream()->write(buf.get(), m_apploaderSz); } /* Extract Dol */ SystemString dolPath = path + _S("/main.dol"); - if (force || Stat(dolPath.c_str(), &theStat)) + if (ctx.force || Stat(dolPath.c_str(), &theStat)) { + if (ctx.verbose && ctx.progressCB) + ctx.progressCB("main.dol"); std::unique_ptr buf = getDOLBuf(); NewFileIO(dolPath)->beginWriteStream()->write(buf.get(), m_dolSz); } /* Extract Filesystem */ - return m_nodes[0].extractToDirectory(path, force); + return m_nodes[0].extractToDirectory(path, ctx); } }