Hi,

I have 2 problems extracting incremental archive.

I have no problem restoring my level 0 because I start from an empty dir.

But if the level 0 contain a symlink, the extraction of the level 1 will
happily follow that symlink.

I tried the -U option, it remove the symlink, but I get a lot of:
  tar: foo: Cannot unlink: Directory not empty
And worse, the file in the dir foo that should have been removed are not
removed.  extract_dir is not called for that directory.

Without -U, it is SECURITY problem
With -U, some file are not removed, and tar exit with and error status.


The other problem is if a level 0 contain a not empty directory and the
level 1 have the same entry with a file, the directory will not be
removed and the file will not be extracted.

--recursive-unlink should help for that, but I can't use it to extract
a level 1 because all file extracted by the level 0 will be removed.


I would like to make the following change to tar behaviour when extracting
incremental (-G,-g) with -U

- Don't write error message if the directory is not empty
- Call extract_dir if the directory is not empty
- Recursively rmdir a directory if we are not extracting a directory.


The attached path do that.

Any comment?

Jean-Louis

diff -u -r tar-1.15.91.orig/src/common.h tar-1.15.91/src/common.h
--- tar-1.15.91.orig/src/common.h	2006-06-12 09:22:46.000000000 -0400
+++ tar-1.15.91/src/common.h	2006-07-12 10:16:54.000000000 -0400
@@ -561,6 +561,7 @@
 {
   ORDINARY_REMOVE_OPTION,
   RECURSIVE_REMOVE_OPTION,
+  NOT_EMPTY_DIR_REMOVE_OPTION,
 
   /* FIXME: The following value is never used. It seems to be intended
      as a placeholder for a hypothetical option that should instruct tar
diff -u -r tar-1.15.91.orig/src/extract.c tar-1.15.91/src/extract.c
--- tar-1.15.91.orig/src/extract.c	2006-06-12 09:22:46.000000000 -0400
+++ tar-1.15.91/src/extract.c	2006-07-12 10:24:34.000000000 -0400
@@ -634,7 +634,9 @@
       if (errno == EEXIST
 	  && (interdir_made
 	      || old_files_option == DEFAULT_OLD_FILES
-	      || old_files_option == OVERWRITE_OLD_FILES))
+	      || old_files_option == OVERWRITE_OLD_FILES
+	      || old_files_option == UNLINK_FIRST_OLD_FILES
+		 && incremental_option))
 	{
 	  struct stat st;
 	  if (stat (file_name, &st) == 0)
@@ -1055,6 +1057,7 @@
 prepare_to_extract (char const *file_name, int typeflag, tar_extractor_t *fun)
 {
   int rc = 1;
+  int extract_a_dir = 0;
 
   if (EXTRACT_OVER_PIPE)
     rc = 0;
@@ -1073,7 +1076,10 @@
       /* 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;
+        {
+	  extract_a_dir = 1;
+	  *fun = extract_dir;
+	}
       else
 	{
 	  *fun = extract_file;
@@ -1111,6 +1117,7 @@
 
     case DIRTYPE:
     case GNUTYPE_DUMPDIR:
+      extract_a_dir = 1;
       *fun = extract_dir;
       if (current_stat_info.is_dumpdir)
 	delay_directory_restore_option = true;
@@ -1152,8 +1159,12 @@
     {
     case UNLINK_FIRST_OLD_FILES:
       if (!remove_any_file (file_name,
-                            recursive_unlink_option ? RECURSIVE_REMOVE_OPTION
-                                                      : ORDINARY_REMOVE_OPTION)
+                            recursive_unlink_option ||
+			    (incremental_option && !extract_a_dir)
+				? RECURSIVE_REMOVE_OPTION
+                                : (incremental_option && extract_a_dir)
+				    ? NOT_EMPTY_DIR_REMOVE_OPTION
+				    : ORDINARY_REMOVE_OPTION)
 	  && errno && errno != ENOENT)
 	{
 	  unlink_error (file_name);
diff -u -r tar-1.15.91.orig/src/misc.c tar-1.15.91/src/misc.c
--- tar-1.15.91.orig/src/misc.c	2005-12-01 07:29:26.000000000 -0500
+++ tar-1.15.91/src/misc.c	2006-07-12 10:18:00.000000000 -0400
@@ -368,6 +368,9 @@
 	case WANT_DIRECTORY_REMOVE_OPTION:
 	  return -1;
 
+	case NOT_EMPTY_DIR_REMOVE_OPTION:
+	  return 1;
+
 	case RECURSIVE_REMOVE_OPTION:
 	  {
 	    char *directory = savedir (file_name);
_______________________________________________
Bug-tar mailing list
[email protected]
http://lists.gnu.org/mailman/listinfo/bug-tar

Reply via email to