From 1c940d499beb539f846ed2509e3fee7772adf250 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Fri, 17 May 2013 10:51:56 -0500 Subject: [PATCH 1/1] read_dentry_tree(): Ignore duplicate dentries --- src/dentry.c | 40 +++++++++++++++++++++++++++------------- src/hardlink.c | 7 +++++++ 2 files changed, 34 insertions(+), 13 deletions(-) diff --git a/src/dentry.c b/src/dentry.c index 5082eac6..b7a0032a 100644 --- a/src/dentry.c +++ b/src/dentry.c @@ -1025,6 +1025,7 @@ dentry_add_child(struct wim_dentry * restrict parent, struct wim_dentry * restrict child) { wimlib_assert(dentry_is_directory(parent)); + wimlib_assert(parent != child); struct rb_root *root = &parent->d_inode->i_children; struct rb_node **new = &(root->rb_node); @@ -1781,24 +1782,37 @@ read_dentry_tree(const u8 metadata_resource[], u64 metadata_resource_len, break; } memcpy(child, &cur_child, sizeof(struct wim_dentry)); - dentry_add_child(dentry, child); - inode_add_dentry(child, child->d_inode); - - /* If there are children of this child, call this procedure - * recursively. */ - if (child->subdir_offset != 0) { - ret = read_dentry_tree(metadata_resource, - metadata_resource_len, child); - if (ret) - break; - } /* Advance to the offset of the next child. Note: We need to * advance by the TOTAL length of the dentry, not by the length - * child->length, which although it does take into account the - * padding, it DOES NOT take into account alternate stream + * cur_child.length, which although it does take into account + * the padding, it DOES NOT take into account alternate stream * entries. */ cur_offset += dentry_total_length(child); + + if (dentry_add_child(dentry, child)) { + WARNING("Ignoring duplicate dentry \"%"WS"\"", + child->file_name); + WARNING("(In directory \"%"TS"\")", dentry_full_path(dentry)); + free_dentry(child); + } else { + inode_add_dentry(child, child->d_inode); + /* If there are children of this child, call this + * procedure recursively. */ + if (child->subdir_offset != 0) { + if (!dentry_is_directory(child)) { + ret = read_dentry_tree(metadata_resource, + metadata_resource_len, + child); + if (ret) + break; + } else { + WARNING("Ignoring children of non-directory \"%"TS"\"", + dentry_full_path(child)); + } + } + + } } return ret; } diff --git a/src/hardlink.c b/src/hardlink.c index 7c82f4ba..5e2c6261 100644 --- a/src/hardlink.c +++ b/src/hardlink.c @@ -346,6 +346,13 @@ fix_nominal_inode(struct wim_inode *inode, struct list_head *inode_list, wimlib_assert(inode->i_nlink == inode_link_count(inode)); + if (inode->i_nlink > 1 && + (inode->i_attributes & FILE_ATTRIBUTE_DIRECTORY)) + { + ERROR("Found unsupported directory hard link!"); + return WIMLIB_ERR_INVALID_DENTRY; + } + LIST_HEAD(dentries_with_data_streams); LIST_HEAD(dentries_with_no_data_streams); HLIST_HEAD(true_inodes); -- 2.43.0