Fixed several issues with preserving xattrs when using --backup.
authorWayne Davison <wayned@samba.org>
Sat, 17 May 2008 16:30:46 +0000 (09:30 -0700)
committerWayne Davison <wayned@samba.org>
Sat, 17 May 2008 16:35:46 +0000 (09:35 -0700)
backup.c
generator.c
rsync.c
t_stub.c
util.c
xattrs.c

index 22cfc71..c3f66eb 100644 (file)
--- a/backup.c
+++ b/backup.c
@@ -204,6 +204,7 @@ static int keep_backup(const char *fname)
        stat_x sx;
        struct file_struct *file;
        char *buf;
        stat_x sx;
        struct file_struct *file;
        char *buf;
+       int save_preserve_xattrs = preserve_xattrs;
        int kept = 0;
        int ret_code;
 
        int kept = 0;
        int ret_code;
 
@@ -338,7 +339,9 @@ static int keep_backup(const char *fname)
                        robust_unlink(fname); /* Just in case... */
                }
        }
                        robust_unlink(fname); /* Just in case... */
                }
        }
+       preserve_xattrs = 0;
        set_file_attrs(buf, file, NULL, fname, 0);
        set_file_attrs(buf, file, NULL, fname, 0);
+       preserve_xattrs = save_preserve_xattrs;
        unmake_file(file);
 
        if (verbose > 1) {
        unmake_file(file);
 
        if (verbose > 1) {
index 16f167e..27e5b97 100644 (file)
@@ -1944,9 +1944,16 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
 
   cleanup:
        if (back_file) {
 
   cleanup:
        if (back_file) {
+               int save_preserve_xattrs = preserve_xattrs;
                if (f_copy >= 0)
                        close(f_copy);
                if (f_copy >= 0)
                        close(f_copy);
+#ifdef SUPPORT_XATTRS
+               if (preserve_xattrs)
+                       copy_xattrs(fname, backupptr);
+#endif
+               preserve_xattrs = 0;
                set_file_attrs(backupptr, back_file, NULL, NULL, 0);
                set_file_attrs(backupptr, back_file, NULL, NULL, 0);
+               preserve_xattrs = save_preserve_xattrs;
                if (verbose > 1) {
                        rprintf(FINFO, "backed up %s to %s\n",
                                fname, backupptr);
                if (verbose > 1) {
                        rprintf(FINFO, "backed up %s to %s\n",
                                fname, backupptr);
diff --git a/rsync.c b/rsync.c
index 48894c9..9921da0 100644 (file)
--- a/rsync.c
+++ b/rsync.c
@@ -561,8 +561,11 @@ int finish_transfer(const char *fname, const char *fnametmp,
                goto do_set_file_attrs;
        }
 
                goto do_set_file_attrs;
        }
 
-       if (make_backups > 0 && overwriting_basis && !make_backup(fname))
-               return 1;
+       if (make_backups > 0 && overwriting_basis) {
+               if (!make_backup(fname))
+                       return 1;
+               fnamecmp = get_backup_name(fname);
+       }
 
        /* Change permissions before putting the file into place. */
        set_file_attrs(fnametmp, file, NULL, fnamecmp,
 
        /* Change permissions before putting the file into place. */
        set_file_attrs(fnametmp, file, NULL, fnamecmp,
index 44131a9..6a205fa 100644 (file)
--- a/t_stub.c
+++ b/t_stub.c
@@ -26,6 +26,7 @@ int module_id = -1;
 int relative_paths = 0;
 int human_readable = 0;
 int module_dirlen = 0;
 int relative_paths = 0;
 int human_readable = 0;
 int module_dirlen = 0;
+int preserve_xattrs = 0;
 mode_t orig_umask = 002;
 char *partial_dir;
 char *module_dir;
 mode_t orig_umask = 002;
 char *partial_dir;
 char *module_dir;
@@ -69,6 +70,11 @@ struct filter_list_struct daemon_filter_list;
        return -1;
 }
 
        return -1;
 }
 
+ int copy_xattrs(UNUSED(const char *source), UNUSED(const char *dest))
+{
+       return -1;
+}
+
  char *lp_name(UNUSED(int mod))
 {
        return NULL;
  char *lp_name(UNUSED(int mod))
 {
        return NULL;
diff --git a/util.c b/util.c
index c437517..c71830b 100644 (file)
--- a/util.c
+++ b/util.c
@@ -29,6 +29,7 @@ extern int module_id;
 extern int modify_window;
 extern int relative_paths;
 extern int human_readable;
 extern int modify_window;
 extern int relative_paths;
 extern int human_readable;
+extern int preserve_xattrs;
 extern char *module_dir;
 extern unsigned int module_dirlen;
 extern mode_t orig_umask;
 extern char *module_dir;
 extern unsigned int module_dirlen;
 extern mode_t orig_umask;
@@ -264,6 +265,8 @@ static int safe_read(int desc, char *ptr, size_t len)
 
 /* Copy a file.  If ofd < 0, copy_file unlinks and opens the "dest" file.
  * Otherwise, it just writes to and closes the provided file descriptor.
 
 /* Copy a file.  If ofd < 0, copy_file unlinks and opens the "dest" file.
  * Otherwise, it just writes to and closes the provided file descriptor.
+ * In either case, if --xattrs are being preserved, the dest file will
+ * have its xattrs set from the source file.
  *
  * This is used in conjunction with the --temp-dir, --backup, and
  * --copy-dest options. */
  *
  * This is used in conjunction with the --temp-dir, --backup, and
  * --copy-dest options. */
@@ -339,6 +342,11 @@ int copy_file(const char *source, const char *dest, int ofd,
                return -1;
        }
 
                return -1;
        }
 
+#ifdef SUPPORT_XATTRS
+       if (preserve_xattrs)
+               copy_xattrs(source, dest);
+#endif
+
        return 0;
 }
 
        return 0;
 }
 
index 552a63b..b6a82e4 100644 (file)
--- a/xattrs.c
+++ b/xattrs.c
@@ -288,6 +288,48 @@ int get_xattr(const char *fname, stat_x *sxp)
        return 0;
 }
 
        return 0;
 }
 
+int copy_xattrs(const char *source, const char *dest)
+{
+       ssize_t list_len, name_len;
+       size_t datum_len;
+       char *name, *ptr;
+#ifdef HAVE_LINUX_XATTRS
+       int user_only = am_sender ? 0 : !am_root;
+#endif
+
+       /* This puts the name list into the "namebuf" buffer. */
+       if ((list_len = get_xattr_names(source)) < 0)
+               return -1;
+
+       for (name = namebuf; list_len > 0; name += name_len) {
+               name_len = strlen(name) + 1;
+               list_len -= name_len;
+
+#ifdef HAVE_LINUX_XATTRS
+               /* We always ignore the system namespace, and non-root
+                * ignores everything but the user namespace. */
+               if (user_only ? !HAS_PREFIX(name, USER_PREFIX)
+                             : HAS_PREFIX(name, SYSTEM_PREFIX))
+                       continue;
+#endif
+
+               datum_len = 0;
+               if (!(ptr = get_xattr_data(source, name, &datum_len, 0)))
+                       return -1;
+               if (sys_lsetxattr(dest, name, ptr, datum_len) < 0) {
+                       int save_errno = errno ? errno : EINVAL;
+                       rsyserr(FERROR_XFER, errno,
+                               "rsync_xal_set: lsetxattr(\"%s\",\"%s\") failed",
+                               dest, name);
+                       errno = save_errno;
+                       return -1;
+               }
+               free(ptr);
+       }
+
+       return 0;
+}
+
 static int find_matching_xattr(item_list *xalp)
 {
        size_t i, j;
 static int find_matching_xattr(item_list *xalp)
 {
        size_t i, j;