bug-tar
[Top][All Lists]
Advanced

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

Re: [Bug-tar] broken --remove-files in tar-1.23


From: Sergey Poznyakoff
Subject: Re: [Bug-tar] broken --remove-files in tar-1.23
Date: Tue, 16 Mar 2010 15:51:10 +0200

Alexander Kozlov <address@hidden> ha escrit:

> $ mkdir -p a/b
> $ ln -s b a/c
> $ tar --remove-files -czf a.tar.gz a
> tar: /home/build/tmp/a: Cannot rmdir: Directory not empty
> tar: Exiting with failure status due to previous errors

Thanks for reporting. Please try the attached patch.

Regards,
Sergey

diff --git a/src/misc.c b/src/misc.c
index f81111f..ec93589 100644
--- a/src/misc.c
+++ b/src/misc.c
@@ -230,10 +230,99 @@ zap_slashes (char *name)
   return name;
 }
 
+/* Normalize NAME by resolving any relative references and
+   removing trailing slashes.  Destructive version: modifies its argument. */ 
+int
+normalize_filename_x (char *name)
+{
+  char *p, *q;
+
+  p = name;
+  if (DOUBLE_SLASH_IS_DISTINCT_ROOT && *p == '/')
+    p++;
+
+  /* Remove /./, resolve /../ and compress sequences of slashes */
+  for (q = p; *q; )
+    {
+      if (*q == '/')
+       {
+         *p++ = *q++;
+         while (*q == '/')
+           q++;
+         continue;
+       }
+      else if (p == name)
+       {
+         if (*q == '.')
+           {
+             if (q[1] == '/')
+               {
+                 q += 2;
+                 continue;
+               }
+             if (q[1] == '.' && q[2] == '/')
+               return 1;
+           }
+       }
+      else
+       {
+         if (*q == '.' && p[-1] == '/')
+           {
+             if (q[1] == '/')
+               {
+                 q += 2;
+                 while (*q == '/')
+                   q++;
+                 continue;
+               }
+             else if (q[1] == '.' && q[2] == '/')
+               {
+                 do
+                   {
+                     --p;
+                   }
+                 while (p > name && p[-1] != '/');
+                 q += 3;
+                 continue;
+               }
+           }
+       }
+      *p++ = *q++;
+    }
+
+  /* Remove trailing slashes */
+  while (p-1 > name && p[-1] == '/')
+    p--;
+  
+  *p = 0;
+  return 0;
+}
+
+/* Normalize NAME by resolving any relative references, removing trailing
+   slashes, and converting it to absolute file name.  Return the normalized
+   name, or NULL in case of error. */
+
 char *
 normalize_filename (const char *name)
 {
-  return zap_slashes (canonicalize_filename_mode (name, CAN_MISSING));
+  char *copy;
+
+  if (name[0] != '/')
+    {
+      copy = xgetcwd ();
+      copy = xrealloc (copy, strlen (copy) + strlen (name) + 2);
+
+      strcat (copy, "/");
+      strcat (copy, name);
+    }
+  else
+    copy = xstrdup (name);
+  if (normalize_filename_x (copy))
+    {
+      free (copy);
+      return NULL;
+    }
+  return xrealloc (copy, strlen (copy) + 1);
 }
 
 
@@ -870,5 +959,3 @@ namebuf_name (namebuf_t buf, const char *name)
   return buf->buffer;
 }
 
-
-  

reply via email to

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