summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWayne Davison <wayned@samba.org>2009-04-10 16:09:39 -0700
committerWayne Davison <wayned@samba.org>2009-04-10 16:09:39 -0700
commitea53d161be54a474088df51063df128ff5da5af4 (patch)
treea9b49475719b70b107c4e483f2a59ada57454523
parent7875e6fe63805a3412cb4a8673a2dbf233631110 (diff)
downloadrsync-ea53d161be54a474088df51063df128ff5da5af4.tar.gz
Fixed an ACL/xattr corruption issue where the --backup option could cause
rsync to associate the wrong ACL/xattr information with received files.
-rw-r--r--NEWS3
-rw-r--r--acls.c38
-rw-r--r--backup.c32
-rw-r--r--xattrs.c21
4 files changed, 88 insertions, 6 deletions
diff --git a/NEWS b/NEWS
index 1e80e042..a077de62 100644
--- a/NEWS
+++ b/NEWS
@@ -34,6 +34,9 @@ Changes since 3.0.5:
- Fixed the dropping of an ACL mask when no named ACL values were present.
+ - Fixed an ACL/xattr corruption issue where the --backup option could cause
+ rsync to associate the wrong ACL/xattr information with received files.
+
- Fixed the use of --dry-run with --read-batch.
- Fixed configure's erroneous use of target.
diff --git a/acls.c b/acls.c
index 434bc61d..e2bdc4c9 100644
--- a/acls.c
+++ b/acls.c
@@ -88,6 +88,9 @@ static const rsync_acl empty_rsync_acl = {
static item_list access_acl_list = EMPTY_ITEM_LIST;
static item_list default_acl_list = EMPTY_ITEM_LIST;
+static size_t prior_access_count = (size_t)-1;
+static size_t prior_default_count = (size_t)-1;
+
/* === Calculations on ACL types === */
static const char *str_acl_type(SMB_ACL_TYPE_T type)
@@ -788,17 +791,50 @@ static int cache_rsync_acl(rsync_acl *racl, SMB_ACL_TYPE_T type, item_list *racl
/* Turn the ACL data in stat_x into cached ACL data, setting the index
* values in the file struct. */
-void cache_acl(struct file_struct *file, stat_x *sxp)
+void cache_tmp_acl(struct file_struct *file, stat_x *sxp)
{
+ if (prior_access_count == (size_t)-1)
+ prior_access_count = access_acl_list.count;
+
F_ACL(file) = cache_rsync_acl(sxp->acc_acl,
SMB_ACL_TYPE_ACCESS, &access_acl_list);
if (S_ISDIR(sxp->st.st_mode)) {
+ if (prior_default_count == (size_t)-1)
+ prior_default_count = default_acl_list.count;
F_DIR_DEFACL(file) = cache_rsync_acl(sxp->def_acl,
SMB_ACL_TYPE_DEFAULT, &default_acl_list);
}
}
+static void uncache_duo_acls(item_list *duo_list, size_t start)
+{
+ acl_duo *duo_item = duo_list->items;
+ acl_duo *duo_start = duo_item + start;
+
+ duo_item += duo_list->count;
+ duo_list->count = start;
+
+ while (duo_item-- > duo_start) {
+ rsync_acl_free(&duo_item->racl);
+ if (duo_item->sacl)
+ sys_acl_free_acl(duo_item->sacl);
+ }
+}
+
+void uncache_tmp_acls(void)
+{
+ if (prior_access_count != (size_t)-1) {
+ uncache_duo_acls(&access_acl_list, prior_access_count);
+ prior_access_count = (size_t)-1;
+ }
+
+ if (prior_default_count != (size_t)-1) {
+ uncache_duo_acls(&default_acl_list, prior_default_count);
+ prior_default_count = (size_t)-1;
+ }
+}
+
#ifndef HAVE_OSX_ACLS
static mode_t change_sacl_perms(SMB_ACL_T sacl, rsync_acl *racl, mode_t old_mode, mode_t mode)
{
diff --git a/backup.c b/backup.c
index ecc40d52..7512d921 100644
--- a/backup.c
+++ b/backup.c
@@ -148,19 +148,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 = '/';
@@ -223,20 +229,26 @@ static int keep_backup(const char *fname)
if (!(buf = get_backup_name(fname))) {
unmake_file(file);
+#ifdef SUPPORT_ACLS
+ uncache_tmp_acls();
+#endif
+#ifdef SUPPORT_XATTRS
+ uncache_tmp_xattrs();
+#endif
return 0;
}
#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
@@ -326,6 +338,12 @@ static int keep_backup(const char *fname)
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 1;
}
@@ -344,6 +362,12 @@ static int keep_backup(const char *fname)
set_file_attrs(buf, file, NULL, fname, 0);
preserve_xattrs = save_preserve_xattrs;
unmake_file(file);
+#ifdef SUPPORT_ACLS
+ uncache_tmp_acls();
+#endif
+#ifdef SUPPORT_XATTRS
+ uncache_tmp_xattrs();
+#endif
if (verbose > 1) {
rprintf(FINFO, "backed up %s to %s\n",
diff --git a/xattrs.c b/xattrs.c
index 0eb73237..674d3578 100644
--- a/xattrs.c
+++ b/xattrs.c
@@ -81,6 +81,8 @@ static char *namebuf = NULL;
static item_list empty_xattr = EMPTY_ITEM_LIST;
static item_list rsync_xal_l = EMPTY_ITEM_LIST;
+static size_t prior_xattr_count = (size_t)-1;
+
/* ------------------------------------------------------------------------- */
static void rsync_xal_free(item_list *xalp)
@@ -724,13 +726,15 @@ void receive_xattr(struct file_struct *file, int f)
/* Turn the xattr data in stat_x into cached xattr data, setting the index
* values in the file struct. */
-void cache_xattr(struct file_struct *file, stat_x *sxp)
+void cache_tmp_xattr(struct file_struct *file, stat_x *sxp)
{
int ndx;
if (!sxp->xattr)
return;
+ if (prior_xattr_count == (size_t)-1)
+ prior_xattr_count = rsync_xal_l.count;
ndx = find_matching_xattr(sxp->xattr);
if (ndx < 0)
rsync_xal_store(sxp->xattr); /* adds item to rsync_xal_l */
@@ -738,6 +742,21 @@ void cache_xattr(struct file_struct *file, stat_x *sxp)
F_XATTR(file) = ndx;
}
+void uncache_tmp_xattrs(void)
+{
+ if (prior_xattr_count != (size_t)-1) {
+ item_list *xattr_item = rsync_xal_l.items;
+ item_list *xattr_start = xattr_item + prior_xattr_count;
+ xattr_item += rsync_xal_l.count;
+ rsync_xal_l.count = prior_xattr_count;
+ while (xattr_item-- > xattr_start) {
+ rsync_xal_free(xattr_item);
+ free(xattr_item);
+ }
+ prior_xattr_count = (size_t)-1;
+ }
+}
+
static int rsync_xal_set(const char *fname, item_list *xalp,
const char *fnamecmp, stat_x *sxp)
{