*
* Copyright (C) 1996 Andrew Tridgell
* Copyright (C) 1996 Paul Mackerras
- * Copyright (C) 2006 Wayne Davison
+ * Copyright (C) 2006-2009 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
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)
{
- return type == SMB_ACL_TYPE_ACCESS ? "SMB_ACL_TYPE_ACCESS"
- : type == SMB_ACL_TYPE_DEFAULT ? "SMB_ACL_TYPE_DEFAULT"
- : "unknown SMB_ACL_TYPE_T";
+ switch (type) {
+ case SMB_ACL_TYPE_ACCESS:
+#ifdef HAVE_OSX_ACLS
+ return "ACL_TYPE_EXTENDED";
+#else
+ return "ACL_TYPE_ACCESS";
+#endif
+ case SMB_ACL_TYPE_DEFAULT:
+ return "ACL_TYPE_DEFAULT";
+ default:
+ break;
+ }
+ return "unknown ACL type!";
}
static int calc_sacl_entries(const rsync_acl *racl)
else {
if (racl->group_obj == racl->mask_obj)
racl->group_obj = NO_ENTRY;
- racl->mask_obj = NO_ENTRY;
+ if (racl->names.count != 0)
+ racl->mask_obj = NO_ENTRY;
}
racl->other_obj = NO_ENTRY;
}
ida->access = access;
}
if (rc) {
- rsyserr(FERROR, errno, "unpack_smb_acl: %s()", errfun);
+ rsyserr(FERROR_XFER, errno, "unpack_smb_acl: %s()", errfun);
rsync_acl_free(racl);
return False;
}
static int store_access_in_entry(uint32 access, SMB_ACL_ENTRY_T entry)
{
if (sys_acl_set_access_bits(entry, access)) {
- rsyserr(FERROR, errno, "store_access_in_entry sys_acl_set_access_bits()");
+ rsyserr(FERROR_XFER, errno, "store_access_in_entry sys_acl_set_access_bits()");
return -1;
}
return 0;
SMB_ACL_ENTRY_T entry;
if (!(*smb_acl = sys_acl_init(calc_sacl_entries(racl)))) {
- rsyserr(FERROR, errno, "pack_smb_acl: sys_acl_init()");
+ rsyserr(FERROR_XFER, errno, "pack_smb_acl: sys_acl_init()");
return False;
}
break;
#endif
COE( sys_acl_create_entry,(smb_acl, &entry) );
- COE( sys_acl_set_info,(entry,
-#ifdef SMB_ACL_NEED_SORT
- SMB_ACL_USER,
-#else
- ida->access & NAME_IS_USER ? SMB_ACL_USER : SMB_ACL_GROUP,
-#endif
- ida->access & ~NAME_IS_USER, ida->id) );
+ COE( sys_acl_set_info,
+ (entry,
+ ida->access & NAME_IS_USER ? SMB_ACL_USER : SMB_ACL_GROUP,
+ ida->access & ~NAME_IS_USER, ida->id) );
}
#ifndef HAVE_OSX_ACLS
#ifdef DEBUG
if (sys_acl_valid(*smb_acl) < 0)
- rprintf(FERROR, "pack_smb_acl: warning: system says the ACL I packed is invalid\n");
+ rprintf(FERROR_XFER, "pack_smb_acl: warning: system says the ACL I packed is invalid\n");
#endif
return True;
error_exit:
if (errfun) {
- rsyserr(FERROR, errno, "pack_smb_acl %s()", errfun);
+ rsyserr(FERROR_XFER, errno, "pack_smb_acl %s()", errfun);
}
sys_acl_free_acl(*smb_acl);
return False;
if ((buf = get_xattr_acl(fname, type == SMB_ACL_TYPE_ACCESS, &len)) == NULL)
return 0;
cnt = (len - 4*4) / (4+4);
- if (len < 4*4 || len != (size_t)cnt*(4+4) + 4*4)
+ if (len < 4*4 || len != (size_t)cnt*(4+4) + 4*4) {
+ free(buf);
return -1;
+ }
racl->user_obj = IVAL(buf, 0);
racl->group_obj = IVAL(buf, 4);
if (type == SMB_ACL_TYPE_ACCESS)
rsync_acl_fake_perms(racl, mode);
} else {
- rsyserr(FERROR, errno, "get_acl: sys_acl_get_file(%s, %s)",
+ rsyserr(FERROR_XFER, errno, "get_acl: sys_acl_get_file(%s, %s)",
fname, str_acl_type(type));
return -1;
}
for (ida = idal->idas; count--; ida++) {
uint32 xbits = ida->access << 2;
- char *name;
+ const char *name;
if (ida->access & NAME_IS_USER) {
xbits |= XFLAG_NAME_IS_USER;
name = add_uid(ida->id);
access |= NAME_IS_USER;
} else if (am_root >= 0 && access & ~SMB_ACL_VALID_OBJ_BITS) {
value_error:
- rprintf(FERROR, "recv_acl_access: value out of range: %x\n",
+ rprintf(FERROR_XFER, "recv_acl_access: value out of range: %x\n",
access);
exit_cleanup(RERR_STREAMIO);
}
int ndx = read_varint(f);
if (ndx < 0 || (size_t)ndx > racl_list->count) {
- rprintf(FERROR, "recv_acl_index: %s ACL index %d > %d\n",
+ rprintf(FERROR_XFER, "recv_acl_index: %s ACL index %d > %d\n",
str_acl_type(type), ndx, (int)racl_list->count);
exit_cleanup(RERR_STREAMIO);
}
/* If we received a superfluous mask, throw it away. */
duo_item->racl.mask_obj = NO_ENTRY;
#else
- if (!duo_item->racl.names.count) {
- /* If we received a superfluous mask, throw it away. */
- if (duo_item->racl.mask_obj != NO_ENTRY) {
- /* Mask off the group perms with it first. */
- duo_item->racl.group_obj &= duo_item->racl.mask_obj | NO_ENTRY;
- duo_item->racl.mask_obj = NO_ENTRY;
- }
- } else if (duo_item->racl.mask_obj == NO_ENTRY) /* Must be non-empty with lists. */
+ if (duo_item->racl.names.count && duo_item->racl.mask_obj == NO_ENTRY) /* Must be non-empty with lists. */
duo_item->racl.mask_obj = (computed_mask_bits | duo_item->racl.group_obj) & ~NO_ENTRY;
#endif
/* 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)
{
if (rc) {
error_exit:
if (errfun) {
- rsyserr(FERROR, errno, "change_sacl_perms: %s()",
+ rsyserr(FERROR_XFER, errno, "change_sacl_perms: %s()",
errfun);
}
return (mode_t)~0;
#endif
rc = sys_acl_delete_def_file(fname);
if (rc < 0) {
- rsyserr(FERROR, errno, "set_acl: sys_acl_delete_def_file(%s)",
+ rsyserr(FERROR_XFER, errno, "set_acl: sys_acl_delete_def_file(%s)",
fname);
return -1;
}
}
#endif
if (sys_acl_set_file(fname, type, duo_item->sacl) < 0) {
- rsyserr(FERROR, errno, "set_acl: sys_acl_set_file(%s, %s)",
- fname, str_acl_type(type));
+ rsyserr(FERROR_XFER, errno, "set_acl: sys_acl_set_file(%s, %s)",
+ fname, str_acl_type(type));
return -1;
}
if (type == SMB_ACL_TYPE_ACCESS)
}
/* Otherwise fall through. */
default:
- rprintf(FERROR, "default_perms_for_dir: sys_acl_get_file(%s, %s): %s, falling back on umask\n",
+ rprintf(FWARNING,
+ "default_perms_for_dir: sys_acl_get_file(%s, %s): %s, falling back on umask\n",
dir, str_acl_type(SMB_ACL_TYPE_DEFAULT), strerror(errno));
}
return perms;
ok = unpack_smb_acl(sacl, &racl);
sys_acl_free_acl(sacl);
if (!ok) {
- rprintf(FERROR, "default_perms_for_dir: unpack_smb_acl failed, falling back on umask\n");
+ rprintf(FWARNING, "default_perms_for_dir: unpack_smb_acl failed, falling back on umask\n");
return perms;
}