Fixes
authorEric Biggers <ebiggers3@gmail.com>
Mon, 20 Aug 2012 07:41:15 +0000 (02:41 -0500)
committerEric Biggers <ebiggers3@gmail.com>
Mon, 20 Aug 2012 07:41:15 +0000 (02:41 -0500)
src/lookup_table.h
src/mount.c
src/symlink.c

index b59eff22a227ffcb52b7bad11d81a547a925e1e3..4ec44cd394aab373a9ce9d6c6178aedec3019859 100644 (file)
@@ -101,13 +101,9 @@ struct lookup_table_entry {
         * output_resource_entry is the struct resource_entry for the position of the
         * file resource when written to the output file. */
        u32 out_refcnt;
-       union {
-               struct resource_entry output_resource_entry;
-               struct {
-                       struct list_head staging_list;
-                       struct list_head lte_group_list;
-               };
-       };
+       struct resource_entry output_resource_entry;
+       struct list_head lte_group_list;
+       struct list_head staging_list;
 };
 
 extern struct lookup_table *new_lookup_table(size_t capacity);
index 6d21e84127c16d5086ef7305ef512eec5023dfd3..286eadbddd8c3b99d2cc5f97341469084ac68b24 100644 (file)
@@ -310,6 +310,8 @@ lte_extract_fds(struct lookup_table_entry *old_lte, u64 link_group)
                                break;
                }
        }
+       DEBUG("old_lte: %u fds open; new_lte: %u fds open",
+             old_lte->num_opened_fds, new_lte->num_opened_fds);
        old_lte->num_opened_fds -= num_transferred_fds;
        new_lte->num_opened_fds = num_transferred_fds;
        new_lte->num_allocated_fds = num_transferred_fds;
@@ -344,7 +346,7 @@ static void lte_transfer_stream_entries(struct lookup_table_entry *new_lte,
 {
        /*INIT_LIST_HEAD(&new_lte->lte_group_list);*/
        if (stream_idx == 0) {
-               struct list_head *pos;
+               struct list_head *pos = &dentry->link_group_list;
                do {
                        struct dentry *d;
                        d = container_of(pos, struct dentry, link_group_list);
@@ -873,8 +875,11 @@ static void wimfs_destroy(void *p)
                        if (status == 0)
                                status = ret;
                }
+       } else {
+               DEBUG("Read-only mount");
        }
 done:
+       DEBUG("Sending status %u", status);
        ret = mq_send(daemon_to_unmount_mq, &status, 1, 1);
        if (ret == -1)
                ERROR_WITH_ERRNO("Failed to send status to unmount process");
@@ -1006,6 +1011,7 @@ static int wimfs_mkdir(const char *path, mode_t mode)
 
        newdir = new_dentry(basename);
        newdir->attributes |= FILE_ATTRIBUTE_DIRECTORY;
+       newdir->resolved = true;
        link_dentry(newdir, parent);
        return 0;
 }
@@ -1052,6 +1058,8 @@ static int wimfs_mknod(const char *path, mode_t mode, dev_t rdev)
                        return -ENOMEM;
                dentry->resolved = true;
                dentry->hard_link = next_link_group_id++;
+               dentry->lte_group_list.type = STREAM_TYPE_NORMAL;
+               INIT_LIST_HEAD(&dentry->lte_group_list.list);
                link_dentry(dentry, parent);
        }
        return 0;
@@ -1385,6 +1393,7 @@ static int wimfs_symlink(const char *to, const char *from)
        list_add(&dentry->ads_entries[1].lte_group_list.list,
                 &lte->lte_group_list);
        dentry->ads_entries[1].lte = lte;
+       dentry->resolved = true;
 
        link_dentry(dentry, dentry_parent);
        return 0;
@@ -1559,7 +1568,7 @@ WIMLIBAPI int wimlib_mount(WIMStruct *wim, int image, const char *dir,
 
        next_link_group_id = assign_link_groups(wim->image_metadata[image - 1].lgt);
 
-       resolve_lookup_table_entries(wim_root_dentry(wim), w->lookup_table);
+       resolve_lookup_table_entries(wim_root_dentry(wim), wim->lookup_table);
 
        if (flags & WIMLIB_MOUNT_FLAG_READWRITE)
                wim_get_current_image_metadata(wim)->modified = true;
index c94ba7509c01ae6c01dbe3abf78862613fdfa6ab..f7fa10d4a89b2ce4e55024749be8ec8b10c6f368 100644 (file)
@@ -126,26 +126,45 @@ out:
        return buf;
 }
 
+static const struct lookup_table_entry *
+dentry_first_lte(const struct dentry *dentry, const struct lookup_table *table)
+{
+       const struct lookup_table_entry *lte;
+       if (dentry->resolved) {
+               if (dentry->lte)
+                       return dentry->lte;
+               for (u16 i = 0; i < dentry->num_ads; i++)
+                       if (dentry->ads_entries[i].lte)
+                               return dentry->ads_entries[i].lte;
+       } else {
+               const u8 *hash = dentry->hash;
+               u16 i = 0;
+               while (1) {
+                       if ((lte = __lookup_resource(table, hash)))
+                               break;
+                       if (i == dentry->num_ads)
+                               return NULL;
+                       hash = dentry->ads_entries[i].hash;
+                       i++;
+               }
+       }
+       return NULL;
+}
+
 /* Get the symlink target from a dentry that's already checked to be either a
  * "real" symlink or a junction point. */
 ssize_t dentry_readlink(const struct dentry *dentry, char *buf, size_t buf_len,
                        const WIMStruct *w)
 {
-       struct resource_entry *res_entry;
-       struct lookup_table_entry *lte;
-       u16 i = 0;
-       const u8 *hash = dentry->hash;
+       const struct resource_entry *res_entry;
+       const struct lookup_table_entry *lte;
 
        wimlib_assert(dentry_is_symlink(dentry));
 
-       while (1) {
-               if ((lte = __lookup_resource(w->lookup_table, hash)))
-                       break;
-               if (i == dentry->num_ads)
-                       return -EIO;
-               hash = dentry->ads_entries[i].hash;
-               i++;
-       }
+       lte = dentry_first_lte(dentry, w->lookup_table);
+       if (!lte)
+               return -EIO;
+
        res_entry = &lte->resource_entry;
        if (res_entry->original_size > 10000)
                return -EIO;