[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: snapshot in a few hours

From: Eric Blake
Subject: Re: snapshot in a few hours
Date: Fri, 04 Sep 2009 14:10:29 -0600
User-agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv: Gecko/20090812 Thunderbird/ Mnenhy/

Hash: SHA1

According to Eric Blake on 9/4/2009 2:06 PM:
> According to Jim Meyering on 9/4/2009 12:12 PM:
>>> copy.c needs to use #if LINK_FOLLOWS_SYMLINKS instead of #ifdef.
>> Sounds good.
> How about the following two patches?

Aargh.  Did it again, and attached the wrong file.

- --
Don't work too hard, make some time for fun as well!

Eric Blake             address@hidden
Version: GnuPG v1.4.9 (Cygwin)
Comment: Public key at home.comcast.net/~ericblake/eblake.gpg
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

>From ed13602fa561e66a2695ddd7eeeb2f218ce9020f Mon Sep 17 00:00:00 2001
From: Eric Blake <address@hidden>
Date: Fri, 4 Sep 2009 12:40:39 -0600
Subject: [PATCH 1/2] 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.
 gnulib     |    2 +-
 src/copy.c |   30 ++++++++++++++++--------------
 2 files changed, 17 insertions(+), 15 deletions(-)

diff --git a/gnulib b/gnulib
index 9b740ea..ee67d8e 160000
--- a/gnulib
+++ b/gnulib
@@ -1 +1 @@
-Subproject commit 9b740ea4bcb104eeceb0c847a376d2b7dbb77d1b
+Subproject commit ee67d8ea6bd183f5ce32d90a6764705d766c3d6b
diff --git a/src/copy.c b/src/copy.c
index e604ec5..178a640 100644
--- a/src/copy.c
+++ b/src/copy.c
@@ -1974,21 +1974,23 @@ copy_internal (char const *src_name, char const 

+  /* 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
-  /* 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)
-           )
+              || !S_ISLNK (src_mode)
+              || x->dereference != DEREF_NEVER))
       if (link (src_name, dst_name))

>From 410eddc47c10082591b2487b234a3b5a6155daaf Mon Sep 17 00:00:00 2001
From: Eric Blake <address@hidden>
Date: Fri, 4 Sep 2009 13:56:16 -0600
Subject: [PATCH 2/2] ln: add comments related to POSIX 2008

(do_link): Update comments per POSIX; add FIXME for -L, -P.
 src/ln.c |   35 ++++++++++++++---------------------
 1 files changed, 14 insertions(+), 21 deletions(-)

diff --git a/src/ln.c b/src/ln.c
index d9b9285..4c6ec8a 100644
--- a/src/ln.c
+++ b/src/ln.c
@@ -39,10 +39,6 @@
   proper_name ("Mike Parker"), \
   proper_name ("David MacKenzie")

 /* 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;

-          && 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,14 @@ 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 continuing onwards cannot succeed,
+     so we are justified in trying link() before blindly removing B,
+     and calling link() twice for a successful 'ln -f'.

      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

reply via email to

[Prev in Thread] Current Thread [Next in Thread]