diff --git a/src/copy.c b/src/copy.c index c17b942..95d05f0 100644 --- a/src/copy.c +++ b/src/copy.c @@ -1488,6 +1488,37 @@ restore_default_fscreatecon_or_die (void) _("failed to restore the default file creation context")); } +static bool +create_hard_link (char const *src_name, char const *dst_name, + bool replace, bool verbose) +{ + /* We want to guarantee that symlinks are not followed. */ + bool link_failed = (linkat (AT_FDCWD, src_name, AT_FDCWD, dst_name, 0) != 0); + + /* If the link failed because of an existing destination, + remove that file and then call link again. */ + if (link_failed && errno == EEXIST && replace) + { + if (unlink (dst_name) != 0) + { + error (0, errno, _("cannot remove %s"), quote (dst_name)); + return false; + } + if (verbose) + printf (_("removed %s\n"), quote (dst_name)); + link_failed = (linkat (AT_FDCWD, src_name, AT_FDCWD, dst_name, 0) != 0); + } + + if (link_failed) + { + error (0, errno, _("cannot create hard link %s to %s"), + quote_n (0, dst_name), quote_n (1, src_name)); + return false; + } + + return true; +} + /* Copy the file SRC_NAME to the file DST_NAME. The files may be of any type. NEW_DST should be true if the file DST_NAME cannot exist because its parent directory was just created; NEW_DST should @@ -1948,31 +1979,8 @@ copy_internal (char const *src_name, char const *dst_name, } else { - /* 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. */ - if (link_failed && errno == EEXIST) - { - if (unlink (dst_name) != 0) - { - error (0, errno, _("cannot remove %s"), quote (dst_name)); - goto un_backup; - } - if (x->verbose) - printf (_("removed %s\n"), quote (dst_name)); - link_failed = (linkat (AT_FDCWD, earlier_file, AT_FDCWD, - dst_name, 0) != 0); - } - - if (link_failed) - { - error (0, errno, _("cannot create hard link %s to %s"), - quote_n (0, dst_name), quote_n (1, earlier_file)); - goto un_backup; - } + if (!create_hard_link (earlier_file, dst_name, true, x->verbose)) + goto un_backup; return true; } @@ -2274,11 +2282,8 @@ copy_internal (char const *src_name, char const *dst_name, && !(LINK_FOLLOWS_SYMLINKS && S_ISLNK (src_mode) && x->dereference == DEREF_NEVER)) { - if (linkat (AT_FDCWD, src_name, AT_FDCWD, dst_name, 0)) - { - error (0, errno, _("cannot create link %s"), quote (dst_name)); - goto un_backup; - } + if (!create_hard_link (src_name, dst_name, false, false)) + goto un_backup; } else if (S_ISREG (src_mode) || (x->copy_as_regular && !S_ISLNK (src_mode)))