hardlink fixes
authorEric Biggers <ebiggers3@gmail.com>
Sun, 19 Aug 2012 04:32:58 +0000 (23:32 -0500)
committerEric Biggers <ebiggers3@gmail.com>
Sun, 19 Aug 2012 04:32:58 +0000 (23:32 -0500)
src/dentry.c
src/hardlink.c
src/modify.c
src/security.c
src/wim.c
src/wimlib_internal.h

index e47f8380e2fdffabb3b7aca7d2967c1d07c8c7bf..cf77adc765c6180100c43cbea5726a844ca86881 100644 (file)
@@ -500,19 +500,21 @@ struct dentry *new_dentry(const char *name)
        
        dentry = MALLOC(sizeof(struct dentry));
        if (!dentry)
-               return NULL;
+               goto err;
 
        dentry_common_init(dentry);
-       if (change_dentry_name(dentry, name) != 0) {
-               FREE(dentry);
-               return NULL;
-       }
+       if (change_dentry_name(dentry, name) != 0)
+               goto err;
 
        dentry_update_all_timestamps(dentry);
        dentry->next   = dentry;
        dentry->prev   = dentry;
        dentry->parent = dentry;
        return dentry;
+err:
+       FREE(dentry);
+       ERROR("Failed to allocate new dentry");
+       return NULL;
 }
 
 static void dentry_free_ads_entries(struct dentry *dentry)
@@ -665,6 +667,7 @@ static int do_name_change(char **file_name_ret,
        *file_name_utf8_ret     = file_name_utf8;
        *file_name_len_ret      = utf16_len;
        *file_name_utf8_len_ret = utf8_len;
+       return 0;
 }
 
 /* Changes the name of a dentry to @new_name.  Only changes the file_name and
index 929837e534f8f7c38f94c6ee47f65acdd543280d..67be5aab450e985bd2b6fd016dc17d22fb2b5e45 100644 (file)
@@ -6,7 +6,7 @@
 struct link_group {
        u64 link_group_id;
        struct link_group *next;
-       struct list_head *link_group_head;
+       struct list_head dentry_list;
 };
 
 struct link_group_table {
@@ -15,6 +15,7 @@ struct link_group_table {
        u64 capacity;
 };
 
+#include <sys/mman.h>
 
 struct link_group_table *new_link_group_table(u64 capacity)
 {
@@ -43,7 +44,7 @@ int link_group_table_insert(struct dentry *dentry, struct link_group_table *tabl
        group = table->array[pos];
        while (group) {
                if (group->link_group_id == dentry->hard_link) {
-                       list_add(&dentry->link_group_list, group->link_group_head);
+                       list_add(&dentry->link_group_list, &group->dentry_list);
                        return 0;
                }
                group = group->next;
@@ -54,11 +55,11 @@ int link_group_table_insert(struct dentry *dentry, struct link_group_table *tabl
        group = MALLOC(sizeof(struct link_group));
        if (!group)
                return WIMLIB_ERR_NOMEM;
-       INIT_LIST_HEAD(&dentry->link_group_list);
-       group->link_group_id = dentry->hard_link;
-       group->next = table->array[pos];
-       group->link_group_head = &dentry->link_group_list;
-       table->array[pos] = group;
+       group->link_group_id   = dentry->hard_link;
+       group->next            = table->array[pos];
+       INIT_LIST_HEAD(&group->dentry_list);
+       list_add(&dentry->link_group_list, &group->dentry_list);
+       table->array[pos]      = group;
 
        /* XXX Make the table grow when too many entries have been inserted. */
        table->num_entries++;
