1
0
mirror of git://git.sv.gnu.org/coreutils.git synced 2026-04-10 06:03:31 +02:00

mv, cp: tweak LINK_FOLLOWS_SYMLINKS logic

* gnulib: Update to latest gnulib.
* src/copy.c (copy_internal): Adjust comment in light of POSIX
2008, and deal with macro now being tri-state.
This commit is contained in:
Eric Blake
2009-09-04 12:40:39 -06:00
parent a23afe7b72
commit 3346c0afbc
2 changed files with 17 additions and 15 deletions

2
gnulib

Submodule gnulib updated: 9b740ea4bc...ee67d8ea6b

View File

@@ -1974,21 +1974,23 @@ copy_internal (char const *src_name, char const *dst_name,
}
}
/* POSIX 2008 states that it is implementation-defined whether
link() on a symlink creates a hard-link to the symlink, or only
to the referent (effectively dereferencing the symlink) (POSIX
2001 required the latter behavior, although many systems provided
the former). Yet cp, invoked with `--link --no-dereference',
should not follow the link. 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.
LINK_FOLLOWS_SYMLINKS is tri-state; if it is -1, we don't know
how link() behaves, so we use the fallback case for safety.
FIXME - use a gnulib linkat emulation for more fine-tuned
emulation, particularly when LINK_FOLLOWS_SYMLINKS is -1. */
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
)
&& (!LINK_FOLLOWS_SYMLINKS
|| !S_ISLNK (src_mode)
|| x->dereference != DEREF_NEVER))
{
if (link (src_name, dst_name))
{