X-Git-Url: https://wimlib.net/git/?p=wimlib;a=blobdiff_plain;f=src%2Fhardlink.c;h=5e2c62618ad43b5e2641d97a31cb86f899425e97;hp=3022cadfc47069340e5ae86c67fe1a06dd85bd10;hb=1c940d499beb539f846ed2509e3fee7772adf250;hpb=1770f3592215549707de3c5f2a1c4858e50b17ba diff --git a/src/hardlink.c b/src/hardlink.c index 3022cadf..5e2c6261 100644 --- a/src/hardlink.c +++ b/src/hardlink.c @@ -23,10 +23,14 @@ * along with wimlib; if not, see http://www.gnu.org/licenses/. */ -#include "wimlib_internal.h" -#include "dentry.h" -#include "list.h" -#include "lookup_table.h" +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "wimlib/capture.h" +#include "wimlib/dentry.h" +#include "wimlib/error.h" +#include "wimlib/lookup_table.h" /* NULL NULL * ^ ^ @@ -168,25 +172,32 @@ inode_ref_streams(struct wim_inode *inode) */ int inode_table_new_dentry(struct wim_inode_table *table, const tchar *name, - u64 ino, u64 devno, struct wim_dentry **dentry_ret) + u64 ino, u64 devno, bool noshare, + struct wim_dentry **dentry_ret) { struct wim_dentry *dentry; struct wim_inode *inode; int ret; - 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 (noshare) { + ret = new_dentry_with_timeless_inode(name, &dentry); + if (ret) + return ret; + list_add_tail(&dentry->d_inode->i_list, &table->extra_inodes); + } else { + 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 (inode->i_nlink > 1) + inode_ref_streams(inode); + dentry->d_inode = inode; + inode_add_dentry(dentry, inode); } - if (inode->i_nlink > 1) - inode_ref_streams(inode); - dentry->d_inode = inode; - inode_add_dentry(dentry, inode); *dentry_ret = dentry; return 0; } @@ -298,8 +309,6 @@ fix_true_inode(struct wim_inode *inode, struct list_head *inode_list) return WIMLIB_ERR_INVALID_DENTRY; } /* Free the unneeded `struct wim_inode'. */ - dentry->d_inode->i_hlist.next = NULL; - dentry->d_inode->i_hlist.pprev = NULL; free_inode(dentry->d_inode); dentry->d_inode = ref_inode; ref_inode->i_nlink++; @@ -337,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); @@ -458,6 +474,7 @@ fix_inodes(struct wim_inode_table *table, struct list_head *inode_list, INIT_LIST_HEAD(inode_list); for (u64 i = 0; i < table->capacity; i++) { hlist_for_each_entry_safe(inode, cur, tmp, &table->array[i], i_hlist) { + INIT_LIST_HEAD(&inode->i_list); ret = fix_nominal_inode(inode, inode_list, ino_changes_needed); if (ret) return ret; @@ -539,7 +556,13 @@ inode_table_prepare_inode_list(struct wim_inode_table *table, struct hlist_node *cur, *tmp; u64 cur_ino = 1; - INIT_LIST_HEAD(head); + list_for_each_entry(inode, head, i_list) { + if (inode->i_nlink > 1) + inode->i_ino = cur_ino++; + else + inode->i_ino = 0; + } + for (size_t i = 0; i < table->capacity; i++) { hlist_for_each_entry_safe(inode, cur, tmp, &table->array[i], i_hlist) { @@ -551,5 +574,6 @@ inode_table_prepare_inode_list(struct wim_inode_table *table, } INIT_HLIST_HEAD(&table->array[i]); } + list_splice_tail(&table->extra_inodes, head); table->num_entries = 0; }