tar -Z, uncompress support
[oweals/busybox.git] / archival / tar.c
index 72b4c99521e96dbdbc0c122c562bb26215e1d103..4e763a404476118ab884f87971e2df5ecc81dcc4 100644 (file)
@@ -594,8 +594,28 @@ static llist_t *append_file_list_to_list(llist_t *list)
 }
 #endif
 
+#ifdef CONFIG_FEATURE_TAR_COMPRESS
+static char get_header_tar_Z(archive_handle_t *archive_handle)
+{
+       /* Cant lseek over pipe's */
+       archive_handle->seek = seek_by_char;
+
+       /* do the decompression, and cleanup */
+       if ((bb_xread_char(archive_handle->src_fd) != 0x1f) || (bb_xread_char(archive_handle->src_fd) != 0x9d)) {
+               bb_error_msg_and_die("Invalid magic");
+       }
+
+       archive_handle->src_fd = open_transformer(archive_handle->src_fd, uncompress);
+       archive_handle->offset = 0;
+       while (get_header_tar(archive_handle) == EXIT_SUCCESS);
+
+       /* Can only do one file at a time */
+       return(EXIT_FAILURE);
+}
+#endif
+
+static const char tar_options[]="ctxjT:X:C:f:OpvzkZ";
 
-static const char tar_options[]="ctxjT:X:C:f:Opvz";
 #define CTX_CREATE     1
 #define CTX_TEST       2
 #define CTX_EXTRACT    4
@@ -608,6 +628,8 @@ static const char tar_options[]="ctxjT:X:C:f:Opvz";
 #define TAR_OPT_P        512
 #define TAR_OPT_VERBOSE  1024
 #define TAR_OPT_GZIP     2048
+#define TAR_OPT_KEEP_OLD       4096
+#define TAR_OPT_UNCOMPRESS     8192
 
 int tar_main(int argc, char **argv)
 {
@@ -632,7 +654,7 @@ int tar_main(int argc, char **argv)
 
        /* Initialise default values */
        tar_handle = init_handle();
-       tar_handle->flags = ARCHIVE_CREATE_LEADING_DIRS | ARCHIVE_PRESERVE_DATE;
+       tar_handle->flags = ARCHIVE_CREATE_LEADING_DIRS | ARCHIVE_PRESERVE_DATE | ARCHIVE_EXTRACT_UNCONDITIONAL;
 
        bb_opt_complementaly = "c~tx:t~cx:x~ct:X*";
        opt = bb_getopt_ulflags(argc, argv, tar_options,
@@ -646,45 +668,62 @@ int tar_main(int argc, char **argv)
                bb_show_usage();
        ctx_flag = opt & (CTX_CREATE | CTX_TEST | CTX_EXTRACT);
        if(ctx_flag & CTX_TEST) {
-                       if ((tar_handle->action_header == header_list) || 
-                               (tar_handle->action_header == header_verbose_list)) {
-                               tar_handle->action_header = header_verbose_list;
-                       } else {
-                               tar_handle->action_header = header_list;
-                       }
+               if ((tar_handle->action_header == header_list) || 
+                       (tar_handle->action_header == header_verbose_list)) {
+                       tar_handle->action_header = header_verbose_list;
+               } else {
+                       tar_handle->action_header = header_list;
+               }
        }
        if(ctx_flag & CTX_EXTRACT) {
                if (tar_handle->action_data != data_extract_to_stdout)
-                               tar_handle->action_data = data_extract_all;
-                       }
+                       tar_handle->action_data = data_extract_all;
+               }
        if(opt & TAR_OPT_2STDOUT) {
                /* To stdout */
-                       tar_handle->action_data = data_extract_to_stdout;
+               tar_handle->action_data = data_extract_to_stdout;
        }
        if(opt & TAR_OPT_VERBOSE) {
-                       if ((tar_handle->action_header == header_list) || 
-                               (tar_handle->action_header == header_verbose_list)) 
-                       {
-                               tar_handle->action_header = header_verbose_list;
-                       } else {
-                               tar_handle->action_header = header_list;
-                       }
+               if ((tar_handle->action_header == header_list) || 
+                       (tar_handle->action_header == header_verbose_list)) 
+               {
+               tar_handle->action_header = header_verbose_list;
+               } else {
+                       tar_handle->action_header = header_list;
+               }
        }
-#ifdef CONFIG_FEATURE_TAR_GZIP
-       if(opt & TAR_OPT_GZIP) {
-                       get_header_ptr = get_header_tar_gz;
+       if (opt & TAR_OPT_KEEP_OLD) {
+               tar_handle->flags &= ~ARCHIVE_EXTRACT_UNCONDITIONAL;
        }
+
+       if(opt & TAR_OPT_GZIP) {
+#ifdef CONFIG_FEATURE_TAR_GZIP
+               get_header_ptr = get_header_tar_gz;
+#else
+               bb_show_usage();
 #endif
-#ifdef CONFIG_FEATURE_TAR_BZIP2
+       }
        if(opt & TAR_OPT_BZIP2) {
-                       get_header_ptr = get_header_tar_bz2;
+#ifdef CONFIG_FEATURE_TAR_BZIP2
+               get_header_ptr = get_header_tar_bz2;
+#else
+               bb_show_usage();
+#endif
        }
+       if(opt & TAR_OPT_UNCOMPRESS) {
+#ifdef CONFIG_FEATURE_TAR_COMPRESS
+               get_header_ptr = get_header_tar_Z;
+#else
+               bb_show_usage();
 #endif
-#ifdef CONFIG_FEATURE_TAR_EXCLUDE
+       }
        if(opt & TAR_OPT_EXCLUDE) {
+#ifdef CONFIG_FEATURE_TAR_EXCLUDE
                tar_handle->reject = append_file_list_to_list(tar_handle->reject);
-       }
+#else
+               bb_show_usage();
 #endif
+       }
        /* Check if we are reading from stdin */
        if ((argv[optind]) && (*argv[optind] == '-')) {
                /* Default is to read from stdin, so just skip to next arg */