+ /* Set appropriate magic number. */
+ if (write_flags & WIMLIB_WRITE_FLAG_PIPABLE)
+ wim->hdr.magic = PWM_MAGIC;
+ else
+ wim->hdr.magic = WIM_MAGIC;
+
+ /* Clear header flags that will be set automatically. */
+ wim->hdr.flags &= ~(WIM_HDR_FLAG_METADATA_ONLY |
+ WIM_HDR_FLAG_RESOURCE_ONLY |
+ WIM_HDR_FLAG_SPANNED |
+ WIM_HDR_FLAG_WRITE_IN_PROGRESS);
+
+ /* Set SPANNED header flag if writing part of a split WIM. */
+ if (total_parts != 1)
+ wim->hdr.flags |= WIM_HDR_FLAG_SPANNED;
+
+ /* Set part number and total parts of split WIM. This will be 1 and 1
+ * if the WIM is standalone. */
+ wim->hdr.part_number = part_number;
+ wim->hdr.total_parts = total_parts;
+
+ /* Use GUID if specified; otherwise generate a new one. */
+ if (guid)
+ memcpy(wim->hdr.guid, guid, WIMLIB_GUID_LEN);
+ else
+ randomize_byte_array(wim->hdr.guid, WIMLIB_GUID_LEN);
+
+ /* Clear references to resources that have not been written yet. */
+ zero_resource_entry(&wim->hdr.lookup_table_res_entry);
+ zero_resource_entry(&wim->hdr.xml_res_entry);
+ zero_resource_entry(&wim->hdr.boot_metadata_res_entry);
+ zero_resource_entry(&wim->hdr.integrity);
+
+ /* Set image count and boot index correctly for single image writes. */
+ if (image != WIMLIB_ALL_IMAGES) {
+ wim->hdr.image_count = 1;
+ if (wim->hdr.boot_idx == image)
+ wim->hdr.boot_idx = 1;
+ else
+ wim->hdr.boot_idx = 0;
+ }
+
+ /* Split WIMs can't be bootable. */
+ if (total_parts != 1)
+ wim->hdr.boot_idx = 0;
+
+ /* Initialize output file descriptor. */
+ if (write_flags & WIMLIB_WRITE_FLAG_FILE_DESCRIPTOR) {
+ /* File descriptor was explicitly provided. Return error if
+ * file descriptor is not seekable, unless writing a pipable WIM
+ * was requested. */
+ wim->out_fd.fd = *(const int*)path_or_fd;
+ wim->out_fd.offset = 0;
+ if (!filedes_is_seekable(&wim->out_fd)) {
+ ret = WIMLIB_ERR_INVALID_PARAM;
+ if (!(write_flags & WIMLIB_WRITE_FLAG_PIPABLE))
+ goto out_restore_hdr;
+ if (write_flags & WIMLIB_WRITE_FLAG_CHECK_INTEGRITY) {
+ ERROR("Can't include integrity check when "
+ "writing pipable WIM to pipe!");
+ goto out_restore_hdr;
+ }
+ }
+
+ } else {
+ /* Filename of WIM to write was provided; open file descriptor
+ * to it. */
+ ret = open_wim_writable(wim, (const tchar*)path_or_fd,
+ O_TRUNC | O_CREAT | O_RDWR);
+ if (ret)
+ goto out_restore_hdr;
+ }
+
+ /* Write initial header. This is merely a "dummy" header since it
+ * doesn't have all the information yet, so it will be overwritten later
+ * (unless writing a pipable WIM). */
+ if (!(write_flags & WIMLIB_WRITE_FLAG_PIPABLE))
+ wim->hdr.flags |= WIM_HDR_FLAG_WRITE_IN_PROGRESS;
+ ret = write_wim_header(&wim->hdr, &wim->out_fd);
+ wim->hdr.flags &= ~WIM_HDR_FLAG_WRITE_IN_PROGRESS;
+ if (ret)
+ goto out_restore_hdr;
+
+ if (stream_list_override) {
+ struct wim_lookup_table_entry *lte;
+ INIT_LIST_HEAD(<_stream_list_override);
+ list_for_each_entry(lte, stream_list_override,
+ write_streams_list)
+ {
+ list_add_tail(<e->lookup_table_list,
+ <_stream_list_override);
+ }
+ }
+
+ /* Write metadata resources and streams. */
+ if (!(write_flags & WIMLIB_WRITE_FLAG_PIPABLE)) {
+ /* Default case: create a normal (non-pipable) WIM. */
+ ret = write_wim_streams(wim, image, write_flags, num_threads,
+ progress_func, stream_list_override);
+ if (ret)
+ goto out_restore_hdr;
+
+ ret = write_wim_metadata_resources(wim, image, write_flags,
+ progress_func);
+ if (ret)
+ goto out_restore_hdr;
+ } else {
+ /* Non-default case: create pipable WIM. */
+ ret = write_pipable_wim(wim, image, write_flags, num_threads,
+ progress_func, stream_list_override);
+ if (ret)
+ goto out_restore_hdr;
+ write_flags |= WIMLIB_WRITE_FLAG_HEADER_AT_END;
+ }
+
+ if (stream_list_override)
+ stream_list_override = <_stream_list_override;
+
+ /* Write lookup table, XML data, and (optional) integrity table. */
+ ret = finish_write(wim, image, write_flags, progress_func,
+ stream_list_override);
+out_restore_hdr:
+ memcpy(&wim->hdr, &hdr_save, sizeof(struct wim_header));
+ close_wim_writable(wim, write_flags);