From e9489cd6cb380b30727bd3d074eacc59abca080e Mon Sep 17 00:00:00 2001 From: Wayne Davison Date: Sat, 17 May 2008 09:30:46 -0700 Subject: [PATCH] Fixed several issues with preserving xattrs when using --backup. --- backup.c | 3 +++ generator.c | 7 +++++++ rsync.c | 7 +++++-- t_stub.c | 6 ++++++ util.c | 8 ++++++++ xattrs.c | 42 ++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 71 insertions(+), 2 deletions(-) diff --git a/backup.c b/backup.c index 22cfc712..c3f66ebe 100644 --- 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; + int save_preserve_xattrs = preserve_xattrs; int kept = 0; int ret_code; @@ -338,7 +339,9 @@ static int keep_backup(const char *fname) robust_unlink(fname); /* Just in case... */ } } + preserve_xattrs = 0; set_file_attrs(buf, file, NULL, fname, 0); + preserve_xattrs = save_preserve_xattrs; unmake_file(file); if (verbose > 1) { diff --git a/generator.c b/generator.c index 16f167e5..27e5b97d 100644 --- a/generator.c +++ b/generator.c @@ -1944,9 +1944,16 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, cleanup: if (back_file) { + int save_preserve_xattrs = preserve_xattrs; 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); + preserve_xattrs = save_preserve_xattrs; if (verbose > 1) { rprintf(FINFO, "backed up %s to %s\n", fname, backupptr); diff --git a/rsync.c b/rsync.c index 48894c97..9921da04 100644 --- a/rsync.c +++ b/rsync.c @@ -561,8 +561,11 @@ int finish_transfer(const char *fname, const char *fnametmp, 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, diff --git a/t_stub.c b/t_stub.c index 44131a9f..6a205fa3 100644 --- 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 preserve_xattrs = 0; mode_t orig_umask = 002; char *partial_dir; char *module_dir; @@ -69,6 +70,11 @@ struct filter_list_struct daemon_filter_list; return -1; } + int copy_xattrs(UNUSED(const char *source), UNUSED(const char *dest)) +{ + return -1; +} + char *lp_name(UNUSED(int mod)) { return NULL; diff --git a/util.c b/util.c index c4375175..c71830bd 100644 --- 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 preserve_xattrs; 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. + * 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. */ @@ -339,6 +342,11 @@ int copy_file(const char *source, const char *dest, int ofd, return -1; } +#ifdef SUPPORT_XATTRS + if (preserve_xattrs) + copy_xattrs(source, dest); +#endif + return 0; } diff --git a/xattrs.c b/xattrs.c index 552a63b3..b6a82e42 100644 --- a/xattrs.c +++ b/xattrs.c @@ -288,6 +288,48 @@ int get_xattr(const char *fname, stat_x *sxp) 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; -- 2.34.1