Changes for compatibility with Slackware installation scripts.

* src/buffer.c (short_read): the "Record size" message
is controlled by the WARN_RECORD_SIZE warning_option bit.
* src/common.h (keep_directory_symlink_option): New global.
(WARN_RECORD_SIZE): New constant.
(WARN_VERBOSE_WARNINGS): Add WARN_RECORD_SIZE.
* src/extract.c (extract_dir): If keep_directory_symlink_option is
set, follow symlinks to directories.
* src/suffix.c (compression_suffixes): Add support for txz
suffix.
* src/tar.c (KEEP_DIRECTORY_SYMLINK_OPTION): New constant.
(options): New option --keep-directory-symlink.
(parse_opt): Handle this option.
* src/warning.c: Implement "record-size" warning control.

* NEWS: Update.
* doc/tar.texi: Document new features.
This commit is contained in:
Sergey Poznyakoff
2013-09-23 19:35:29 +03:00
parent 570a2c5f3d
commit 2c06a80918
8 changed files with 90 additions and 20 deletions

19
NEWS
View File

@@ -1,4 +1,4 @@
GNU tar NEWS - User visible changes. 2013-02-10 GNU tar NEWS - User visible changes. 2013-09-23
Please send GNU tar bug reports to <bug-tar@gnu.org> Please send GNU tar bug reports to <bug-tar@gnu.org>
@@ -70,6 +70,23 @@ prevent from being expanded too early, for example:
* New configure option --enable-gcc-warnings, intended for debugging. * New configure option --enable-gcc-warnings, intended for debugging.
* New warning control option --warning=[no-]record-size
On extraction, this option controls whether to display actual record
size, if it differs from the default.
* New command line option --keep-directory-symlink
By default, if when trying to extract a directory from the archive,
tar discovers that the corresponding file name already exists and is a
symbolic link, it first unlinks the entry, and then extracts the directory.
This option disables this behavior and instructs tar to follow
symlinks to directories when extracting from the archive.
It is mainly intended to provide compatibility with the Slackware
installation scripts.
version 1.26 - Sergey Poznyakoff, 2011-03-12 version 1.26 - Sergey Poznyakoff, 2011-03-12

View File

@@ -2804,6 +2804,21 @@ Specifies that @command{tar} should ask the user for confirmation before
performing potentially destructive options, such as overwriting files. performing potentially destructive options, such as overwriting files.
@xref{interactive}. @xref{interactive}.
@opsummary{--keep-directory-symlink}
@item --keep-directory-symlink
This option changes the behavior of tar when it encounters a symlink
with the same name as the directory that it is about to extract. By
default, in this case tar would first remove the symlink and then
proceed extracting the directory.
The @option{--keep-directory-symlink} option disables this behavior
and instructs tar to follow symlinks to directories when extracting
from the archive.
It is mainly intended to provide compatibility with the Slackware
installation scripts.
@opsummary{keep-newer-files} @opsummary{keep-newer-files}
@item --keep-newer-files @item --keep-newer-files
@@ -4221,6 +4236,10 @@ tar (child): trying gzip
This means that @command{tar} first tried to decompress This means that @command{tar} first tried to decompress
@file{archive.Z} using @command{compress}, and, when that @file{archive.Z} using @command{compress}, and, when that
failed, switched to @command{gzip}. failed, switched to @command{gzip}.
@kwindex record-size
@cindex @samp{Record size = %lu blocks}, warning message
@item record-size
@samp{Record size = %lu blocks}
@end table @end table
@subheading Keywords controlling incremental extraction: @subheading Keywords controlling incremental extraction:
@@ -10706,15 +10725,16 @@ When reading an archive, @command{tar} can usually figure out the
record size on itself. When this is the case, and a non-standard record size on itself. When this is the case, and a non-standard
record size was used when the archive was created, @command{tar} will record size was used when the archive was created, @command{tar} will
print a message about a non-standard blocking factor, and then operate print a message about a non-standard blocking factor, and then operate
normally. On some tape devices, however, @command{tar} cannot figure normally@footnote{If this message is not needed, you can turn it off
out the record size itself. On most of those, you can specify a using the @option{--warning=no-record-size} option.}. On some tape
blocking factor (with @option{--blocking-factor}) larger than the devices, however, @command{tar} cannot figure out the record size
actual blocking factor, and then use the @option{--read-full-records} itself. On most of those, you can specify a blocking factor (with
(@option{-B}) option. (If you specify a blocking factor with @option{--blocking-factor}) larger than the actual blocking factor,
@option{--blocking-factor} and don't use the and then use the @option{--read-full-records} (@option{-B}) option.
@option{--read-full-records} option, then @command{tar} will not (If you specify a blocking factor with @option{--blocking-factor} and
attempt to figure out the recording size itself.) On some devices, don't use the @option{--read-full-records} option, then @command{tar}
you must always specify the record size exactly with will not attempt to figure out the recording size itself.) On some
devices, you must always specify the record size exactly with
@option{--blocking-factor} when reading, because @command{tar} cannot @option{--blocking-factor} when reading, because @command{tar} cannot
figure it out. In any case, use @option{--list} (@option{-t}) before figure it out. In any case, use @option{--list} (@option{-t}) before
doing any extractions to see whether @command{tar} is reading the archive doing any extractions to see whether @command{tar} is reading the archive

