-----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 e...@byu.net -----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 <e...@byu.net> 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 <e...@byu.net> 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