From: Eric Biggers Date: Thu, 28 Mar 2013 23:14:46 +0000 (-0500) Subject: split, join: Read input WIM(s) sequentially X-Git-Tag: v1.3.3~99 X-Git-Url: https://wimlib.net/git/?p=wimlib;a=commitdiff_plain;h=a8972bde4b080d2dd33a7500705d431b0f1fe901 split, join: Read input WIM(s) sequentially --- diff --git a/src/extract_image.c b/src/extract_image.c index 5f311766..d331dc0d 100644 --- a/src/extract_image.c +++ b/src/extract_image.c @@ -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, diff --git a/src/join.c b/src/join.c index 0f47f0b7..e566ba28 100644 --- a/src/join.c +++ b/src/join.c @@ -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) { diff --git a/src/lookup_table.c b/src/lookup_table.c index b22def29..064215ec 100644 --- a/src/lookup_table.c +++ b/src/lookup_table.c @@ -28,6 +28,7 @@ #include "lookup_table.h" #include "buffer_io.h" #include +#include #ifdef WITH_FUSE #include @@ -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. diff --git a/src/lookup_table.h b/src/lookup_table.h index dad230f7..eacd9aa4 100644 --- a/src/lookup_table.h +++ b/src/lookup_table.h @@ -274,6 +274,7 @@ static inline void lookup_table_unlink(struct wim_lookup_table *table, struct wim_lookup_table_entry *lte) { hlist_del(<e->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[]); diff --git a/src/split.c b/src/split.c index 6054d368..c0557837 100644 --- a/src/split.c +++ b/src/split.c @@ -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;