summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAki <please@ignore.pl>2022-09-11 14:24:01 +0200
committerAki <please@ignore.pl>2022-09-11 14:24:01 +0200
commit60291e0f668f8d45aa1e4a83068e0a9067749e60 (patch)
tree4bf90b8b0767604cdeefa3e9b1db05a5918cd9b1
parentb00704ef37155c17daff1986cda3274d95560bad (diff)
downloadstarshatter-60291e0f668f8d45aa1e4a83068e0a9067749e60.zip
starshatter-60291e0f668f8d45aa1e4a83068e0a9067749e60.tar.gz
starshatter-60291e0f668f8d45aa1e4a83068e0a9067749e60.tar.bz2
Implemented file extraction in dat utility
-rw-r--r--ArchiveEx/dat.cpp43
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;
+}