+ struct avl_tree_node *res;
+ struct sd_node dummy;
+
+ copy_hash(dummy.hash, hash);
+ res = avl_tree_lookup_node(set->root, &dummy.index_node,
+ _avl_cmp_nodes_by_hash);
+ if (!res)
+ return -1;
+ return SD_NODE(res)->security_id;
+}
+
+/*
+ * Adds a security descriptor to the indexed security descriptor set as well as
+ * the corresponding `struct wim_security_data', and returns the new security
+ * ID; or, if there is an existing security descriptor that is the same, return
+ * the security ID for it. If a new security descriptor cannot be allocated,
+ * return -1.
+ */
+s32
+sd_set_add_sd(struct wim_sd_set *sd_set, const char *descriptor, size_t size)
+{
+ u8 hash[SHA1_HASH_SIZE];
+ s32 security_id;
+ struct sd_node *new;
+ u8 **descriptors;
+ u64 *sizes;
+ u8 *descr_copy;
+ struct wim_security_data *sd;
+ bool bret;
+
+ sha1_buffer(descriptor, size, hash);
+
+ security_id = lookup_sd(sd_set, hash);
+ if (security_id >= 0) /* Identical descriptor already exists */
+ goto out;
+
+ /* Need to add a new security descriptor */
+ security_id = -1;
+
+ new = MALLOC(sizeof(*new));
+ if (!new)
+ goto out;
+
+ descr_copy = memdup(descriptor, size);
+ if (!descr_copy)
+ goto out_free_node;
+
+ sd = sd_set->sd;
+ new->security_id = sd->num_entries;
+ copy_hash(new->hash, hash);
+
+ /* There typically are only a few dozen security descriptors in a
+ * directory tree, so expanding the array of security descriptors by
+ * only 1 extra space each time should not be a problem. */
+ descriptors = REALLOC(sd->descriptors,
+ (sd->num_entries + 1) * sizeof(sd->descriptors[0]));
+ if (!descriptors)
+ goto out_free_descr;
+ sd->descriptors = descriptors;
+ sizes = REALLOC(sd->sizes,
+ (sd->num_entries + 1) * sizeof(sd->sizes[0]));
+ if (!sizes)
+ goto out_free_descr;
+ sd->sizes = sizes;
+ sd->descriptors[sd->num_entries] = descr_copy;
+ sd->sizes[sd->num_entries] = size;
+ sd->num_entries++;
+ bret = insert_sd_node(sd_set, new);
+ wimlib_assert(bret);
+ security_id = new->security_id;
+ goto out;
+out_free_descr:
+ FREE(descr_copy);
+out_free_node:
+ FREE(new);
+out:
+ return security_id;