From 4c7979f7c249606c0d6b73fd01b92b0825d83741 Mon Sep 17 00:00:00 2001 From: Jim Meyering Date: Sat, 3 Jun 2006 09:04:22 +0000 Subject: Make `cp --link --no-dereference' work also on systems where the link system call cannot create a hard link to a symbolic link. (copy_internal) [LINK_FOLLOWS_SYMLINKS]: Don't use the link syscall on a symlink when it would do the wrong thing. Based on the patch by Aurelien Jarno: --- src/copy.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/copy.c b/src/copy.c index a6f6ec54e..a6ea3e6b6 100644 --- a/src/copy.c +++ b/src/copy.c @@ -1594,7 +1594,22 @@ copy_internal (char const *src_name, char const *dst_name, } } #endif - else if (x->hard_link) + + else if (x->hard_link +#ifdef LINK_FOLLOWS_SYMLINKS + /* A POSIX-conforming link syscall dereferences a symlink, yet cp, + invoked with `--link --no-dereference', should not. Thus, with + a POSIX-conforming link system call, we can't use link() here, + since that would create a hard link to the referent (effectively + dereferencing the symlink), rather than to the symlink itself. + We can approximate the desired behavior by skipping this hard-link + creating block and instead copying the symlink, via the `S_ISLNK'- + copying code below. + When link operates on the symlinks themselves, we use this block + and just call link(). */ + && !(S_ISLNK (src_mode) && x->dereference == DEREF_NEVER) +#endif + ) { preserve_metadata = false; if (link (src_name, dst_name)) -- cgit v1.2.3-70-g09d2