[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Bug-tar] Previously existing files should not be an error when -k i
From: |
Sergey Poznyakoff |
Subject: |
Re: [Bug-tar] Previously existing files should not be an error when -k is specified |
Date: |
Thu, 14 May 2009 12:51:39 +0300 |
Jonathan Kamens <address@hidden> ha escrit:
> If I specify -k to tell tar not to overwrite old files, and indeed
> there are some old files that tar doesn't overwrite, then it prints
> error messages about these files, which is wrong, and it exits with a
> non-zero status, which is also wrong.
Thanks for reporting. It is fixed in the repository. Attached is a
patch against git HEAD.
Regards,
Sergey
* src/extract.c (maybe_recoverable): Return three-state value.
(extract_dir): Skip extraction if maybe_recoverable indicates so.
(extract_file): Likewise.
---
src/extract.c | 52 ++++++++++++++++++++++++++++++++++++----------------
2 files changed, 37 insertions(+), 17 deletions(-)
diff --git a/src/extract.c b/src/extract.c
index 6d70398..300f52b 100644
--- a/src/extract.c
+++ b/src/extract.c
@@ -486,17 +486,24 @@ file_newer_p (const char *file_name, struct tar_stat_info
*tar_stat)
return false;
}
+#define RECOVER_NO 0
+#define RECOVER_OK 1
+#define RECOVER_SKIP 2
+
/* Attempt repairing what went wrong with the extraction. Delete an
already existing file or create missing intermediate directories.
- Return nonzero if we somewhat increased our chances at a successful
- extraction. errno is properly restored on zero return. */
+ Return RECOVER_OK if we somewhat increased our chances at a successful
+ 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
maybe_recoverable (char *file_name, int *interdir_made)
{
int e = errno;
if (*interdir_made)
- return 0;
+ return RECOVER_NO;
switch (errno)
{
@@ -506,13 +513,13 @@ maybe_recoverable (char *file_name, int *interdir_made)
switch (old_files_option)
{
case KEEP_OLD_FILES:
- return 0;
+ return RECOVER_SKIP;
case KEEP_NEWER_FILES:
if (file_newer_p (file_name, ¤t_stat_info))
{
errno = e;
- return 0;
+ return RECOVER_NO;
}
/* FALL THROUGH */
@@ -522,7 +529,7 @@ maybe_recoverable (char *file_name, int *interdir_made)
{
int r = remove_any_file (file_name, ORDINARY_REMOVE_OPTION);
errno = EEXIST;
- return r;
+ return r > 0 ? RECOVER_OK : RECOVER_NO;
}
case UNLINK_FIRST_OLD_FILES:
@@ -534,15 +541,15 @@ maybe_recoverable (char *file_name, int *interdir_made)
if (! make_directories (file_name))
{
errno = ENOENT;
- return 0;
+ return RECOVER_NO;
}
*interdir_made = 1;
- return 1;
+ return RECOVER_OK;
default:
/* 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;
}
- if (maybe_recoverable (file_name, &interdir_made))
- continue;
-
- if (errno != EEXIST)
+ switch (maybe_recoverable (file_name, &interdir_made))
{
- mkdir_error (file_name);
- return 1;
+ case RECOVER_OK:
+ continue;
+
+ case RECOVER_SKIP:
+ break;
+
+ case RECOVER_NO:
+ if (errno != EEXIST)
+ {
+ mkdir_error (file_name);
+ return 1;
+ }
+ break;
}
break;
}
@@ -760,13 +775,18 @@ extract_file (char *file_name, int typeflag)
}
else
{
+ int recover = RECOVER_NO;
do
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)
{
skip_member ();
+ if (recover == RECOVER_SKIP)
+ return 0;
open_error (file_name);
return 1;
}
--
1.6.0