From: Eric Biggers Date: Sun, 7 Jun 2015 19:47:07 +0000 (-0500) Subject: Consistently forbid directory hard links from being honored on capture X-Git-Tag: v1.8.2~61 X-Git-Url: https://wimlib.net/git/?p=wimlib;a=commitdiff_plain;h=6c36e2e6311e29cede36518e4363d1bcdd87ddb3 Consistently forbid directory hard links from being honored on capture --- diff --git a/src/inode_table.c b/src/inode_table.c index e8ccced9..32c2e5b3 100644 --- a/src/inode_table.c +++ b/src/inode_table.c @@ -91,39 +91,41 @@ inode_table_new_dentry(struct wim_inode_table *table, const tchar *name, { struct wim_dentry *dentry; struct wim_inode *inode; + struct hlist_head *list; 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_new_inode(name, false, &dentry); - if (ret) - return ret; - hlist_add_head(&dentry->d_inode->i_hlist_node, &table->extra_inodes); + /* No hard link detection */ + list = &table->extra_inodes; } else { - size_t pos; - - /* File that can be hardlinked--- search the table for an - * existing inode matching the inode number and device. */ - pos = hash_u64(hash_u64(ino) + hash_u64(devno)) % table->capacity; - hlist_for_each_entry(inode, &table->array[pos], i_hlist_node) { - if (inode->i_ino == ino && inode->i_devno == devno) { - /* Found; use the existing inode. */ - return new_dentry_with_existing_inode(name, inode, - dentry_ret); + /* Hard link detection */ + list = &table->array[hash_u64(hash_u64(ino) + hash_u64(devno)) + % table->capacity]; + hlist_for_each_entry(inode, list, i_hlist_node) { + if (inode->i_ino != ino || inode->i_devno != devno) + continue; + if (inode->i_attributes & FILE_ATTRIBUTE_DIRECTORY) { + WARNING("Not honoring directory hard link " + "of \"%"TS"\"", + inode_any_full_path(inode)); + continue; } + /* Inode found; use it. */ + return new_dentry_with_existing_inode(name, inode, + dentry_ret); } - /* Not found; create a new inode and add it to the table. */ - ret = new_dentry_with_new_inode(name, false, &dentry); - if (ret) - return ret; - inode = dentry->d_inode; - inode->i_ino = ino; - inode->i_devno = devno; - hlist_add_head(&inode->i_hlist_node, &table->array[pos]); + /* Inode not found; create it. */ table->num_entries++; } + + ret = new_dentry_with_new_inode(name, false, &dentry); + if (ret) + return ret; + inode = dentry->d_inode; + hlist_add_head(&inode->i_hlist_node, list); + inode->i_ino = ino; + inode->i_devno = devno; *dentry_ret = dentry; return 0; } diff --git a/src/unix_capture.c b/src/unix_capture.c index b56c55db..2843c36a 100644 --- a/src/unix_capture.c +++ b/src/unix_capture.c @@ -388,8 +388,7 @@ unix_build_dentry_tree_recursive(struct wim_dentry **tree_ret, } ret = inode_table_new_dentry(params->inode_table, relpath, - stbuf.st_ino, stbuf.st_dev, - S_ISDIR(stbuf.st_mode), &tree); + stbuf.st_ino, stbuf.st_dev, false, &tree); if (ret) goto out; diff --git a/src/win32_capture.c b/src/win32_capture.c index 450dfb58..8937891e 100644 --- a/src/win32_capture.c +++ b/src/win32_capture.c @@ -1290,8 +1290,7 @@ retry_open: filename, file_info.ino, params->capture_root_dev, - (file_info.num_links <= 1 || - (file_info.attributes & FILE_ATTRIBUTE_DIRECTORY)), + (file_info.num_links <= 1), &root); if (ret) goto out;