+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;
+}
+
+/* Initialize a `struct sd_set' mapping from SHA1 message digests of security
+ * descriptors to indices into the security descriptors table of the WIM image
+ * (security IDs). */
+int
+init_sd_set(struct wim_sd_set *sd_set, struct wim_security_data *sd)