summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAki <please@ignore.pl>2022-08-20 22:44:21 +0200
committerAki <please@ignore.pl>2022-08-20 22:44:21 +0200
commitbc9502fbc36946f1d96d3f188e18346baddbf1d5 (patch)
tree947f5e58a5ac977954ccd028181831b6fd776523
parente4bb06e7a22d766e7c0c689a9fa392346f5a3daa (diff)
downloadstarshatter-bc9502fbc36946f1d96d3f188e18346baddbf1d5.zip
starshatter-bc9502fbc36946f1d96d3f188e18346baddbf1d5.tar.gz
starshatter-bc9502fbc36946f1d96d3f188e18346baddbf1d5.tar.bz2
Added stub of CLI utility for handling archives
This will eventually deprecate Datafile
-rw-r--r--ArchiveEx/CMakeLists.txt8
-rw-r--r--ArchiveEx/dat.cpp140
2 files changed, 148 insertions, 0 deletions
diff --git a/ArchiveEx/CMakeLists.txt b/ArchiveEx/CMakeLists.txt
index b2a1948..62e414e 100644
--- a/ArchiveEx/CMakeLists.txt
+++ b/ArchiveEx/CMakeLists.txt
@@ -11,3 +11,11 @@ target_link_libraries(
ArchiveEx
PRIVATE Zlib::zlib
)
+add_executable(
+ dat
+ dat.cpp
+ )
+target_link_libraries(
+ dat
+ PRIVATE ArchiveEx
+ )
diff --git a/ArchiveEx/dat.cpp b/ArchiveEx/dat.cpp
new file mode 100644
index 0000000..ae1304d
--- /dev/null
+++ b/ArchiveEx/dat.cpp
@@ -0,0 +1,140 @@
+#include <unistd.h>
+
+#include <exception>
+#include <iostream>
+#include <ostream>
+#include <string>
+#include <vector>
+
+#include <Archive.h>
+
+
+enum class Action
+{
+ NOTHING,
+ LIST,
+ UPDATE,
+ EXTRACT,
+};
+
+
+struct Options
+{
+ bool help {false};
+ Action action {Action::NOTHING};
+ bool create {false};
+ const char* archive {nullptr};
+ std::vector<std::string> files {};
+};
+
+
+class ArgsError : std::exception
+{
+public:
+ ArgsError(int opt, const char* msg) : option {opt}, message {msg} {}
+ int option;
+ const char* message;
+};
+
+
+static Options ParseArgs(int argc, char* argv[]);
+static void PrintUsage(std::ostream& out=std::cerr);
+static void PrintHelp(std::ostream& out=std::cout);
+
+
+static const char* program {"dat"};
+
+
+int
+main(int argc, char* argv[])
+try {
+ program = argv[0];
+ const auto opts = ParseArgs(argc, argv);
+ if (opts.help) {
+ PrintUsage(std::cout);
+ PrintHelp();
+ return 0;
+ }
+ ArchiveEx::Archive archive(opts.archive, opts.create);
+ switch (opts.action) {
+ case Action::NOTHING:
+ break;
+ case Action::LIST:
+ archive.PrintNamesOfEntries();
+ break;
+ case Action::UPDATE:
+ for (const auto& file : opts.files)
+ archive.Insert(file.c_str()); // Support recursive directories tar-like
+ break;
+ case Action::EXTRACT:
+ break; // Not implemented
+ }
+}
+catch (const ArgsError& err) {
+ std::cerr << err.message;
+ if (err.option > 0)
+ std::cerr << ": " << static_cast<char>(err.option);
+ std::cerr << std::endl;
+ PrintUsage();
+ return 1;
+}
+catch (const char* err) {
+ std::cerr << err << std::endl;
+ return 1;
+}
+
+
+Options
+ParseArgs(int argc, char* argv[])
+{
+ int opt;
+ Options opts;
+ while (-1 != (opt = getopt(argc, argv, ":hluxc"))) {
+ switch (opt) {
+ case 'h':
+ opts.help = true;
+ return opts; // No need to waste time as program won't do anything else anyway.
+ case 'l':
+ opts.action = Action::LIST;
+ break;
+ case 'u':
+ opts.action = Action::UPDATE;
+ break;
+ case 'x':
+ opts.action = Action::EXTRACT;
+ break;
+ case 'c':
+ opts.create = true;
+ break;
+ case ':':
+ throw ArgsError(optopt, "missing argument for option");
+ default:
+ throw ArgsError(optopt, "invalid option");
+ }
+ }
+ if (optind >= argc)
+ throw ArgsError(0, "missing archive name");
+ opts.archive = argv[optind++];
+ for (; optind < argc; ++optind)
+ opts.files.emplace_back(argv[optind]);
+ return opts;
+}
+
+
+void
+PrintUsage(std::ostream& out)
+{
+ out << "Usage: " << program << " [-hluxc] archive [file [files...]]" << std::endl;
+}
+
+
+void
+PrintHelp(std::ostream& out)
+{
+ out << "Options:" << std::endl;
+ out << " -h\tPrints this help message and exits." << std::endl;
+ out << " -l\tLists files in the archive." << std::endl;
+ out << " -u\tInserts files from file system into archive." << std::endl;
+ out << " -x\tExtracts files from the archive." << std::endl;
+ out << " -c\tCreate the archive if it does not exist." << std::endl;
+}