+/* Structure for returning 0-terminated lists of offsets (nodes,
+ * values, etc).
+ */
+struct offset_list {
+ size_t *offsets;
+ size_t len;
+ size_t alloc;
+};
+
+static void
+init_offset_list (struct offset_list *list)
+{
+ list->len = 0;
+ list->alloc = 0;
+ list->offsets = NULL;
+}
+
+#define INIT_OFFSET_LIST(name) \
+ struct offset_list name; \
+ init_offset_list (&name)
+
+/* Preallocates the offset_list, but doesn't make the contents longer. */
+static int
+grow_offset_list (struct offset_list *list, size_t alloc)
+{
+ assert (alloc >= list->len);
+ size_t *p = realloc (list->offsets, alloc * sizeof (size_t));
+ if (p == NULL)
+ return -1;
+ list->offsets = p;
+ list->alloc = alloc;
+ return 0;
+}
+
+static int
+add_to_offset_list (struct offset_list *list, size_t offset)
+{
+ if (list->len >= list->alloc) {
+ if (grow_offset_list (list, list->alloc ? list->alloc * 2 : 4) == -1)
+ return -1;
+ }
+ list->offsets[list->len] = offset;
+ list->len++;
+ return 0;
+}
+
+static void
+free_offset_list (struct offset_list *list)
+{
+ free (list->offsets);
+}
+
+static size_t *
+return_offset_list (struct offset_list *list)
+{
+ if (add_to_offset_list (list, 0) == -1)
+ return NULL;
+ return list->offsets; /* caller frees */
+}
+
+/* Iterate over children, returning child nodes and intermediate blocks. */
+static int
+get_children (hive_h *h, hive_node_h node,
+ hive_node_h **children_ret, size_t **blocks_ret)