summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Eggert <eggert@cs.ucla.edu>2010-11-08 11:14:28 -0800
committerPaul Eggert <eggert@cs.ucla.edu>2010-11-08 11:14:28 -0800
commit777042e024d4bf7357ffd060ad05763d463fe441 (patch)
treec5d89f89849df1dde4b9834644637f487b3c034e
parent18013998308a5eb0b646d7682c392793ab0cf639 (diff)
parentecd700fbfb6c4d04fd67f4fdf9944ff6377ff064 (diff)
downloadtar-777042e024d4bf7357ffd060ad05763d463fe441.tar.gz
Merge branch 'master' of ssh://git.sv.gnu.org/srv/git/tar
-rw-r--r--NEWS30
-rw-r--r--configure.ac2
-rw-r--r--doc/tar.texi35
-rw-r--r--src/buffer.c95
-rw-r--r--src/common.h7
-rw-r--r--src/system.c31
-rw-r--r--src/warning.c4
7 files changed, 182 insertions, 22 deletions
diff --git a/NEWS b/NEWS
index 66d9c880..8244bad1 100644
--- a/NEWS
+++ b/NEWS
@@ -1,7 +1,35 @@
-GNU tar NEWS - User visible changes. 2010-10-24
+GNU tar NEWS - User visible changes. 2010-11-07
Please send GNU tar bug reports to <bug-tar@gnu.org>
+version 1.25 - Sergey Poznyakoff, 2010-11-07
+
+* Fix extraction of empty directories with the -C option in effect.
+* Fix extraction of device nodes.
+* Make sure name matching occurs before eventual name transformation.
+
+Tar 1.24 changed the ordering of name matching and name transformation
+so that the former saw already transformed file names. This made it
+impossible to match file names in certain cases. It is fixed now.
+
+* Fix the behavior of tar -x --overwrite on hosts lacking O_NOFOLLOW.
+
+* Improve the testsuite.
+
+* Alternative decompression programs.
+
+If extraction from a compressed archive fails because the corresponding
+compression program is not installed and the following two conditions
+are met, tar retries extraction using an alternative decompressor:
+
+ 1. Another compression program supported by tar is able to handle this
+ compression format.
+ 2. The compression program was not explicitly requested in the command
+ line by the use of such options as -z, -j, etc.
+
+For example, if `compress' is not available, tar will try `gzip'.
+
+
version 1.24 - Sergey Poznyakoff, 2010-10-24
* The --full-time option.
diff --git a/configure.ac b/configure.ac
index 1de1ed3b..d112474f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -19,7 +19,7 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301, USA.
-AC_INIT([GNU tar], [1.24], [bug-tar@gnu.org])
+AC_INIT([GNU tar], [1.25], [bug-tar@gnu.org])
AC_CONFIG_SRCDIR([src/tar.c])
AC_CONFIG_AUX_DIR([build-aux])
AC_CONFIG_HEADERS([config.h])
diff --git a/doc/tar.texi b/doc/tar.texi
index 6d9d9cc5..2c259ff9 100644
--- a/doc/tar.texi
+++ b/doc/tar.texi
@@ -4166,6 +4166,23 @@ Disable all warning messages.
@cindex @samp{Ignoring unknown extended header keyword `%s'}, warning message
@item unknown-keyword
@samp{Ignoring unknown extended header keyword `%s'}
+@kwindex decompress-program
+@item decompress-program
+Controls verbose messages describing execution failures when trying
+alternative decompressor programs (@pxref{alternative decompression
+programs}). This warning is disabled by default (unless
+@option{--verbose} is used). A common example of what you can get
+when using this warning is:
+
+@smallexample
+$ @kbd{tar --warning=decompress-program -x -f archive.Z}
+tar (child): cannot run compress: No such file or directory
+tar (child): trying gzip
+@end smallexample
+
+This means that @command{tar} first tried to decompress
+@file{archive.Z} using @command{compress}, and, when that
+failed, switched to @command{gzip}.
@end table
@subheading Keywords controlling incremental extraction:
@@ -8755,6 +8772,24 @@ certain compression formats. If this approach fails, @command{tar}
falls back to using archive name suffix to determine its format
(@pxref{auto-compress}, for a list of recognized suffixes).
+@anchor{alternative decompression programs}
+@cindex alternative decompression programs
+Some compression programs are able to handle different compression
+formats. @GNUTAR{} uses this, if the principal decompressor for the
+given format is not available. For example, if @command{compress} is
+not installed, @command{tar} will try to use @command{gzip}. As of
+version @value{VERSION} the following alternatives are
+tried@footnote{To verbosely trace the decompressor selection, use the
+@option{--warning=decompress-program} option
+(@pxref{warnings,decompress-program}).}:
+
+@multitable @columnfractions 0.3 0.3 0.3
+@headitem Format @tab Main decompressor @tab Alternatives
+@item compress @tab compress @tab gzip
+@item lzma @tab lzma @tab xz
+@item bzip2 @tab bzip2 @tab lbzip2
+@end multitable
+
The only case when you have to specify a decompression option while
reading the archive is when reading from a pipe or from a tape drive
that does not support random access. However, in this case @GNUTAR{}
diff --git a/src/buffer.c b/src/buffer.c
index ef4bbac6..e52b1b10 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -261,8 +261,8 @@ compute_duration ()
/* Compression detection */
enum compress_type {
- ct_tar, /* Plain tar file */
ct_none, /* Unknown compression type */
+ ct_tar, /* Plain tar file */
ct_compress,
ct_gzip,
ct_bzip2,
@@ -272,31 +272,102 @@ enum compress_type {
ct_xz
};
+static enum compress_type archive_compression_type = ct_none;
+
struct zip_magic
{
enum compress_type type;
size_t length;
char const *magic;
+};
+
+struct zip_program
+{
+ enum compress_type type;
char const *program;
char const *option;
};
static struct zip_magic const magic[] = {
- { ct_tar },
{ ct_none, },
- { ct_compress, 2, "\037\235", COMPRESS_PROGRAM, "-Z" },
- { ct_gzip, 2, "\037\213", GZIP_PROGRAM, "-z" },
- { ct_bzip2, 3, "BZh", BZIP2_PROGRAM, "-j" },
- { ct_lzip, 4, "LZIP", LZIP_PROGRAM, "--lzip" },
- { ct_lzma, 6, "\xFFLZMA", LZMA_PROGRAM, "--lzma" },
- { ct_lzop, 4, "\211LZO", LZOP_PROGRAM, "--lzop" },
- { ct_xz, 6, "\xFD" "7zXZ", XZ_PROGRAM, "-J" },
+ { ct_tar },
+ { ct_compress, 2, "\037\235" },
+ { ct_gzip, 2, "\037\213" },
+ { ct_bzip2, 3, "BZh" },
+ { ct_lzip, 4, "LZIP" },
+ { ct_lzma, 6, "\xFFLZMA" },
+ { ct_lzop, 4, "\211LZO" },
+ { ct_xz, 6, "\xFD" "7zXZ" },
};
#define NMAGIC (sizeof(magic)/sizeof(magic[0]))
-#define compress_option(t) magic[t].option
-#define compress_program(t) magic[t].program
+static struct zip_program zip_program[] = {
+ { ct_compress, COMPRESS_PROGRAM, "-Z" },
+ { ct_compress, GZIP_PROGRAM, "-z" },
+ { ct_gzip, GZIP_PROGRAM, "-z" },
+ { ct_bzip2, BZIP2_PROGRAM, "-j" },
+ { ct_bzip2, "lbzip2", "-j" },
+ { ct_lzip, LZIP_PROGRAM, "--lzip" },
+ { ct_lzma, LZMA_PROGRAM, "--lzma" },
+ { ct_lzma, XZ_PROGRAM, "-J" },
+ { ct_lzop, LZOP_PROGRAM, "--lzop" },
+ { ct_xz, XZ_PROGRAM, "-J" },
+ { ct_none }
+};
+
+static struct zip_program const *
+find_zip_program (enum compress_type type, int *pstate)
+{
+ int i;
+
+ for (i = *pstate; zip_program[i].type != ct_none; i++)
+ {
+ if (zip_program[i].type == type)
+ {
+ *pstate = i + 1;
+ return zip_program + i;
+ }
+ }
+ *pstate = i;
+ return NULL;
+}
+
+const char *
+first_decompress_program (int *pstate)
+{
+ struct zip_program const *zp;
+
+ if (use_compress_program_option)
+ return use_compress_program_option;
+
+ if (archive_compression_type == ct_none)
+ return NULL;
+
+ *pstate = 0;
+ zp = find_zip_program (archive_compression_type, pstate);
+ return zp ? zp->program : NULL;
+}
+
+const char *
+next_decompress_program (int *pstate)
+{
+ struct zip_program const *zp;
+
+ if (use_compress_program_option)
+ return NULL;
+ zp = find_zip_program (archive_compression_type, pstate);
+ return zp ? zp->program : NULL;
+}
+
+static const char *
+compress_option (enum compress_type type)
+{
+ struct zip_program const *zp;
+ int i = 0;
+ zp = find_zip_program (type, &i);
+ return zp ? zp->option : NULL;
+}
/* Check if the file ARCHIVE is a compressed archive. */
static enum compress_type
@@ -395,7 +466,7 @@ open_compressed_archive (void)
break;
default:
- use_compress_program_option = compress_program (type);
+ archive_compression_type = type;
break;
}
}
diff --git a/src/common.h b/src/common.h
index 4a638240..69097b3f 100644
--- a/src/common.h
+++ b/src/common.h
@@ -440,6 +440,9 @@ void mv_size_left (off_t size);
void buffer_write_global_xheader (void);
+const char *first_decompress_program (int *pstate);
+const char *next_decompress_program (int *pstate);
+
/* Module create.c. */
enum dump_status
@@ -805,10 +808,12 @@ void checkpoint_run (bool do_write);
#define WARN_UNKNOWN_CAST 0x00010000
#define WARN_UNKNOWN_KEYWORD 0x00020000
#define WARN_XDEV 0x00040000
+#define WARN_DECOMPRESS_PROGRAM 0x00080000
/* The warnings composing WARN_VERBOSE_WARNINGS are enabled by default
in verbose mode */
-#define WARN_VERBOSE_WARNINGS (WARN_RENAME_DIRECTORY|WARN_NEW_DIRECTORY)
+#define WARN_VERBOSE_WARNINGS (WARN_RENAME_DIRECTORY|WARN_NEW_DIRECTORY|\
+ WARN_DECOMPRESS_PROGRAM)
#define WARN_ALL (~WARN_VERBOSE_WARNINGS)
void set_warning_option (const char *arg);
diff --git a/src/system.c b/src/system.c
index a11afd75..ba4ac2d3 100644
--- a/src/system.c
+++ b/src/system.c
@@ -455,6 +455,29 @@ sys_child_open_for_compress (void)
wait_for_grandchild (grandchild_pid);
}
+static void
+run_decompress_program (void)
+{
+ int i;
+ const char *p, *prog = NULL;
+
+ for (p = first_decompress_program (&i); p; p = next_decompress_program (&i))
+ {
+ if (prog)
+ {
+ WARNOPT (WARN_DECOMPRESS_PROGRAM,
+ (0, errno, _("cannot run %s"), prog));
+ WARNOPT (WARN_DECOMPRESS_PROGRAM,
+ (0, 0, _("trying %s"), p));
+ }
+ prog = p;
+ execlp (p, p, "-d", NULL);
+ }
+ if (!prog)
+ FATAL_ERROR ((0, 0, _("unable to run decompression program")));
+ exec_fatal (prog);
+}
+
/* Set ARCHIVE for uncompressing, then reading an archive. */
pid_t
sys_child_open_for_uncompress (void)
@@ -501,9 +524,7 @@ sys_child_open_for_uncompress (void)
open_fatal (archive_name_array[0]);
xdup2 (archive, STDIN_FILENO);
priv_set_restore_linkdir ();
- execlp (use_compress_program_option, use_compress_program_option,
- "-d", (char *) 0);
- exec_fatal (use_compress_program_option);
+ run_decompress_program ();
}
/* We do need a grandchild tar. */
@@ -520,9 +541,7 @@ sys_child_open_for_uncompress (void)
xdup2 (child_pipe[PREAD], STDIN_FILENO);
xclose (child_pipe[PWRITE]);
priv_set_restore_linkdir ();
- execlp (use_compress_program_option, use_compress_program_option,
- "-d", (char *) 0);
- exec_fatal (use_compress_program_option);
+ run_decompress_program ();
}
/* The child tar is still here! */
diff --git a/src/warning.c b/src/warning.c
index 4374a88c..5d1bcabc 100644
--- a/src/warning.c
+++ b/src/warning.c
@@ -41,6 +41,7 @@ static char const *const warning_args[] = {
"unknown-cast",
"unknown-keyword",
"xdev",
+ "decompress-program",
NULL
};
@@ -64,7 +65,8 @@ static int warning_types[] = {
WARN_TIMESTAMP,
WARN_UNKNOWN_CAST,
WARN_UNKNOWN_KEYWORD,
- WARN_XDEV
+ WARN_XDEV,
+ WARN_DECOMPRESS_PROGRAM
};
ARGMATCH_VERIFY (warning_args, warning_types);