From 3a8cc1af15f0c9c6a71c5abc9219237f1613e8cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A1draig=20Brady?= Date: Wed, 25 Jan 2012 16:42:42 +0000 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 ('.'); } putchar (use_nuls ? '\0' : '\n'); diff --git a/tests/misc/realpath b/tests/misc/realpath index fb01393..8a1f336 100755 --- a/tests/misc/realpath +++ b/tests/misc/realpath @@ -41,13 +41,18 @@ realpath -m '' && fail=1 # symlink resolution this=$(realpath .) -test "$(realpath $relative ldir2/..)" = "$this/dir1" || fail=1 -test "$(realpath -L $relative ldir2/..)" = "$this" || fail=1 -test "$(realpath -s $relative ldir2)" = "$this/ldir2" || fail=1 +test "$(realpath ldir2/..)" = "$this/dir1" || fail=1 +test "$(realpath -L ldir2/..)" = "$this" || fail=1 +test "$(realpath -s ldir2)" = "$this/ldir2" || fail=1 # relative string handling test $(realpath -m --relative-to=prefix prefixed/1) = '../prefixed/1' || fail=1 test $(realpath -m --relative-to=prefixed prefix/1) = '../prefix/1' || fail=1 test $(realpath -m --relative-to=prefixed prefixed/1) = '1' || fail=1 +# Ensure no redundant trailing '/' present, as was the case in v8.15 +test $(realpath -sm --relative-to=/usr /) = '..' || fail=1 +# Ensure no redundant leading '../' present, as was the case in v8.15 +test $(realpath -sm --relative-to=/ /usr) = 'usr' || fail=1 + Exit $fail -- 1.7.6.4