71 lines
2.4 KiB
Diff
71 lines
2.4 KiB
Diff
From e52293aa7fcf283758f97bc9bcc945707ccbce0a Mon Sep 17 00:00:00 2001
|
|
From: =?utf8?q?R=C3=A9my=20Lefevre?= <lefevreremy@gmail.com>
|
|
Date: Tue, 2 Apr 2013 02:48:28 +0100
|
|
Subject: [PATCH 1/1] ln: --relative: fix updating of existing symlinks
|
|
|
|
Don't dereference an existing symlink being replaced.
|
|
I.E. generate the symlink relative to the symlink's containing dir,
|
|
rather than to some arbitrary place it points to.
|
|
|
|
* src/ln.c (convert_abs_rel): Don't consider the final component
|
|
of the symlink name when canonicalizing, as we want to avoid
|
|
dereferencing the final component.
|
|
* tests/ln/relative.sh: Add a test case.
|
|
Resolves http://bugs.gnu.org/14116
|
|
---
|
|
src/ln.c | 14 ++++++++------
|
|
tests/ln/relative.sh | 5 +++++
|
|
2 files changed, 13 insertions(+), 6 deletions(-)
|
|
|
|
diff --git a/src/ln.c b/src/ln.c
|
|
index 1aa1473..2489b9a 100644
|
|
--- a/src/ln.c
|
|
+++ b/src/ln.c
|
|
@@ -132,22 +132,24 @@ target_directory_operand (char const *file)
|
|
static char *
|
|
convert_abs_rel (const char *from, const char *target)
|
|
{
|
|
- char *realtarget = canonicalize_filename_mode (target, CAN_MISSING);
|
|
+ /* Get dirname to generate paths relative to. We don't resolve
|
|
+ the full TARGET as the last component could be an existing symlink. */
|
|
+ char *targetdir = dir_name (target);
|
|
+
|
|
+ char *realdest = canonicalize_filename_mode (targetdir, CAN_MISSING);
|
|
char *realfrom = canonicalize_filename_mode (from, CAN_MISSING);
|
|
|
|
/* Write to a PATH_MAX buffer. */
|
|
char *relative_from = xmalloc (PATH_MAX);
|
|
|
|
- /* Get dirname to generate paths relative to. */
|
|
- realtarget[dir_len (realtarget)] = '\0';
|
|
-
|
|
- if (!relpath (realfrom, realtarget, relative_from, PATH_MAX))
|
|
+ if (!relpath (realfrom, realdest, relative_from, PATH_MAX))
|
|
{
|
|
free (relative_from);
|
|
relative_from = NULL;
|
|
}
|
|
|
|
- free (realtarget);
|
|
+ free (targetdir);
|
|
+ free (realdest);
|
|
free (realfrom);
|
|
|
|
return relative_from ? relative_from : xstrdup (from);
|
|
diff --git a/tests/ln/relative.sh b/tests/ln/relative.sh
|
|
index 0418b8a..818da83 100755
|
|
--- a/tests/ln/relative.sh
|
|
+++ b/tests/ln/relative.sh
|
|
@@ -29,4 +29,9 @@ test $(readlink usr/bin/foo) = '../lib/foo/foo' || fail=1
|
|
ln -sr usr/bin/foo usr/lib/foo/link-to-foo
|
|
test $(readlink usr/lib/foo/link-to-foo) = 'foo' || fail=1
|
|
|
|
+# Correctly update an existing link, which was broken in <= 8.21
|
|
+ln -s dir1/dir2/f existing_link
|
|
+ln -srf here existing_link
|
|
+test $(readlink existing_link) = 'here' || fail=1
|
|
+
|
|
Exit $fail
|
|
--
|
|
1.7.2.5
|
|
|