Fix --remove-source-files sanity check w/--copy-links the right way.
[rsync.git] / backup.c
index 0ef4d9ec148455b675dcb78e4530673e9e362d7c..5f40b39af9592ef5017d341cf953cde93565fc2c 100644 (file)
--- a/backup.c
+++ b/backup.c
@@ -2,7 +2,7 @@
  * Backup handling code.
  *
  * Copyright (C) 1999 Andrew Tridgell
- * Copyright (C) 2003-2009 Wayne Davison
+ * Copyright (C) 2003-2018 Wayne Davison
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -98,7 +98,7 @@ static BOOL copy_valid_path(const char *fname)
        for ( ; b; name = b + 1, b = strchr(name, '/')) {
                *b = '\0';
 
-               while (mkdir_defmode(backup_dir_buf) < 0) {
+               while (do_mkdir(backup_dir_buf, ACCESSPERMS) < 0) {
                        if (errno == EEXIST) {
                                val = validate_backup_dir();
                                if (val > 0)
@@ -157,16 +157,28 @@ static BOOL copy_valid_path(const char *fname)
 char *get_backup_name(const char *fname)
 {
        if (backup_dir) {
+               static int initialized = 0;
+               if (!initialized) {
+                       int ret;
+                       if (backup_dir_len > 1)
+                               backup_dir_buf[backup_dir_len-1] = '\0';
+                       ret = make_path(backup_dir_buf, 0);
+                       if (backup_dir_len > 1)
+                               backup_dir_buf[backup_dir_len-1] = '/';
+                       if (ret < 0)
+                               return NULL;
+                       initialized = 1;
+               }
                /* copy fname into backup_dir_buf while validating the dirs. */
                if (copy_valid_path(fname))
                        return backup_dir_buf;
+               /* copy_valid_path() has printed an error message. */
                return NULL;
-       } else {
-               if (stringjoin(backup_dir_buf, MAXPATHLEN,
-                              fname, backup_suffix, NULL) < MAXPATHLEN)
-                       return backup_dir_buf;
        }
 
+       if (stringjoin(backup_dir_buf, MAXPATHLEN, fname, backup_suffix, NULL) < MAXPATHLEN)
+               return backup_dir_buf;
+
        rprintf(FERROR, "backup filename too long\n");
        return NULL;
 }
@@ -208,23 +220,24 @@ static inline int link_or_rename(const char *from, const char *to,
        return 0;
 }
 
-/* Hard-link, rename, or copy an item to the backup name.  Returns 2 if item
- * was duplicated into backup area, 1 if item was moved, or 0 for failure.*/
+/* Hard-link, rename, or copy an item to the backup name.  Returns 0 for
+ * failure, 1 if item was moved, 2 if item was duplicated or hard linked
+ * into backup area, or 3 if item doesn't exist or isn't a regular file. */
 int make_backup(const char *fname, BOOL prefer_rename)
 {
        stat_x sx;
        struct file_struct *file;
        int save_preserve_xattrs;
-       char *buf = get_backup_name(fname);
+       char *buf;
        int ret = 0;
 
-       if (!buf)
-               return 0;
-
        init_stat_x(&sx);
        /* Return success if no file to keep. */
        if (x_lstat(fname, &sx.st, NULL) < 0)
-               return 1;
+               return 3;
+
+       if (!(buf = get_backup_name(fname)))
+               return 0;
 
        /* Try a hard-link or a rename first.  Using rename is not atomic, but
         * is more efficient than forcing a copy for larger files when no hard-
@@ -244,7 +257,7 @@ int make_backup(const char *fname, BOOL prefer_rename)
 
        /* Fall back to making a copy. */
        if (!(file = make_file(fname, NULL, &sx.st, 0, NO_FILTERS)))
-               return 1; /* the file could have disappeared */
+               return 3; /* the file could have disappeared */
 
 #ifdef SUPPORT_ACLS
        if (preserve_acls && !S_ISLNK(file->mode)) {
@@ -299,7 +312,7 @@ int make_backup(const char *fname, BOOL prefer_rename)
 #ifdef SUPPORT_XATTRS
                uncache_tmp_xattrs();
 #endif
-               return 2;
+               return 3;
        }
 
        /* Copy to backup tree if a file. */
@@ -323,7 +336,7 @@ int make_backup(const char *fname, BOOL prefer_rename)
 
        save_preserve_xattrs = preserve_xattrs;
        preserve_xattrs = 0;
-       set_file_attrs(buf, file, NULL, fname, 0);
+       set_file_attrs(buf, file, NULL, fname, ATTRS_SET_NANO);
        preserve_xattrs = save_preserve_xattrs;
 
        unmake_file(file);