Fixes
authorEric Biggers <ebiggers3@gmail.com>
Tue, 4 Sep 2012 00:52:31 +0000 (19:52 -0500)
committerEric Biggers <ebiggers3@gmail.com>
Tue, 4 Sep 2012 00:52:31 +0000 (19:52 -0500)
src/dentry.c
src/dentry.h
src/hardlink.c
src/ntfs-apply.c
src/ntfs-capture.c
tests/test-imagex-mount

index 32c8357..2359711 100644 (file)
@@ -192,7 +192,7 @@ struct ads_entry *inode_add_ads(struct inode *inode, const char *stream_name)
        inode->ads_entries = ads_entries;
 
        new_entry = new_ads_entry(stream_name);
-       if (new_entry)
+       if (!new_entry)
                return NULL;
        inode->num_ads = num_ads;
        ads_entries[num_ads - 1] = new_entry;
@@ -600,12 +600,16 @@ err:
        return NULL;
 }
 
-struct dentry *new_dentry_with_inode(const char *name)
+
+static struct dentry *__new_dentry_with_inode(const char *name, bool timeless)
 {
        struct dentry *dentry;
        dentry = new_dentry(name);
        if (dentry) {
-               dentry->inode = new_inode();
+               if (timeless)
+                       dentry->inode = new_timeless_inode();
+               else
+                       dentry->inode = new_inode();
                if (dentry->inode) {
                        inode_add_dentry(dentry, dentry->inode);
                } else {
@@ -616,6 +620,16 @@ struct dentry *new_dentry_with_inode(const char *name)
        return dentry;
 }
 
+struct dentry *new_dentry_with_timeless_inode(const char *name)
+{
+       return __new_dentry_with_inode(name, true);
+}
+
+struct dentry *new_dentry_with_inode(const char *name)
+{
+       return __new_dentry_with_inode(name, false);
+}
+
 void free_ads_entry(struct ads_entry *entry)
 {
        if (entry) {
@@ -1687,7 +1701,7 @@ int read_dentry_tree(const u8 metadata_resource[], u64 metadata_resource_len,
 
                child->parent = dentry;
                prev_child = child;
-               list_add(&child->inode_dentry_list, &child->inode->dentry_list);
+               inode_add_dentry(child, child->inode);
 
                /* If there are children of this child, call this procedure
                 * recursively. */
index e2b6294..f87353e 100644 (file)
@@ -189,7 +189,10 @@ struct inode {
                list_for_each_entry((dentry), &(inode)->dentry_list, inode_dentry_list)
 
 #define inode_add_dentry(dentry, inode) \
-               list_add(&(dentry)->inode_dentry_list, &(inode)->dentry_list)
+       ({                                                              \
+               wimlib_assert((inode)->dentry_list.next != NULL);               \
+               list_add(&(dentry)->inode_dentry_list, &(inode)->dentry_list);  \
+       })
 
 /* 
  * In-memory structure for a WIM directory entry (dentry).  There is a directory
@@ -352,6 +355,7 @@ extern struct dentry *new_dentry(const char *name);
 extern struct inode *new_inode();
 extern struct inode *new_timeless_inode();
 extern struct dentry *new_dentry_with_inode(const char *name);
+extern struct dentry *new_dentry_with_timeless_inode(const char *name);
 
 extern void free_ads_entry(struct ads_entry *entry);
 extern void inode_free_ads_entries(struct inode *inode);
index 5c2f20c..d9f0640 100644 (file)
@@ -117,8 +117,7 @@ int inode_table_insert(struct dentry *dentry, void *__table)
                pos = d_inode->ino % table->capacity;
                hlist_for_each_entry(inode, cur, &table->array[pos], hlist) {
                        if (inode->ino == d_inode->ino) {
-                               list_add(&dentry->inode_dentry_list,
-                                        &inode->dentry_list);
+                               inode_add_dentry(dentry, inode);
                                inode->link_count++;
                                return 0;
                        }
@@ -157,7 +156,7 @@ u64 assign_inode_numbers(struct hlist_head *inode_list)
 static void print_inode_dentries(const struct inode *inode)
 {
        struct dentry *dentry;
-       list_for_each_entry(dentry, &inode->dentry_list, inode_dentry_list)
+       inode_for_each_dentry(dentry, inode)
                printf("`%s'\n", dentry->full_path_utf8);
 }
 
@@ -217,21 +216,6 @@ static bool inodes_consistent(const struct inode * restrict ref_inode,
        return true;
 }
 
-#ifdef ENABLE_DEBUG
-static void
-print_dentry_list(const struct dentry *first_dentry)
-{
-       const struct dentry *dentry = first_dentry;
-       do {
-               printf("`%s'\n", dentry->full_path_utf8);
-       } while ((dentry = container_of(dentry->inode_dentry_list.next,
-                                       struct dentry,
-                                       inode_dentry_list)) != first_dentry);
-}
-
-#endif
-
-
 /* Fix up a "true" inode and check for inconsistencies */
 static int fix_true_inode(struct inode *inode)
 {
@@ -241,21 +225,10 @@ static int fix_true_inode(struct inode *inode)
        u64 last_ctime = 0;
        u64 last_mtime = 0;
        u64 last_atime = 0;
-       bool found_short_name = false;
 
        inode_for_each_dentry(dentry, inode) {
-               if (!ref_dentry || ref_dentry->inode->num_ads == 0)
+               if (!ref_dentry || dentry->inode->num_ads > ref_dentry->inode->num_ads)
                        ref_dentry = dentry;
-               if (dentry->short_name_len) {
-                       if (found_short_name) {
-                               ERROR("Multiple short names in hard link "
-                                     "group!");
-                               inconsistent_inode(inode);
-                               return WIMLIB_ERR_INVALID_DENTRY;
-                       } else {
-                               found_short_name = true;
-                       }
-               }
                if (dentry->inode->creation_time > last_ctime)
                        last_ctime = dentry->inode->creation_time;
                if (dentry->inode->last_write_time > last_mtime)
@@ -267,10 +240,13 @@ static int fix_true_inode(struct inode *inode)
        ref_inode = ref_dentry->inode;
        ref_inode->link_count = 1;
 
-       inode_for_each_dentry(dentry, inode) {
+       list_del(&inode->dentry_list);
+       list_add(&ref_inode->dentry_list, &ref_dentry->inode_dentry_list);
+
+       inode_for_each_dentry(dentry, ref_inode) {
                if (dentry != ref_dentry) {
                        if (!inodes_consistent(ref_inode, dentry->inode)) {
-                               inconsistent_inode(dentry->inode);
+                               inconsistent_inode(ref_inode);
                                return WIMLIB_ERR_INVALID_DENTRY;
                        }
                        /* Free the unneeded `struct inode'. */
@@ -293,13 +269,12 @@ static int fix_true_inode(struct inode *inode)
  * the same hard link group ID.
  *
  * If dentries in the inode are found to be inconsistent, we may split the inode
- * into several "true" inodes.  @new_inodes points to a linked list of
- * these split inodes, and if we create any, they will be added to this list.
+ * into several "true" inodes.
  *
- * After splitting up each nominal inode into the "true" inodes we
- * will canonicalize the link group by getting rid of all the superfluous
- * `struct inodes'.  There will be just one `struct inode' for each hard link
- * group remaining.
+ * After splitting up each nominal inode into the "true" inodes we will
+ * canonicalize the link group by getting rid of all the unnecessary `struct
+ * inodes'.  There will be just one `struct inode' for each hard link group
+ * remaining.
  */
 static int
 fix_nominal_inode(struct inode *inode, struct hlist_head *inode_list)
@@ -337,17 +312,14 @@ fix_nominal_inode(struct inode *inode, struct hlist_head *inode_list)
        /* If there are no dentries with data streams, we require the nominal
         * inode to be a true inode */
        if (list_empty(&dentries_with_data_streams)) {
-               DEBUG("No data streams");
        #ifdef ENABLE_DEBUG
-               {
-                       if (inode->link_count > 1) {
-                               DEBUG("Found link group of size %zu without "
-                                     "any data streams:", inode->link_count);
-                               print_inode_dentries(inode);
-                               DEBUG("We are going to interpret it as true "
-                                     "link group, provided that the dentries "
-                                     "are consistent.");
-                       }
+               if (inode->link_count > 1) {
+                       DEBUG("Found link group of size %zu without "
+                             "any data streams:", inode->link_count);
+                       print_inode_dentries(inode);
+                       DEBUG("We are going to interpret it as true "
+                             "link group, provided that the dentries "
+                             "are consistent.");
                }
        #endif
                hlist_add_head(&inode->hlist, inode_list);
@@ -359,20 +331,19 @@ fix_nominal_inode(struct inode *inode, struct hlist_head *inode_list)
          * inodes. */
        num_true_inodes = 0;
        list_for_each_entry(dentry, &dentries_with_data_streams, tmp_list) {
-               /* Look for a true inode that is consistent with
-                * this dentry and add this dentry to it.  Or, if none
-                * of the true inodes are consistent with this
-                * dentry, make a new one. */
+               /* Look for a true inode that is consistent with this dentry and
+                * add this dentry to it.  Or, if none of the true inodes are
+                * consistent with this dentry, add a new one (if that happens,
+                * we have split the hard link group). */
                hlist_for_each_entry(inode, cur, &true_inodes, hlist) {
                        if (ref_inodes_consistent(inode, dentry->inode)) {
-                               list_add(&dentry->inode_dentry_list,
-                                        &inode->dentry_list);
+                               inode_add_dentry(dentry, inode);
                                goto next_dentry_2;
                        }
                }
                num_true_inodes++;
                INIT_LIST_HEAD(&dentry->inode->dentry_list);
-               list_add(&dentry->inode_dentry_list, &dentry->inode->dentry_list);
+               inode_add_dentry(dentry, dentry->inode);
                hlist_add_head(&dentry->inode->hlist, &true_inodes);
 next_dentry_2:
                ;
@@ -389,39 +360,33 @@ next_dentry_2:
                        ERROR("We split up inode 0x%"PRIx64" due to "
                              "inconsistencies,", inode->ino);
                        ERROR("but dentries with no stream information remained. "
-                             "We don't know which true hard link");
-                       ERROR("inode to assign them to.");
+                             "We don't know which inode");
+                       ERROR("to assign them to.");
                        return WIMLIB_ERR_INVALID_DENTRY;
                }
-               inode = container_of(true_inodes.first,
-                                    struct inode,
-                                    hlist);
+               inode = container_of(true_inodes.first, struct inode, hlist);
                /* Assign the streamless dentries to the one and only true
                 * inode. */
                list_for_each_entry(dentry, &dentries_with_no_data_streams, tmp_list)
-                       list_add(&dentry->inode_dentry_list, &inode->dentry_list);
+                       inode_add_dentry(dentry, inode);
        }
+       #ifdef ENABLE_DEBUG
         if (num_true_inodes != 1) {
-               #ifdef ENABLE_DEBUG
-               {
-                       inode = container_of(true_inodes.first,
-                                            struct inode,
-                                            hlist);
-
-                       printf("Split nominal inode 0x%"PRIx64" into %zu "
-                              "inodes:\n",
-                              inode->ino, num_true_inodes);
-                       puts("------------------------------------------------------------------------------");
-                       size_t i = 1;
-                       hlist_for_each_entry(inode, cur, &true_inodes, hlist) {
-                               printf("[Split inode %zu]\n", i++);
-                               print_inode_dentries(inode);
-                               putchar('\n');
-                       }
-                       puts("------------------------------------------------------------------------------");
+               inode = container_of(true_inodes.first, struct inode, hlist);
+
+               printf("Split nominal inode 0x%"PRIx64" into %zu "
+                      "inodes:\n",
+                      inode->ino, num_true_inodes);
+               puts("------------------------------------------------------------------------------");
+               size_t i = 1;
+               hlist_for_each_entry(inode, cur, &true_inodes, hlist) {
+                       printf("[Split inode %zu]\n", i++);
+                       print_inode_dentries(inode);
+                       putchar('\n');
                }
-               #endif
+               puts("------------------------------------------------------------------------------");
         }
+       #endif
 
        hlist_for_each_entry_safe(inode, cur, tmp, &true_inodes, hlist) {
                hlist_add_head(&inode->hlist, inode_list);
@@ -434,13 +399,18 @@ next_dentry_2:
 
 /*
  * Goes through each hard link group (dentries sharing the same hard link group
- * ID field) that's been inserted into the inode table and shars the `struct
+ * ID field) that's been inserted into the inode table and shares the `struct
  * inode's among members of each hard link group.
  *
  * In the process, the dentries belonging to each inode are checked for
  * consistency.  If they contain data features that indicate they cannot really
  * correspond to the same inode, this should be an error, but in reality this
  * case needs to be handled, so we split the dentries into different inodes.
+ *
+ * After this function returns, the inodes are no longer in the inode table, and
+ * the inode table should be destroyed.  A list of the inodes, including all
+ * split inodes as well as the inodes that were good before, is returned in the
+ * list @inode_list.
  */
 int fix_inodes(struct inode_table *table, struct hlist_head *inode_list)
 {
index 5e36469..1a97e72 100644 (file)
@@ -378,9 +378,7 @@ static int preapply_dentry_with_dos_name(struct dentry *dentry,
                }
        }
        /* If there's a dentry with a DOS name, extract it first */
-       if (dentry_with_dos_name
-           && !dentry_with_dos_name->inode->extracted_file)
-       {
+       if (dentry_with_dos_name && !dentry_is_extracted(dentry)) {
                char *p;
                const char *dir_name;
                char orig;
@@ -431,6 +429,7 @@ static int do_wim_apply_dentry_ntfs(struct dentry *dentry, ntfs_inode *dir_ni,
        bool is_hardlink = false;
        ntfs_volume *vol = dir_ni->vol;
        struct inode *inode = dentry->inode;
+       dentry->is_extracted = true;
 
        if (inode->attributes & FILE_ATTRIBUTE_DIRECTORY) {
                type = S_IFDIR;
index 6751754..7c92c9e 100644 (file)
@@ -257,7 +257,6 @@ static int capture_ntfs_streams(struct dentry *dentry, ntfs_inode *ni,
                                ntfs_volume **ntfs_vol_p,
                                ATTR_TYPES type)
 {
-
        ntfs_attr_search_ctx *actx;
        u8 attr_hash[SHA1_HASH_SIZE];
        struct ntfs_location *ntfs_loc = NULL;
@@ -458,7 +457,7 @@ static int wim_ntfs_capture_filldir(void *dirent, const ntfschar *name,
        ntfs_inode *ni = ntfs_inode_open(ctx->dir_ni->vol, mref);
        if (!ni) {
                ERROR_WITH_ERRNO("Failed to open NTFS inode");
-               ret = 1;
+               goto out_free_utf8_name;
        }
        path_len = ctx->path_len;
        if (path_len != 1)
@@ -498,8 +497,6 @@ static int change_dentry_short_name(struct dentry *dentry,
        return 0;
 }
 
-/*#define HAVE_NTFS_INODE_FUNCTIONS*/
-
 /* Recursively build a WIM dentry tree corresponding to a NTFS volume.
  * At the same time, update the WIM lookup table with lookup table entries for
  * the NTFS streams, and build an array of security descriptors.
@@ -557,7 +554,7 @@ static int build_dentry_tree_ntfs_recursive(struct dentry **root_p,
        if (flags & WIMLIB_ADD_IMAGE_FLAG_VERBOSE)
                printf("Scanning `%s'\n", path);
 
-       root = new_dentry_with_inode(path_basename(path));
+       root = new_dentry_with_timeless_inode(path_basename(path));
        if (!root)
                return WIMLIB_ERR_NOMEM;
        *root_p = root;
index 1134abf..ee8501f 100755 (executable)
@@ -27,12 +27,8 @@ imagex_mountrw() {
 }
 
 cleanup() {
-       if mountpoint tmp &> /dev/null; then
-               fusermount -u tmp > /dev/null;
-       fi
-       if mountpoint tmp.mnt &> /dev/null; then
-               fusermount -u tmp.mnt > /dev/null;
-       fi
+       fusermount -u tmp &> /dev/null || true
+       fusermount -u tmp.mnt &> /dev/null || true
        rm -rf dir* tmp* *.wim *.swm empty.wim tmp.orig tmp.mnt \
                        tmp.apply mount.log test.tar wimlib-staging*
 }