From 60291e0f668f8d45aa1e4a83068e0a9067749e60 Mon Sep 17 00:00:00 2001 From: Aki Date: Sun, 11 Sep 2022 14:24:01 +0200 Subject: Implemented file extraction in dat utility --- ArchiveEx/dat.cpp | 43 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/ArchiveEx/dat.cpp b/ArchiveEx/dat.cpp index a8f112d..3c026b2 100644 --- a/ArchiveEx/dat.cpp +++ b/ArchiveEx/dat.cpp @@ -1,10 +1,15 @@ +#include #include +#include #include #include +#include #include +#include #include #include +#include #include #include @@ -42,10 +47,14 @@ public: }; +class ExtractError : std::exception {}; + + static Options ParseArgs(int argc, char* argv[]); static void PrintUsage(std::ostream& out=std::cerr); static void PrintHelp(std::ostream& out=std::cout); static void UpdateFile(ArchiveEx::Archive& archive, const std::string& path, bool warn=true); +static void ExtractFile(ArchiveEx::Archive& archive, const char* filepath); static const char* program {"dat"}; @@ -77,7 +86,16 @@ try { UpdateFile(archive, file); break; case Action::EXTRACT: - break; // Not implemented + archive.ForEachEntry([opts, &archive](const char* name){ + for (const auto& pattern : opts.files) { + const int match = fnmatch(pattern.c_str(), name, FNM_PATHNAME | FNM_LEADING_DIR); + if (match == 0) { + ExtractFile(archive, name); + break; + } + } + }); + break; } } catch (const ArgsError& err) { @@ -172,3 +190,26 @@ UpdateFile(ArchiveEx::Archive& archive, const std::string& path, bool warn) break; } } + + +void +ExtractFile(ArchiveEx::Archive& archive, const char* filepath) +try { + fs::path path{filepath}; + std::uint8_t* tmp{nullptr}; + const int length = archive.Extract(filepath, tmp); + if (0 > length) + throw ExtractError(); + std::unique_ptr buf{tmp}; + std::error_code ec; + const bool created = fs::create_directories(path.parent_path(), ec); + if (!created) + throw ExtractError(); + std::ofstream file{path}; + if (!file.is_open()) + throw ExtractError(); + file.write(reinterpret_cast(buf.get()), length); +} +catch (const ExtractError& err) { + std::cerr << "could not extract: " << filepath << std::endl; +} -- cgit v1.1