]> Dogcows Code - chaz/tar/blobdiff - src/extract.c
Fix extraction from concatenated incremental archives.
[chaz/tar] / src / extract.c
index 327b67f0e136e3ba9bbe70c90f3149d13b31139a..5aaeb1bf603192d01693f330043f3225a2e52690 100644 (file)
@@ -1,7 +1,7 @@
 /* Extract files from a tar archive.
 
-   Copyright 1988, 1992-1994, 1996-2001, 2003-2007, 2010, 2012-2013
-   Free Software Foundation, Inc.
+   Copyright 1988, 1992-1994, 1996-2001, 2003-2007, 2010, 2012-2014 Free
+   Software Foundation, Inc.
 
    This file is part of GNU tar.
 
@@ -297,7 +297,7 @@ set_mode (char const *file_name,
 static void
 check_time (char const *file_name, struct timespec t)
 {
-  if (t.tv_sec <= 0)
+  if (t.tv_sec < 0)
     WARNOPT (WARN_TIMESTAMP,
             (0, 0, _("%s: implausibly old time stamp %s"),
              file_name, tartime (t, true)));
@@ -537,6 +537,38 @@ repair_delayed_set_stat (char const *dir,
          quotearg_colon (dir)));
 }
 
+static void
+free_delayed_set_stat (struct delayed_set_stat *data)
+{
+  xheader_xattr_free (data->xattr_map, data->xattr_map_size);
+  free (data->cntx_name);
+  free (data->acls_a_ptr);
+  free (data->acls_d_ptr);
+  free (data);
+}
+
+void
+remove_delayed_set_stat (const char *fname)
+{
+  struct delayed_set_stat *data, *next, *prev = NULL;
+  for (data = delayed_set_stat_head; data; data = next)
+    {
+      next = data->next;
+      if (chdir_current == data->change_dir
+         && strcmp (data->file_name, fname) == 0)
+       {
+         free_delayed_set_stat (data);
+         if (prev)
+           prev->next = next;
+         else
+           delayed_set_stat_head = next;
+         return;
+       }
+      else
+       prev = data;
+    }
+}
+
 /* After a file/link/directory creation has failed, see if
    it's because some required directory was not present, and if so,
    create all required directories.  Return zero if all the required
@@ -846,16 +878,26 @@ apply_nonancestor_delayed_set_stat (char const *file_name, bool after_links)
        }
 
       delayed_set_stat_head = data->next;
-      xheader_xattr_free (data->xattr_map, data->xattr_map_size);
-      free (data->cntx_name);
-      free (data->acls_a_ptr);
-      free (data->acls_d_ptr);
-      free (data);
+      free_delayed_set_stat (data);
     }
 }
 
 \f
-
+static bool
+is_directory_link (const char *file_name)
+{
+  struct stat st;
+  int e = errno;
+  int res;
+  
+  res = (fstatat (chdir_fd, file_name, &st, AT_SYMLINK_NOFOLLOW) == 0 &&
+        S_ISLNK (st.st_mode) &&
+        fstatat (chdir_fd, file_name, &st, 0) == 0 &&
+        S_ISDIR (st.st_mode));
+  errno = e;
+  return res;
+}
+\f
 /* Extractor functions for various member types */
 
 static int
@@ -911,10 +953,15 @@ extract_dir (char *file_name, int typeflag)
 
       if (errno == EEXIST
          && (interdir_made
+             || keep_directory_symlink_option
              || old_files_option == DEFAULT_OLD_FILES
              || old_files_option == OVERWRITE_OLD_FILES))
        {
          struct stat st;
+
+         if (keep_directory_symlink_option && is_directory_link (file_name))
+           return 0;
+         
          if (deref_stat (file_name, &st) == 0)
            {
              current_mode = st.st_mode;
@@ -1341,7 +1388,7 @@ extract_symlink (char *file_name, int typeflag)
   if (!warned_once)
     {
       warned_once = 1;
-      WARNOPT (WARN_SYMBOLIC_CAST,
+      WARNOPT (WARN_SYMLINK_CAST,
               (0, 0,
                _("Attempting extraction of symbolic links as hard links")));
     }
@@ -1421,6 +1468,13 @@ extract_failure (char *file_name, int typeflag)
   return 1;
 }
 
+static int
+extract_skip (char *file_name, int typeflag)
+{
+  skip_member ();
+  return 0;
+}
+
 typedef int (*tar_extractor_t) (char *file_name, int typeflag);
 
 \f
@@ -1501,7 +1555,7 @@ prepare_to_extract (char const *file_name, int typeflag, tar_extractor_t *fun)
       ERROR ((0, 0,
              _("%s: Cannot extract -- file is continued from another volume"),
              quotearg_colon (current_stat_info.file_name)));
-      *fun = extract_failure;
+      *fun = extract_skip;
       break;
 
     case GNUTYPE_LONGNAME:
This page took 0.027864 seconds and 4 git commands to generate.