summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEric Blake <ebb9@byu.net>2009-09-04 13:56:16 -0600
committerEric Blake <ebb9@byu.net>2009-09-04 14:54:55 -0600
commitc69228092616ec097986f5484e56f01ec95594c3 (patch)
tree7f16284ed3193788d0847dab2fb4c17a1f714152 /src
parent3346c0afbc5fcf68322dccd69fb291854c269935 (diff)
downloadcoreutils-c69228092616ec097986f5484e56f01ec95594c3.tar.xz
ln: add comments related to POSIX 2008
* src/ln.c (ENABLE_HARD_LINK_TO_SYMLINK_WARNING): Delete. (do_link): Update comments per POSIX; add FIXME for -L, -P.
Diffstat (limited to 'src')
-rw-r--r--src/ln.c36
1 files changed, 15 insertions, 21 deletions
diff --git a/src/ln.c b/src/ln.c
index d9b9285f4..6a1dc3207 100644
--- a/src/ln.c
+++ b/src/ln.c
@@ -39,10 +39,6 @@
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