View File

@@ -884,16 +884,16 @@ short_read (size_t status)
left = record_size - status; left = record_size - status;
if (left && left % BLOCKSIZE == 0 if (left && left % BLOCKSIZE == 0
&& verbose_option && (warning_option & WARN_RECORD_SIZE)
&& record_start_block == 0 && status != 0 && record_start_block == 0 && status != 0
&& archive_is_dev ()) && archive_is_dev ())
{ {
unsigned long rsize = status / BLOCKSIZE; unsigned long rsize = status / BLOCKSIZE;
WARN ((0, 0, WARN ((0, 0,
ngettext ("Record size = %lu block", ngettext ("Record size = %lu block",
"Record size = %lu blocks", "Record size = %lu blocks",
rsize), rsize),
rsize)); rsize));
} }
while (left % BLOCKSIZE != 0 while (left % BLOCKSIZE != 0

View File

@@ -190,6 +190,8 @@ enum old_files
}; };
GLOBAL enum old_files old_files_option; GLOBAL enum old_files old_files_option;
GLOBAL bool keep_directory_symlink_option;
/* Specified file name for incremental list. */ /* Specified file name for incremental list. */
GLOBAL const char *listed_incremental_option; GLOBAL const char *listed_incremental_option;
/* Incremental dump level */ /* Incremental dump level */
@@ -872,11 +874,12 @@ void checkpoint_run (bool do_write);
#define WARN_DECOMPRESS_PROGRAM 0x00080000 #define WARN_DECOMPRESS_PROGRAM 0x00080000
#define WARN_EXISTING_FILE 0x00100000 #define WARN_EXISTING_FILE 0x00100000
#define WARN_XATTR_WRITE 0x00200000 #define WARN_XATTR_WRITE 0x00200000
#define WARN_RECORD_SIZE 0x00400000
/* The warnings composing WARN_VERBOSE_WARNINGS are enabled by default /* These warnings are enabled by default in verbose mode: */
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|WARN_EXISTING_FILE) WARN_DECOMPRESS_PROGRAM|WARN_EXISTING_FILE|\
WARN_RECORD_SIZE)
#define WARN_ALL (~WARN_VERBOSE_WARNINGS) #define WARN_ALL (~WARN_VERBOSE_WARNINGS)
void set_warning_option (const char *arg); void set_warning_option (const char *arg);

View File

