#define SAME_GROUP(A, B) ((A).st_gid == (B).st_gid)
#define SAME_OWNER_AND_GROUP(A, B) (SAME_OWNER (A, B) && SAME_GROUP (A, B))
+/* LINK_FOLLOWS_SYMLINKS is tri-state; if it is -1, we don't know
+ how link() behaves, so assume we can't hardlink symlinks in that case. */
+#if defined HAVE_LINKAT || ! LINK_FOLLOWS_SYMLINKS
+# define CAN_HARDLINK_SYMLINKS 1
+#else
+# define CAN_HARDLINK_SYMLINKS 0
+#endif
+
struct dir_list
{
struct dir_list *parent;
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.
Note gnulib's linkat module, guarantees that the symlink is not
dereferenced. However its emulation currently doesn't maintain
timestamps or ownership so we only call it when we know the
emulation will not be needed. */
else if (x->hard_link
- && !(LINK_FOLLOWS_SYMLINKS && S_ISLNK (src_mode)
+ && !(! CAN_HARDLINK_SYMLINKS && S_ISLNK (src_mode)
&& x->dereference == DEREF_NEVER))
{
if (! create_hard_link (src_name, dst_name, false, false, dereference))
/* If we've just created a hard-link due to cp's --link option,
we're done. */
if (x->hard_link && ! S_ISDIR (src_mode)
- && !(LINK_FOLLOWS_SYMLINKS && S_ISLNK (src_mode)
+ && !(! CAN_HARDLINK_SYMLINKS && S_ISLNK (src_mode)
&& x->dereference == DEREF_NEVER))
return delayed_ok;
print_ver_ cp
if grep '^#define HAVE_LINKAT 1' "$CONFIG_HEADER" > /dev/null \
- && grep '^#define LINK_FOLLOWS_SYMLINKS 0' "$CONFIG_HEADER" > /dev/null; then
- # With this config (which is the case on GNU/Linux) cp will attempt to
- # linkat() to hardlink a symlink. So now see if the current file system
- # supports this operation.
+ || grep '^#define LINK_FOLLOWS_SYMLINKS 0' "$CONFIG_HEADER" > /dev/null; then
+ # With this config cp will attempt to linkat() to hardlink a symlink.
+ # So now double check the current file system supports this operation.
ln -s testtarget test_sl || framework_failure_
ln -P test_sl test_hl_sl || framework_failure_
ino_sl="$(stat -c '%i' test_sl)" || framework_failure_