split, join: Read input WIM(s) sequentially
authorEric Biggers <ebiggers3@gmail.com>
Thu, 28 Mar 2013 23:14:46 +0000 (18:14 -0500)
committerEric Biggers <ebiggers3@gmail.com>
Thu, 28 Mar 2013 23:14:46 +0000 (18:14 -0500)
src/extract_image.c
src/join.c
src/lookup_table.c
src/lookup_table.h
src/split.c

index 5f31176..d331dc0 100644 (file)
@@ -569,54 +569,6 @@ maybe_apply_dentry(struct wim_dentry *dentry, void *arg)
        return ret;
 }
 
-static int
-cmp_streams_by_wim_position(const void *p1, const void *p2)
-{
-       const struct wim_lookup_table_entry *lte1, *lte2;
-       lte1 = *(const struct wim_lookup_table_entry**)p1;
-       lte2 = *(const struct wim_lookup_table_entry**)p2;
-       if (lte1->resource_entry.offset < lte2->resource_entry.offset)
-               return -1;
-       else if (lte1->resource_entry.offset > lte2->resource_entry.offset)
-               return 1;
-       else
-               return 0;
-}
-
-static int
-sort_stream_list_by_wim_position(struct list_head *stream_list)
-{
-       struct list_head *cur;
-       size_t num_streams;
-       struct wim_lookup_table_entry **array;
-       size_t i;
-       size_t array_size;
-
-       num_streams = 0;
-       list_for_each(cur, stream_list)
-               num_streams++;
-       array_size = num_streams * sizeof(array[0]);
-       array = MALLOC(array_size);
-       if (!array) {
-               ERROR("Failed to allocate %zu bytes to sort stream entries",
-                     array_size);
-               return WIMLIB_ERR_NOMEM;
-       }
-       cur = stream_list->next;
-       for (i = 0; i < num_streams; i++) {
-               array[i] = container_of(cur, struct wim_lookup_table_entry, staging_list);
-               cur = cur->next;
-       }
-
-       qsort(array, num_streams, sizeof(array[0]), cmp_streams_by_wim_position);
-
-       INIT_LIST_HEAD(stream_list);
-       for (i = 0; i < num_streams; i++)
-               list_add_tail(&array[i]->staging_list, stream_list);
-       FREE(array);
-       return 0;
-}
-
 static void
 calculate_bytes_to_extract(struct list_head *stream_list,
                           int extract_flags,
index 0f47f0b..e566ba2 100644 (file)
@@ -40,7 +40,9 @@ static int
 lookup_table_join(struct wim_lookup_table *table,
                  struct wim_lookup_table *new)
 {
-       return for_lookup_table_entry(new, move_lte_to_table, table);
+       for_lookup_table_entry(new, move_lte_to_table, table);
+       new->num_entries = 0;
+       return 0;
 }
 
 /*
@@ -124,8 +126,10 @@ join_wims(WIMStruct **swms, unsigned num_swms,
                }
                swms[i]->out_fp = joined_wim->out_fp;
                swms[i]->hdr.part_number = 1;
-               ret = for_lookup_table_entry(swms[i]->lookup_table,
-                                            copy_resource, swms[i]);
+
+               ret = for_lookup_table_entry_pos_sorted(swms[i]->lookup_table,
+                                                       copy_resource,
+                                                       swms[i]);
                swms[i]->out_fp = NULL;
 
                if (i != 0) {
index b22def2..064215e 100644 (file)
@@ -28,6 +28,7 @@
 #include "lookup_table.h"
 #include "buffer_io.h"
 #include <errno.h>
+#include <stdlib.h>
 
 #ifdef WITH_FUSE
 #include <unistd.h>
@@ -273,6 +274,93 @@ for_lookup_table_entry(struct wim_lookup_table *table,
        return 0;
 }
 
+static int
+cmp_streams_by_wim_position(const void *p1, const void *p2)
+{
+       const struct wim_lookup_table_entry *lte1, *lte2;
+       lte1 = *(const struct wim_lookup_table_entry**)p1;
+       lte2 = *(const struct wim_lookup_table_entry**)p2;
+       if (lte1->resource_entry.offset < lte2->resource_entry.offset)
+               return -1;
+       else if (lte1->resource_entry.offset > lte2->resource_entry.offset)
+               return 1;
+       else
+               return 0;
+}
+
+int
+sort_stream_list_by_wim_position(struct list_head *stream_list)
+{
+       struct list_head *cur;
+       size_t num_streams;
+       struct wim_lookup_table_entry **array;
+       size_t i;
+       size_t array_size;
+
+       num_streams = 0;
+       list_for_each(cur, stream_list)
+               num_streams++;
+       array_size = num_streams * sizeof(array[0]);
+       array = MALLOC(array_size);
+       if (!array) {
+               ERROR("Failed to allocate %zu bytes to sort stream entries",
+                     array_size);
+               return WIMLIB_ERR_NOMEM;
+       }
+       cur = stream_list->next;
+       for (i = 0; i < num_streams; i++) {
+               array[i] = container_of(cur, struct wim_lookup_table_entry, staging_list);
+               cur = cur->next;
+       }
+
+       qsort(array, num_streams, sizeof(array[0]), cmp_streams_by_wim_position);
+
+       INIT_LIST_HEAD(stream_list);
+       for (i = 0; i < num_streams; i++)
+               list_add_tail(&array[i]->staging_list, stream_list);
+       FREE(array);
+       return 0;
+}
+
+
+static int
+add_lte_to_array(struct wim_lookup_table_entry *lte,
+                void *_pp)
+{
+       struct wim_lookup_table_entry ***pp = _pp;
+       *(*pp)++ = lte;
+       return 0;
+}
+
+/* Iterate through the lookup table entries, but first sort them by stream
+ * offset in the WIM.  Caution: this is intended to be used when the stream
+ * offset field has actually been set. */
+int
+for_lookup_table_entry_pos_sorted(struct wim_lookup_table *table,
+                                 int (*visitor)(struct wim_lookup_table_entry *,
+                                                void *),
+                                 void *arg)
+{
+       struct wim_lookup_table_entry **lte_array, **p;
+       size_t num_streams = table->num_entries;
+       int ret;
+
+       lte_array = MALLOC(num_streams * sizeof(lte_array[0]));
+       if (!lte_array)
+               return WIMLIB_ERR_NOMEM;
+       p = lte_array;
+       for_lookup_table_entry(table, add_lte_to_array, &p);
+
+       wimlib_assert(p == lte_array + num_streams);
+
+       qsort(lte_array, num_streams, sizeof(lte_array[0]),
+             cmp_streams_by_wim_position);
+       ret = 0;
+       for (size_t i = 0; i < num_streams && ret == 0; i++)
+               ret = visitor(lte_array[i], arg);
+       FREE(lte_array);
+       return ret;
+}
 
 /*
  * Reads the lookup table from a WIM file.
index dad230f..eacd9aa 100644 (file)
@@ -274,6 +274,7 @@ static inline void
 lookup_table_unlink(struct wim_lookup_table *table, struct wim_lookup_table_entry *lte)
 {
        hlist_del(&lte->hash_list);
+       wimlib_assert(table->num_entries != 0);
        table->num_entries--;
 }
 
@@ -295,6 +296,15 @@ for_lookup_table_entry(struct wim_lookup_table *table,
                       int (*visitor)(struct wim_lookup_table_entry *, void *),
                       void *arg);
 
+extern int
+sort_stream_list_by_wim_position(struct list_head *stream_list);
+
+extern int
+for_lookup_table_entry_pos_sorted(struct wim_lookup_table *table,
+                                 int (*visitor)(struct wim_lookup_table_entry *,
+                                                void *),
+                                 void *arg);
+
 extern struct wim_lookup_table_entry *
 __lookup_resource(const struct wim_lookup_table *table, const u8 hash[]);
 
index 6054d36..c055783 100644 (file)
@@ -200,8 +200,9 @@ wimlib_split(WIMStruct *w, const tchar *swm_name,
                list_add_tail(&metadata_lte->staging_list, &args.lte_list);
        }
 
-       ret = for_lookup_table_entry(w->lookup_table,
-                                    copy_resource_to_swm, &args);
+       ret = for_lookup_table_entry_pos_sorted(w->lookup_table,
+                                               copy_resource_to_swm,
+                                               &args);
        if (ret != 0)
                goto out;