aboutsummaryrefslogtreecommitdiff
path: root/findutils
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2016-11-25 20:14:33 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2016-11-25 20:14:33 +0100
commitccc9985c455753298a8799a4d12d5f531c67ae81 (patch)
tree78d6082132ec226ba81ccb797c6defe927d67b42 /findutils
parent4b89d512b1215e7b9d619af03496540d30cbbd1a (diff)
downloadbusybox-w32-ccc9985c455753298a8799a4d12d5f531c67ae81.tar.gz
busybox-w32-ccc9985c455753298a8799a4d12d5f531c67ae81.tar.bz2
busybox-w32-ccc9985c455753298a8799a4d12d5f531c67ae81.zip
find: fix handling of trailing slashes in -name PATTERN comparisons
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'findutils')
-rw-r--r--findutils/find.c46
1 files changed, 37 insertions, 9 deletions
diff --git a/findutils/find.c b/findutils/find.c
index d71c69782..27698e537 100644
--- a/findutils/find.c
+++ b/findutils/find.c
@@ -502,26 +502,54 @@ static char *strcpy_upcase(char *dst, const char *src)
502 502
503ACTF(name) 503ACTF(name)
504{ 504{
505 int r;
505 const char *tmp = bb_basename(fileName); 506 const char *tmp = bb_basename(fileName);
506 if (tmp != fileName && *tmp == '\0') { 507 /* GNU findutils: find DIR/ -name DIR
507 /* "foo/bar/". Oh no... go back to 'b' */ 508 * prints "DIR/" (DIR// prints "DIR//" etc).
508 tmp--; 509 * Need to strip trailing "/".
509 while (tmp != fileName && *--tmp != '/') 510 * Such names can come only from top-level names, but
510 continue; 511 * we can't do this before recursive_action() call,
511 if (*tmp == '/') 512 * since then "find FILE/ -name FILE"
512 tmp++; 513 * would also work (on non-directories), which is wrong.
514 */
515 char *trunc_slash = NULL;
516
517 if (*tmp == '\0') {
518 /* "foo/bar/[//...]" */
519 while (tmp != fileName && tmp[-1] == '/')
520 tmp--;
521 if (tmp == fileName) { /* entire fileName is "//.."? */
522 /* yes, convert "//..." to "/"
523 * Testcases:
524 * find / -maxdepth 1 -name /: prints /
525 * find // -maxdepth 1 -name /: prints //
526 * find / -maxdepth 1 -name //: prints nothing
527 * find // -maxdepth 1 -name //: prints nothing
528 */
529 if (tmp[1])
530 trunc_slash = (char*)tmp + 1;
531 } else {
532 /* no, it's "foo/bar/[//...]", go back to 'b' */
533 trunc_slash = (char*)tmp;
534 while (tmp != fileName && tmp[-1] != '/')
535 tmp--;
536 }
513 } 537 }
538
514 /* Was using FNM_PERIOD flag too, 539 /* Was using FNM_PERIOD flag too,
515 * but somewhere between 4.1.20 and 4.4.0 GNU find stopped using it. 540 * but somewhere between 4.1.20 and 4.4.0 GNU find stopped using it.
516 * find -name '*foo' should match .foo too: 541 * find -name '*foo' should match .foo too:
517 */ 542 */
543 if (trunc_slash) *trunc_slash = '\0';
518#if FNM_CASEFOLD 544#if FNM_CASEFOLD
519 return fnmatch(ap->pattern, tmp, (ap->iname ? FNM_CASEFOLD : 0)) == 0; 545 r = fnmatch(ap->pattern, tmp, (ap->iname ? FNM_CASEFOLD : 0));
520#else 546#else
521 if (ap->iname) 547 if (ap->iname)
522 tmp = strcpy_upcase(alloca(strlen(tmp) + 1), tmp); 548 tmp = strcpy_upcase(alloca(strlen(tmp) + 1), tmp);
523 return fnmatch(ap->pattern, tmp, 0) == 0; 549 r = fnmatch(ap->pattern, tmp, 0);
524#endif 550#endif
551 if (trunc_slash) *trunc_slash = '/';
552 return r == 0;
525} 553}
526 554
527#if ENABLE_FEATURE_FIND_PATH 555#if ENABLE_FEATURE_FIND_PATH