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

From: Jim Meyering <[email-masked]>
Date: Wed, 25 Jan 2012 18:10:20 +0100

Pádraig Brady wrote:
...
> Subject: [PATCH] realpath: remove extraneous '/' for --relative-to edge cases
>
> * src/realpath.c (path_common_prefix): Be consistent and
> always include a leading '/' in the count returned.
> (relpath): Account for the change in path_common_prefix()
> and avoid outputting extra '/' chars in relative paths that
> span the root dir.
> * tests/misc/realpath: Add the two reported cases.
> Reported by Mike Frysinger
> ---
>  src/realpath.c      |   16 +++++++++++-----
>  tests/misc/realpath |   11 ++++++++---
>  2 files changed, 19 insertions(+), 8 deletions(-)
>
> diff --git a/src/realpath.c b/src/realpath.c
> index b39f7bf..8a07ab6 100644
> --- a/src/realpath.c
> +++ b/src/realpath.c
> @@ -136,7 +136,7 @@ path_common_prefix (const char *path1, const char *path2)
>        if (*path1 != *path2)
>          break;
>        if (*path1 == '/')
> -        ret = i;
> +        ret = i + 1;
>        path1++;
>        path2++;
>        i++;
> @@ -171,11 +171,16 @@ relpath (const char *can_fname)
>        const char *relto_suffix = can_relative_to + common_index;
>        const char *fname_suffix = can_fname + common_index;
>
> +      /* skip over extraneous '/'.  */
> +      if (*relto_suffix == '/')
> +        relto_suffix++;
> +      if (*fname_suffix == '/')
> +        fname_suffix++;
> +
>        /* Replace remaining components of --relative-to with '..', to get
>           to a common directory.  Then output the remainder of fname.  */
>        if (*relto_suffix)
>          {
> -          ++relto_suffix;
>            printf ("%s", "..");
>            for (; *relto_suffix; ++relto_suffix)
>              {
> @@ -183,14 +188,15 @@ relpath (const char *can_fname)
>                  printf ("%s", "/..");
>              }
>
> -          printf ("%s", fname_suffix);
> +          if (*fname_suffix)
> +            printf ("/%s", fname_suffix);
>          }
>        else
>          {
>            if (*fname_suffix)
> -            printf ("%s", ++fname_suffix);
> +            printf ("%s", fname_suffix);
>            else
> -            printf ("%c", '.');
> +            putchar ('.');
>          }

That looks fine and passes existing and new tests (of course).
Thanks.

On an unrelated note, have you considered removing the remaining
printf uses in favor of fputc/fputs, since they're all trivial?