diff options
author | Sergey Poznyakoff <gray@gnu.org> | 2020-06-22 22:17:46 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org> | 2020-06-22 22:17:46 +0300 |
commit | 34d15af170a5d6e60b70979001e8940d9a382f35 (patch) | |
tree | cd307d8c86a1da72d79f17fa54070df25bdd1333 | |
parent | 63712973c77ede016d859760b18d272bd175fd8e (diff) | |
download | tar-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.c | 128 |
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, ¤t_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, ¤t_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. */ |