ash: fix slash treatment in expmeta
authorRon Yorston <rmy@pobox.com>
Fri, 4 Sep 2015 09:32:41 +0000 (10:32 +0100)
committerDenys Vlasenko <vda.linux@googlemail.com>
Fri, 4 Sep 2015 20:23:54 +0000 (22:23 +0200)
Commit 549deab caused this sequence of commands:

   mkdir foo
   cd foo
   touch a b
   echo "./"*

to return './*' instead of the expected './a ./b'.  The problem
was caused by the backport of commit 880d952 from dash.  In dash
the issue was fixed by two further commits by Herbert Xu:

<d6d06ff> [EXPAND] Fixed non-leading slash treatment in expmeta
<36f0fa8> [EXPAND] Fix slash treatment in expmeta

(See git://git.kernel.org/pub/scm/utils/dash/dash.git)

Apply these fixes to BusyBox ash, thus causing the new test
glob3.tests to succeed.

function                                             old     new   delta
expmeta                                              469     528     +59

Reported-by: Aaro Koskinen <aaro.koskinen@iki.fi>
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
shell/ash.c

index f6190c3e250cc6b2cce219c1be88db602fecbad1..42c91257ed6cd65895407789bbe66712c6749113 100644 (file)
@@ -6992,10 +6992,11 @@ expmeta(char *expdir, char *enddir, char *name)
        struct dirent *dp;
        int atend;
        int matchdot;
+       int esc;
 
        metaflag = 0;
        start = name;
-       for (p = name; *p; p++) {
+       for (p = name; esc = 0, *p; p += esc + 1) {
                if (*p == '*' || *p == '?')
                        metaflag = 1;
                else if (*p == '[') {
@@ -7012,15 +7013,16 @@ expmeta(char *expdir, char *enddir, char *name)
                                        break;
                                }
                        }
-               } else if (*p == '\\')
-                       p++;
-               else if (*p == '/') {
-                       if (metaflag)
-                               goto out;
-                       start = p + 1;
+               } else {
+                       if (*p == '\\')
+                               esc++;
+                       if (p[esc] == '/') {
+                               if (metaflag)
+                                       break;
+                               start = p + esc + 1;
+                       }
                }
        }
- out:
        if (metaflag == 0) {    /* we've reached the end of the file name */
                if (enddir != expdir)
                        metaflag++;
@@ -7060,7 +7062,8 @@ expmeta(char *expdir, char *enddir, char *name)
                atend = 1;
        } else {
                atend = 0;
-               *endname++ = '\0';
+               *endname = '\0';
+               endname += esc + 1;
        }
        matchdot = 0;
        p = start;
@@ -7085,7 +7088,7 @@ expmeta(char *expdir, char *enddir, char *name)
        }
        closedir(dirp);
        if (!atend)
-               endname[-1] = '/';
+               endname[-esc - 1] = esc ? '\\' : '/';
 }
 
 static struct strlist *