Improved link_or_rename() to handle prefer_rename better.
[rsync/rsync.git] / backup.c
index a81f947..ed99ee9 100644 (file)
--- a/backup.c
+++ b/backup.c
@@ -106,19 +106,25 @@ int make_bak_dir(const char *fullpath)
 #ifdef SUPPORT_ACLS
                                if (preserve_acls && !S_ISLNK(file->mode)) {
                                        get_acl(rel, &sx);
-                                       cache_acl(file, &sx);
+                                       cache_tmp_acl(file, &sx);
                                        free_acl(&sx);
                                }
 #endif
 #ifdef SUPPORT_XATTRS
                                if (preserve_xattrs) {
                                        get_xattr(rel, &sx);
-                                       cache_xattr(file, &sx);
+                                       cache_tmp_xattr(file, &sx);
                                        free_xattr(&sx);
                                }
 #endif
                                set_file_attrs(fbuf, file, NULL, NULL, 0);
                                unmake_file(file);
+#ifdef SUPPORT_ACLS
+                               uncache_tmp_acls();
+#endif
+#ifdef SUPPORT_XATTRS
+                               uncache_tmp_xattrs();
+#endif
                        }
                }
                *p = '/';
@@ -139,28 +145,23 @@ int make_bak_dir(const char *fullpath)
 static inline int link_or_rename(const char *from, const char *to,
                                 BOOL prefer_rename, STRUCT_STAT *stp)
 {
-       if (S_ISLNK(stp->st_mode)) {
-               if (prefer_rename)
-                       goto do_rename;
+#ifdef SUPPORT_HARD_LINKS
+       if (!prefer_rename) {
 #ifndef CAN_HARDLINK_SYMLINK
-               return 0; /* Use copy code. */
+               if (S_ISLNK(stp->st_mode))
+                       return 0; /* Use copy code. */
 #endif
-       }
-       if (IS_SPECIAL(stp->st_mode) || IS_DEVICE(stp->st_mode)) {
-               if (prefer_rename)
-                       goto do_rename;
 #ifndef CAN_HARDLINK_SPECIAL
-               return 0; /* Use copy code. */
+               if (IS_SPECIAL(stp->st_mode) || IS_DEVICE(stp->st_mode))
+                       return 0; /* Use copy code. */
 #endif
-       }
-#ifdef SUPPORT_HARD_LINKS
-       if (!S_ISDIR(stp->st_mode)) {
-               if (do_link(from, to) == 0)
-                       return 2;
-               return 0;
+               if (!S_ISDIR(stp->st_mode)) {
+                       if (do_link(from, to) == 0)
+                               return 2;
+                       return 0;
+               }
        }
 #endif
-  do_rename:
        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
@@ -195,7 +196,7 @@ int make_backup(const char *fname, BOOL prefer_rename)
         * linking is possible. */
        if ((ret = link_or_rename(fname, buf, prefer_rename, &sx.st)) != 0)
                goto success;
-       if (errno == EEXIST) {
+       if (errno == EEXIST || errno == EISDIR) {
                STRUCT_STAT bakst;
                if (do_lstat(buf, &bakst) == 0) {
                        int flags = get_del_for_flag(bakst.st_mode) | DEL_FOR_BACKUP | DEL_RECURSE;
@@ -219,14 +220,14 @@ int make_backup(const char *fname, BOOL prefer_rename)
 #ifdef SUPPORT_ACLS
        if (preserve_acls && !S_ISLNK(file->mode)) {
                get_acl(fname, &sx);
-               cache_acl(file, &sx);
+               cache_tmp_acl(file, &sx);
                free_acl(&sx);
        }
 #endif
 #ifdef SUPPORT_XATTRS
        if (preserve_xattrs) {
                get_xattr(fname, &sx);
-               cache_xattr(file, &sx);
+               cache_tmp_xattr(file, &sx);
                free_xattr(&sx);
        }
 #endif
@@ -284,7 +285,7 @@ int make_backup(const char *fname, BOOL prefer_rename)
 #ifdef SUPPORT_LINKS
        if (!ret && preserve_links && S_ISLNK(file->mode)) {
                const char *sl = F_SYMLINK(file);
-               if (safe_symlinks && unsafe_symlink(sl, buf)) {
+               if (safe_symlinks && unsafe_symlink(sl, fname)) {
                        if (INFO_GTE(SYMSAFE, 1)) {
                                rprintf(FINFO, "ignoring unsafe symlink %s -> %s\n",
                                        full_fname(buf), sl);
@@ -313,6 +314,12 @@ int make_backup(const char *fname, BOOL prefer_rename)
                rprintf(FINFO, "make_bak: skipping non-regular file %s\n",
                        fname);
                unmake_file(file);
+#ifdef SUPPORT_ACLS
+               uncache_tmp_acls();
+#endif
+#ifdef SUPPORT_XATTRS
+               uncache_tmp_xattrs();
+#endif
                return 2;
        }
 
@@ -322,6 +329,12 @@ int make_backup(const char *fname, BOOL prefer_rename)
                        rsyserr(FERROR, errno, "keep_backup failed: %s -> \"%s\"",
                                full_fname(fname), buf);
                        unmake_file(file);
+#ifdef SUPPORT_ACLS
+                       uncache_tmp_acls();
+#endif
+#ifdef SUPPORT_XATTRS
+                       uncache_tmp_xattrs();
+#endif
                        return 0;
                }
                ret = 2;
@@ -333,6 +346,12 @@ int make_backup(const char *fname, BOOL prefer_rename)
        preserve_xattrs = save_preserve_xattrs;
 
        unmake_file(file);
+#ifdef SUPPORT_ACLS
+       uncache_tmp_acls();
+#endif
+#ifdef SUPPORT_XATTRS
+       uncache_tmp_xattrs();
+#endif
 
   success:
        if (INFO_GTE(BACKUP, 1)) {