+struct lte_overwrite_prepare_args {
+ WIMStruct *wim;
+ off_t end_offset;
+ struct list_head *stream_list;
+};
+
+static int
+lte_overwrite_prepare(struct wim_lookup_table_entry *lte, void *arg)
+{
+ struct lte_overwrite_prepare_args *args = arg;
+
+ if (lte->resource_location == RESOURCE_IN_WIM &&
+ lte->wim == args->wim &&
+ lte->resource_entry.offset + lte->resource_entry.size > args->end_offset)
+ {
+ #ifdef ENABLE_ERROR_MESSAGES
+ ERROR("The following resource is after the XML data:");
+ print_lookup_table_entry(lte, stderr);
+ #endif
+ return WIMLIB_ERR_RESOURCE_ORDER;
+ }
+
+ lte->out_refcnt = lte->refcnt;
+ memcpy(<e->output_resource_entry, <e->resource_entry,
+ sizeof(struct resource_entry));
+ if (!(lte->resource_entry.flags & WIM_RESHDR_FLAG_METADATA))
+ if (lte->resource_location != RESOURCE_IN_WIM || lte->wim != args->wim)
+ list_add(<e->staging_list, args->stream_list);
+ return 0;
+}
+
+static int
+wim_prepare_streams(WIMStruct *wim, off_t end_offset,
+ struct list_head *stream_list)
+{
+ struct lte_overwrite_prepare_args args = {
+ .wim = wim,
+ .end_offset = end_offset,
+ .stream_list = stream_list,
+ };
+ int ret;
+
+ for (int i = 0; i < wim->hdr.image_count; i++) {
+ ret = lte_overwrite_prepare(wim->image_metadata[i]->metadata_lte,
+ &args);
+ if (ret)
+ return ret;
+ }
+ return for_lookup_table_entry(wim->lookup_table,
+ lte_overwrite_prepare, &args);
+}
+
+struct stream_size_table {
+ struct hlist_head *array;
+ size_t num_entries;
+ size_t capacity;
+};
+
+static int
+init_stream_size_table(struct stream_size_table *tab, size_t capacity)
+{
+ tab->array = CALLOC(capacity, sizeof(tab->array[0]));
+ if (!tab->array)
+ return WIMLIB_ERR_NOMEM;
+ tab->num_entries = 0;
+ tab->capacity = capacity;
+ return 0;
+}
+
+static void
+destroy_stream_size_table(struct stream_size_table *tab)
+{
+ FREE(tab->array);
+}
+
+static int
+stream_size_table_insert(struct wim_lookup_table_entry *lte, void *_tab)
+{
+ struct stream_size_table *tab = _tab;
+ size_t pos;
+ struct wim_lookup_table_entry *hashed_lte;
+ struct hlist_node *tmp;
+
+ pos = hash_u64(wim_resource_size(lte)) % tab->capacity;
+ lte->unique_size = 1;
+ hlist_for_each_entry(hashed_lte, tmp, &tab->array[pos], hash_list_2) {
+ if (wim_resource_size(hashed_lte) == wim_resource_size(lte)) {
+ lte->unique_size = 0;
+ hashed_lte->unique_size = 0;
+ break;
+ }
+ }
+
+ hlist_add_head(<e->hash_list_2, &tab->array[pos]);
+ tab->num_entries++;
+ return 0;
+}
+
+
+struct find_streams_ctx {
+ struct list_head stream_list;
+ struct stream_size_table stream_size_tab;
+};
+
+static int
+inode_find_streams_to_write(struct wim_inode *inode,
+ struct wim_lookup_table *table,
+ struct list_head *stream_list,
+ struct stream_size_table *tab)
+{
+ struct wim_lookup_table_entry *lte;
+ for (unsigned i = 0; i <= inode->i_num_ads; i++) {
+ lte = inode_stream_lte(inode, i, table);
+ if (lte) {
+ if (lte->out_refcnt == 0) {
+ if (lte->unhashed)
+ stream_size_table_insert(lte, tab);
+ list_add_tail(<e->write_streams_list, stream_list);
+ }
+ lte->out_refcnt += inode->i_nlink;
+ }
+ }
+ return 0;
+}