From 8064efdaf4a671926b15164b034348f5c0eb68ad Mon Sep 17 00:00:00 2001
From: Bernhard Voelker <mail@bernhard-voelker.de>
Date: Sun, 12 Feb 2017 14:13:36 +0100
Subject: [PATCH] find: fix -printf '%h' for arguments with a trailing slash

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): Also output "." as the leading directory
instead of the argument itself stripped by the trailing slash
when there is only one single directory separator at the end of the
pathname (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                                 |  7 ++++++-
 find/print.c                         |  9 +++++++--
 find/testsuite/find.gnu/printf-h.exp | 13 +++++++++----
 find/testsuite/find.gnu/printf-h.xo  | 32 +++++++++++++++++++++++++++++++-
 4 files changed, 53 insertions(+), 8 deletions(-)

diff --git a/NEWS b/NEWS
index ba89f9d..a8414a7 100644
--- a/NEWS
+++ b/NEWS
@@ -40,8 +40,13 @@ in the use of FTS.
 find no longer leaks memory for a recently added member in gnulib's
 mount list structure.
 
+#50259: find -printf '%h' now outputs "." for arguments with a trailing slash.
+        Previously, it e.g. would output "foo/foo/" for "%h/%f" when "foo/"
+        was passed; now it outputs "./foo" correctly.
+        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 2035157..02b072b 100644
--- a/find/print.c
+++ b/find/print.c
@@ -966,9 +966,14 @@ do_fprintf (struct format_val *dest,
           /* sanitised */
           {
             cp = strrchr (pathname, '/');
-            if (cp == NULL)     /* No leading directories. */
+            if ((cp == NULL)           /* No leading directories, or pathname */
+                || ((*(cp+1) == '\0')  /* contains only a single, trailing    */
+                    && (strchr (pathname, '/') == cp) /* directory separator  */
+                    && (cp != pathname)))  /*  yet not the root "/" directory.*/
               {
-                /* If there is no slash in the pathname, we still
+                /* If there is no slash in the pathname, or if there is only
+                 * one single directory separator at the end of pathname
+                 * (unless this is the root "/" directory), we still
                  * print the string because it contains characters
                  * other than just '%s'.  The %h expands to ".".
                  */
diff --git a/find/testsuite/find.gnu/printf-h.exp b/find/testsuite/find.gnu/printf-h.exp
index fb0187c..2403c6d 100644
--- a/find/testsuite/find.gnu/printf-h.exp
+++ b/find/testsuite/find.gnu/printf-h.exp
@@ -1,5 +1,10 @@
 # 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
+exec touch foo/bar
+exec ln -s foo foolink
+# Combinations: {,./}{/,.,foo,foolink}{,/,/.}
+
+find_start p {/ // //. . ./ .// ./// .///. ./. ././ ././. ./foo/./bar ./foo/bar foo/./bar foo/bar ./foo ./foo/. foo foo/ foo/. ./foo/ ./foolink/./bar ./foolink/bar foolink/./bar foolink/bar ./foolink ./foolink/. foolink foolink/ foolink/. ./foolink/ -maxdepth 0 -printf "%p,%h,%f\n" }
+
+exec rm -rf foo
diff --git a/find/testsuite/find.gnu/printf-h.xo b/find/testsuite/find.gnu/printf-h.xo
index dc6ce01..961be9e 100644
--- a/find/testsuite/find.gnu/printf-h.xo
+++ b/find/testsuite/find.gnu/printf-h.xo
@@ -1 +1,31 @@
-RESULT: . tmp
+/,,/
+//,/,/
+//.,/,.
+.,.,.
+./,.,./
+.//,./,./
+.///,.//,./
+.///.,.//,.
+./.,.,.
+././,./.,./
+././.,./.,.
+./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/
+./foolink/./bar,./foolink/.,bar
+./foolink/bar,./foolink,bar
+foolink/./bar,foolink/.,bar
+foolink/bar,foolink,bar
+./foolink,.,foolink
+./foolink/.,./foolink,.
+foolink,.,foolink
+foolink/,.,foolink/
+foolink/.,foolink,.
+./foolink/,./foolink,foolink/
-- 
2.1.4

