bug-tar
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Bug-tar] Problems extracting incremental archive


From: Jean-Louis Martineau
Subject: [Bug-tar] Problems extracting incremental archive
Date: Wed, 12 Jul 2006 10:58:27 -0400
User-agent: Thunderbird 1.5.0.4 (X11/20060614)

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);

reply via email to

[Prev in Thread] Current Thread [Next in Thread]