diff --git a/src/copy.c b/src/copy.c index 71813dc..7b12337 100644 --- a/src/copy.c +++ b/src/copy.c @@ -1676,7 +1676,7 @@ restore_default_fscreatecon_or_die (void) will be created as a symbolic link to SRC_NAME. */ static bool create_hard_link (char const *src_name, char const *dst_name, - bool replace, bool verbose, bool dereference) + bool replace, bool verbose, bool dereference, bool simulate) { /* We want to guarantee that symlinks are not followed, unless requested. */ int flags = 0; @@ -1703,7 +1703,8 @@ create_hard_link (char const *src_name, char const *dst_name, if (link_failed) { - error (0, errno, _("cannot create hard link %s to %s"), + if (errno != EPERM || ! simulate) + error (0, errno, _("cannot create hard link %s to %s"), quote_n (0, dst_name), quote_n (1, src_name)); return false; } @@ -1877,7 +1878,7 @@ copy_internal (char const *src_name, char const *dst_name, /* Note we currently replace DST_NAME unconditionally, even if it was a newer separate file. */ if (! create_hard_link (earlier_file, dst_name, true, - x->verbose, dereference)) + x->verbose, dereference, false)) { goto un_backup; } @@ -2207,7 +2208,7 @@ copy_internal (char const *src_name, char const *dst_name, else { if (! create_hard_link (earlier_file, dst_name, true, x->verbose, - dereference)) + dereference, false)) goto un_backup; return true; @@ -2505,8 +2506,14 @@ copy_internal (char const *src_name, char const *dst_name, && !(! CAN_HARDLINK_SYMLINKS && S_ISLNK (src_mode) && x->dereference == DEREF_NEVER)) { - if (! create_hard_link (src_name, dst_name, false, false, dereference)) - goto un_backup; + bool can_simulate = S_ISLNK (src_mode); + if (! create_hard_link (src_name, dst_name, false, false, dereference, + can_simulate)) + { + if (errno == EPERM && can_simulate) + goto skip_hardlink; + goto un_backup; + } } else if (S_ISREG (src_mode) || (x->copy_as_regular && !S_ISLNK (src_mode))) @@ -2549,6 +2556,7 @@ copy_internal (char const *src_name, char const *dst_name, } } else if (S_ISLNK (src_mode)) + skip_hardlink: { char *src_link_val = areadlink_with_size (src_name, src_sb.st_size); dest_is_symlink = true;