|
@@ -450,43 +450,6 @@ file_newer_p (const char *file_name, struct tar_stat_info *tar_stat)
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
-/* Prepare to extract a file.
|
|
|
- Return zero if extraction should not proceed. */
|
|
|
-
|
|
|
-static int
|
|
|
-prepare_to_extract (char const *file_name)
|
|
|
-{
|
|
|
- if (to_stdout_option)
|
|
|
- return 0;
|
|
|
-
|
|
|
- switch (old_files_option)
|
|
|
- {
|
|
|
- case UNLINK_FIRST_OLD_FILES:
|
|
|
- if (!remove_any_file (file_name,
|
|
|
- recursive_unlink_option ? RECURSIVE_REMOVE_OPTION
|
|
|
- : ORDINARY_REMOVE_OPTION)
|
|
|
- && errno && errno != ENOENT)
|
|
|
- {
|
|
|
- unlink_error (file_name);
|
|
|
- return 0;
|
|
|
- }
|
|
|
- break;
|
|
|
-
|
|
|
- case KEEP_NEWER_FILES:
|
|
|
- if (file_newer_p (file_name, ¤t_stat_info))
|
|
|
- {
|
|
|
- WARN ((0, 0, _("Current %s is newer"), quote (file_name)));
|
|
|
- return 0;
|
|
|
- }
|
|
|
- break;
|
|
|
-
|
|
|
- default:
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- return 1;
|
|
|
-}
|
|
|
-
|
|
|
/* Attempt repairing what went wrong with the extraction. Delete an
|
|
|
already existing file or create missing intermediate directories.
|
|
|
Return nonzero if we somewhat increased our chances at a successful
|
|
@@ -602,8 +565,11 @@ apply_nonancestor_delayed_set_stat (char const *file_name, bool after_symlinks)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+
|
|
|
|
|
|
-void
|
|
|
+/* Extractor functions for various member types */
|
|
|
+
|
|
|
+static int
|
|
|
extract_dir (char *file_name, int typeflag)
|
|
|
{
|
|
|
int status;
|
|
@@ -618,48 +584,41 @@ extract_dir (char *file_name, int typeflag)
|
|
|
|
|
|
mode = (current_stat_info.stat.st_mode | (we_are_root ? 0 : MODE_WXUSR)) & MODE_RWX;
|
|
|
|
|
|
- status = prepare_to_extract (file_name);
|
|
|
- if (status == 0)
|
|
|
- return;
|
|
|
+ while ((status = mkdir (file_name, mode)))
|
|
|
+ {
|
|
|
+ if (errno == EEXIST
|
|
|
+ && (interdir_made
|
|
|
+ || old_files_option == DEFAULT_OLD_FILES
|
|
|
+ || old_files_option == OVERWRITE_OLD_FILES))
|
|
|
+ {
|
|
|
+ struct stat st;
|
|
|
+ if (stat (file_name, &st) == 0)
|
|
|
+ {
|
|
|
+ if (interdir_made)
|
|
|
+ {
|
|
|
+ repair_delayed_set_stat (file_name, &st);
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ if (S_ISDIR (st.st_mode))
|
|
|
+ {
|
|
|
+ mode = st.st_mode & ~ current_umask;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ errno = EEXIST;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (maybe_recoverable (file_name, &interdir_made))
|
|
|
+ continue;
|
|
|
+
|
|
|
+ if (errno != EEXIST)
|
|
|
+ {
|
|
|
+ mkdir_error (file_name);
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ }
|
|
|
|
|
|
- if (status > 0)
|
|
|
- while ((status = mkdir (file_name, mode)))
|
|
|
- {
|
|
|
- if (errno == EEXIST
|
|
|
- && (interdir_made
|
|
|
- || old_files_option == DEFAULT_OLD_FILES
|
|
|
- || old_files_option == OVERWRITE_OLD_FILES))
|
|
|
- {
|
|
|
- struct stat st;
|
|
|
- if (stat (file_name, &st) == 0)
|
|
|
- {
|
|
|
- if (interdir_made)
|
|
|
- {
|
|
|
- repair_delayed_set_stat (file_name, &st);
|
|
|
- return;
|
|
|
- }
|
|
|
- if (S_ISDIR (st.st_mode))
|
|
|
- {
|
|
|
- mode = st.st_mode & ~ current_umask;
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- errno = EEXIST;
|
|
|
- }
|
|
|
-
|
|
|
- if (maybe_recoverable (file_name, &interdir_made))
|
|
|
- continue;
|
|
|
-
|
|
|
- if (errno != EEXIST)
|
|
|
- {
|
|
|
- mkdir_error (file_name);
|
|
|
- if (backup_option)
|
|
|
- undo_last_backup ();
|
|
|
- return;
|
|
|
- }
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
if (status == 0
|
|
|
|| old_files_option == DEFAULT_OLD_FILES
|
|
|
|| old_files_option == OVERWRITE_OLD_FILES)
|
|
@@ -668,6 +627,8 @@ extract_dir (char *file_name, int typeflag)
|
|
|
(status == 0
|
|
|
? ARCHIVED_PERMSTATUS
|
|
|
: UNKNOWN_PERMSTATUS));
|
|
|
+
|
|
|
+ return status;
|
|
|
}
|
|
|
|
|
|
|
|
@@ -708,7 +669,7 @@ open_output_file (char *file_name, int typeflag)
|
|
|
return fd;
|
|
|
}
|
|
|
|
|
|
-static void
|
|
|
+static int
|
|
|
extract_file (char *file_name, int typeflag)
|
|
|
{
|
|
|
int fd;
|
|
@@ -721,32 +682,20 @@ extract_file (char *file_name, int typeflag)
|
|
|
|
|
|
/* FIXME: deal with protection issues. */
|
|
|
|
|
|
- do
|
|
|
+ if (to_stdout_option)
|
|
|
+ fd = STDOUT_FILENO;
|
|
|
+ else
|
|
|
{
|
|
|
- if (to_stdout_option)
|
|
|
- fd = STDOUT_FILENO;
|
|
|
- else
|
|
|
+ do
|
|
|
+ fd = open_output_file (file_name, typeflag);
|
|
|
+ while (fd < 0 && maybe_recoverable (file_name, &interdir_made));
|
|
|
+
|
|
|
+ if (fd < 0)
|
|
|
{
|
|
|
- if (! prepare_to_extract (file_name))
|
|
|
- {
|
|
|
- skip_member ();
|
|
|
- if (backup_option)
|
|
|
- undo_last_backup ();
|
|
|
- return;
|
|
|
- }
|
|
|
- fd = open_output_file (file_name, typeflag);
|
|
|
+ open_error (file_name);
|
|
|
+ return 1;
|
|
|
}
|
|
|
}
|
|
|
- while (fd < 0 && maybe_recoverable (file_name, &interdir_made));
|
|
|
-
|
|
|
- if (fd < 0)
|
|
|
- {
|
|
|
- open_error (file_name);
|
|
|
- skip_member ();
|
|
|
- if (backup_option)
|
|
|
- undo_last_backup ();
|
|
|
- return;
|
|
|
- }
|
|
|
|
|
|
if (current_stat_info.is_sparse)
|
|
|
sparse_extract_file (fd, ¤t_stat_info, &size);
|
|
@@ -783,7 +732,8 @@ extract_file (char *file_name, int typeflag)
|
|
|
(data_block->buffer + written - 1));
|
|
|
if (count != written)
|
|
|
{
|
|
|
- write_error_details (file_name, count, written);
|
|
|
+ write_error_details (file_name, count, written); /* FIXME: shouldn't we
|
|
|
+ restore from backup? */
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
@@ -797,38 +747,30 @@ extract_file (char *file_name, int typeflag)
|
|
|
it doesn't exist, or we don't want to touch it anyway. */
|
|
|
|
|
|
if (to_stdout_option)
|
|
|
- return;
|
|
|
+ return 0;
|
|
|
|
|
|
status = close (fd);
|
|
|
if (status < 0)
|
|
|
- {
|
|
|
- close_error (file_name);
|
|
|
- if (backup_option)
|
|
|
- undo_last_backup ();
|
|
|
- }
|
|
|
+ close_error (file_name);
|
|
|
|
|
|
set_stat (file_name, ¤t_stat_info.stat, 0, 0,
|
|
|
- (old_files_option == OVERWRITE_OLD_FILES
|
|
|
- ? UNKNOWN_PERMSTATUS
|
|
|
- : ARCHIVED_PERMSTATUS),
|
|
|
+ (old_files_option == OVERWRITE_OLD_FILES ?
|
|
|
+ UNKNOWN_PERMSTATUS : ARCHIVED_PERMSTATUS),
|
|
|
typeflag);
|
|
|
+
|
|
|
+ return status;
|
|
|
}
|
|
|
|
|
|
-static void
|
|
|
-extract_link (char *file_name)
|
|
|
+static int
|
|
|
+extract_link (char *file_name, int typeflag)
|
|
|
{
|
|
|
- char const *link_name;
|
|
|
+ char const *link_name = safer_name_suffix (current_stat_info.link_name, true);
|
|
|
int interdir_made = 0;
|
|
|
|
|
|
- if (!prepare_to_extract (file_name))
|
|
|
- return;
|
|
|
-
|
|
|
do
|
|
|
{
|
|
|
struct stat st1, st2;
|
|
|
int e;
|
|
|
- link_name = safer_name_suffix (current_stat_info.link_name, true);
|
|
|
-
|
|
|
int status = link (link_name, file_name);
|
|
|
e = errno;
|
|
|
|
|
@@ -848,14 +790,14 @@ extract_link (char *file_name)
|
|
|
ds->sources = p;
|
|
|
break;
|
|
|
}
|
|
|
- return;
|
|
|
+ return 0;
|
|
|
}
|
|
|
else if ((e == EEXIST && strcmp (link_name, file_name) == 0)
|
|
|
|| (lstat (link_name, &st1) == 0
|
|
|
&& lstat (file_name, &st2) == 0
|
|
|
&& st1.st_dev == st2.st_dev
|
|
|
&& st1.st_ino == st2.st_ino))
|
|
|
- return;
|
|
|
+ return 0;
|
|
|
|
|
|
errno = e;
|
|
|
}
|
|
@@ -864,27 +806,23 @@ extract_link (char *file_name)
|
|
|
if (!(incremental_option && errno == EEXIST))
|
|
|
{
|
|
|
link_error (link_name, file_name);
|
|
|
- if (backup_option)
|
|
|
- undo_last_backup ();
|
|
|
+ return 1;
|
|
|
}
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
-static void
|
|
|
-extract_symlink (char *file_name)
|
|
|
+static int
|
|
|
+extract_symlink (char *file_name, int typeflag)
|
|
|
{
|
|
|
#ifdef HAVE_SYMLINK
|
|
|
int status, fd;
|
|
|
int interdir_made = 0;
|
|
|
|
|
|
- if (! prepare_to_extract (file_name))
|
|
|
- return;
|
|
|
-
|
|
|
if (absolute_names_option
|
|
|
|| ! (IS_ABSOLUTE_FILE_NAME (current_stat_info.link_name)
|
|
|
|| contains_dot_dot (current_stat_info.link_name)))
|
|
|
{
|
|
|
- while (status = symlink (current_stat_info.link_name, file_name),
|
|
|
- status != 0)
|
|
|
+ while ((status = symlink (current_stat_info.link_name, file_name)))
|
|
|
if (!maybe_recoverable (file_name, &interdir_made))
|
|
|
break;
|
|
|
|
|
@@ -958,8 +896,7 @@ extract_symlink (char *file_name)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- if (status != 0 && backup_option)
|
|
|
- undo_last_backup ();
|
|
|
+ return status;
|
|
|
|
|
|
#else
|
|
|
static int warned_once;
|
|
@@ -969,48 +906,37 @@ extract_symlink (char *file_name)
|
|
|
warned_once = 1;
|
|
|
WARN ((0, 0, _("Attempting extraction of symbolic links as hard links")));
|
|
|
}
|
|
|
- extract_link (file_name);
|
|
|
+ return extract_link (file_name, typeflag);
|
|
|
#endif
|
|
|
}
|
|
|
|
|
|
#if S_IFCHR || S_IFBLK
|
|
|
-static void
|
|
|
+static int
|
|
|
extract_node (char *file_name, int typeflag)
|
|
|
{
|
|
|
int status;
|
|
|
int interdir_made = 0;
|
|
|
|
|
|
do
|
|
|
- {
|
|
|
- if (! prepare_to_extract (file_name))
|
|
|
- return;
|
|
|
-
|
|
|
- status = mknod (file_name, current_stat_info.stat.st_mode,
|
|
|
- current_stat_info.stat.st_rdev);
|
|
|
- }
|
|
|
+ status = mknod (file_name, current_stat_info.stat.st_mode,
|
|
|
+ current_stat_info.stat.st_rdev);
|
|
|
while (status && maybe_recoverable (file_name, &interdir_made));
|
|
|
|
|
|
if (status != 0)
|
|
|
- {
|
|
|
- mknod_error (file_name);
|
|
|
- if (backup_option)
|
|
|
- undo_last_backup ();
|
|
|
- }
|
|
|
+ mknod_error (file_name);
|
|
|
else
|
|
|
set_stat (file_name, ¤t_stat_info.stat, 0, 0, ARCHIVED_PERMSTATUS, typeflag);
|
|
|
+ return status;
|
|
|
}
|
|
|
#endif
|
|
|
|
|
|
#if HAVE_MKFIFO || defined mkfifo
|
|
|
-static void
|
|
|
+static int
|
|
|
extract_fifo (char *file_name, int typeflag)
|
|
|
{
|
|
|
int status;
|
|
|
int interdir_made = 0;
|
|
|
|
|
|
- if (! prepare_to_extract (file_name))
|
|
|
- return;
|
|
|
-
|
|
|
while ((status = mkfifo (file_name, current_stat_info.stat.st_mode)))
|
|
|
if (!maybe_recoverable (file_name, &interdir_made))
|
|
|
break;
|
|
@@ -1019,148 +945,219 @@ extract_fifo (char *file_name, int typeflag)
|
|
|
set_stat (file_name, ¤t_stat_info.stat, NULL, 0,
|
|
|
ARCHIVED_PERMSTATUS, typeflag);
|
|
|
else
|
|
|
- {
|
|
|
- mkfifo_error (file_name);
|
|
|
- if (backup_option)
|
|
|
- undo_last_backup ();
|
|
|
- }
|
|
|
+ mkfifo_error (file_name);
|
|
|
+ return status;
|
|
|
}
|
|
|
#endif
|
|
|
|
|
|
-/* Extract a file from the archive. */
|
|
|
-void
|
|
|
-extract_archive (void)
|
|
|
+static int
|
|
|
+extract_mangle_wrapper (char *file_name, int typeflag)
|
|
|
{
|
|
|
- char typeflag;
|
|
|
- char *file_name;
|
|
|
-
|
|
|
- set_next_block_after (current_header);
|
|
|
- decode_header (current_header, ¤t_stat_info, ¤t_format, 1);
|
|
|
-
|
|
|
- if (interactive_option && !confirm ("extract", current_stat_info.file_name))
|
|
|
- {
|
|
|
- skip_member ();
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- /* Print the block from current_header and current_stat. */
|
|
|
-
|
|
|
- if (verbose_option)
|
|
|
- print_header (¤t_stat_info, -1);
|
|
|
-
|
|
|
- file_name = safer_name_suffix (current_stat_info.file_name, false);
|
|
|
- if (strip_name_components)
|
|
|
- {
|
|
|
- size_t prefix_len = stripped_prefix_len (file_name, strip_name_components);
|
|
|
- if (prefix_len == (size_t) -1)
|
|
|
- {
|
|
|
- skip_member ();
|
|
|
- return;
|
|
|
- }
|
|
|
- file_name += prefix_len;
|
|
|
- }
|
|
|
+ extract_mangle ();
|
|
|
+ return 0;
|
|
|
+}
|
|
|
|
|
|
- apply_nonancestor_delayed_set_stat (file_name, 0);
|
|
|
+
|
|
|
+static int
|
|
|
+extract_failure (char *file_name, int typeflag)
|
|
|
+{
|
|
|
+ return 1;
|
|
|
+}
|
|
|
|
|
|
- /* Take a safety backup of a previously existing file. */
|
|
|
+typedef int (*tar_extractor_t) (char *file_name, int typeflag);
|
|
|
|
|
|
- if (backup_option && !to_stdout_option)
|
|
|
- if (!maybe_backup_file (file_name, 0))
|
|
|
- {
|
|
|
- int e = errno;
|
|
|
- ERROR ((0, e, _("%s: Was unable to backup this file"),
|
|
|
- quotearg_colon (file_name)));
|
|
|
- skip_member ();
|
|
|
- return;
|
|
|
- }
|
|
|
+
|
|
|
|
|
|
- /* Extract the archive entry according to its type. */
|
|
|
+/* Prepare to extract a file. Find extractor function.
|
|
|
+ Return zero if extraction should not proceed. */
|
|
|
|
|
|
- /* KLUDGE */
|
|
|
- typeflag = sparse_member_p (¤t_stat_info) ?
|
|
|
- GNUTYPE_SPARSE : current_header->header.typeflag;
|
|
|
+static int
|
|
|
+prepare_to_extract (char const *file_name, int typeflag, tar_extractor_t *fun)
|
|
|
+{
|
|
|
+ int rc = 1;
|
|
|
+
|
|
|
+ if (to_stdout_option)
|
|
|
+ rc = 0;
|
|
|
|
|
|
+ /* Select the extractor */
|
|
|
switch (typeflag)
|
|
|
{
|
|
|
- case GNUTYPE_SPARSE: /* FIXME: Shouldn't we call extract_file at once? */
|
|
|
+ case GNUTYPE_SPARSE:
|
|
|
+ *fun = extract_file;
|
|
|
+ rc = 1;
|
|
|
+ break;
|
|
|
+
|
|
|
case AREGTYPE:
|
|
|
case REGTYPE:
|
|
|
case CONTTYPE:
|
|
|
-
|
|
|
/* Appears to be a file. But BSD tar uses the convention that a slash
|
|
|
suffix means a directory. */
|
|
|
-
|
|
|
if (current_stat_info.had_trailing_slash)
|
|
|
- extract_dir (file_name, typeflag);
|
|
|
+ *fun = extract_dir;
|
|
|
else
|
|
|
- extract_file (file_name, typeflag);
|
|
|
+ {
|
|
|
+ *fun = extract_file;
|
|
|
+ rc = 1;
|
|
|
+ }
|
|
|
break;
|
|
|
|
|
|
case SYMTYPE:
|
|
|
- extract_symlink (file_name);
|
|
|
+ *fun = extract_symlink;
|
|
|
break;
|
|
|
-
|
|
|
+
|
|
|
case LNKTYPE:
|
|
|
- extract_link (file_name);
|
|
|
+ *fun = extract_link;
|
|
|
break;
|
|
|
|
|
|
#if S_IFCHR
|
|
|
case CHRTYPE:
|
|
|
current_stat_info.stat.st_mode |= S_IFCHR;
|
|
|
- extract_node (file_name, typeflag);
|
|
|
+ *fun = extract_node;
|
|
|
break;
|
|
|
#endif
|
|
|
|
|
|
#if S_IFBLK
|
|
|
case BLKTYPE:
|
|
|
current_stat_info.stat.st_mode |= S_IFBLK;
|
|
|
- extract_node (file_name, typeflag);
|
|
|
+ *fun = extract_node;
|
|
|
break;
|
|
|
#endif
|
|
|
|
|
|
#if HAVE_MKFIFO || defined mkfifo
|
|
|
case FIFOTYPE:
|
|
|
- extract_fifo (file_name, typeflag);
|
|
|
+ *fun = extract_fifo;
|
|
|
break;
|
|
|
#endif
|
|
|
|
|
|
case DIRTYPE:
|
|
|
case GNUTYPE_DUMPDIR:
|
|
|
- extract_dir (file_name, typeflag);
|
|
|
+ *fun = extract_dir;
|
|
|
break;
|
|
|
|
|
|
case GNUTYPE_VOLHDR:
|
|
|
if (verbose_option)
|
|
|
fprintf (stdlis, _("Reading %s\n"), quote (current_stat_info.file_name));
|
|
|
+ *fun = NULL;
|
|
|
break;
|
|
|
|
|
|
case GNUTYPE_NAMES:
|
|
|
- extract_mangle ();
|
|
|
+ *fun = extract_mangle_wrapper;
|
|
|
break;
|
|
|
|
|
|
case GNUTYPE_MULTIVOL:
|
|
|
ERROR ((0, 0,
|
|
|
_("%s: Cannot extract -- file is continued from another volume"),
|
|
|
quotearg_colon (current_stat_info.file_name)));
|
|
|
- skip_member ();
|
|
|
- if (backup_option)
|
|
|
- undo_last_backup ();
|
|
|
+ *fun = extract_failure;
|
|
|
break;
|
|
|
|
|
|
case GNUTYPE_LONGNAME:
|
|
|
case GNUTYPE_LONGLINK:
|
|
|
ERROR ((0, 0, _("Unexpected long name header")));
|
|
|
- skip_member ();
|
|
|
- if (backup_option)
|
|
|
- undo_last_backup ();
|
|
|
+ *fun = extract_failure;
|
|
|
break;
|
|
|
|
|
|
default:
|
|
|
WARN ((0, 0,
|
|
|
_("%s: Unknown file type '%c', extracted as normal file"),
|
|
|
quotearg_colon (file_name), typeflag));
|
|
|
- extract_file (file_name, typeflag);
|
|
|
+ *fun = extract_file;
|
|
|
}
|
|
|
+
|
|
|
+ /* Determine whether the extraction should proceed */
|
|
|
+ if (rc == 0)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ switch (old_files_option)
|
|
|
+ {
|
|
|
+ case UNLINK_FIRST_OLD_FILES:
|
|
|
+ if (!remove_any_file (file_name,
|
|
|
+ recursive_unlink_option ? RECURSIVE_REMOVE_OPTION
|
|
|
+ : ORDINARY_REMOVE_OPTION)
|
|
|
+ && errno && errno != ENOENT)
|
|
|
+ {
|
|
|
+ unlink_error (file_name);
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+
|
|
|
+ case KEEP_NEWER_FILES:
|
|
|
+ if (file_newer_p (file_name, ¤t_stat_info))
|
|
|
+ {
|
|
|
+ WARN ((0, 0, _("Current %s is newer"), quote (file_name)));
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+
|
|
|
+ default:
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ return 1;
|
|
|
+}
|
|
|
+
|
|
|
+/* Extract a file from the archive. */
|
|
|
+void
|
|
|
+extract_archive (void)
|
|
|
+{
|
|
|
+ char typeflag;
|
|
|
+ char *file_name;
|
|
|
+ tar_extractor_t fun;
|
|
|
+
|
|
|
+ set_next_block_after (current_header);
|
|
|
+ decode_header (current_header, ¤t_stat_info, ¤t_format, 1);
|
|
|
+
|
|
|
+ if (interactive_option && !confirm ("extract", current_stat_info.file_name))
|
|
|
+ {
|
|
|
+ skip_member ();
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Print the block from current_header and current_stat. */
|
|
|
+
|
|
|
+ if (verbose_option)
|
|
|
+ print_header (¤t_stat_info, -1);
|
|
|
+
|
|
|
+ file_name = safer_name_suffix (current_stat_info.file_name, false);
|
|
|
+ if (strip_name_components)
|
|
|
+ {
|
|
|
+ size_t prefix_len = stripped_prefix_len (file_name, strip_name_components);
|
|
|
+ if (prefix_len == (size_t) -1)
|
|
|
+ {
|
|
|
+ skip_member ();
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ file_name += prefix_len;
|
|
|
+ }
|
|
|
+
|
|
|
+ apply_nonancestor_delayed_set_stat (file_name, 0);
|
|
|
+
|
|
|
+ /* Take a safety backup of a previously existing file. */
|
|
|
+
|
|
|
+ if (backup_option && !to_stdout_option)
|
|
|
+ if (!maybe_backup_file (file_name, 0))
|
|
|
+ {
|
|
|
+ int e = errno;
|
|
|
+ ERROR ((0, e, _("%s: Was unable to backup this file"),
|
|
|
+ quotearg_colon (file_name)));
|
|
|
+ skip_member ();
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Extract the archive entry according to its type. */
|
|
|
+
|
|
|
+ /* KLUDGE */
|
|
|
+ typeflag = sparse_member_p (¤t_stat_info) ?
|
|
|
+ GNUTYPE_SPARSE : current_header->header.typeflag;
|
|
|
+
|
|
|
+ if (prepare_to_extract (file_name, typeflag, &fun))
|
|
|
+ {
|
|
|
+ if (fun && (*fun) (file_name, typeflag) && backup_option)
|
|
|
+ undo_last_backup ();
|
|
|
+ }
|
|
|
+ else
|
|
|
+ skip_member ();
|
|
|
+
|
|
|
}
|
|
|
|
|
|
/* Extract the symbolic links whose final extraction were delayed. */
|