* WIMLIB_ERR_READ
* WIMLIB_ERR_UNEXPECTED_END_OF_FILE
*/
-static int
+int
read_integrity_table(WIMStruct *wim, u64 num_checked_bytes,
struct integrity_table **table_ret)
{
return 0;
invalid:
- ERROR("Integrity table is invalid");
return WIMLIB_ERR_INVALID_INTEGRITY_TABLE;
}
* chunks of the file).
*
* This function can optionally re-use entries from an older integrity table.
- * To do this, ensure that @wim->hdr.integrity_table_reshdr is the resource
- * header for the older table (note: this is an input-output parameter), and set
- * @old_lookup_table_end to the offset of the byte directly following the last
- * byte checked by the old table. If the old integrity table is invalid or
- * cannot be read, a warning is printed and the integrity information is
- * re-calculated.
+ * To do this, specify old_lookup_table_end and old_table.
*
* @wim:
* WIMStruct for the WIM file. @wim->out_fd must be a seekable descriptor
* If nonzero, the offset of the byte directly following the old lookup
* table in the WIM.
*
- * Return values:
- * WIMLIB_ERR_SUCCESS (0)
- * WIMLIB_ERR_NOMEM
- * WIMLIB_ERR_UNEXPECTED_END_OF_FILE
- * WIMLIB_ERR_WRITE
+ * @old_table
+ * Pointer to the old integrity table read into memory, or NULL if not
+ * specified.
*/
int
write_integrity_table(WIMStruct *wim,
off_t new_lookup_table_end,
- off_t old_lookup_table_end)
+ off_t old_lookup_table_end,
+ struct integrity_table *old_table)
{
- struct integrity_table *old_table;
struct integrity_table *new_table;
int ret;
u32 new_table_size;
wimlib_assert(old_lookup_table_end <= new_lookup_table_end);
- old_table = NULL;
- if (wim_has_integrity_table(wim) && old_lookup_table_end != 0) {
- ret = read_integrity_table(wim,
- old_lookup_table_end - WIM_HEADER_DISK_SIZE,
- &old_table);
- if (ret == WIMLIB_ERR_INVALID_INTEGRITY_TABLE) {
- WARNING("Old integrity table is invalid! "
- "Ignoring it");
- } else if (ret != 0) {
- WARNING("Can't read old integrity table! "
- "Ignoring it");
- }
- }
-
ret = calculate_integrity_table(&wim->out_fd, new_lookup_table_end,
old_table, old_lookup_table_end,
&new_table, wim->progfunc, wim->progctx);
if (ret)
- goto out_free_old_table;
+ return ret;
new_table_size = new_table->size;
NULL,
0);
FREE(new_table);
-out_free_old_table:
- FREE(old_table);
DEBUG("ret=%d", ret);
return ret;
}
*/
/*
- * 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.
*
* (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;
-
- if (wim->hdr.integrity_table_reshdr.offset_in_wim <
- wim->hdr.xml_data_reshdr.offset_in_wim +
- wim->hdr.xml_data_reshdr.size_in_wim)
- {
- /* Old integrity table was partially overwritten by the
- * XML data. */
- old_lookup_table_end = 0;
+ }
}
new_lookup_table_end = wim->hdr.lookup_table_reshdr.offset_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)