Do not issue errors on existing files when given the -k option

* Makefile.am (dist-hook): Fix rule.
* src/extract.c (maybe_recoverable): Return three-state value.
(extract_dir): Skip extraction if maybe_recoverable indicates so.
(extract_file): Likewise.
This commit is contained in:
Sergey Poznyakoff
2009-05-14 11:28:41 +03:00
parent 705fab49eb
commit 8f390db92f
2 changed files with 37 additions and 17 deletions

View File

@@ -23,7 +23,7 @@ EXTRA_DIST = ChangeLog.1 Make.rules
SUBDIRS = doc gnu lib rmt src scripts po tests SUBDIRS = doc gnu lib rmt src scripts po tests
dist-hook: dist-hook:
$(MAKE) changelog_dir=$(distdir) make-ChangeLog $(MAKE) changelog_dir=$(distdir) ChangeLog
-rm -f $(distdir).cpio -rm -f $(distdir).cpio
find $(distdir) | cpio -Hcrc -o | \ find $(distdir) | cpio -Hcrc -o | \
GZIP=$(GZIP_ENV) gzip -c > $(distdir).cpio.gz GZIP=$(GZIP_ENV) gzip -c > $(distdir).cpio.gz

View File

@@ -486,17 +486,24 @@ file_newer_p (const char *file_name, struct tar_stat_info *tar_stat)
return false; return false;
} }
#define RECOVER_NO 0
#define RECOVER_OK 1
#define RECOVER_SKIP 2
/* Attempt repairing what went wrong with the extraction. Delete an /* Attempt repairing what went wrong with the extraction. Delete an
already existing file or create missing intermediate directories. already existing file or create missing intermediate directories.
Return nonzero if we somewhat increased our chances at a successful Return RECOVER_OK if we somewhat increased our chances at a successful
extraction. errno is properly restored on zero return. */ extraction, RECOVER_NO if there are no chances, and RECOVER_SKIP if the
caller should skip extraction of that member. The value of errno is
properly restored on returning RECOVER_NO. */
static int static int
maybe_recoverable (char *file_name, int *interdir_made) maybe_recoverable (char *file_name, int *interdir_made)
{ {
int e = errno; int e = errno;
if (*interdir_made) if (*interdir_made)
return 0; return RECOVER_NO;
switch (errno) switch (errno)
{ {
@@ -506,13 +513,13 @@ maybe_recoverable (char *file_name, int *interdir_made)
switch (old_files_option) switch (old_files_option)
{ {
case KEEP_OLD_FILES: case KEEP_OLD_FILES:
return 0; return RECOVER_SKIP;
case KEEP_NEWER_FILES: case KEEP_NEWER_FILES:
if (file_newer_p (file_name, &current_stat_info)) if (file_newer_p (file_name, &current_stat_info))
{ {
errno = e; errno = e;
return 0; return RECOVER_NO;
} }
/* FALL THROUGH */ /* FALL THROUGH */
@@ -522,7 +529,7 @@ maybe_recoverable (char *file_name, int *interdir_made)
{ {
int r = remove_any_file (file_name, ORDINARY_REMOVE_OPTION); int r = remove_any_file (file_name, ORDINARY_REMOVE_OPTION);
errno = EEXIST; errno = EEXIST;
return r; return r > 0 ? RECOVER_OK : RECOVER_NO;
} }
case UNLINK_FIRST_OLD_FILES: case UNLINK_FIRST_OLD_FILES:
@@ -534,15 +541,15 @@ maybe_recoverable (char *file_name, int *interdir_made)
if (! make_directories (file_name)) if (! make_directories (file_name))
{ {
errno = ENOENT; errno = ENOENT;
return 0; return RECOVER_NO;
} }
*interdir_made = 1; *interdir_made = 1;
return 1; return RECOVER_OK;
default: default:
/* Just say we can't do anything about it... */ /* Just say we can't do anything about it... */
return 0; return RECOVER_NO;
} }
} }
@@ -666,13 +673,21 @@ extract_dir (char *file_name, int typeflag)
errno = EEXIST; errno = EEXIST;
} }
if (maybe_recoverable (file_name, &interdir_made)) switch (maybe_recoverable (file_name, &interdir_made))
continue;
if (errno != EEXIST)
{ {
mkdir_error (file_name); case RECOVER_OK:
return 1; continue;
case RECOVER_SKIP:
break;
case RECOVER_NO:
if (errno != EEXIST)
{
mkdir_error (file_name);
return 1;
}
break;
} }
break; break;
} }
@@ -760,13 +775,18 @@ extract_file (char *file_name, int typeflag)
} }
else else
{ {
int recover = RECOVER_NO;
do do
fd = open_output_file (file_name, typeflag, mode ^ invert_permissions); fd = open_output_file (file_name, typeflag, mode ^ invert_permissions);
while (fd < 0 && maybe_recoverable (file_name, &interdir_made)); while (fd < 0
&& (recover = maybe_recoverable (file_name, &interdir_made))
== RECOVER_OK);
if (fd < 0) if (fd < 0)
{ {
skip_member (); skip_member ();
if (recover == RECOVER_SKIP)
return 0;
open_error (file_name); open_error (file_name);
return 1; return 1;
} }