+struct find_streams_ctx {
+ struct list_head stream_list;
+ struct stream_size_table stream_size_tab;
+};
+
+static void
+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;
+ }
+ }
+}
+
+static int
+image_find_streams_to_write(WIMStruct *w)
+{
+ struct find_streams_ctx *ctx;
+ struct wim_image_metadata *imd;
+ struct wim_inode *inode;
+ struct wim_lookup_table_entry *lte;
+
+ ctx = w->private;
+ imd = wim_get_current_image_metadata(w);
+
+ image_for_each_unhashed_stream(lte, imd)
+ lte->out_refcnt = 0;
+
+ /* Go through this image's inodes to find any streams that have not been
+ * found yet. */
+ image_for_each_inode(inode, imd) {
+ inode_find_streams_to_write(inode, w->lookup_table,
+ &ctx->stream_list,
+ &ctx->stream_size_tab);
+ }
+ return 0;
+}
+
+/* Given a WIM that from which one or all of the images is being written, build
+ * the list of unique streams ('struct wim_lookup_table_entry's) that must be
+ * written, plus any unhashed streams that need to be written but may be
+ * identical to other hashed or unhashed streams being written. 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_stream_list(WIMStruct *wim, int image, struct list_head *stream_list)
+{
+ int ret;
+ struct find_streams_ctx ctx;
+
+ for_lookup_table_entry(wim->lookup_table, lte_zero_out_refcnt, NULL);
+ ret = init_stream_size_table(&ctx.stream_size_tab,
+ wim->lookup_table->capacity);
+ if (ret)
+ return ret;
+ for_lookup_table_entry(wim->lookup_table, stream_size_table_insert,
+ &ctx.stream_size_tab);
+ INIT_LIST_HEAD(&ctx.stream_list);
+ wim->private = &ctx;
+ ret = for_image(wim, image, image_find_streams_to_write);
+ destroy_stream_size_table(&ctx.stream_size_tab);
+ if (ret == 0)
+ list_transfer(&ctx.stream_list, stream_list);
+ return ret;
+}
+
+/* Writes the streams for the specified @image in @wim to @wim->out_fp.
+ */
+static int
+write_wim_streams(WIMStruct *wim, int image, int write_flags,
+ unsigned num_threads,
+ wimlib_progress_func_t progress_func)
+{
+ int ret;
+ struct list_head stream_list;
+
+ ret = prepare_stream_list(wim, image, &stream_list);
+ if (ret)
+ return ret;
+ return write_stream_list(&stream_list,
+ wim->lookup_table,
+ wim->out_fp,
+ wimlib_get_compression_type(wim),
+ write_flags,
+ num_threads,
+ progress_func);
+}
+
+/*
+ * Finish writing a WIM file: write the lookup table, xml data, and integrity
+ * table (optional), then overwrite the WIM header.
+ *
+ * write_flags is a bitwise OR of the following:
+ *
+ * (public) WIMLIB_WRITE_FLAG_CHECK_INTEGRITY:
+ * Include an integrity table.
+ *
+ * (public) WIMLIB_WRITE_FLAG_SHOW_PROGRESS:
+ * Show progress information when (if) writing the integrity table.
+ *
+ * (private) WIMLIB_WRITE_FLAG_NO_LOOKUP_TABLE:
+ * Don't write the lookup table.
+ *
+ * (private) WIMLIB_WRITE_FLAG_REUSE_INTEGRITY_TABLE:
+ * When (if) writing the integrity table, re-use entries from the
+ * existing integrity table, if possible.
+ *
+ * (private) WIMLIB_WRITE_FLAG_CHECKPOINT_AFTER_XML:
+ * After writing the XML data but before writing the integrity
+ * table, write a temporary WIM header and flush the stream so that
+ * the WIM is less likely to become corrupted upon abrupt program
+ * termination.
+ *
+ * (private) WIMLIB_WRITE_FLAG_FSYNC:
+ * fsync() the output file before closing it.
+ *
+ */
+int
+finish_write(WIMStruct *w, int image, int write_flags,
+ wimlib_progress_func_t progress_func)
+{
+ int ret;
+ struct wim_header hdr;
+ FILE *out = w->out_fp;