]> Dogcows Code - chaz/tar/blobdiff - src/extract.c
Use quote()
[chaz/tar] / src / extract.c
index 0ed41532592c683bec9a905e2ad749bf6c080957..dcb341df308663c43009b84c3ba6c7fd6eb2fd8f 100644 (file)
    with this program; if not, write to the Free Software Foundation, Inc.,
    59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
-#include "system.h"
+#include <system.h>
 #include <quotearg.h>
 #include <errno.h>
+#include <xgetcwd.h>
 
 #if HAVE_UTIME_H
 # include <utime.h>
@@ -113,8 +114,20 @@ extr_init (void)
   we_are_root = geteuid () == 0;
   same_permissions_option += we_are_root;
   same_owner_option += we_are_root;
-  xalloc_fail_func = extract_finish;
 
+  /* Save 'root device' to avoid purging mount points.
+     FIXME: Should the same be done after handling -C option ? */
+  if (one_file_system_option)
+    {
+      struct stat st;      
+      char *dir = xgetcwd ();
+
+      if (deref_stat (true, dir, &st))
+       stat_diag (dir);
+      else
+       root_device = st.st_dev;
+    }
+  
   /* Option -p clears the kernel umask, so it does not affect proper
      restoration of file permissions.  New intermediate directories will
      comply with umask at start of program.  */
@@ -354,7 +367,7 @@ repair_delayed_set_stat (char const *dir,
 static int
 make_directories (char *file_name)
 {
-  char *cursor0 = file_name + FILESYSTEM_PREFIX_LEN (file_name);
+  char *cursor0 = file_name + FILE_SYSTEM_PREFIX_LEN (file_name);
   char *cursor;                        /* points into the file name */
   int did_something = 0;       /* did we do anything yet? */
   int mode;
@@ -449,7 +462,9 @@ prepare_to_extract (char const *file_name)
   switch (old_files_option)
     {
     case UNLINK_FIRST_OLD_FILES:
-      if (!remove_any_file (file_name, recursive_unlink_option)
+      if (!remove_any_file (file_name, 
+                            recursive_unlink_option ? RECURSIVE_REMOVE_OPTION 
+                                                      : ORDINARY_REMOVE_OPTION)
          && errno && errno != ENOENT)
        {
          unlink_error (file_name);
@@ -460,7 +475,7 @@ prepare_to_extract (char const *file_name)
     case KEEP_NEWER_FILES:
       if (file_newer_p (file_name, &current_stat_info))
        {
-         WARN ((0, 0, _("Current `%s' is newer"), file_name));
+         WARN ((0, 0, _("Current %s is newer"), quote (file_name)));
          return 0;
        }
       break;
@@ -506,7 +521,7 @@ maybe_recoverable (char *file_name, int *interdir_made)
        case NO_OVERWRITE_DIR_OLD_FILES:
        case OVERWRITE_OLD_FILES:
          {
-           int r = remove_any_file (file_name, 0);
+           int r = remove_any_file (file_name, ORDINARY_REMOVE_OPTION);
            errno = EEXIST;
            return r;
          }
@@ -798,8 +813,7 @@ extract_archive (void)
        break;
 
       if (absolute_names_option
-         || ! (ISSLASH (current_stat_info.link_name
-                        [FILESYSTEM_PREFIX_LEN (current_stat_info.link_name)])
+         || ! (IS_ABSOLUTE_FILE_NAME (current_stat_info.link_name)
                || contains_dot_dot (current_stat_info.link_name)))
        {
          while (status = symlink (current_stat_info.link_name, file_name),
@@ -912,11 +926,12 @@ extract_archive (void)
        /* MSDOS does not implement links.  However, djgpp's link() actually
           copies the file.  */
        status = link (link_name, file_name);
+       e = errno;
 
        if (status == 0)
          {
            struct delayed_symlink *ds = delayed_symlink_head;
-           if (ds && stat (link_name, &st1) == 0)
+           if (ds && lstat (link_name, &st1) == 0)
              for (; ds; ds = ds->next)
                if (ds->dev == st1.st_dev
                    && ds->ino == st1.st_ino
@@ -932,17 +947,20 @@ extract_archive (void)
                  }
            break;
          }
+
+       if ((e == EEXIST && strcmp (link_name, file_name) == 0)
+           || (lstat (link_name, &st1) == 0
+               && lstat (file_name, &st2) == 0
+               && st1.st_dev == st2.st_dev
+               && st1.st_ino == st2.st_ino))
+         break;
+
+       errno = e;
        if (maybe_recoverable (file_name, &interdir_made))
          goto again_link;
 
        if (incremental_option && errno == EEXIST)
          break;
-       e = errno;
-       if (stat (link_name, &st1) == 0
-           && stat (file_name, &st2) == 0
-           && st1.st_dev == st2.st_dev
-           && st1.st_ino == st2.st_ino)
-         break;
 
        link_error (link_name, file_name);
        if (backup_option)
@@ -1012,7 +1030,7 @@ extract_archive (void)
          /* Read the entry and delete files that aren't listed in the
             archive.  */
 
-         gnu_restore (file_name);
+         purge_directory (file_name);
        }
       else if (typeflag == GNUTYPE_DUMPDIR)
        skip_member ();
@@ -1193,3 +1211,10 @@ fatal_exit (void)
   error (TAREXIT_FAILURE, 0, _("Error is not recoverable: exiting now"));
   abort ();
 }
+
+void
+xalloc_die (void)
+{
+  error (0, 0, "%s", _("memory exhausted"));
+  fatal_exit ();
+}
This page took 0.025521 seconds and 4 git commands to generate.