From 2a6129bfccec9f23a50f037e187f85c4d000bc87 Mon Sep 17 00:00:00 2001 From: Bernhard Voelker Date: Mon, 20 Feb 2017 18:53:48 +0100 Subject: [PATCH 098/224] find: fix -printf '%h' for arguments with one or more trailing slashes Previously, find would output the pathname name for the '%h' format when that was passed with a trailing slash: $ mkdir foo $ find foo/ -printf '%h/%f\n' foo/foo/ * find/print.c (do_fprintf -> 'h'): Strip trailing slashes, i.e. any number of directory separators, unless this is the root "/" directory. * find/testsuite/find.gnu/printf-h.exp: Enhance test with various combinations of "/", "./", "foo/", "./foo", "./foolink/", etc. * find/testsuite/find.gnu/printf-h.xo: Add the expected output for the above new test cases. * NEWS: Mention the fix. Bug introduced in commit FINDUTILS_4_2_18-1-6-g0fd15a4. Reported by Tavian Barnes in https://savannah.gnu.org/bugs/?50259 --- NEWS | 8 ++- find/print.c | 21 +++++-- find/testsuite/find.gnu/printf-h.exp | 94 ++++++++++++++++++++++++++-- find/testsuite/find.gnu/printf-h.xo | 70 ++++++++++++++++++++- 4 files changed, 181 insertions(+), 12 deletions(-) diff --git a/find/print.c b/find/print.c index 20351572..db6155c9 100644 --- a/find/print.c +++ b/find/print.c @@ -965,8 +965,18 @@ do_fprintf (struct format_val *dest, case 'h': /* leading directories part of path */ /* sanitised */ { - cp = strrchr (pathname, '/'); - if (cp == NULL) /* No leading directories. */ + char *pname = strdup (pathname); + + /* Remove trailing slashes - unless it's the root '/' directory. */ + char *s = pname + strlen (pname) -1; + for ( ; pname <= s; s--) + if (*s != '/') + break; + if (pname < s && *(s+1) == '/') + *(s+1) = '\0'; + + s = strrchr (pname, '/'); + if (s == NULL) /* No leading directories. */ { /* If there is no slash in the pathname, we still * print the string because it contains characters @@ -976,11 +986,10 @@ do_fprintf (struct format_val *dest, } else { - char *s = strdup (pathname); - s[cp - pathname] = 0; - checked_print_quoted (dest, segment->text, s); - free (s); + *s = '\0'; + checked_print_quoted (dest, segment->text, pname); } + free (pname); } break; diff --git a/find/testsuite/find.gnu/printf-h.exp b/find/testsuite/find.gnu/printf-h.exp index fb0187cc..094a37b5 100644 --- a/find/testsuite/find.gnu/printf-h.exp +++ b/find/testsuite/find.gnu/printf-h.exp @@ -1,5 +1,91 @@ # Test case for Savannah bug ID #12085. -exec rm -rf tmp -exec touch tmp -find_start p {tmp -printf "RESULT: %h %f\n" } -exec rm -rf tmp +exec rm -rf foo +exec mkdir foo foo/bar +exec ln -s foo foolink +# +# Create the combinations with: +# $ printf '%s \\\n' {,./,.//}{/,.,foo,foolink,foo/bar}{,/,//,/.,//.} | sort -u +# +# Manual check against installed version: +# $ for opt in '' -H -L -P ; do +# printf "\n=== Differences for option: '%s' ===\n" "$opt" +# diff -u0 \ +# <( /usr/bin/find $opt {,./,.//}{/,.,foo,foolink,foo/bar}{,/,//,/.,//.} \ +# -maxdepth 1 -printf "%h/%f,%%p=%p,%%h='%h',%%f='%f'\n" ) \ +# <( ./find $opt {,./,.//}{/,.,foo,foolink,foo/bar}{,/,//,/.,//.} \ +# -maxdepth 1 -printf "%h/%f,%%p=%p,%%h='%h',%%f='%f'\n" ) +# done | column -t -s, + +find_start p {\ +/ \ +// \ +/// \ +///. \ +//. \ +. \ +./ \ +.// \ +./// \ +.//// \ +.///// \ +./////. \ +.////. \ +.///. \ +.//. \ +.//./ \ +.//.// \ +.//.//. \ +.//./. \ +./. \ +././ \ +./.// \ +././/. \ +././. \ +.//foo \ +.//foo/ \ +.//foo// \ +.//foo//. \ +.//foo/. \ +./foo \ +./foo/ \ +./foo// \ +./foo//. \ +./foo/. \ +foo \ +foo/ \ +foo// \ +foo//. \ +foo/. \ +.//foo/bar \ +.//foo/bar/ \ +.//foo/bar// \ +.//foo/bar//. \ +.//foo/bar/. \ +./foo/bar \ +./foo/bar/ \ +./foo/bar// \ +./foo/bar//. \ +./foo/bar/. \ +foo/bar \ +foo/bar/ \ +foo/bar// \ +foo/bar//. \ +foo/bar/. \ +.//foolink \ +.//foolink/ \ +.//foolink// \ +.//foolink//. \ +.//foolink/. \ +./foolink \ +./foolink/ \ +./foolink// \ +./foolink//. \ +./foolink/. \ +foolink \ +foolink/ \ +foolink// \ +foolink//. \ +foolink/. \ +-maxdepth 0 -printf "%p,%h,%f\n" } + +exec rm -rf foo foolink diff --git a/find/testsuite/find.gnu/printf-h.xo b/find/testsuite/find.gnu/printf-h.xo index dc6ce01e..0ed6ad9d 100644 --- a/find/testsuite/find.gnu/printf-h.xo +++ b/find/testsuite/find.gnu/printf-h.xo @@ -1 +1,69 @@ -RESULT: . tmp +/,,/ +//,/,/ +///,//,/ +///.,//,. +//.,/,. +.,.,. +./,.,./ +.//,./,./ +.///,.//,./ +.////,.///,./ +./////,.////,./ +./////.,.////,. +.////.,.///,. +.///.,.//,. +.//.,./,. +.//./,./,./ +.//.//,./,./ +.//.//.,.//./,. +.//./.,.//.,. +./.,.,. +././,.,./ +././/,.,./ +././/.,././,. +././.,./.,. +.//foo/bar,.//foo,bar +.//foo/bar/,.//foo,bar/ +.//foo/bar//,.//foo,bar/ +.//foo/bar//.,.//foo/bar/,. +.//foo/bar/.,.//foo/bar,. +./foo/bar,./foo,bar +./foo/bar/,./foo,bar/ +./foo/bar//,./foo,bar/ +./foo/bar//.,./foo/bar/,. +./foo/bar/.,./foo/bar,. +foo/bar,foo,bar +foo/bar/,foo,bar/ +foo/bar//,foo,bar/ +foo/bar//.,foo/bar/,. +foo/bar/.,foo/bar,. +.//foo,./,foo +.//foo/,./,foo/ +.//foo//,./,foo/ +.//foo//.,.//foo/,. +.//foo/.,.//foo,. +./foo,.,foo +./foo/,.,foo/ +./foo//,.,foo/ +./foo//.,./foo/,. +./foo/.,./foo,. +foo,.,foo +foo/,.,foo/ +foo//,.,foo/ +foo//.,foo/,. +foo/.,foo,. +.//foolink,./,foolink +.//foolink/,./,foolink/ +.//foolink//,./,foolink/ +.//foolink//.,.//foolink/,. +.//foolink/.,.//foolink,. +./foolink,.,foolink +./foolink/,.,foolink/ +./foolink//,.,foolink/ +./foolink//.,./foolink/,. +./foolink/.,./foolink,. +foolink,.,foolink +foolink/,.,foolink/ +foolink//,.,foolink/ +foolink//.,foolink/,. +foolink/.,foolink,. -- 2.19.1