}
}
-static inline bool
-blob_is_in_file(const struct blob_descriptor *blob)
-{
- return blob->blob_location == BLOB_IN_FILE_ON_DISK
-#ifdef __WIN32__
- || blob->blob_location == BLOB_IN_WINNT_FILE_ON_DISK
- || blob->blob_location == BLOB_WIN32_ENCRYPTED
-#endif
- ;
-}
-
static void
init_done_with_file_info(struct list_head *blob_list)
{
* identical to another blob already being written or one that would be filtered
* out of the output WIM using blob_filtered() with the context @filter_ctx.
* Each such duplicate blob will be removed from @blob_list, its reference count
- * transfered to the pre-existing duplicate blob, its memory freed, and will not
- * be written. Alternatively, if a blob in @blob_list is a duplicate with any
- * blob in @blob_table that has not been marked for writing or would not be
+ * transferred to the pre-existing duplicate blob, its memory freed, and will
+ * not be written. Alternatively, if a blob in @blob_list is a duplicate with
+ * any blob in @blob_table that has not been marked for writing or would not be
* hard-filtered, it is freed and the pre-existing duplicate is written instead,
* taking ownership of the reference count and slot in the @blob_table_list.
*
struct wim_image_metadata *imd;
imd = wim->image_metadata[i - 1];
- /* Build a new metadata resource only if image was modified from
- * the original (or was newly added). Otherwise just copy the
- * existing one. */
- if (imd->modified) {
+ if (is_image_dirty(imd)) {
+ /* The image was modified from the original, or was
+ * newly added, so we have to build and write a new
+ * metadata resource. */
ret = write_metadata_resource(wim, i,
write_resource_flags);
- } else if (write_flags & WIMLIB_WRITE_FLAG_UNSAFE_COMPACT) {
- /* For compactions, existing metadata resources are
- * written along with the existing file resources. */
- ret = 0;
- } else if (write_flags & WIMLIB_WRITE_FLAG_APPEND) {
- blob_set_out_reshdr_for_reuse(imd->metadata_blob);
+ } else if (is_image_unchanged_from_wim(imd, wim) &&
+ (write_flags & (WIMLIB_WRITE_FLAG_UNSAFE_COMPACT |
+ WIMLIB_WRITE_FLAG_APPEND)))
+ {
+ /* The metadata resource is already in the WIM file.
+ * For appends, we don't need to write it at all. For
+ * compactions, we re-write existing metadata resources
+ * along with the existing file resources, not here. */
+ if (write_flags & WIMLIB_WRITE_FLAG_APPEND)
+ blob_set_out_reshdr_for_reuse(imd->metadata_blob);
ret = 0;
} else {
+ /* The metadata resource is in a WIM file other than the
+ * one being written to. We need to rewrite it,
+ * possibly compressed differently; but rebuilding the
+ * metadata itself isn't necessary. */
ret = write_wim_resource(imd->metadata_blob,
&wim->out_fd,
wim->out_compression_type,
wim_has_solid_resources(wim);
}
+/* Update the images' filecount/bytecount stats (in the XML info) to take into
+ * account any recent modifications. */
+static int
+update_image_stats(WIMStruct *wim)
+{
+ if (!wim_has_metadata(wim))
+ return 0;
+ for (int i = 0; i < wim->hdr.image_count; i++) {
+ struct wim_image_metadata *imd = wim->image_metadata[i];
+ if (imd->stats_outdated) {
+ int ret = xml_update_image_info(wim, i + 1);
+ if (ret)
+ return ret;
+ imd->stats_outdated = false;
+ }
+ }
+ return 0;
+}
+
/* Write a standalone WIM or split WIM (SWM) part to a new file or to a file
* descriptor. */
int
wim->out_hdr.boot_idx = 1;
}
+ /* Update image stats if needed. */
+ ret = update_image_stats(wim);
+ if (ret)
+ return ret;
+
/* Set up the output file descriptor. */
if (write_flags & WIMLIB_WRITE_FLAG_FILE_DESCRIPTOR) {
/* File descriptor was explicitly provided. */
return write_standalone_wim(wim, &fd, image, write_flags, num_threads);
}
+/* Have there been any changes to images in the specified WIM, including updates
+ * as well as deletions and additions of entire images, but excluding changes to
+ * the XML document? */
static bool
-any_images_modified(WIMStruct *wim)
+any_images_changed(WIMStruct *wim)
{
+ if (wim->image_deletion_occurred)
+ return true;
for (int i = 0; i < wim->hdr.image_count; i++)
- if (wim->image_metadata[i]->modified)
+ if (!is_image_unchanged_from_wim(wim->image_metadata[i], wim))
return true;
return false;
}
* with the file resources. */
for (int i = 0; i < wim->hdr.image_count; i++) {
struct wim_image_metadata *imd = wim->image_metadata[i];
- if (!imd->modified) {
+ if (is_image_unchanged_from_wim(imd, wim)) {
fully_reference_blob_for_write(imd->metadata_blob,
&blob_list);
}
* don't allow any file and metadata resources to appear without
* returning WIMLIB_ERR_RESOURCE_ORDER (due to the fact that we
* would otherwise overwrite these resources). */
- if (!wim->image_deletion_occurred && !any_images_modified(wim)) {
- /* If no images have been modified and no images have
- * been deleted, a new blob table does not need to be
- * written. We shall write the new XML data and
- * optional integrity table immediately after the blob
- * table. Note that this may overwrite an existing
- * integrity table. */
+ if (!any_images_changed(wim)) {
+ /* If no images have been modified, added, or deleted,
+ * then a new blob table does not need to be written.
+ * We shall write the new XML data and optional
+ * integrity table immediately after the blob table.
+ * Note that this may overwrite an existing integrity
+ * table. */
old_wim_end = old_blob_table_end;
write_flags |= WIMLIB_WRITE_FLAG_NO_NEW_BLOBS;
} else if (wim_has_integrity_table(wim)) {
wimlib_assert(list_empty(&blob_list));
}
+ /* Update image stats if needed. */
+ ret = update_image_stats(wim);
+ if (ret)
+ goto out;
+
ret = open_wim_writable(wim, wim->filename, O_RDWR);
if (ret)
goto out;