-/* Insert a dentry into the inode table based on the inode number of the
- * attached inode (which came from the hard link group ID field of the on-disk
- * WIM dentry) */
-static int
-inode_table_insert(struct wim_dentry *dentry, void *_table)
-{
- struct wim_inode_table *table = _table;
- struct wim_inode *d_inode = dentry->d_inode;
-
- if (d_inode->i_ino == 0) {
- /* A dentry with a hard link group ID of 0 indicates that it's
- * in a hard link group by itself. Add it to the list of extra
- * inodes rather than inserting it into the hash lists. */
- list_add_tail(&d_inode->i_list, &table->extra_inodes);
- } else {
- size_t pos;
- struct wim_inode *inode;
- struct hlist_node *cur;
-
- /* Try adding this dentry to an existing inode */
- pos = d_inode->i_ino % table->capacity;
- hlist_for_each_entry(inode, cur, &table->array[pos], i_hlist) {
- if (inode->i_ino == d_inode->i_ino) {
- if (unlikely((inode->i_attributes & FILE_ATTRIBUTE_DIRECTORY) ||
- (d_inode->i_attributes & FILE_ATTRIBUTE_DIRECTORY)))
- {
- ERROR("Unsupported directory hard link "
- "\"%"TS"\" <=> \"%"TS"\"",
- dentry_full_path(dentry),
- dentry_full_path(inode_first_dentry(inode)));
- return WIMLIB_ERR_INVALID_METADATA_RESOURCE;
- }
- inode_add_dentry(dentry, inode);
- return 0;
- }
- }
-
- /* No inode in the table has the same number as this one, so add
- * it to the table. */
- hlist_add_head(&d_inode->i_hlist, &table->array[pos]);
-
- /* XXX Make the table grow when too many entries have been
- * inserted. */
- table->num_entries++;
- }
- return 0;
-}
-
-static struct wim_inode *
-inode_table_get_inode(struct wim_inode_table *table, u64 ino, u64 devno)
-{
- u64 hash = hash_u64(hash_u64(ino) + hash_u64(devno));
- size_t pos = hash % table->capacity;
- struct wim_inode *inode;
- struct hlist_node *cur;
-
- hlist_for_each_entry(inode, cur, &table->array[pos], i_hlist) {
- if (inode->i_ino == ino && inode->i_devno == devno) {
- DEBUG("Using existing inode {devno=%"PRIu64", ino=%"PRIu64"}",
- devno, ino);
- inode->i_nlink++;
- return inode;
- }
- }
- inode = new_timeless_inode();
- if (inode) {
- inode->i_ino = ino;
- inode->i_devno = devno;
- hlist_add_head(&inode->i_hlist, &table->array[pos]);
- table->num_entries++;
- }
- return inode;
-}
-
-void
-inode_ref_streams(struct wim_inode *inode)
-{
- for (unsigned i = 0; i <= inode->i_num_ads; i++) {
- struct wim_lookup_table_entry *lte;
- lte = inode_stream_lte_resolved(inode, i);
- if (lte)
- lte->refcnt++;
- }
-}
-
-/* Given a directory entry with the name @name for the file with the inode
- * number @ino and device number @devno, create a new WIM dentry with an
- * associated inode, where the inode is shared if an inode with the same @ino
- * and @devno has already been created. On success, the new WIM dentry is
- * written to *dentry_ret, and its inode has i_nlink > 1 if a previously
- * existing inode was used.
- */
-int
-inode_table_new_dentry(struct wim_inode_table *table, const tchar *name,
- u64 ino, u64 devno, bool noshare,
- struct wim_dentry **dentry_ret)
-{
- struct wim_dentry *dentry;
- struct wim_inode *inode;
- int ret;
-
- if (noshare) {
- /* File that cannot be hardlinked--- Return a new inode with its
- * inode and device numbers left at 0. */
- ret = new_dentry_with_timeless_inode(name, &dentry);
- if (ret)
- return ret;
- list_add_tail(&dentry->d_inode->i_list, &table->extra_inodes);
- } else {
- /* File that can be hardlinked--- search the table for an
- * existing inode matching the inode number and device;
- * otherwise create a new inode. */
- ret = new_dentry(name, &dentry);
- if (ret)
- return ret;
- inode = inode_table_get_inode(table, ino, devno);
- if (!inode) {
- free_dentry(dentry);
- return WIMLIB_ERR_NOMEM;
- }
- /* If using an existing inode, we need to gain a reference to
- * each of its streams. */
- if (inode->i_nlink > 1)
- inode_ref_streams(inode);
- dentry->d_inode = inode;
- inode_add_dentry(dentry, inode);
- }
- *dentry_ret = dentry;
- return 0;
-}
-