]> Dogcows Code - chaz/tar/blobdiff - src/unlink.c
Use relative addressing in deferred unlinks.
[chaz/tar] / src / unlink.c
index 8c58b8d1e2c223f6d937006d668a48e8a61f728a..6677148ea5ecd976d4a9aa3bbecac42747cf1951 100644 (file)
@@ -24,7 +24,9 @@
 struct deferred_unlink
   {
     struct deferred_unlink *next;   /* Next unlink in the queue */
-    char *file_name;                /* Absolute name of the file to unlink */
+    int dir_idx;                    /* Directory index in wd */
+    char *file_name;                /* Name of the file to unlink, relative
+                                      to dir_idx */
     bool is_dir;                    /* True if file_name is a directory */
     off_t records_written;          /* Number of records written when this
                                       entry got added to the queue */
@@ -70,16 +72,30 @@ static void
 flush_deferred_unlinks (bool force)
 {
   struct deferred_unlink *p, *prev = NULL;
-
+  int saved_chdir = chdir_current;
+  
   for (p = dunlink_head; p; )
     {
       struct deferred_unlink *next = p->next;
+
       if (force
          || records_written > p->records_written + deferred_unlink_delay)
        {
+         chdir_do (p->dir_idx);
          if (p->is_dir)
            {
-             if (unlinkat (chdir_fd, p->file_name, AT_REMOVEDIR) != 0)
+             const char *fname;
+
+             if (p->file_name[0] == 0 ||
+                 strcmp (p->file_name, ".") == 0)
+               {
+                 fname = tar_dirname ();
+                 chdir_do (p->dir_idx - 1);
+               }
+             else
+               fname = p->file_name;
+                 
+             if (unlinkat (chdir_fd, fname, AT_REMOVEDIR) != 0)
                {
                  switch (errno)
                    {
@@ -97,7 +113,7 @@ flush_deferred_unlinks (bool force)
                        }
                      /* fall through */
                    default:
-                     rmdir_error (p->file_name);
+                     rmdir_error (fname);
                    }
                }
            }
@@ -122,6 +138,7 @@ flush_deferred_unlinks (bool force)
     }
   if (!dunlink_head)
     dunlink_tail = NULL;
+  chdir_do (saved_chdir);
 }
 
 void
@@ -147,7 +164,9 @@ queue_deferred_unlink (const char *name, bool is_dir)
 
   p = dunlink_alloc ();
   p->next = NULL;
-  p->file_name = normalize_filename (name);
+  p->dir_idx = chdir_current;
+  p->file_name = xstrdup (name);
+  normalize_filename_x (p->file_name);
   p->is_dir = is_dir;
   p->records_written = records_written;
 
This page took 0.022711 seconds and 4 git commands to generate.