]> git.seodisparate.com - SimpleArchiver/commitdiff
Support "-f -" to read/write archive stdin/stdout
authorStephen Seo <seo.disparate@gmail.com>
Fri, 19 Jul 2024 07:45:51 +0000 (16:45 +0900)
committerStephen Seo <seo.disparate@gmail.com>
Fri, 19 Jul 2024 07:45:51 +0000 (16:45 +0900)
src/main.c
src/parser.c
src/parser.h

index 82efda6781e1cc8303a2d7829636b4653c41c33e..592ed503f3f31f192bf735421692eb62a850b174 100644 (file)
@@ -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);
-
-    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 ((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);
 #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 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;
+    } 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);
+      }
     }
-
-    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);
+  } else if ((parsed.flags & 3) == 2) {
+    // 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);
+      }
+      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);
-
-    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);
+    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);
+      }
+      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;
index db409d0659aa01fa80459c88cd4c6e39d6a668c2..9924909ba0c15a1019c1489501f9029d0c2c3681 100644 (file)
@@ -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> : 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 <full_compress_cmd> : 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) {
index 218470443c46a83a11ec73da9848a63147ea54ae..4e0e7296481362334abeb68648312c80f59b769c 100644 (file)
@@ -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;