]> git.ipfire.org Git - thirdparty/coreutils.git/commitdiff
mv, cp: tweak LINK_FOLLOWS_SYMLINKS logic
authorEric Blake <ebb9@byu.net>
Fri, 4 Sep 2009 18:40:39 +0000 (12:40 -0600)
committerEric Blake <ebb9@byu.net>
Fri, 4 Sep 2009 20:54:52 +0000 (14:54 -0600)
* 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.

gnulib
src/copy.c

diff --git a/gnulib b/gnulib
index 9b740ea4bcb104eeceb0c847a376d2b7dbb77d1b..ee67d8ea6bd183f5ce32d90a6764705d766c3d6b 160000 (submodule)
--- a/gnulib
+++ b/gnulib
@@ -1 +1 @@
-Subproject commit 9b740ea4bcb104eeceb0c847a376d2b7dbb77d1b
+Subproject commit ee67d8ea6bd183f5ce32d90a6764705d766c3d6b
index e604ec55a0dda15ecf61c5c3d4592e0518409b57..178a6404b26e6812b5c9cace6dc5b6d86bcb7166 100644 (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))
         {