+ }
+
+ hlist_add_head(<e->hash_list_2, &tab->array[pos]);
+ tab->num_entries++;
+ return 0;
+}
+
+
+struct lte_overwrite_prepare_args {
+ WIMStruct *wim;
+ off_t end_offset;
+ struct list_head stream_list;
+ struct stream_size_table stream_size_tab;
+};
+
+/* First phase of preparing streams for an in-place overwrite. This is called
+ * on all streams, both hashed and unhashed, except the metadata resources. */
+static int
+lte_overwrite_prepare(struct wim_lookup_table_entry *lte, void *_args)
+{
+ struct lte_overwrite_prepare_args *args = _args;
+
+ wimlib_assert(!(lte->resource_entry.flags & WIM_RESHDR_FLAG_METADATA));
+ if (lte->resource_location != RESOURCE_IN_WIM || lte->wim != args->wim)
+ list_add_tail(<e->write_streams_list, &args->stream_list);
+ lte->out_refcnt = lte->refcnt;
+ stream_size_table_insert(lte, &args->stream_size_tab);
+ return 0;
+}
+
+/* Second phase of preparing streams for an in-place overwrite. This is called
+ * on existing metadata resources and hashed streams, but not unhashed streams.
+ *
+ * NOTE: lte->output_resource_entry is in union with lte->hash_list_2, so
+ * lte_overwrite_prepare_2() must be called after lte_overwrite_prepare(), as
+ * the latter uses lte->hash_list_2, while the former expects to set
+ * lte->output_resource_entry. */
+static int
+lte_overwrite_prepare_2(struct wim_lookup_table_entry *lte, void *_args)
+{
+ struct lte_overwrite_prepare_args *args = _args;
+
+ if (lte->resource_location == RESOURCE_IN_WIM && lte->wim == args->wim) {
+ /* We can't do an in place overwrite on the WIM if there are
+ * streams after the XML data. */
+ if (lte->resource_entry.offset +
+ lte->resource_entry.size > args->end_offset)
+ {
+ if (wimlib_print_errors) {
+ ERROR("The following resource is after the XML data:");
+ print_lookup_table_entry(lte, stderr);
+ }
+ return WIMLIB_ERR_RESOURCE_ORDER;
+ }
+ copy_resource_entry(<e->output_resource_entry,
+ <e->resource_entry);
+ }
+ return 0;
+}
+
+/* Given a WIM that we are going to overwrite in place with zero or more
+ * additional streams added, construct a list the list of new unique streams
+ * ('struct wim_lookup_table_entry's) that must be written, plus any unhashed
+ * streams that need to be added but may be identical to other hashed or
+ * unhashed streams. These unhashed streams are checksummed while the streams
+ * are being written. To aid this process, the member @unique_size is set to 1
+ * on streams that have a unique size and therefore must be written.
+ *
+ * The out_refcnt member of each 'struct wim_lookup_table_entry' is set to
+ * indicate the number of times the stream is referenced in only the streams
+ * that are being written; this may still be adjusted later when unhashed
+ * streams are being resolved.
+ */
+static int
+prepare_streams_for_overwrite(WIMStruct *wim, off_t end_offset,
+ struct list_head *stream_list)
+{
+ int ret;
+ struct lte_overwrite_prepare_args args;
+ unsigned i;
+
+ args.wim = wim;
+ args.end_offset = end_offset;
+ ret = init_stream_size_table(&args.stream_size_tab,
+ wim->lookup_table->capacity);
+ if (ret)
+ return ret;
+
+ INIT_LIST_HEAD(&args.stream_list);
+ for (i = 0; i < wim->hdr.image_count; i++) {
+ struct wim_image_metadata *imd;
+ struct wim_lookup_table_entry *lte;