summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org>2020-06-22 22:17:46 +0300
committerSergey Poznyakoff <gray@gnu.org>2020-06-22 22:17:46 +0300
commit34d15af170a5d6e60b70979001e8940d9a382f35 (patch)
treecd307d8c86a1da72d79f17fa54070df25bdd1333
parent63712973c77ede016d859760b18d272bd175fd8e (diff)
downloadtar-34d15af170a5d6e60b70979001e8940d9a382f35.tar.gz
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.
-rw-r--r--src/extract.c128
1 files changed, 50 insertions, 78 deletions
diff --git a/src/extract.c b/src/extract.c
index 252b4388..b73a5917 100644
--- a/src/extract.c
+++ b/src/extract.c
@@ -1621,47 +1621,23 @@ extract_fifo (char *file_name, int typeflag)
}
#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);
-
/* 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)
{
- int rc = 1;
-
- if (EXTRACT_OVER_PIPE)
- rc = 0;
+ tar_extractor_t extractor = NULL;
/* Select the extractor */
switch (typeflag)
{
case GNUTYPE_SPARSE:
- *fun = extract_file;
- rc = 1;
+ extractor = extract_file;
break;
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
suffix means a directory. */
if (current_stat_info.had_trailing_slash)
- *fun = extract_dir;
+ extractor = extract_dir;
else
- {
- *fun = extract_file;
- rc = 1;
- }
+ extractor = extract_file;
break;
case SYMTYPE:
- *fun = extract_symlink;
+ extractor = extract_symlink;
break;
case LNKTYPE:
- *fun = extract_link;
+ extractor = extract_link;
break;
#if S_IFCHR
case CHRTYPE:
current_stat_info.stat.st_mode |= S_IFCHR;
- *fun = extract_node;
+ extractor = extract_node;
break;
#endif
#if S_IFBLK
case BLKTYPE:
current_stat_info.stat.st_mode |= S_IFBLK;
- *fun = extract_node;
+ extractor = extract_node;
break;
#endif
#if HAVE_MKFIFO || defined mkfifo
case FIFOTYPE:
- *fun = extract_fifo;
+ extractor = extract_fifo;
break;
#endif
case DIRTYPE:
case GNUTYPE_DUMPDIR:
- *fun = extract_dir;
+ extractor = extract_dir;
if (current_stat_info.is_dumpdir)
delay_directory_restore_option = true;
break;
case GNUTYPE_VOLHDR:
- *fun = extract_volhdr;
- break;
-
+ return false;
+
case GNUTYPE_MULTIVOL:
ERROR ((0, 0,
_("%s: Cannot extract -- file is continued from another volume"),
quotearg_colon (current_stat_info.file_name)));
- *fun = extract_skip;
- break;
+ return false;
case GNUTYPE_LONGNAME:
case GNUTYPE_LONGLINK:
ERROR ((0, 0, _("Unexpected long name header")));
- *fun = extract_failure;
- break;
+ return false;
default:
WARNOPT (WARN_UNKNOWN_CAST,
(0, 0,
_("%s: Unknown file type '%c', extracted as normal file"),
quotearg_colon (file_name), typeflag));
- *fun = extract_file;
+ extractor = extract_file;
}
- /* Determine whether the extraction should proceed */
- if (rc == 0)
- return 0;
-
- switch (old_files_option)
+ if (!EXTRACT_OVER_PIPE)
{
- case UNLINK_FIRST_OLD_FILES:
- if (!remove_any_file (file_name,
- recursive_unlink_option ? RECURSIVE_REMOVE_OPTION
- : ORDINARY_REMOVE_OPTION)
- && errno && errno != ENOENT)
+ switch (old_files_option)
{
- unlink_error (file_name);
- return 0;
- }
- break;
+ 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 false;
+ }
+ break;
- case KEEP_NEWER_FILES:
- if (file_newer_p (file_name, 0, &current_stat_info))
- {
- WARNOPT (WARN_IGNORE_NEWER,
- (0, 0, _("Current %s is newer or same age"),
- quote (file_name)));
- return 0;
- }
- break;
+ case KEEP_NEWER_FILES:
+ if (file_newer_p (file_name, 0, &current_stat_info))
+ {
+ WARNOPT (WARN_IGNORE_NEWER,
+ (0, 0, _("Current %s is newer or same age"),
+ quote (file_name)));
+ return false;
+ }
+ break;
- default:
- break;
+ default:
+ break;
+ }
}
-
- return 1;
+ *fun = extractor;
+
+ return true;
}
/* 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 (fun && (*fun) (current_stat_info.file_name, typeflag)
- && backup_option)
- undo_last_backup ();
+ if (fun (current_stat_info.file_name, typeflag) == 0)
+ return;
}
else
skip_member ();
+ if (backup_option)
+ undo_last_backup ();
}
/* Extract the links whose final extraction were delayed. */