summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/cli.c23
-rw-r--r--src/cli.h1
-rw-r--r--src/main.c17
3 files changed, 20 insertions, 21 deletions
diff --git a/src/cli.c b/src/cli.c
index 7d00434..3891032 100644
--- a/src/cli.c
+++ b/src/cli.c
@@ -34,8 +34,6 @@
" -e, --extract\tExtract the contents of the archive. " \
"This is the default.\n" \
" -l, --list\t\tList the contents of the archive.\n\n" \
- " -a, --archive\tAlternate way of specifying archive" \
- "to extract.\n" \
" -o, --output\t\tPath to extract files to.\n" \
" -g, --game\t\tGame the archive is from. Required for " \
"file decryption\n" \
@@ -68,14 +66,13 @@ struct configuration parse_args(int argc, char *argv[]) {
{"quiet", no_argument, NULL, 'q'},
{"extract", no_argument, NULL, 'e'},
{"list", no_argument, NULL, 'l'},
- {"archive", required_argument, NULL, 'a'},
{"output", required_argument, NULL, 'o'},
{"game", required_argument, NULL, 'g'},
{NULL, 0, NULL, 0}
};
do {
- current = getopt_long(argc, argv, "hvelqa:o:g:", long_options,
+ current = getopt_long(argc, argv, "hvelqo:g:", long_options,
&option_index);
switch (current) {
case 'h':
@@ -90,10 +87,6 @@ struct configuration parse_args(int argc, char *argv[]) {
case 'q':
parsed.quiet = 1;
break;
- case 'a':
- count++;
- parsed.archive = optarg;
- break;
case 'o':
count++;
size_t path_size = strlen(optarg);
@@ -128,15 +121,13 @@ struct configuration parse_args(int argc, char *argv[]) {
count++;
} while (current >= 0);
- /* getopt "sorts" the argument array such that all of the flags come
- first. argv[count] is the first positional argument encountered. */
- if (parsed.archive == NULL) {
- if (argv[count] == NULL) {
- fprintf(stderr, "No archive path provided.\n");
- exit(EXIT_FAILURE);
- }
- parsed.archive = argv[count];
+ /* getopt pushes non-flag arguments to the end of argv, and `count`
+ is only incremented when a flag argument is parsed. */
+ if (count == argc) {
+ fprintf(stderr, "No archive path provided.\n");
+ exit(EXIT_FAILURE);
}
+ parsed.vararg_index = count;
/* The output path is allocated on the heap to simplify freeing. */
if (parsed.output == NULL) {
diff --git a/src/cli.h b/src/cli.h
index 3f96f28..d16d4a7 100644
--- a/src/cli.h
+++ b/src/cli.h
@@ -38,6 +38,7 @@ typedef enum mode_type {
/* Binary structure for storing command-line options. */
struct configuration {
int quiet; /* Level of output verbosity. */
+ int vararg_index; /* Index of where a variadic list of paths starts. */
game_type game; /* Which decryption key to use. */
mode_type mode; /* What to do after initial sanity checks. */
char *output; /* Path to extract files to. */
diff --git a/src/main.c b/src/main.c
index dc23460..2ba65db 100644
--- a/src/main.c
+++ b/src/main.c
@@ -29,6 +29,7 @@
#define XP3_TABLE_OFFSET 11
#define XP3_VERSION_OFFSET 19
+void handle_archive(char *path);
int is_xp3_archive(FILE *archive);
int get_archive_version(FILE *archive);
uint64_t get_table_offset(FILE *archive, uint8_t archive_version);
@@ -39,15 +40,23 @@ struct configuration arguments;
int main(int argc, char *argv[]) {
arguments = parse_args(argc, argv);
+ for (int i = arguments.vararg_index; i < argc; i++)
+ handle_archive(argv[i]);
+ free(arguments.output);
+ return 0;
+}
- FILE *archive = fopen(arguments.archive, "rb");
+
+/* Extracts the archive at the specified path. */
+void handle_archive(char *path) {
+ FILE *archive = fopen(path, "rb");
if (archive == NULL) {
/* Including the expanded path in the error message is
much more useful to the user than `perror("fopen")`. */
- perror(arguments.archive);
+ perror(path);
exit(EXIT_FAILURE);
} else if (!is_xp3_archive(archive)) {
- fprintf(stderr, "%s is not an XP3 archive.\n", arguments.archive);
+ fprintf(stderr, "%s is not an XP3 archive.\n", path);
fclose(archive);
exit(EXIT_FAILURE);
}
@@ -82,10 +91,8 @@ int main(int argc, char *argv[]) {
list(data_stream);
}
- free(arguments.output);
free(data_stream.start);
fclose(archive);
- return 0;
}