- Use F_OWNER() and F_GROUP() instead of F_UID() and F_GID().
[rsync/rsync.git] / acls.c
diff --git a/acls.c b/acls.c
index e73eec3..af554cb 100644 (file)
--- a/acls.c
+++ b/acls.c
@@ -6,9 +6,8 @@
  * 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
@@ -34,6 +33,7 @@ extern int protocol_version;
 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)
@@ -41,6 +41,8 @@ extern int inc_recurse;
 #define XMIT_MASK_OBJ (1<<4)
 #define XMIT_OTHER_OBJ (1<<5)
 
+#define NO_ENTRY ((uchar)0x80)
+
 /* === ACL structures === */
 
 typedef struct {
@@ -58,7 +60,6 @@ typedef struct {
        uchar len;
 } idname;
 
-#define NO_ENTRY ((uchar)0x80)
 typedef struct rsync_acl {
        ida_entries users;
        ida_entries groups;
@@ -510,7 +511,7 @@ static int get_rsync_acl(const char *fname, rsync_acl *racl,
                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);
@@ -560,11 +561,11 @@ static void send_ida_entries(const ida_entries *idal, int user_names, int f)
        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);
@@ -581,7 +582,7 @@ static void send_rsync_acl(rsync_acl *racl, SMB_ACL_TYPE_T type,
        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);
@@ -631,7 +632,6 @@ static void send_rsync_acl(rsync_acl *racl, SMB_ACL_TYPE_T type,
  * 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);
@@ -674,11 +674,10 @@ static uchar recv_acl_access(uchar *name_follows_val, int f)
 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;
@@ -686,20 +685,21 @@ static uchar recv_ida_entries(ida_entries *ent, int user_names, int f)
        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;
@@ -715,11 +715,11 @@ static int recv_rsync_acl(item_list *racl_list, SMB_ACL_TYPE_T type, int f)
        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);
        }
 
@@ -969,63 +969,29 @@ int set_acl(const char *fname, const struct file_struct *file, statx *sxp)
        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(). */
@@ -1044,7 +1010,9 @@ int default_perms_for_dir(const char *dir)
        if (sacl == NULL) {
                /* Couldn't get an ACL.  Darn. */
                switch (errno) {
+#ifdef ENOTSUP
                case ENOTSUP:
+#endif
                case ENOSYS:
                        /* No ACLs are available. */
                        break;