+static int dict_int_cmp(const void *a, const void *b)
+{
+ intptr_t ia, ib;
+
+ ia = (intptr_t)a;
+ ib = (intptr_t)b;
+
+ return (ia-ib);
+}
+
+/*
+ * Add a duplicate block record
+ */
+static void add_dupe(e2fsck_t ctx, ext2_ino_t ino, blk64_t cluster,
+ struct ext2_inode *inode)
+{
+ dnode_t *n;
+ struct dup_cluster *db;
+ struct dup_inode *di;
+ struct cluster_el *cluster_el;
+ struct inode_el *ino_el;
+
+ n = dict_lookup(&clstr_dict, INT_TO_VOIDPTR(cluster));
+ if (n)
+ db = (struct dup_cluster *) dnode_get(n);
+ else {
+ db = (struct dup_cluster *) e2fsck_allocate_memory(ctx,
+ sizeof(struct dup_cluster), "duplicate cluster header");
+ db->num_bad = 0;
+ db->inode_list = 0;
+ dict_alloc_insert(&clstr_dict, INT_TO_VOIDPTR(cluster), db);
+ }
+ ino_el = (struct inode_el *) e2fsck_allocate_memory(ctx,
+ sizeof(struct inode_el), "inode element");
+ ino_el->inode = ino;
+ ino_el->next = db->inode_list;
+ db->inode_list = ino_el;
+ db->num_bad++;
+
+ n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(ino));
+ if (n)
+ di = (struct dup_inode *) dnode_get(n);
+ else {
+ di = (struct dup_inode *) e2fsck_allocate_memory(ctx,
+ sizeof(struct dup_inode), "duplicate inode header");
+ if (ino == EXT2_ROOT_INO) {
+ di->dir = EXT2_ROOT_INO;
+ dup_inode_founddir++;
+ } else
+ di->dir = 0;
+
+ di->num_dupblocks = 0;
+ di->cluster_list = 0;
+ di->inode = *inode;
+ dict_alloc_insert(&ino_dict, INT_TO_VOIDPTR(ino), di);
+ }
+ cluster_el = (struct cluster_el *) e2fsck_allocate_memory(ctx,
+ sizeof(struct cluster_el), "cluster element");
+ cluster_el->cluster = cluster;
+ cluster_el->next = di->cluster_list;
+ di->cluster_list = cluster_el;
+ di->num_dupblocks++;
+}
+
+/*
+ * Free a duplicate inode record
+ */
+static void inode_dnode_free(dnode_t *node,
+ void *context EXT2FS_ATTR((unused)))
+{
+ struct dup_inode *di;
+ struct cluster_el *p, *next;
+
+ di = (struct dup_inode *) dnode_get(node);
+ for (p = di->cluster_list; p; p = next) {
+ next = p->next;
+ free(p);
+ }
+ free(di);
+ free(node);
+}
+
+/*
+ * Free a duplicate cluster record
+ */
+static void cluster_dnode_free(dnode_t *node,
+ void *context EXT2FS_ATTR((unused)))
+{
+ struct dup_cluster *dc;
+ struct inode_el *p, *next;
+
+ dc = (struct dup_cluster *) dnode_get(node);
+ for (p = dc->inode_list; p; p = next) {
+ next = p->next;
+ free(p);
+ }
+ free(dc);
+ free(node);
+}
+
+