findutils/find-fix-printf-h-for-arguments-with-one-or-more-tra.patch
2019-09-30 10:38:48 -04:00

251 lines
6.0 KiB
Diff

From 2a6129bfccec9f23a50f037e187f85c4d000bc87 Mon Sep 17 00:00:00 2001
From: Bernhard Voelker <mail@bernhard-voelker.de>
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 <tavianator@gmail.com> 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