return did_something; /* tell them to retry if we made one */
}
+static bool
+file_newer_p (const char *file_name, struct tar_stat_info *tar_stat)
+{
+ struct stat st;
+
+ if (stat (file_name, &st))
+ {
+ stat_warn (file_name);
+ return true; /* Be on the safe side */
+ }
+ if (!S_ISDIR (st.st_mode)
+ && st.st_mtime >= current_stat_info.stat.st_mtime)
+ {
+ return true;
+ }
+ return false;
+}
+
/* Prepare to extract a file.
Return zero if extraction should not proceed. */
if (to_stdout_option)
return 0;
- if (old_files_option == UNLINK_FIRST_OLD_FILES
- && !remove_any_file (file_name, recursive_unlink_option)
- && errno && errno != ENOENT)
+ switch (old_files_option)
{
- unlink_error (file_name);
- return 0;
+ case UNLINK_FIRST_OLD_FILES:
+ if (!remove_any_file (file_name, recursive_unlink_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"), file_name));
+ return 0;
+ }
+ break;
+
+ default:
+ break;
}
return 1;
static int
maybe_recoverable (char *file_name, int *interdir_made)
{
+ int e = errno;
+
if (*interdir_made)
return 0;
switch (old_files_option)
{
- default:
+ case KEEP_OLD_FILES:
return 0;
+ case KEEP_NEWER_FILES:
+ if (file_newer_p (file_name, ¤t_stat_info))
+ {
+ errno = e;
+ return 0;
+ }
+ /* FALL THROUGH */
+
case DEFAULT_OLD_FILES:
case NO_OVERWRITE_DIR_OLD_FILES:
case OVERWRITE_OLD_FILES:
errno = EEXIST;
return r;
}
+
+ case UNLINK_FIRST_OLD_FILES:
+ break;
}
case ENOENT:
int openflag;
mode_t mode;
off_t size;
- off_t file_size;
int interdir_made = 0;
char typeflag;
char *file_name;
if (verbose_option)
print_header (¤t_stat_info, -1);
- file_name = safer_name_suffix (current_stat_info.file_name, 0);
+ file_name = safer_name_suffix (current_stat_info.file_name, false);
if (strip_path_elements)
{
size_t prefix_len = stripped_prefix_len (file_name, strip_path_elements);
/* Extract the archive entry according to its type. */
- typeflag = current_header->header.typeflag;
- /*KLUDGE*/
- if (current_stat_info.archive_file_size != current_stat_info.stat.st_size)
- typeflag = GNUTYPE_SPARSE;
+ /* KLUDGE */
+ typeflag = sparse_member_p (¤t_stat_info) ?
+ GNUTYPE_SPARSE : current_header->header.typeflag;
switch (typeflag)
{
}
extract_file:
- if (typeflag == GNUTYPE_SPARSE)
+ if (current_stat_info.is_sparse)
{
sparse_extract_file (fd, ¤t_stat_info, &size);
}
again_link:
{
- char const *link_name = safer_name_suffix (current_stat_info.link_name, 1);
+ char const *link_name = safer_name_suffix (current_stat_info.link_name,
+ true);
struct stat st1, st2;
int e;