@@ -97,10 +98,10 @@ u64 assign_link_groups(struct link_group_table *table)
                struct dentry *dentry;
                while (group) {
                        next_group = group->next;
-                       if (list_empty(group->link_group_head)) {
+                       if (list_is_singular(&group->dentry_list)) {
                                /* Hard link group of size 1.  Change the hard
                                 * link ID to 0 and discard the link_group */
-                               dentry = container_of(group->link_group_head,
+                               dentry = container_of(group->dentry_list.next,
                                                      struct dentry,
                                                      link_group_list);
                                dentry->hard_link = 0;
@@ -110,7 +111,7 @@ u64 assign_link_groups(struct link_group_table *table)
                                 * dentries in the group the next available hard
                                 * link IDs and queue the group to be
                                 * re-inserted into the table. */
-                               list_for_each_entry(dentry, group->link_group_head,
+                               list_for_each_entry(dentry, &group->dentry_list,
                                                    link_group_list)
                                        dentry->hard_link = id;
                                group->next = remaining_groups;
index fab9ee059d2558571363e8bb2698540d1b7027ed..947316aa9fb5fe4fb566eebcb564e41710004e20 100644 (file)
  * the WIM. */
 #define WIMLIB_ADD_IMAGE_FLAG_ROOT 0x80000000
 
-static void destroy_image_metadata(struct image_metadata *imd,
-                                  struct lookup_table *lt)
+void destroy_image_metadata(struct image_metadata *imd,struct lookup_table *lt)
 {
-       free_dentry_tree(imd->root_dentry, lt, true);
+       if (lt)
+               free_dentry_tree(imd->root_dentry, lt, true);
+       else
+               free_dentry_tree(imd->root_dentry, NULL, false);
        free_security_data(imd->security_data);
        free_link_group_table(imd->lgt);
 
        /* Get rid of the lookup table entry for this image's metadata resource
         * */
-       lookup_table_remove(lt, imd->metadata_lte);
+       if (lt)
+               lookup_table_remove(lt, imd->metadata_lte);
 }
 
 /* 
@@ -60,9 +63,7 @@ static void destroy_image_metadata(struct image_metadata *imd,
  *
  * @root:  A dentry that has already been created for the root of the dentry
  *        tree.
- * @source_path:  The path to the root of the tree on disk. 
- * @root_stat:   A pointer to a `struct stat' that contains the metadata for the
- *                     root of the tree on disk. 
+ * @root_disk_path:  The path to the root of the tree on disk. 
  * @lookup_table: The lookup table for the WIM file.  For each file added to the
  *             dentry tree being built, an entry is added to the lookup table, 
  *             unless an identical file is already in the lookup table.  These
@@ -78,7 +79,7 @@ static int build_dentry_tree(struct dentry *root, const char *root_disk_path,
                             struct lookup_table* lookup_table,
                             int add_flags)
 {
-       DEBUG("`%s'", root_disk_path);
+       DEBUG("%s", root_disk_path);
        struct stat root_stbuf;
        int ret;
        int (*stat_fn)(const char *restrict, struct stat *restrict);
@@ -130,10 +131,8 @@ static int build_dentry_tree(struct dentry *root, const char *root_disk_path,
                                        continue;
                        strcpy(name + len + 1, p->d_name);
                        child = new_dentry(p->d_name);
-                       if (!child) {
-                               ERROR("No memory to allocate new dentry");
+                       if (!child)
                                return WIMLIB_ERR_NOMEM;
-                       }
                        ret = build_dentry_tree(child, name, lookup_table,
                                                add_flags);
                        link_dentry(child, root);
@@ -295,6 +294,7 @@ static int add_new_dentry_tree(WIMStruct *w, struct dentry *root_dentry)
        struct image_metadata *imd;
        struct image_metadata *new_imd;
        struct wim_security_data *sd;
+       struct link_group_table *lgt;
 
        DEBUG("Reallocating image metadata array for image_count = %u",
              w->hdr.image_count + 1);
@@ -317,22 +317,30 @@ static int add_new_dentry_tree(WIMStruct *w, struct dentry *root_dentry)
        sd->refcnt = 1;
        sd->total_length = 8;
 
+       lgt = new_link_group_table(9001);
+       if (!lgt)
+               goto out_free_security_data;
+
        metadata_lte->resource_entry.flags = WIM_RESHDR_FLAG_METADATA;
        randomize_byte_array(metadata_lte->hash, WIM_HASH_SIZE);
        lookup_table_insert(w->lookup_table, metadata_lte);
 
-       w->hdr.image_count++;
+       new_imd = &imd[w->hdr.image_count];
 
-       new_imd                 = &imd[w->hdr.image_count - 1];
-       new_imd->metadata_lte   = metadata_lte;
-       new_imd->modified       = true;
        new_imd->root_dentry    = root_dentry;
+       new_imd->metadata_lte   = metadata_lte;
        new_imd->security_data  = sd;
+       new_imd->lgt            = lgt;
+       new_imd->modified       = true;
+
        FREE(w->image_metadata);
        w->image_metadata       = imd;
+       w->hdr.image_count++;
 
        /* Change the current image to the new one. */
        return wimlib_select_image(w, w->hdr.image_count);
+out_free_security_data:
+       FREE(sd);
 out_free_metadata_lte:
        FREE(metadata_lte);
 out_free_imd:
@@ -520,7 +528,6 @@ WIMLIBAPI int wimlib_add_image(WIMStruct *w, const char *dir,
                               const char *flags_element, int flags)
 {
        struct dentry *root_dentry;
-       struct stat root_stat;
        struct image_metadata *imd;
        int ret;
 
@@ -571,10 +578,12 @@ WIMLIBAPI int wimlib_add_image(WIMStruct *w, const char *dir,
        if (ret != 0)
                goto out_free_dentry_tree;
 
+       DEBUG("Inserting dentries into hard link group table");
        ret = for_dentry_in_tree(root_dentry, link_group_table_insert, 
-                                &w->image_metadata[w->hdr.image_count - 1].lgt);
+                                w->image_metadata[w->hdr.image_count - 1].lgt);
        if (ret != 0)
                goto out_destroy_imd;
+       DEBUG("Assigning hard link groups");
        assign_link_groups(w->image_metadata[w->hdr.image_count - 1].lgt);
 
        if (flags & WIMLIB_ADD_IMAGE_FLAG_BOOT)
@@ -588,6 +597,7 @@ WIMLIBAPI int wimlib_add_image(WIMStruct *w, const char *dir,
 out_destroy_imd:
        destroy_image_metadata(&w->image_metadata[w->hdr.image_count - 1],
                               w->lookup_table);
+       w->hdr.image_count--;
        return ret;
 out_free_dentry_tree:
        free_dentry_tree(root_dentry, w->lookup_table, true);
index ccca9624121e5beb370d30748b63a8cf96e7cee3..b7b333e246a07f3045384c07ac8e2ada3a12477e 100644 (file)
@@ -268,7 +268,7 @@ void free_security_data(struct wim_security_data *sd)
        if (!sd)
                return;
        wimlib_assert(sd->refcnt >= 1);
-       if (sd->refcnt == 1) {
+       if (--sd->refcnt == 0) {
                u8 **descriptors = sd->descriptors;
                u32 num_entries  = sd->num_entries;
                if (descriptors)
@@ -277,7 +277,5 @@ void free_security_data(struct wim_security_data *sd)
                FREE(sd->sizes);
                FREE(sd->descriptors);
                FREE(sd);
-       } else {
-               sd->refcnt--;
        }
 }
index 12b8418327eaa79dc596982f77f52f610835091e..5507b21242a703436992bf463268becc545f622a 100644 (file)
--- a/src/wim.c
+++ b/src/wim.c
@@ -207,10 +207,8 @@ int wimlib_select_image(WIMStruct *w, int image)
                imd = wim_get_current_image_metadata(w);
                if (!imd->modified) {
                        DEBUG("Freeing image %u", w->current_image);
-                       free_dentry_tree(imd->root_dentry, NULL, false);
-                       imd->root_dentry = NULL;
-                       free_security_data(imd->security_data);
-                       imd->security_data = NULL;
+                       destroy_image_metadata(imd, NULL);
+                       memset(imd, 0, sizeof(*imd));
                }
        }
 
@@ -556,11 +554,8 @@ WIMLIBAPI void wimlib_free(WIMStruct *w)
        FREE(w->xml_data);
        free_wim_info(w->wim_info);
        if (w->image_metadata) {
-               for (i = 0; i < w->hdr.image_count; i++) {
-                       free_dentry_tree(w->image_metadata[i].root_dentry, 
-                                        NULL, false);
-                       free_security_data(w->image_metadata[i].security_data);
-               }
+               for (i = 0; i < w->hdr.image_count; i++)
+                       destroy_image_metadata(&w->image_metadata[i], NULL);
                FREE(w->image_metadata);
        }
        FREE(w);
index ec1f2807597a6cdd9b3330e492a627f2accbde8a..86b0716d0d3b148efb817cf106a87e2fe53eefc2 100644 (file)
@@ -346,6 +346,9 @@ extern int write_integrity_table(FILE *out, u64 end_header_offset,
                                 int show_progress);
 extern int check_wim_integrity(WIMStruct *w, int show_progress, int *status);
 
+/* modify.c */
+extern void destroy_image_metadata(struct image_metadata *imd,
+                                  struct lookup_table *lt);
 
 /* resource.c */
 extern const u8 *get_resource_entry(const u8 *p, struct resource_entry *entry);