#include "lookup_table.h"
#include "buffer_io.h"
#include <errno.h>
+#include <stdlib.h>
#ifdef WITH_FUSE
#include <unistd.h>
struct wim_lookup_table *table;
struct hlist_head *array;
- table = MALLOC(sizeof(struct wim_lookup_table));
+ table = CALLOC(1, sizeof(struct wim_lookup_table));
if (table) {
array = CALLOC(capacity, sizeof(array[0]));
if (array) {
#ifdef WITH_FUSE
if (lte->resource_location == RESOURCE_IN_STAGING_FILE) {
unlink(lte->staging_file_name);
- list_del(<e->staging_list);
+ list_del(<e->unhashed_list);
}
#endif
free_lookup_table_entry(lte);
wimlib_assert(lte != NULL);
wimlib_assert(lte->refcnt != 0);
if (--lte->refcnt == 0) {
- lookup_table_unlink(table, lte);
+ if (!lte->unhashed)
+ lookup_table_unlink(table, lte);
#ifdef WITH_FUSE
if (lte->num_opened_fds == 0)
#endif
{
wimlib_assert2(!(lte->resource_entry.flags & WIM_RESHDR_FLAG_METADATA));
ret = visitor(lte, arg);
- if (ret != 0)
+ if (ret)
return ret;
}
}
return 0;
}
+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
+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.
w->current_image + 1,
cur_entry->resource_entry.offset);
w->image_metadata[
- w->current_image++].metadata_lte = cur_entry;
+ w->current_image++]->metadata_lte = cur_entry;
} else {
/* Lookup table entry for a stream that is not a
* metadata resource */
if (start_offset == -1)
return WIMLIB_ERR_WRITE;
+ /* Write lookup table entries for metadata resources */
if (image == WIMLIB_ALL_IMAGES) {
start_image = 1;
end_image = w->hdr.image_count;
for (int i = start_image; i <= end_image; i++) {
struct wim_lookup_table_entry *metadata_lte;
- metadata_lte = w->image_metadata[i - 1].metadata_lte;
+ metadata_lte = w->image_metadata[i - 1]->metadata_lte;
metadata_lte->out_refcnt = 1;
metadata_lte->output_resource_entry.flags |= WIM_RESHDR_FLAG_METADATA;
ret = write_lookup_table_entry(metadata_lte, out);
return ret;
}
+ /* Write lookup table entries for other resources */
ret = for_lookup_table_entry(w->lookup_table, write_lookup_table_entry, out);
if (ret)
return ret;
+ /* Fill in the resource entry for the lookup table itself */
end_offset = ftello(out);
if (end_offset == -1)
return WIMLIB_ERR_WRITE;
tfprintf(out, T("Part Number = %hu\n"), lte->part_number);
tfprintf(out, T("Reference Count = %u\n"), lte->refcnt);
- tfprintf(out, T("Hash = 0x"));
- print_hash(lte->hash, out);
- tputc(T('\n'), out);
+ if (lte->unhashed) {
+ tfprintf(out, T("(Unhashed, back ptr at %p)\n"), lte->my_ptr);
+ } else {
+ tfprintf(out, T("Hash = 0x"));
+ print_hash(lte->hash, out);
+ tputc(T('\n'), out);
+ }
tfprintf(out, T("Flags = "));
u8 flags = lte->resource_entry.flags;
for_lookup_table_entry(table, lte_add_stream_size, &total_size);
return total_size;
}
+
+void
+free_lte_list(struct list_head *list)
+{
+ struct wim_lookup_table_entry *lte, *tmp;
+
+ list_for_each_entry_safe(lte, tmp, list, staging_list) {
+ DEBUG("%p", lte);
+ free_lookup_table_entry(lte);
+}
+ INIT_LIST_HEAD(list);
+}