Ahem: add new faq entry to list at top of FAQ.html
[oweals/busybox.git] / archival / bunzip2.c
index 9f346f266286b18ae8061a2e7a988415133ea897..5cd013c0ce87d72948caa915f2b1d60eedbb4d5a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Modified for busybox by Glenn McGrath <bug1@optushome.com.au>
+ *  Modified for busybox by Glenn McGrath <bug1@iinet.net.au>
  *  Added support output to stdout by Thomas Lundquist <thomasez@zelow.no>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  */
 
+#include <fcntl.h>
 #include <getopt.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
 #include <unistd.h>
 
 #include "busybox.h"
 #include "unarchive.h"
 
+#define BUNZIP2_OPT_STDOUT     1
+#define BUNZIP2_OPT_FORCE      2
+
 int bunzip2_main(int argc, char **argv)
 {
-       const int bunzip_to_stdout = 1;
-       const int bunzip_force = 2;
-       int flags = 0;
-       int opt = 0;
+       char *compressed_name;
+       /* Note: Ignore the warning about save_name being used uninitialized.
+        * That is not the case, but gcc has trouble working that out... */
+#warning The save_name warning is OK, ignore it
+       char *save_name;
+       unsigned long opt;
        int status;
+       int src_fd;
+       int dst_fd;
 
-       FILE *src_stream;
-       FILE *dst_stream;
-       char *save_name = NULL;
-       char *delete_name = NULL;
-
-       /* if called as bzcat */
-       if (strcmp(applet_name, "bzcat") == 0)
-               flags |= bunzip_to_stdout;
+       opt = bb_getopt_ulflags(argc, argv, "cf");
 
-       while ((opt = getopt(argc, argv, "cfh")) != -1) {
-               switch (opt) {
-               case 'c':
-                       flags |= bunzip_to_stdout;
-                       break;
-               case 'f':
-                       flags |= bunzip_force;
-                       break;
-               case 'h':
-               default:
-                       show_usage(); /* exit's inside usage */
-               }
+       /* if called as bzcat force the stdout flag */
+       if (bb_applet_name[2] == 'c') {
+               opt |= BUNZIP2_OPT_STDOUT;
        }
 
        /* Set input filename and number */
-       if (argv[optind] == NULL || strcmp(argv[optind], "-") == 0) {
-               flags |= bunzip_to_stdout;
-               src_stream = stdin;
-       } else {
+       compressed_name = argv[optind];
+       if ((compressed_name) && (compressed_name[0] != '-') && (compressed_name[1] != '\0')) {
                /* Open input file */
-               src_stream = xfopen(argv[optind], "r");
-
-               save_name = xstrdup(argv[optind]);
-               if (strcmp(save_name + strlen(save_name) - 4, ".bz2") != 0)
-                       error_msg_and_die("Invalid extension");
-               save_name[strlen(save_name) - 4] = '\0';
+               src_fd = bb_xopen(compressed_name, O_RDONLY);
+       } else {
+               src_fd = STDIN_FILENO;
+               opt |= BUNZIP2_OPT_STDOUT;
        }
 
        /* Check that the input is sane.  */
-       if (isatty(fileno(src_stream)) && (flags & bunzip_force) == 0)
-               error_msg_and_die("compressed data not read from terminal.  Use -f to force it.");
-
-       if (flags & bunzip_to_stdout) {
-               dst_stream = stdout;
-       } else {
-               dst_stream = xfopen(save_name, "w");
+       if (isatty(src_fd) && (opt & BUNZIP2_OPT_FORCE) == 0) {
+               bb_error_msg_and_die("compressed data not read from terminal.  Use -f to force it.");
        }
 
-       if (uncompressStream(src_stream, dst_stream)) {
-               if (!(flags & bunzip_to_stdout))
-                       delete_name = argv[optind];
-               status = EXIT_SUCCESS;
+       if (opt & BUNZIP2_OPT_STDOUT) {
+               dst_fd = STDOUT_FILENO;
        } else {
-               if (!(flags & bunzip_to_stdout))
-                       delete_name = save_name;
-               status = EXIT_FAILURE;
+               int len = strlen(compressed_name) - 4;
+               if (strcmp(compressed_name + len, ".bz2") != 0) {
+                       bb_error_msg_and_die("Invalid extension");
+               }
+               save_name = bb_xstrndup(compressed_name, len);
+               dst_fd = bb_xopen(save_name, O_WRONLY | O_CREAT);
        }
 
-       if (delete_name) {
+       status = uncompressStream(src_fd, dst_fd);
+       if(!(opt & BUNZIP2_OPT_STDOUT)) {
+               char *delete_name;
+               if (status) {
+                       delete_name = save_name;
+               } else {
+                       delete_name = compressed_name;
+               }
                if (unlink(delete_name) < 0) {
-                       error_msg_and_die("Couldn't remove %s", delete_name);
+                       bb_error_msg_and_die("Couldn't remove %s", delete_name);
                }
        }