summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBernhard Voelker <mail@bernhard-voelker.de>2017-02-20 18:53:48 +0100
committerBernhard Voelker <mail@bernhard-voelker.de>2017-02-20 18:54:08 +0100
commit2a6129bfccec9f23a50f037e187f85c4d000bc87 (patch)
tree96ba9cd3ef4ca61fdfe19376e7419661ca32cd50
parent9d849f77d55882e4049aec5676024b94097f33f7 (diff)
downloadfindutils-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--NEWS8
-rw-r--r--find/print.c21
-rw-r--r--find/testsuite/find.gnu/printf-h.exp94
-rw-r--r--find/testsuite/find.gnu/printf-h.xo70
4 files changed, 181 insertions, 12 deletions
diff --git a/NEWS b/NEWS
index c98a7705..6f2ca4e4 100644
--- a/NEWS
+++ b/NEWS
@@ -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,.