Fix "just in case" unlink. Prefer renaming of normal files
[rsync/rsync.git] / backup.c
index ed99ee9..5f860f7 100644 (file)
--- a/backup.c
+++ b/backup.c
@@ -155,18 +155,18 @@ static inline int link_or_rename(const char *from, const char *to,
                if (IS_SPECIAL(stp->st_mode) || IS_DEVICE(stp->st_mode))
                        return 0; /* Use copy code. */
 #endif
-               if (!S_ISDIR(stp->st_mode)) {
-                       if (do_link(from, to) == 0)
-                               return 2;
+               if (do_link(from, to) == 0)
+                       return 2;
+               /* We prefer to rename a regular file rather than copy it. */
+               if (!S_ISREG(stp->st_mode) || errno == EEXIST || errno == EISDIR)
                        return 0;
-               }
        }
 #endif
        if (do_rename(from, to) == 0) {
                if (stp->st_nlink > 1 && !S_ISDIR(stp->st_mode)) {
                        /* If someone has hard-linked the file into the backup
                         * dir, rename() might return success but do nothing! */
-                       robust_unlink(to); /* Just in case... */
+                       robust_unlink(from); /* Just in case... */
                }
                return 1;
        }