Consistently forbid directory hard links from being honored on capture
authorEric Biggers <ebiggers3@gmail.com>
Sun, 7 Jun 2015 19:47:07 +0000 (14:47 -0500)
committerEric Biggers <ebiggers3@gmail.com>
Tue, 23 Jun 2015 02:17:21 +0000 (21:17 -0500)
src/inode_table.c
src/unix_capture.c
src/win32_capture.c

index e8ccced99b8f9fa01f2c834d59d7e81422ad0c91..32c2e5b39df6c872d9bfe62cf7b58aafb8d8d207 100644 (file)
@@ -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;
 }
index b56c55db1a676ab8997428bebf9b1919cf5d5ee1..2843c36a6c698204c4aace20f32ebb6bc435f008 100644 (file)
@@ -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;
 
index 450dfb5898cf0dbf34e765ff0733b3ec39ade226..8937891e75ee205376142a627264470d8e00fb07 100644 (file)
@@ -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;