extern int orig_umask;
extern int numeric_ids;
extern int inc_recurse;
+extern int preserve_devices;
+extern int preserve_specials;
/* Flags used to indicate what items are being transmitted for an entry. */
#define XMIT_USER_OBJ (1<<0)
/* Removes the permission-bit entries from the ACL because these
* can be reconstructed from the file's mode. */
-static void rsync_acl_strip_perms(rsync_acl *racl)
+static void rsync_acl_strip_perms(stat_x *sxp)
{
+ rsync_acl *racl = sxp->acc_acl;
+
racl->user_obj = NO_ENTRY;
if (racl->mask_obj == NO_ENTRY)
racl->group_obj = NO_ENTRY;
else {
- if (racl->group_obj == racl->mask_obj)
+ int group_perms = (sxp->st.st_mode >> 3) & 7;
+ if (racl->group_obj == group_perms)
racl->group_obj = NO_ENTRY;
- if (racl->names.count != 0)
+#ifndef HAVE_SOLARIS_ACLS
+ if (racl->names.count != 0 && racl->mask_obj == group_perms)
racl->mask_obj = NO_ENTRY;
+#endif
}
racl->other_obj = NO_ENTRY;
}
/* Truncate the temporary list now that its idas have been saved. */
temp_ida_list.count = 0;
-#ifdef ACLS_NEED_MASK
- if (!racl->names.count && racl->mask_obj != NO_ENTRY) {
- /* Throw away a superfluous mask, but mask off the
- * group perms with it first. */
- racl->group_obj &= racl->mask_obj;
- racl->mask_obj = NO_ENTRY;
- }
-#endif
-
return True;
}
}
racl->user_obj = IVAL(buf, 0);
+ if (racl->user_obj == NO_ENTRY)
+ racl->user_obj = (mode >> 6) & 7;
racl->group_obj = IVAL(buf, 4);
+ if (racl->group_obj == NO_ENTRY)
+ racl->group_obj = (mode >> 3) & 7;
racl->mask_obj = IVAL(buf, 8);
racl->other_obj = IVAL(buf, 12);
+ if (racl->other_obj == NO_ENTRY)
+ racl->other_obj = mode & 7;
if (cnt) {
char *bp = buf + 4*4;
int get_acl(const char *fname, stat_x *sxp)
{
sxp->acc_acl = create_racl();
+
+ if (S_ISREG(sxp->st.st_mode) || S_ISDIR(sxp->st.st_mode)) {
+ /* Everyone supports this. */
+ } else if (S_ISLNK(sxp->st.st_mode)) {
+ return 0;
+ } else if (IS_SPECIAL(sxp->st.st_mode)) {
+#ifndef NO_SPECIAL_ACLS
+ if (!preserve_specials)
+#endif
+ return 0;
+ } else if (IS_DEVICE(sxp->st.st_mode)) {
+#ifndef NO_DEVICE_ACLS
+ if (!preserve_devices)
+#endif
+ return 0;
+ }
+
if (get_rsync_acl(fname, sxp->acc_acl, SMB_ACL_TYPE_ACCESS,
sxp->st.st_mode) < 0) {
free_acl(sxp);
const char *name;
if (ida->access & NAME_IS_USER) {
xbits |= XFLAG_NAME_IS_USER;
- name = add_uid(ida->id);
+ name = numeric_ids ? NULL : add_uid(ida->id);
} else
- name = add_gid(ida->id);
+ name = numeric_ids ? NULL : add_gid(ida->id);
write_varint(f, ida->id);
if (inc_recurse && name) {
int len = strlen(name);
rsync_acl_fake_perms(sxp->acc_acl, sxp->st.st_mode);
}
/* Avoid sending values that can be inferred from other data. */
- rsync_acl_strip_perms(sxp->acc_acl);
+ rsync_acl_strip_perms(sxp);
send_rsync_acl(f, sxp->acc_acl, SMB_ACL_TYPE_ACCESS, &access_acl_list);
return computed_mask_bits & ~NO_ENTRY;
}
-static int recv_rsync_acl(int f, item_list *racl_list, SMB_ACL_TYPE_T type)
+static int recv_rsync_acl(int f, item_list *racl_list, SMB_ACL_TYPE_T type, mode_t mode)
{
uchar computed_mask_bits = 0;
acl_duo *duo_item;
/* If we received a superfluous mask, throw it away. */
duo_item->racl.mask_obj = NO_ENTRY;
#else
- 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;
+ if (duo_item->racl.names.count && duo_item->racl.mask_obj == NO_ENTRY) {
+ /* Mask must be non-empty with lists. */
+ if (type == SMB_ACL_TYPE_ACCESS)
+ computed_mask_bits = (mode >> 3) & 7;
+ else
+ computed_mask_bits |= duo_item->racl.group_obj & ~NO_ENTRY;
+ duo_item->racl.mask_obj = computed_mask_bits;
+ }
#endif
duo_item->sacl = NULL;
/* Receive the ACL info the sender has included for this file-list entry. */
void receive_acl(int f, struct file_struct *file)
{
- F_ACL(file) = recv_rsync_acl(f, &access_acl_list, SMB_ACL_TYPE_ACCESS);
+ F_ACL(file) = recv_rsync_acl(f, &access_acl_list, SMB_ACL_TYPE_ACCESS, file->mode);
if (S_ISDIR(file->mode))
- F_DIR_DEFACL(file) = recv_rsync_acl(f, &default_acl_list, SMB_ACL_TYPE_DEFAULT);
+ F_DIR_DEFACL(file) = recv_rsync_acl(f, &default_acl_list, SMB_ACL_TYPE_DEFAULT, 0);
}
static int cache_rsync_acl(rsync_acl *racl, SMB_ACL_TYPE_T type, item_list *racl_list)
COE2( store_access_in_entry,((mode >> 3) & 7, entry) );
break;
case SMB_ACL_MASK:
+#ifndef HAVE_SOLARIS_ACLS
#ifndef ACLS_NEED_MASK
/* mask is only empty when we don't need it. */
if (racl->mask_obj == NO_ENTRY)
break;
#endif
COE2( store_access_in_entry,((mode >> 3) & 7, entry) );
+#endif
break;
case SMB_ACL_OTHER:
COE2( store_access_in_entry,(mode & 7, entry) );
if (sacl == NULL) {
/* Couldn't get an ACL. Darn. */
switch (errno) {
+ case EINVAL:
+ /* If SMB_ACL_TYPE_DEFAULT isn't valid, then the ACLs must be non-POSIX. */
+ break;
#ifdef ENOTSUP
case ENOTSUP:
#endif