]> git.ipfire.org Git - thirdparty/libarchive.git/commitdiff
Only accept \ as path separator when reading archives on Windows. This seems to...
authorTim Kientzle <kientzle@gmail.com>
Sat, 3 Oct 2009 21:44:41 +0000 (17:44 -0400)
committerTim Kientzle <kientzle@gmail.com>
Sat, 3 Oct 2009 21:44:41 +0000 (17:44 -0400)
SVN-Revision: 1480

tar/tree.c
tar/util.c

index 5fbd3c720a1f9b897e22f2bd73d80935b1fb98f6..eeae00b03a88eecb8d0cc7ec09122f7965bafd8a 100644 (file)
@@ -72,9 +72,6 @@ __FBSDID("$FreeBSD: src/usr.bin/tar/tree.c,v 1.9 2008/11/27 05:49:52 kientzle Ex
 #endif
 #if defined(HAVE_WINDOWS_H) && !defined(__CYGWIN__)
 #include <windows.h>
-#define DIRSEP '\\'
-#else
-#define DIRSEP '/'
 #endif
 
 #include "tree.h"
@@ -255,8 +252,8 @@ tree_append(struct tree *t, const char *name, size_t name_length)
        p = t->buff + t->dirname_length;
        t->path_length = t->dirname_length + name_length;
        /* Add a separating '/' if it's needed. */
-       if (t->dirname_length > 0 && p[-1] != '/' && p[-1] != '\\') {
-               *p++ = DIRSEP;
+       if (t->dirname_length > 0 && p[-1] != '/') {
+               *p++ = '/';
                t->path_length ++;
        }
 #if HAVE_STRNCPY_S
@@ -349,7 +346,7 @@ tree_pop(struct tree *t)
        t->dirname_length = te->dirname_length;
        if (t->buff) {
                t->basename = t->buff + t->dirname_length;
-               while (t->basename[0] == '/' || t->basename[0] == '\\')
+               while (t->basename[0] == '/')
                        t->basename++;
        }
        free(te->name);
index d2a3126d8ea469c21af28ff83226f5650ab4f61f..2ae448e6113478140fad1617e0ea8ad183b53eea 100644 (file)
@@ -298,15 +298,16 @@ do_chdir(struct bsdtar *bsdtar)
 }
 
 const char *
-strip_components(const char *path, int elements)
+strip_components(const char *p, int elements)
 {
-       const char *p = path;
-
+       /* Skip as many elements as necessary. */
        while (elements > 0) {
                switch (*p++) {
                case '/':
+#if defined(_WIN32) && !defined(__CYGWIN__)
+               case '\\': /* Support \ path sep on Windows ONLY. */
+#endif
                        elements--;
-                       path = p;
                        break;
                case '\0':
                        /* Path is too short, skip it. */
@@ -314,12 +315,25 @@ strip_components(const char *path, int elements)
                }
        }
 
-       while (*path == '/')
-              ++path;
-       if (*path == '\0')
-              return (NULL);
-
-       return (path);
+       /* Skip any / characters.  This handles short paths that have
+        * additional / termination.  This also handles the case where
+        * the logic above stops in the middle of a duplicate //
+        * sequence (which would otherwise get converted to an
+        * absolute path). */
+       for (;;) {
+               switch (*p) {
+               case '/':
+#if defined(_WIN32) && !defined(__CYGWIN__)
+               case '\\': /* Support \ path sep on Windows ONLY. */
+#endif
+                       ++p;
+                       break;
+               case '\0':
+                       return (NULL);
+               default:
+                       return (p);
+               }
+       }
 }
 
 /*