*/
/*
- * Copyright (C) 2012, 2013 Eric Biggers
+ * Copyright (C) 2012, 2013, 2014 Eric Biggers
*
* This file is part of wimlib, a library for working with WIM files.
*
if (progress_data->next_progress == progress->write_streams.total_bytes) {
progress_data->next_progress = ~(uint64_t)0;
} else {
+ /* Handle rate-limiting of messages */
+
+ /* Send new message as soon as another 1/128 of the
+ * total has been written. (Arbitrary number.) */
progress_data->next_progress =
- min(progress->write_streams.total_bytes,
- progress->write_streams.completed_bytes +
- progress->write_streams.total_bytes / 100);
+ progress->write_streams.completed_bytes +
+ progress->write_streams.total_bytes / 128;
+
+ /* ... Unless that would be more than 5000000 bytes, in
+ * which case send the next after the next 5000000
+ * bytes. (Another arbitrary number.) */
+ if (progress->write_streams.completed_bytes + 5000000 <
+ progress_data->next_progress)
+ progress_data->next_progress =
+ progress->write_streams.completed_bytes + 5000000;
+
+ /* ... But always send a message as soon as we're
+ * completely done. */
+ if (progress->write_streams.total_bytes <
+ progress_data->next_progress)
+ progress_data->next_progress =
+ progress->write_streams.total_bytes;
}
}
return 0;
*
* @out_ctype
* Compression format to use to write the output streams, specified as one
- * of the WIMLIB_COMPRESSION_TYPE_* constants, excepting
- * WIMLIB_COMPRESSION_TYPE_INVALID but including
- * WIMLIB_COMPRESSION_TYPE_NONE.
+ * of the WIMLIB_COMPRESSION_TYPE_* constants.
+ * WIMLIB_COMPRESSION_TYPE_NONE is allowed.
*
* @out_chunk_size
* Chunk size to use to write the streams. It must be a valid chunk size
* (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
* Use the existing <TOTALBYTES> stored in the in-memory XML
* information, rather than setting it to the offset of the XML
* data being written.
+ * (private) WIMLIB_WRITE_FLAG_OVERWRITE
+ * The existing WIM file is being updated in-place. The entries
+ * from its integrity table may be re-used.
*/
static int
finish_write(WIMStruct *wim, int image, int write_flags,
int ret;
off_t hdr_offset;
int write_resource_flags;
- off_t old_lookup_table_end;
+ off_t old_lookup_table_end = 0;
off_t new_lookup_table_end;
u64 xml_totalbytes;
+ struct integrity_table *old_integrity_table = NULL;
DEBUG("image=%d, write_flags=%08x", image, write_flags);
wim->hdr.boot_idx - 1]->metadata_lte->out_reshdr);
}
- /* Write lookup table. (Save old position first.) */
- old_lookup_table_end = wim->hdr.lookup_table_reshdr.offset_in_wim +
- wim->hdr.lookup_table_reshdr.size_in_wim;
+ /* If overwriting the WIM file containing an integrity table in-place,
+ * we'd like to re-use the information in the old integrity table
+ * instead of recalculating it. But we might overwrite the old
+ * integrity table when we expand the XML data. Read it into memory
+ * just in case. */
+ if ((write_flags & (WIMLIB_WRITE_FLAG_OVERWRITE |
+ WIMLIB_WRITE_FLAG_CHECK_INTEGRITY)) ==
+ (WIMLIB_WRITE_FLAG_OVERWRITE |
+ WIMLIB_WRITE_FLAG_CHECK_INTEGRITY)
+ && wim_has_integrity_table(wim))
+ {
+ old_lookup_table_end = wim->hdr.lookup_table_reshdr.offset_in_wim +
+ wim->hdr.lookup_table_reshdr.size_in_wim;
+ (void)read_integrity_table(wim,
+ old_lookup_table_end - WIM_HEADER_DISK_SIZE,
+ &old_integrity_table);
+ /* If we couldn't read the old integrity table, we can still
+ * re-calculate the full integrity table ourselves. Hence the
+ * ignoring of the return value. */
+ }
+
+ /* Write lookup table. */
if (!(write_flags & WIMLIB_WRITE_FLAG_NO_LOOKUP_TABLE)) {
ret = write_wim_lookup_table(wim, image, write_flags,
&wim->hdr.lookup_table_reshdr,
lookup_table_list);
- if (ret)
+ if (ret) {
+ free_integrity_table(old_integrity_table);
return ret;
+ }
}
/* Write XML data. */
ret = write_wim_xml_data(wim, image, xml_totalbytes,
&wim->hdr.xml_data_reshdr,
write_resource_flags);
- if (ret)
+ if (ret) {
+ free_integrity_table(old_integrity_table);
return ret;
+ }
/* Write integrity table (optional). */
if (write_flags & WIMLIB_WRITE_FLAG_CHECK_INTEGRITY) {
checkpoint_hdr.flags |= WIM_HDR_FLAG_WRITE_IN_PROGRESS;
ret = write_wim_header_at_offset(&checkpoint_hdr,
&wim->out_fd, 0);
- if (ret)
+ if (ret) {
+ free_integrity_table(old_integrity_table);
return ret;
+ }
}
- if (!(write_flags & WIMLIB_WRITE_FLAG_REUSE_INTEGRITY_TABLE))
- old_lookup_table_end = 0;
-
new_lookup_table_end = wim->hdr.lookup_table_reshdr.offset_in_wim +
wim->hdr.lookup_table_reshdr.size_in_wim;
ret = write_integrity_table(wim,
new_lookup_table_end,
- old_lookup_table_end);
+ old_lookup_table_end,
+ old_integrity_table);
+ free_integrity_table(old_integrity_table);
if (ret)
return ret;
} else {
if (ret)
goto out_truncate;
- write_flags |= WIMLIB_WRITE_FLAG_REUSE_INTEGRITY_TABLE;
ret = finish_write(wim, WIMLIB_ALL_IMAGES, write_flags,
&lookup_table_list);
if (ret)