@@ -855,7 +855,21 @@ apply_nonancestor_delayed_set_stat (char const *file_name, bool after_links)
} }
static bool
is_directory_link (const char *file_name)
{
struct stat st;
int e = errno;
int res;
res = (fstatat (chdir_fd, file_name, &st, AT_SYMLINK_NOFOLLOW) == 0 &&
S_ISLNK (st.st_mode) &&
fstatat (chdir_fd, file_name, &st, 0) == 0 &&
S_ISDIR (st.st_mode));
errno = e;
return res;
}
/* Extractor functions for various member types */ /* Extractor functions for various member types */
static int static int
@@ -911,10 +925,15 @@ extract_dir (char *file_name, int typeflag)
if (errno == EEXIST if (errno == EEXIST
&& (interdir_made && (interdir_made
|| keep_directory_symlink_option
|| old_files_option == DEFAULT_OLD_FILES || old_files_option == DEFAULT_OLD_FILES
|| old_files_option == OVERWRITE_OLD_FILES)) || old_files_option == OVERWRITE_OLD_FILES))
{ {
struct stat st; struct stat st;
if (keep_directory_symlink_option && is_directory_link (file_name))
return 0;
if (deref_stat (file_name, &st) == 0) if (deref_stat (file_name, &st) == 0)
{ {
current_mode = st.st_mode; current_mode = st.st_mode;

View File

@@ -43,6 +43,7 @@ static struct compression_suffix compression_suffixes[] = {
{ S(tlz, LZMA) }, { S(tlz, LZMA) },
{ S(lzo, LZOP) }, { S(lzo, LZOP) },
{ S(xz, XZ) }, { S(xz, XZ) },
{ S(txz, XZ) }, /* Slackware */
#undef S #undef S
#undef __CAT2__ #undef __CAT2__
}; };

View File

@@ -286,6 +286,7 @@ enum
IGNORE_COMMAND_ERROR_OPTION, IGNORE_COMMAND_ERROR_OPTION,
IGNORE_FAILED_READ_OPTION, IGNORE_FAILED_READ_OPTION,
INDEX_FILE_OPTION, INDEX_FILE_OPTION,
KEEP_DIRECTORY_SYMLINK_OPTION,
KEEP_NEWER_FILES_OPTION, KEEP_NEWER_FILES_OPTION,
LEVEL_OPTION, LEVEL_OPTION,
LZIP_OPTION, LZIP_OPTION,
@@ -485,6 +486,9 @@ static struct argp_option options[] = {
{"overwrite-dir", OVERWRITE_DIR_OPTION, 0, 0, {"overwrite-dir", OVERWRITE_DIR_OPTION, 0, 0,
N_("overwrite metadata of existing directories when extracting (default)"), N_("overwrite metadata of existing directories when extracting (default)"),
GRID+1 }, GRID+1 },
{"keep-directory-symlink", KEEP_DIRECTORY_SYMLINK_OPTION, 0, 0,
N_("preserve existing symlinks to directories when extracting"),
GRID+1 },
#undef GRID #undef GRID
#define GRID 40 #define GRID 40
@@ -1767,6 +1771,10 @@ parse_opt (int key, char *arg, struct argp_state *state)
ignore_failed_read_option = true; ignore_failed_read_option = true;
break; break;
case KEEP_DIRECTORY_SYMLINK_OPTION:
keep_directory_symlink_option = true;
break;
case KEEP_NEWER_FILES_OPTION: case KEEP_NEWER_FILES_OPTION:
old_files_option = KEEP_NEWER_FILES; old_files_option = KEEP_NEWER_FILES;
break; break;

View File

@@ -46,6 +46,7 @@ static char const *const warning_args[] = {
"decompress-program", "decompress-program",
"existing-file", "existing-file",
"xattr-write", "xattr-write",
"record-size",
NULL NULL
}; };
@@ -72,7 +73,8 @@ static int warning_types[] = {
WARN_XDEV, WARN_XDEV,
WARN_DECOMPRESS_PROGRAM, WARN_DECOMPRESS_PROGRAM,
WARN_EXISTING_FILE, WARN_EXISTING_FILE,
WARN_XATTR_WRITE WARN_XATTR_WRITE,
WARN_RECORD_SIZE
}; };
ARGMATCH_VERIFY (warning_args, warning_types); ARGMATCH_VERIFY (warning_args, warning_types);