Skip to content

Commit

Permalink
Fixed an ACL/xattr corruption issue where the --backup option could c…
Browse files Browse the repository at this point in the history
…ause

rsync to associate the wrong ACL/xattr information with received files.
  • Loading branch information
Wayne Davison committed Apr 10, 2009
1 parent a055dbd commit cb19751
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 6 deletions.
38 changes: 37 additions & 1 deletion acls.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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)
{
Expand Down
32 changes: 28 additions & 4 deletions backup.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 = '/';
Expand Down Expand Up @@ -219,14 +225,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
Expand Down Expand Up @@ -313,6 +319,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;
}

Expand All @@ -322,6 +334,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;
Expand All @@ -333,6 +351,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)) {
Expand Down
21 changes: 20 additions & 1 deletion xattrs.c
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,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)
Expand Down Expand Up @@ -725,20 +727,37 @@ 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 */

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)
{
Expand Down

0 comments on commit cb19751

Please sign in to comment.