+
+/*
+ * dentry_tree_fix_inodes():
+ *
+ * This function takes as input a tree of WIM dentries that initially has a
+ * different inode associated with each dentry. Sets of dentries that should
+ * share the same inode (a.k.a. hard link groups) are built using the i_ino
+ * field of each inode, then the link count and alias list for one inode in each
+ * set is set correctly and the unnecessary struct wim_inode's freed. The
+ * effect is to correctly associate exactly one struct wim_inode with each
+ * original inode, regardless of how many dentries are aliases for that inode.
+ *
+ * The special inode number of 0 indicates that the dentry is in a hard link
+ * group by itself, and therefore has a 'struct wim_inode' with i_nlink=1 to
+ * itself.
+ *
+ * This function also checks the dentries in each hard link group for
+ * consistency. In some WIMs, such as install.wim for some versions of Windows
+ * 7, dentries can share the same hard link group ID but not actually be hard
+ * linked to each other (based on conflicting information, such as file
+ * contents). This should be an error, but this case needs be handled. So,
+ * each "nominal" inode (the inode based on the inode numbers provided in the
+ * WIM) is examined for consistency and may be split into multiple "true" inodes
+ * that are maximally sized consistent sets of dentries.
+ *
+ * Return 0 on success; WIMLIB_ERR_NOMEM or WIMLIB_ERR_INVALID_DENTRY on
+ * failure. On success, the list of "true" inodes, linked by the i_hlist field,
+ * is returned in the hlist @inode_list.
+ */
+int dentry_tree_fix_inodes(struct wim_dentry *root, struct hlist_head *inode_list)
+{
+ struct wim_inode_table inode_tab;
+ int ret;
+
+ DEBUG("Inserting dentries into inode table");
+ ret = init_inode_table(&inode_tab, 9001);
+ if (ret != 0)
+ return ret;
+
+ for_dentry_in_tree(root, inode_table_insert, &inode_tab);
+
+ DEBUG("Cleaning up the hard link groups");
+ ret = fix_inodes(&inode_tab, inode_list);
+ destroy_inode_table(&inode_tab);
+ return ret;
+}
+
+/* Assign inode numbers to a list of inodes and return the next available
+ * number. */
+u64 assign_inode_numbers(struct hlist_head *inode_list)
+{
+ DEBUG("Assigning inode numbers");
+ struct wim_inode *inode;
+ struct hlist_node *cur;
+ u64 cur_ino = 1;
+ hlist_for_each_entry(inode, cur, inode_list, i_hlist) {
+ inode->i_ino = cur_ino;
+ cur_ino++;
+ }
+ return cur_ino;
+}