* Copyright (C) 2006 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
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
extern int numeric_ids;
extern int inc_recurse;
+/* Flags used to indicate what items are being transmitted for an entry. */
#define XMIT_USER_OBJ (1<<0)
#define XMIT_USER_LIST (1<<1)
#define XMIT_GROUP_OBJ (1<<2)
#define XMIT_MASK_OBJ (1<<4)
#define XMIT_OTHER_OBJ (1<<5)
+#define NO_ENTRY ((uchar)0x80)
+
/* === ACL structures === */
typedef struct {
uchar len;
} idname;
-#define NO_ENTRY ((uchar)0x80)
typedef struct rsync_acl {
ida_entries users;
ida_entries groups;
if (!ok) {
return -1;
}
- } else if (errno == ENOTSUP || errno == ENOSYS) {
+ } else if (no_acl_syscall_error(errno)) {
/* ACLs are not supported, so pretend we have a basic ACL. */
if (type == SMB_ACL_TYPE_ACCESS)
rsync_acl_fake_perms(racl, mode);
id_access *ida;
size_t count = idal->count;
- write_abbrevint(f, idal->count);
+ write_varint(f, idal->count);
for (ida = idal->idas; count--; ida++) {
char *name = user_names ? add_uid(ida->id) : add_gid(ida->id);
- write_abbrevint(f, ida->id);
+ write_varint(f, ida->id);
if (inc_recurse && name) {
int len = strlen(name);
write_byte(f, ida->access | (uchar)0x80);
int ndx = find_matching_rsync_acl(racl, type, racl_list);
/* Send 0 (-1 + 1) to indicate that literal ACL data follows. */
- write_abbrevint(f, ndx + 1);
+ write_varint(f, ndx + 1);
if (ndx < 0) {
rsync_acl *new_racl = EXPAND_ITEM_LIST(racl_list, rsync_acl, 1000);
* This also frees the ACL data. */
void send_acl(statx *sxp, int f)
{
-
if (!sxp->acc_acl) {
sxp->acc_acl = create_racl();
rsync_acl_fake_perms(sxp->acc_acl, sxp->st.st_mode);
static uchar recv_ida_entries(ida_entries *ent, int user_names, int f)
{
uchar computed_mask_bits = 0;
- uchar has_name;
- int i, count = read_abbrevint(f);
+ int i, count = read_varint(f);
if (count) {
- if (!(ent->idas = new_array(id_access, ent->count)))
+ if (!(ent->idas = new_array(id_access, count)))
out_of_memory("recv_ida_entries");
} else
ent->idas = NULL;
ent->count = count;
for (i = 0; i < count; i++) {
- id_t id = read_abbrevint(f);
+ uchar has_name;
+ id_t id = read_varint(f);
int access = recv_acl_access(&has_name, f);
if (has_name) {
if (user_names)
id = recv_user_name(f, id);
else
- id = recv_group_name(f, id);
+ id = recv_group_name(f, id, NULL);
} else if (user_names) {
if (inc_recurse && am_root && !numeric_ids)
id = match_uid(id);
} else {
if (inc_recurse && (!am_root || !numeric_ids))
- id = match_gid(id);
+ id = match_gid(id, NULL);
}
ent->idas[i].id = id;
uchar computed_mask_bits = 0;
acl_duo *duo_item;
uchar flags;
- int ndx = read_abbrevint(f);
+ 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",
- str_acl_type(type), ndx, racl_list->count);
+ str_acl_type(type), ndx, (int)racl_list->count);
exit_cleanup(RERR_STREAMIO);
}
return unchanged;
}
-/* === Enumeration functions for uid mapping === */
-
-/* Context -- one and only one. Should be cycled through once on uid
- * mapping and once on gid mapping. */
-static item_list *_enum_racl_lists[] = {
- &access_acl_list, &default_acl_list, NULL
-};
-
-static item_list **enum_racl_list = &_enum_racl_lists[0];
-static int enum_ida_index = 0;
-static size_t enum_racl_index = 0;
-
-/* This returns the next tag_type id from the given ACL for the next entry,
- * or it returns 0 if there are no more tag_type ids in the acl. */
-static id_t *next_ace_id(SMB_ACL_TAG_T tag_type, const rsync_acl *racl)
-{
- const ida_entries *idal = tag_type == SMB_ACL_USER ? &racl->users : &racl->groups;
- if (enum_ida_index < idal->count) {
- id_access *ida = &idal->idas[enum_ida_index++];
- return &ida->id;
- }
- enum_ida_index = 0;
- return NULL;
-}
-
-static id_t *next_acl_id(SMB_ACL_TAG_T tag_type, const item_list *racl_list)
-{
- for (; enum_racl_index < racl_list->count; enum_racl_index++) {
- id_t *id;
- acl_duo *duo_item = racl_list->items;
- duo_item += enum_racl_index;
- if ((id = next_ace_id(tag_type, &duo_item->racl)) != NULL)
- return id;
- }
- enum_racl_index = 0;
- return NULL;
-}
-
-static id_t *next_acl_list_id(SMB_ACL_TAG_T tag_type)
+/* Non-incremental recursion needs to convert all the received IDs.
+ * This is done in a single pass after receiving the whole file-list. */
+static void match_racl_ids(const item_list *racl_list)
{
- for (; *enum_racl_list; enum_racl_list++) {
- id_t *id = next_acl_id(tag_type, *enum_racl_list);
- if (id)
- return id;
+ int list_cnt, name_cnt;
+ acl_duo *duo_item = racl_list->items;
+ for (list_cnt = racl_list->count; list_cnt--; duo_item++) {
+ ida_entries *idal = &duo_item->racl.users;
+ id_access *ida = idal->idas;
+ for (name_cnt = idal->count; name_cnt--; ida++)
+ ida->id = match_uid(ida->id);
+
+ idal = &duo_item->racl.groups;
+ ida = idal->idas;
+ for (name_cnt = idal->count; name_cnt--; ida++)
+ ida->id = match_gid(ida->id, NULL);
}
- enum_racl_list = &_enum_racl_lists[0];
- return NULL;
}
-id_t *next_acl_uid()
+void match_acl_ids(void)
{
- return next_acl_list_id(SMB_ACL_USER);
-}
-
-id_t *next_acl_gid()
-{
- return next_acl_list_id(SMB_ACL_GROUP);
+ match_racl_ids(&access_acl_list);
+ match_racl_ids(&default_acl_list);
}
/* This is used by dest_mode(). */
if (sacl == NULL) {
/* Couldn't get an ACL. Darn. */
switch (errno) {
+#ifdef ENOTSUP
case ENOTSUP:
+#endif
case ENOSYS:
/* No ACLs are available. */
break;