Subject: bug#10472: `realpath --relative-to=<path> /` outputs inconsistent trailing slash

From: Pádraig Brady <[email-masked]>
Date: Wed, 25 Jan 2012 18:42:45 +0000

On 01/25/2012 06:00 PM, Pádraig Brady wrote:
> On 01/25/2012 05:10 PM, Jim Meyering wrote:
>> On an unrelated note, have you considered removing the remaining
>> printf uses in favor of fputc/fputs, since they're all trivial?
> 
> Good point. I'll undo the s/printf/putchar/ change in this patch,
> and do a follow up, using the lower level functions.

The patch below, gives an 11% improvement.
Tested like:

seq 1000000 | sed 's|.*|/1/2/3/4/&|' > paths
time xargs src/realpath -sm < paths >/dev/null
time xargs src/realpath -sm --relative-to=/1/2/3 < paths >/dev/null

cheers,
Pádraig.

diff --git a/src/realpath.c b/src/realpath.c
index b03f375..2dc5e11 100644
--- a/src/realpath.c
+++ b/src/realpath.c
@@ -181,26 +181,27 @@ relpath (const char *can_fname)
          to a common directory.  Then output the remainder of fname.  */
       if (*relto_suffix)
         {
-          printf ("%s", "..");
+          fputs ("..", stdout);
           for (; *relto_suffix; ++relto_suffix)
             {
               if (*relto_suffix == '/')
-                printf ("%s", "/..");
+                fputs ("/..", stdout);
             }

           if (*fname_suffix)
-            printf ("/%s", fname_suffix);
+            {
+              putchar ('/');
+              fputs (fname_suffix, stdout);
+            }
         }
       else
         {
           if (*fname_suffix)
-            printf ("%s", fname_suffix);
+            fputs (fname_suffix, stdout);
           else
-            printf ("%c", '.');
+            putchar ('.');
         }

-      putchar (use_nuls ? '\0' : '\n');
-
       return true;
     }

@@ -228,7 +229,9 @@ process_path (const char *fname, int can_mode)
     }

   if (!relpath (can_fname))
-    printf ("%s%c", can_fname, (use_nuls ? '\0' : '\n'));
+    fputs (can_fname, stdout);
+
+  putchar (use_nuls ? '\0' : '\n');

   free (can_fname);