Fix the logic of prepare_to_extract.
* src/extract.c (prepare_to_extract): Return true to proceed with the extraction, and false to skip the current member. If extracting over a pipe, skip unlinking logic. (extract_archive): Update accordingly.
This commit is contained in:
128
src/extract.c
128
src/extract.c
@@ -1621,47 +1621,23 @@ extract_fifo (char *file_name, int typeflag)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int
|
|
||||||
extract_volhdr (char *file_name, int typeflag)
|
|
||||||
{
|
|
||||||
skip_member ();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
extract_failure (char *file_name, int typeflag)
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
extract_skip (char *file_name, int typeflag)
|
|
||||||
{
|
|
||||||
skip_member ();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef int (*tar_extractor_t) (char *file_name, int typeflag);
|
typedef int (*tar_extractor_t) (char *file_name, int typeflag);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Prepare to extract a file. Find extractor function.
|
/* Prepare to extract a file. Find extractor function.
|
||||||
Return zero if extraction should not proceed. */
|
Return true to proceed with the extraction, false to skip the current
|
||||||
|
member. */
|
||||||
|
|
||||||
static int
|
static bool
|
||||||
prepare_to_extract (char const *file_name, int typeflag, tar_extractor_t *fun)
|
prepare_to_extract (char const *file_name, int typeflag, tar_extractor_t *fun)
|
||||||
{
|
{
|
||||||
int rc = 1;
|
tar_extractor_t extractor = NULL;
|
||||||
|
|
||||||
if (EXTRACT_OVER_PIPE)
|
|
||||||
rc = 0;
|
|
||||||
|
|
||||||
/* Select the extractor */
|
/* Select the extractor */
|
||||||
switch (typeflag)
|
switch (typeflag)
|
||||||
{
|
{
|
||||||
case GNUTYPE_SPARSE:
|
case GNUTYPE_SPARSE:
|
||||||
*fun = extract_file;
|
extractor = extract_file;
|
||||||
rc = 1;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AREGTYPE:
|
case AREGTYPE:
|
||||||
@@ -1670,106 +1646,101 @@ prepare_to_extract (char const *file_name, int typeflag, tar_extractor_t *fun)
|
|||||||
/* Appears to be a file. But BSD tar uses the convention that a slash
|
/* Appears to be a file. But BSD tar uses the convention that a slash
|
||||||
suffix means a directory. */
|
suffix means a directory. */
|
||||||
if (current_stat_info.had_trailing_slash)
|
if (current_stat_info.had_trailing_slash)
|
||||||
*fun = extract_dir;
|
extractor = extract_dir;
|
||||||
else
|
else
|
||||||
{
|
extractor = extract_file;
|
||||||
*fun = extract_file;
|
|
||||||
rc = 1;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SYMTYPE:
|
case SYMTYPE:
|
||||||
*fun = extract_symlink;
|
extractor = extract_symlink;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case LNKTYPE:
|
case LNKTYPE:
|
||||||
*fun = extract_link;
|
extractor = extract_link;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
#if S_IFCHR
|
#if S_IFCHR
|
||||||
case CHRTYPE:
|
case CHRTYPE:
|
||||||
current_stat_info.stat.st_mode |= S_IFCHR;
|
current_stat_info.stat.st_mode |= S_IFCHR;
|
||||||
*fun = extract_node;
|
extractor = extract_node;
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if S_IFBLK
|
#if S_IFBLK
|
||||||
case BLKTYPE:
|
case BLKTYPE:
|
||||||
current_stat_info.stat.st_mode |= S_IFBLK;
|
current_stat_info.stat.st_mode |= S_IFBLK;
|
||||||
*fun = extract_node;
|
extractor = extract_node;
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if HAVE_MKFIFO || defined mkfifo
|
#if HAVE_MKFIFO || defined mkfifo
|
||||||
case FIFOTYPE:
|
case FIFOTYPE:
|
||||||
*fun = extract_fifo;
|
extractor = extract_fifo;
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
case DIRTYPE:
|
case DIRTYPE:
|
||||||
case GNUTYPE_DUMPDIR:
|
case GNUTYPE_DUMPDIR:
|
||||||
*fun = extract_dir;
|
extractor = extract_dir;
|
||||||
if (current_stat_info.is_dumpdir)
|
if (current_stat_info.is_dumpdir)
|
||||||
delay_directory_restore_option = true;
|
delay_directory_restore_option = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GNUTYPE_VOLHDR:
|
case GNUTYPE_VOLHDR:
|
||||||
*fun = extract_volhdr;
|
return false;
|
||||||
break;
|
|
||||||
|
|
||||||
case GNUTYPE_MULTIVOL:
|
case GNUTYPE_MULTIVOL:
|
||||||
ERROR ((0, 0,
|
ERROR ((0, 0,
|
||||||
_("%s: Cannot extract -- file is continued from another volume"),
|
_("%s: Cannot extract -- file is continued from another volume"),
|
||||||
quotearg_colon (current_stat_info.file_name)));
|
quotearg_colon (current_stat_info.file_name)));
|
||||||
*fun = extract_skip;
|
return false;
|
||||||
break;
|
|
||||||
|
|
||||||
case GNUTYPE_LONGNAME:
|
case GNUTYPE_LONGNAME:
|
||||||
case GNUTYPE_LONGLINK:
|
case GNUTYPE_LONGLINK:
|
||||||
ERROR ((0, 0, _("Unexpected long name header")));
|
ERROR ((0, 0, _("Unexpected long name header")));
|
||||||
*fun = extract_failure;
|
return false;
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
WARNOPT (WARN_UNKNOWN_CAST,
|
WARNOPT (WARN_UNKNOWN_CAST,
|
||||||
(0, 0,
|
(0, 0,
|
||||||
_("%s: Unknown file type '%c', extracted as normal file"),
|
_("%s: Unknown file type '%c', extracted as normal file"),
|
||||||
quotearg_colon (file_name), typeflag));
|
quotearg_colon (file_name), typeflag));
|
||||||
*fun = extract_file;
|
extractor = extract_file;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Determine whether the extraction should proceed */
|
if (!EXTRACT_OVER_PIPE)
|
||||||
if (rc == 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
switch (old_files_option)
|
|
||||||
{
|
{
|
||||||
case UNLINK_FIRST_OLD_FILES:
|
switch (old_files_option)
|
||||||
if (!remove_any_file (file_name,
|
|
||||||
recursive_unlink_option ? RECURSIVE_REMOVE_OPTION
|
|
||||||
: ORDINARY_REMOVE_OPTION)
|
|
||||||
&& errno && errno != ENOENT)
|
|
||||||
{
|
{
|
||||||
unlink_error (file_name);
|
case UNLINK_FIRST_OLD_FILES:
|
||||||
return 0;
|
if (!remove_any_file (file_name,
|
||||||
}
|
recursive_unlink_option
|
||||||
break;
|
? RECURSIVE_REMOVE_OPTION
|
||||||
|
: ORDINARY_REMOVE_OPTION)
|
||||||
|
&& errno && errno != ENOENT)
|
||||||
|
{
|
||||||
|
unlink_error (file_name);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case KEEP_NEWER_FILES:
|
case KEEP_NEWER_FILES:
|
||||||
if (file_newer_p (file_name, 0, ¤t_stat_info))
|
if (file_newer_p (file_name, 0, ¤t_stat_info))
|
||||||
{
|
{
|
||||||
WARNOPT (WARN_IGNORE_NEWER,
|
WARNOPT (WARN_IGNORE_NEWER,
|
||||||
(0, 0, _("Current %s is newer or same age"),
|
(0, 0, _("Current %s is newer or same age"),
|
||||||
quote (file_name)));
|
quote (file_name)));
|
||||||
return 0;
|
return false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
*fun = extractor;
|
||||||
return 1;
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Extract a file from the archive. */
|
/* Extract a file from the archive. */
|
||||||
@@ -1832,13 +1803,14 @@ extract_archive (void)
|
|||||||
|
|
||||||
if (prepare_to_extract (current_stat_info.file_name, typeflag, &fun))
|
if (prepare_to_extract (current_stat_info.file_name, typeflag, &fun))
|
||||||
{
|
{
|
||||||
if (fun && (*fun) (current_stat_info.file_name, typeflag)
|
if (fun (current_stat_info.file_name, typeflag) == 0)
|
||||||
&& backup_option)
|
return;
|
||||||
undo_last_backup ();
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
skip_member ();
|
skip_member ();
|
||||||
|
|
||||||
|
if (backup_option)
|
||||||
|
undo_last_backup ();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Extract the links whose final extraction were delayed. */
|
/* Extract the links whose final extraction were delayed. */
|
||||||
|
|||||||
Reference in New Issue
Block a user