X-Git-Url: https://wimlib.net/git/?p=wimlib;a=blobdiff_plain;f=src%2Flookup_table.c;h=89b57b4e65ee757dc0485c61903750b866319091;hp=4d62ca5b29c7ede86bfd0fcfb460d40c60f425d9;hb=1f2091f5bb860769e20105af2d9eff3a0872c57b;hpb=062465170ddb4520ca6fbc64a0f6e27e786de101 diff --git a/src/lookup_table.c b/src/lookup_table.c index 4d62ca5b..89b57b4e 100644 --- a/src/lookup_table.c +++ b/src/lookup_table.c @@ -88,8 +88,11 @@ clone_lookup_table_entry(const struct wim_lookup_table_entry *old) switch (new->resource_location) { #ifdef __WIN32__ case RESOURCE_WIN32: + case RESOURCE_WIN32_ENCRYPTED: #endif +#ifdef WITH_FUSE case RESOURCE_IN_STAGING_FILE: +#endif case RESOURCE_IN_FILE_ON_DISK: BUILD_BUG_ON((void*)&old->file_on_disk != (void*)&old->staging_file_name); @@ -323,8 +326,11 @@ for_lookup_table_entry_pos_sorted(struct wim_lookup_table *table, 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++) + for (size_t i = 0; i < num_streams; i++) { ret = visitor(lte_array[i], arg); + if (ret) + break; + } FREE(lte_array); return ret; } @@ -589,23 +595,22 @@ write_lookup_table(WIMStruct *w, int image, struct resource_entry *out_res_entry return 0; } - int -lte_zero_real_refcnt(struct wim_lookup_table_entry *lte, void *ignore) +lte_zero_real_refcnt(struct wim_lookup_table_entry *lte, void *_ignore) { lte->real_refcnt = 0; return 0; } int -lte_zero_out_refcnt(struct wim_lookup_table_entry *lte, void *ignore) +lte_zero_out_refcnt(struct wim_lookup_table_entry *lte, void *_ignore) { lte->out_refcnt = 0; return 0; } int -lte_free_extracted_file(struct wim_lookup_table_entry *lte, void *ignore) +lte_free_extracted_file(struct wim_lookup_table_entry *lte, void *_ignore) { if (lte->extracted_file != NULL) { FREE(lte->extracted_file); @@ -634,7 +639,8 @@ print_lookup_table_entry(const struct wim_lookup_table_entry *lte, FILE *out) tfprintf(out, T("Reference Count = %u\n"), lte->refcnt); if (lte->unhashed) { - tfprintf(out, T("(Unhashed, back ptr at %p)\n"), lte->my_ptr); + tfprintf(out, T("(Unhashed: inode %p, stream_id = %u)\n"), + lte->back_inode, lte->back_stream_id); } else { tfprintf(out, T("Hash = 0x")); print_hash(lte->hash, out); @@ -661,6 +667,7 @@ print_lookup_table_entry(const struct wim_lookup_table_entry *lte, FILE *out) break; #ifdef __WIN32__ case RESOURCE_WIN32: + case RESOURCE_WIN32_ENCRYPTED: #endif case RESOURCE_IN_FILE_ON_DISK: tfprintf(out, T("File on Disk = `%"TS"'\n"), @@ -892,14 +899,78 @@ lookup_table_total_stream_size(struct wim_lookup_table *table) return total_size; } -void -free_lte_list(struct list_head *list) +struct wim_lookup_table_entry ** +retrieve_lte_pointer(struct wim_lookup_table_entry *lte) { - struct wim_lookup_table_entry *lte, *tmp; + wimlib_assert(lte->unhashed); + struct wim_inode *inode = lte->back_inode; + u32 stream_id = lte->back_stream_id; + if (stream_id == 0) + return &inode->i_lte; + else + for (u16 i = 0; i < inode->i_num_ads; i++) + if (inode->i_ads_entries[i].stream_id == stream_id) + return &inode->i_ads_entries[i].lte; + wimlib_assert(0); + return NULL; +} - list_for_each_entry_safe(lte, tmp, list, staging_list) { - DEBUG("%p", lte); +/* Calculate the SHA1 message digest of a stream and move it from the list of + * unhashed streams to the stream lookup table, possibly joining it with an + * existing lookup table entry for an identical stream. + * + * @lte: An unhashed lookup table entry. + * @lookup_table: Lookup table for the WIM. + * @lte_ret: On success, write a pointer to the resulting lookup table + * entry to this location. This will be the same as @lte + * if it was inserted into the lookup table, or different if + * a duplicate stream was found. + * + * Returns 0 on success; nonzero if there is an error reading the stream. + */ +int +hash_unhashed_stream(struct wim_lookup_table_entry *lte, + struct wim_lookup_table *lookup_table, + struct wim_lookup_table_entry **lte_ret) +{ + int ret; + struct wim_lookup_table_entry *duplicate_lte; + struct wim_lookup_table_entry **back_ptr; + + wimlib_assert(lte->unhashed); + + /* back_ptr must be saved because @back_inode and @back_stream_id are in + * union with the SHA1 message digest and will no longer be valid once + * the SHA1 has been calculated. */ + back_ptr = retrieve_lte_pointer(lte); + + ret = sha1_resource(lte); + if (ret) + return ret; + + /* Look for a duplicate stream */ + duplicate_lte = __lookup_resource(lookup_table, lte->hash); + list_del(<e->unhashed_list); + if (duplicate_lte) { + /* We have a duplicate stream. Transfer the reference counts + * from this stream to the duplicate, update the reference to + * this stream (in an inode or ads_entry) to point to the + * duplicate, then free this stream. */ + wimlib_assert(!(duplicate_lte->unhashed)); + duplicate_lte->refcnt += lte->refcnt; + duplicate_lte->out_refcnt += lte->refcnt; + *back_ptr = duplicate_lte; free_lookup_table_entry(lte); + lte = duplicate_lte; + } else { + /* No duplicate stream, so we need to insert + * this stream into the lookup table and treat + * it as a hashed stream. */ + lookup_table_insert(lookup_table, lte); + lte->unhashed = 0; + } + if (lte_ret) + *lte_ret = lte; + return 0; } - INIT_LIST_HEAD(list); -} +