]> git.ipfire.org Git - thirdparty/coreutils.git/commitdiff
ln: add comments related to POSIX 2008
authorEric Blake <ebb9@byu.net>
Fri, 4 Sep 2009 19:56:16 +0000 (13:56 -0600)
committerEric Blake <ebb9@byu.net>
Fri, 4 Sep 2009 20:54:55 +0000 (14:54 -0600)
* src/ln.c (ENABLE_HARD_LINK_TO_SYMLINK_WARNING): Delete.
(do_link): Update comments per POSIX; add FIXME for -L, -P.

src/ln.c

index d9b9285f4176af07b7f09dfafdd52e6dfaa9d98c..6a1dc32077bfa7642bb1e0e28a7eea5c13b7c2d5 100644 (file)
--- a/src/ln.c
+++ b/src/ln.c
   proper_name ("Mike Parker"), \
   proper_name ("David MacKenzie")
 
-#ifndef ENABLE_HARD_LINK_TO_SYMLINK_WARNING
-# define ENABLE_HARD_LINK_TO_SYMLINK_WARNING 0
-#endif
-
 /* In being careful not even to try to make hard links to directories,
    we have to know whether link(2) follows symlinks.  If it does, then
    we have to *stat* the `source' to see if the resulting link would be
@@ -150,7 +146,12 @@ do_link (const char *source, const char *dest)
   /* Use stat here instead of lstat.
      On SVR4, link does not follow symlinks, so this check disallows
      making hard links to symlinks that point to directories.  Big deal.
-     On other systems, link follows symlinks, so this check is right.  */
+     On other systems, link follows symlinks, so this check is right.
+
+     FIXME - POSIX 2008 added the AT_SYMLINK_FOLLOW flag to linkat so
+     that we can specify either behavior, via the new options -L
+     (hard-link to symlinks) and -P (hard-link to the referent).  Once
+     gnulib has a decent implementation, we should use it here.  */
   if (!symbolic_link)
     {
       if (STAT_LIKE_LINK (source, &source_stats) != 0)
@@ -159,14 +160,6 @@ do_link (const char *source, const char *dest)
           return false;
         }
 
-      if (ENABLE_HARD_LINK_TO_SYMLINK_WARNING
-          && S_ISLNK (source_stats.st_mode))
-        {
-          error (0, 0, _("%s: warning: making a hard link to a symbolic link\
- is not portable"),
-                 quote (source));
-        }
-
       if (S_ISDIR (source_stats.st_mode))
         {
           source_is_dir = true;
@@ -271,14 +264,15 @@ do_link (const char *source, const char *dest)
   /* If the attempt to create a link failed and we are removing or
      backing up destinations, unlink the destination and try again.
 
-     POSIX 1003.1-2004 requires that ln -f A B must unlink B even on
-     failure (e.g., when A does not exist).  This is counterintuitive,
-     and we submitted a defect report
-     <http://www.opengroup.org/austin/mailarchives/ag-review/msg01794.html>
-     (2004-06-24).  If the committee does not fix the standard we'll
-     have to change the behavior of ln -f, at least if POSIXLY_CORRECT
-     is set.  In the meantime ln -f A B will not unlink B unless the
-     attempt to link A to B failed because B already existed.
+     On the surface, POSIX describes an algorithm that states that
+     'ln -f A B' will call unlink() on B before ever attempting
+     link() on A.  But strictly following this has the counterintuitive
+     effect of losing the contents of B, if A does not exist.
+     Fortunately, POSIX 2008 clarified that an application is free
+     to fail early if it can prove that continuing onwards cannot
+     succeed, so we are justified in trying link() before blindly
+     removing B, thus sometimes calling link() a second time during
+     a successful 'ln -f A B'.
 
      Try to unlink DEST even if we may have backed it up successfully.
      In some unusual cases (when DEST and DEST_BACKUP are hard-links