From dcff34e06ba96f6ffc3ba311268a84b1ce386ef0 Mon Sep 17 00:00:00 2001 From: Stephen Seo Date: Fri, 19 Jul 2024 16:45:51 +0900 Subject: [PATCH] Support "-f -" to read/write archive stdin/stdout --- src/main.c | 120 +++++++++++++++++++++++++++++++++------------------ src/parser.c | 18 ++++++-- src/parser.h | 1 + 3 files changed, 93 insertions(+), 46 deletions(-) diff --git a/src/main.c b/src/main.c index 82efda6..592ed50 100644 --- a/src/main.c +++ b/src/main.c @@ -46,6 +46,12 @@ int main(int argc, const char **argv) { simple_archiver_parse_args(argc, argv, &parsed); + if (!parsed.filename && (parsed.flags & 0x10) == 0) { + fprintf(stderr, "ERROR: Filename not specified!\n"); + simple_archiver_print_usage(); + return 6; + } + if ((parsed.flags & 0x3) == 0 && (parsed.flags & 0x4) == 0) { FILE *file = fopen(parsed.filename, "r"); if (file != NULL) { @@ -68,64 +74,92 @@ int main(int argc, const char **argv) { } if ((parsed.flags & 3) == 0) { - FILE *file = fopen(parsed.filename, "wb"); - if (!file) { - fprintf(stderr, "ERROR: Failed to open \"%s\" for writing!\n", - parsed.filename); - return 2; - } - + // Is creating archive. __attribute__((cleanup(simple_archiver_free_state))) SDArchiverState *state = simple_archiver_init_state(&parsed); + if ((parsed.flags & 0x10) == 0) { + FILE *file = fopen(parsed.filename, "wb"); + if (!file) { + fprintf(stderr, "ERROR: Failed to open \"%s\" for writing!\n", + parsed.filename); + return 2; + } - int ret = simple_archiver_write_all(file, state, filenames); - if (ret != SDAS_SUCCESS) { - fprintf(stderr, "Error during writing.\n"); - char *error_str = simple_archiver_error_to_string(ret); - fprintf(stderr, " %s\n", error_str); - } - fclose(file); + int ret = simple_archiver_write_all(file, state, filenames); + if (ret != SDAS_SUCCESS) { + fprintf(stderr, "Error during writing.\n"); + char *error_str = simple_archiver_error_to_string(ret); + fprintf(stderr, " %s\n", error_str); + } + fclose(file); #if SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_COSMOPOLITAN || \ SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_MAC || \ SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_LINUX - if (ret != SDAS_SUCCESS) { - unlink(parsed.filename); - return 3; - } + if (ret != SDAS_SUCCESS) { + unlink(parsed.filename); + return 3; + } #endif + } else { + int ret = simple_archiver_write_all(stdout, state, filenames); + if (ret != SDAS_SUCCESS) { + fprintf(stderr, "Error during writing.\n"); + char *error_str = simple_archiver_error_to_string(ret); + fprintf(stderr, " %s\n", error_str); + } + } } else if ((parsed.flags & 3) == 2) { - FILE *file = fopen(parsed.filename, "rb"); - if (!file) { - fprintf(stderr, "ERROR: Failed to open \"%s\" for reading!\n", - parsed.filename); - return 4; - } + // Is checking archive. + if ((parsed.flags & 0x10) == 0) { + FILE *file = fopen(parsed.filename, "rb"); + if (!file) { + fprintf(stderr, "ERROR: Failed to open \"%s\" for reading!\n", + parsed.filename); + return 4; + } - int ret = simple_archiver_parse_archive_info(file, 0, NULL); - if (ret != 0) { - fprintf(stderr, "Error during archive checking/examining.\n"); - char *error_str = simple_archiver_error_to_string(ret); - fprintf(stderr, " %s\n", error_str); + int ret = simple_archiver_parse_archive_info(file, 0, NULL); + if (ret != 0) { + fprintf(stderr, "Error during archive checking/examining.\n"); + char *error_str = simple_archiver_error_to_string(ret); + fprintf(stderr, " %s\n", error_str); + } + fclose(file); + } else { + int ret = simple_archiver_parse_archive_info(stdin, 0, NULL); + if (ret != 0) { + fprintf(stderr, "Error during archive checking/examining.\n"); + char *error_str = simple_archiver_error_to_string(ret); + fprintf(stderr, " %s\n", error_str); + } } - fclose(file); } else if ((parsed.flags & 3) == 1) { - FILE *file = fopen(parsed.filename, "rb"); - if (!file) { - fprintf(stderr, "ERROR: Failed to open \"%s\" for reading!\n", - parsed.filename); - return 5; - } - + // Is extracting archive. __attribute__((cleanup(simple_archiver_free_state))) SDArchiverState *state = simple_archiver_init_state(&parsed); + if ((parsed.flags & 0x10) == 0) { + FILE *file = fopen(parsed.filename, "rb"); + if (!file) { + fprintf(stderr, "ERROR: Failed to open \"%s\" for reading!\n", + parsed.filename); + return 5; + } - int ret = simple_archiver_parse_archive_info(file, 1, state); - if (ret != SDAS_SUCCESS) { - fprintf(stderr, "Error during archive extracting.\n"); - char *error_str = simple_archiver_error_to_string(ret); - fprintf(stderr, " %s\n", error_str); + int ret = simple_archiver_parse_archive_info(file, 1, state); + if (ret != SDAS_SUCCESS) { + fprintf(stderr, "Error during archive extracting.\n"); + char *error_str = simple_archiver_error_to_string(ret); + fprintf(stderr, " %s\n", error_str); + } + fclose(file); + } else { + int ret = simple_archiver_parse_archive_info(stdin, 1, state); + if (ret != SDAS_SUCCESS) { + fprintf(stderr, "Error during archive extracting.\n"); + char *error_str = simple_archiver_error_to_string(ret); + fprintf(stderr, " %s\n", error_str); + } } - fclose(file); } return 0; diff --git a/src/parser.c b/src/parser.c index db409d0..9924909 100644 --- a/src/parser.c +++ b/src/parser.c @@ -139,6 +139,9 @@ void simple_archiver_print_usage(void) { fprintf(stderr, "-x : extract archive file\n"); fprintf(stderr, "-t : examine archive file\n"); fprintf(stderr, "-f : filename to work on\n"); + fprintf(stderr, + " Use \"-f -\" to work on stdout when creating archive or stdin " + "when reading archive\n"); fprintf(stderr, "--compressor : requires --decompressor\n"); fprintf(stderr, @@ -210,9 +213,18 @@ int simple_archiver_parse_args(int argc, const char **argv, // set second bit. out->flags |= 0x2; } else if (strcmp(argv[0], "-f") == 0 && argc > 1) { - int size = strlen(argv[1]) + 1; - out->filename = malloc(size); - strncpy(out->filename, argv[1], size); + if (strcmp(argv[1], "-") == 0) { + out->flags |= 0x10; + if (out->filename) { + free(out->filename); + } + out->filename = NULL; + } else { + out->flags &= 0xFFFFFFEF; + int size = strlen(argv[1]) + 1; + out->filename = malloc(size); + strncpy(out->filename, argv[1], size); + } --argc; ++argv; } else if (strcmp(argv[0], "--compressor") == 0 && argc > 1) { diff --git a/src/parser.h b/src/parser.h index 2184704..4e0e729 100644 --- a/src/parser.h +++ b/src/parser.h @@ -29,6 +29,7 @@ typedef struct SDArchiverParsed { /// 0b xxxx x0xx - Do NOT allow create archive overwrite. /// 0b xxxx x1xx - Allow create archive overwrite. /// 0b xxxx 1xxx - Allow extract overwrite. + /// 0b xxx1 xxxx - Create archive to stdout or read archive from stdin. unsigned int flags; /// Null-terminated string. char *filename;