-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>
\f
* 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.
+
\f
version 1.26 - Sergey Poznyakoff, 2011-03-12
performing potentially destructive options, such as overwriting files.
@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}
@item --keep-newer-files
This means that @command{tar} first tried to decompress
@file{archive.Z} using @command{compress}, and, when that
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
@subheading Keywords controlling incremental extraction:
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
print a message about a non-standard blocking factor, and then operate
-normally. On some tape devices, however, @command{tar} cannot figure
-out the record size itself. On most of those, you can specify a
-blocking factor (with @option{--blocking-factor}) larger than the
-actual blocking factor, and then use the @option{--read-full-records}
-(@option{-B}) option. (If you specify a blocking factor with
-@option{--blocking-factor} and don't use the
-@option{--read-full-records} option, then @command{tar} will not
-attempt to figure out the recording size itself.) On some devices,
-you must always specify the record size exactly with
+normally@footnote{If this message is not needed, you can turn it off
+using the @option{--warning=no-record-size} option.}. On some tape
+devices, however, @command{tar} cannot figure out the record size
+itself. On most of those, you can specify a blocking factor (with
+@option{--blocking-factor}) larger than the actual blocking factor,
+and then use the @option{--read-full-records} (@option{-B}) option.
+(If you specify a blocking factor with @option{--blocking-factor} and
+don't use the @option{--read-full-records} option, then @command{tar}
+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
figure it out. In any case, use @option{--list} (@option{-t}) before
doing any extractions to see whether @command{tar} is reading the archive
left = record_size - status;
if (left && left % BLOCKSIZE == 0
- && verbose_option
+ && (warning_option & WARN_RECORD_SIZE)
&& record_start_block == 0 && status != 0
&& archive_is_dev ())
{
unsigned long rsize = status / BLOCKSIZE;
WARN ((0, 0,
- ngettext ("Record size = %lu block",
- "Record size = %lu blocks",
- rsize),
- rsize));
+ ngettext ("Record size = %lu block",
+ "Record size = %lu blocks",
+ rsize),
+ rsize));
}
while (left % BLOCKSIZE != 0
};
GLOBAL enum old_files old_files_option;
+GLOBAL bool keep_directory_symlink_option;
+
/* Specified file name for incremental list. */
GLOBAL const char *listed_incremental_option;
/* Incremental dump level */
#define WARN_DECOMPRESS_PROGRAM 0x00080000
#define WARN_EXISTING_FILE 0x00100000
#define WARN_XATTR_WRITE 0x00200000
+#define WARN_RECORD_SIZE 0x00400000
-/* The warnings composing WARN_VERBOSE_WARNINGS are enabled by default
- in verbose mode */
+/* These warnings are enabled by default in verbose mode: */
#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)
void set_warning_option (const char *arg);
}
\f
-
+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;
+}
+\f
/* Extractor functions for various member types */
static int
if (errno == EEXIST
&& (interdir_made
+ || keep_directory_symlink_option
|| old_files_option == DEFAULT_OLD_FILES
|| old_files_option == OVERWRITE_OLD_FILES))
{
struct stat st;
+
+ if (keep_directory_symlink_option && is_directory_link (file_name))
+ return 0;
+
if (deref_stat (file_name, &st) == 0)
{
current_mode = st.st_mode;
{ S(tlz, LZMA) },
{ S(lzo, LZOP) },
{ S(xz, XZ) },
+ { S(txz, XZ) }, /* Slackware */
#undef S
#undef __CAT2__
};
IGNORE_COMMAND_ERROR_OPTION,
IGNORE_FAILED_READ_OPTION,
INDEX_FILE_OPTION,
+ KEEP_DIRECTORY_SYMLINK_OPTION,
KEEP_NEWER_FILES_OPTION,
LEVEL_OPTION,
LZIP_OPTION,
{"overwrite-dir", OVERWRITE_DIR_OPTION, 0, 0,
N_("overwrite metadata of existing directories when extracting (default)"),
GRID+1 },
+ {"keep-directory-symlink", KEEP_DIRECTORY_SYMLINK_OPTION, 0, 0,
+ N_("preserve existing symlinks to directories when extracting"),
+ GRID+1 },
#undef GRID
#define GRID 40
ignore_failed_read_option = true;
break;
+ case KEEP_DIRECTORY_SYMLINK_OPTION:
+ keep_directory_symlink_option = true;
+ break;
+
case KEEP_NEWER_FILES_OPTION:
old_files_option = KEEP_NEWER_FILES;
break;
"decompress-program",
"existing-file",
"xattr-write",
+ "record-size",
NULL
};
WARN_XDEV,
WARN_DECOMPRESS_PROGRAM,
WARN_EXISTING_FILE,
- WARN_XATTR_WRITE
+ WARN_XATTR_WRITE,
+ WARN_RECORD_SIZE
};
ARGMATCH_VERIFY (warning_args, warning_types);