bug-coreutils
[Top][All Lists]
Advanced

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

Re: link -L/-P


From: Eric Blake
Subject: Re: link -L/-P
Date: Thu, 24 Sep 2009 19:46:11 -0600
User-agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.23) Gecko/20090812 Thunderbird/2.0.0.23 Mnenhy/0.7.6.666

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

According to Pádraig Brady on 9/24/2009 5:13 PM:
> Eric Blake wrote:
> 
>> +  -L, --logical               make hard links to symbolic link references\n\
> 
> s/references/targets/ is a bit clearer to me?

I thought about that, but we already specify:

ln source target

as the synopsis, so I didn't want to confuse target (the file being
created) with target (the contents of the symlink being linked through).

> 
>> +  -P, --physical              make hard links directly to symblic links\n\
> 
> s/symblic/symbolic/

Thanks.  I folded that in, then added a patch to fix copy.c to use linkat
(pushed).  I also noticed a cleanup for stdbuf while searching through
instances of 'link (', although I haven't been able to test that yet,
since stdbuf doesn't compile on cygwin.  I've pushed my work to:

git pull git://repo.or.cz/coreutils/ericb.git master

to make it easier to review.

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

Eric Blake             address@hidden
-----BEGIN PGP SIGNATURE-----
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/

iEYEARECAAYFAkq8IOMACgkQ84KuGfSFAYBlfACgnj+WOzvLELCE56uQl+aqRbNA
IOMAnifSX9AxFgh+ugoSqb3CoJhXrIFg
=ETC+
-----END PGP SIGNATURE-----
>From 4b9126696dfa293986640556960ef4bbf0be442b Mon Sep 17 00:00:00 2001
From: Eric Blake <address@hidden>
Date: Thu, 24 Sep 2009 17:11:26 -0600
Subject: [PATCH 1/2] cp, mv: use linkat to guarantee semantics

* src/copy.c (copy_internal): Use linkat, not link.
---
 src/copy.c |   29 +++++++++++------------------
 1 files changed, 11 insertions(+), 18 deletions(-)

diff --git a/src/copy.c b/src/copy.c
index e3c5c52..49e620a 100644
--- a/src/copy.c
+++ b/src/copy.c
@@ -1687,7 +1687,9 @@ copy_internal (char const *src_name, char const *dst_name,
         }
       else
         {
-          bool link_failed = (link (earlier_file, dst_name) != 0);
+          /* We want to guarantee that symlinks are not followed.  */
+          bool link_failed = (linkat (AT_FDCWD, earlier_file, AT_FDCWD,
+                                      dst_name, 0) != 0);

           /* If the link failed because of an existing destination,
              remove that file and then call link again.  */
@@ -1700,7 +1702,8 @@ copy_internal (char const *src_name, char const *dst_name,
                 }
               if (x->verbose)
                 printf (_("removed %s\n"), quote (dst_name));
-              link_failed = (link (earlier_file, dst_name) != 0);
+              link_failed = (linkat (AT_FDCWD, earlier_file, AT_FDCWD,
+                                     dst_name, 0) != 0);
             }

           if (link_failed)
@@ -1990,25 +1993,15 @@ 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.  */
+  /* cp, invoked with `--link --no-dereference', should not follow the
+     link; we guarantee this with gnulib's linkat module (on systems
+     where link(2) follows the link, gnulib creates a symlink with
+     identical contents, which is good enough for our purposes).  */
   else if (x->hard_link
-           && (!LINK_FOLLOWS_SYMLINKS
-               || !S_ISLNK (src_mode)
+           && (!S_ISLNK (src_mode)
                || x->dereference != DEREF_NEVER))
     {
-      if (link (src_name, dst_name))
+       if (linkat (AT_FDCWD, src_name, AT_FDCWD, dst_name, 0))
         {
           error (0, errno, _("cannot create link %s"), quote (dst_name));
           goto un_backup;
-- 
1.6.5.rc1


>From d7b4703e46ef2b377704f56dac6e57f0648637d4 Mon Sep 17 00:00:00 2001
From: Eric Blake <address@hidden>
Date: Thu, 24 Sep 2009 17:18:47 -0600
Subject: [PATCH 2/2] stdbuf: improve path search

* src/stdbuf.c (set_program_path): use gnulib methods for better
file name handling.
---
 src/stdbuf.c |   26 +++++++++-----------------
 1 files changed, 9 insertions(+), 17 deletions(-)

diff --git a/src/stdbuf.c b/src/stdbuf.c
index afb7821..c33cdfa 100644
--- a/src/stdbuf.c
+++ b/src/stdbuf.c
@@ -145,34 +145,26 @@ set_program_path (const char *arg)
     }
   else
     {
-      char *path;
-      char tmppath[PATH_MAX + 1];
-      ssize_t len = readlink ("/proc/self/exe", tmppath, sizeof (tmppath) - 1);
-      if (len > 0)
-        {
-          tmppath[len] = '\0';
-          program_path = dir_name (tmppath);
-        }
+      char *path = areadlink ("/proc/self/exe");
+      if (path)
+        program_path = dir_name (path);
       else if ((path = getenv ("PATH")))
         {
           char *dir;
           path = xstrdup (path);
           for (dir = strtok (path, ":"); dir != NULL; dir = strtok (NULL, ":"))
             {
-              int req = snprintf (tmppath, sizeof (tmppath), "%s/%s", dir, 
arg);
-              if (req >= sizeof (tmppath))
-                {
-                  error (0, 0, _("path truncated when looking for %s"),
-                         quote (arg));
-                }
-              else if (access (tmppath, X_OK) == 0)
+              char *candidate = file_name_concat (dir, arg);
+              if (access (candidate, X_OK) == 0)
                 {
-                  program_path = dir_name (tmppath);
+                  program_path = dir_name (candidate);
+                  free (candidate);
                   break;
                 }
+              free (candidate);
             }
-          free (path);
         }
+      free (path);
     }
 }

-- 
1.6.5.rc1


reply via email to

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