diff options
author | Aki <please@ignore.pl> | 2022-09-11 14:24:01 +0200 |
---|---|---|
committer | Aki <please@ignore.pl> | 2022-09-11 14:24:01 +0200 |
commit | 60291e0f668f8d45aa1e4a83068e0a9067749e60 (patch) | |
tree | 4bf90b8b0767604cdeefa3e9b1db05a5918cd9b1 | |
parent | b00704ef37155c17daff1986cda3274d95560bad (diff) | |
download | starshatter-60291e0f668f8d45aa1e4a83068e0a9067749e60.zip starshatter-60291e0f668f8d45aa1e4a83068e0a9067749e60.tar.gz starshatter-60291e0f668f8d45aa1e4a83068e0a9067749e60.tar.bz2 |
Implemented file extraction in dat utility
-rw-r--r-- | ArchiveEx/dat.cpp | 43 |
1 files changed, 42 insertions, 1 deletions
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 <fnmatch.h> #include <unistd.h> +#include <cstdint> #include <exception> #include <filesystem> +#include <fstream> #include <iostream> +#include <memory> #include <ostream> #include <string> +#include <system_error> #include <vector> #include <Archive.h> @@ -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<std::uint8_t[]> 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<const char*>(buf.get()), length); +} +catch (const ExtractError& err) { + std::cerr << "could not extract: " << filepath << std::endl; +} |