diff options
author | Bernhard Voelker <mail@bernhard-voelker.de> | 2017-02-20 18:53:48 +0100 |
---|---|---|
committer | Bernhard Voelker <mail@bernhard-voelker.de> | 2017-02-20 18:54:08 +0100 |
commit | 2a6129bfccec9f23a50f037e187f85c4d000bc87 (patch) | |
tree | 96ba9cd3ef4ca61fdfe19376e7419661ca32cd50 | |
parent | 9d849f77d55882e4049aec5676024b94097f33f7 (diff) | |
download | findutils-2a6129bfccec9f23a50f037e187f85c4d000bc87.tar.gz |
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 <tavianator@gmail.com> in
https://savannah.gnu.org/bugs/?50259
-rw-r--r-- | NEWS | 8 | ||||
-rw-r--r-- | find/print.c | 21 | ||||
-rw-r--r-- | find/testsuite/find.gnu/printf-h.exp | 94 | ||||
-rw-r--r-- | find/testsuite/find.gnu/printf-h.xo | 70 |
4 files changed, 181 insertions, 12 deletions
@@ -40,8 +40,14 @@ in the use of FTS. #50326: find no longer leaks memory for a recently added member in gnulib's mount list structure. +#50259: find -printf '%h' now outputs the correct path for arguments with one or + more trailing slashes. Previously, it would e.g. output "foo" instead + of "." when "foo/" was passed; likewise, it would output "/user/xxx/" + instead of "/user" when "/user/xxx//" was passed. + Bug introduced in FINDUTILS-4.2.19. + #48180: find -noop (an internal option not intended to be exposed to the user) - no longer crashes. Bug introduced in FINDUTILS-4.3.1. + no longer crashes. Bug introduced in FINDUTILS-4.3.1. #48030: find -exec + does not pass all arguments for certain specific filename lengths. After the internal (usually 128k) buffer is full and find(1) 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,. |