+static int
+compare_links (const void *av, const void *bv)
+{
+ const struct rpm_name *a = av;
+ const struct rpm_name *b = bv;
+ return memcmp (a->link, b->link, 4);
+}
+
+static int
+read_rpm_name (guestfs_h *g,
+ const unsigned char *key, size_t keylen,
+ const unsigned char *value, size_t valuelen,
+ void *listv)
+{
+ struct rpm_names_list *list = listv;
+ char *name;
+
+ /* Ignore bogus entries. */
+ if (keylen == 0 || valuelen < 4)
+ return 0;
+
+ /* The name (key) field won't be NUL-terminated, so we must do that. */
+ name = safe_malloc (g, keylen+1);
+ memcpy (name, key, keylen);
+ name[keylen] = '\0';
+
+ list->names = safe_realloc (g, list->names,
+ (list->len + 1) * sizeof (struct rpm_name));
+ list->names[list->len].name = name;
+ memcpy (list->names[list->len].link, value, 4);
+ list->len++;
+
+ return 0;
+}
+
+struct read_package_data {
+ struct rpm_names_list *list;
+ struct guestfs_application_list *apps;
+};
+
+static int
+read_package (guestfs_h *g,
+ const unsigned char *key, size_t keylen,
+ const unsigned char *value, size_t valuelen,
+ void *datav)
+{
+ struct read_package_data *data = datav;
+ struct rpm_name nkey, *entry;
+ char *p;