+ } else {
+ integrity_res_entry->offset = cur_offset;
+ integrity_res_entry->size = new_table_size;
+ integrity_res_entry->original_size = new_table_size;
+ integrity_res_entry->flags = 0;
+ ret = 0;
+ }
+out_free_new_table:
+ FREE(new_table);
+out_free_old_table:
+ FREE(old_table);
+ return ret;
+}
+
+/*
+ * Checks a WIM for consistency with the integrity table.
+ *
+ * @fp:
+ * FILE * to the WIM file, opened for reading.
+ *
+ * @table:
+ * The integrity table for the WIM, read into memory.
+ *
+ * @bytes_to_check:
+ * Number of bytes in the WIM that need to be checked (offset of end of the
+ * lookup table minus offset of end of the header).
+ *
+ * @progress_func
+ * If non-NULL, a progress function that will be called after every
+ * verified chunk.
+ *
+ * Returns:
+ * > 0 (WIMLIB_ERR_*) on error
+ * 0 (WIM_INTEGRITY_OK) if the integrity was checked successfully and there
+ * were no inconsistencies.
+ * -1 (WIM_INTEGRITY_NOT_OK) if the WIM failed the integrity check.
+ */
+static int verify_integrity(FILE *fp, const char *filename,
+ const struct integrity_table *table,
+ u64 bytes_to_check,
+ wimlib_progress_func_t progress_func)
+{
+ int ret;
+ u64 offset = WIM_HEADER_DISK_SIZE;
+ u8 sha1_md[SHA1_HASH_SIZE];
+ union wimlib_progress_info progress;
+
+ if (progress_func) {
+ progress.integrity.total_bytes = bytes_to_check;
+ progress.integrity.total_chunks = table->num_entries;
+ progress.integrity.completed_chunks = 0;
+ progress.integrity.completed_bytes = 0;
+ progress.integrity.chunk_size = table->chunk_size;
+ progress.integrity.filename = filename;
+ progress_func(WIMLIB_PROGRESS_MSG_VERIFY_INTEGRITY,
+ &progress);
+ }
+ for (u32 i = 0; i < table->num_entries; i++) {
+ size_t this_chunk_size;
+ if (i == table->num_entries - 1)
+ this_chunk_size = MODULO_NONZERO(bytes_to_check,
+ table->chunk_size);
+ else
+ this_chunk_size = table->chunk_size;
+
+ ret = calculate_chunk_sha1(fp, this_chunk_size, offset, sha1_md);
+ if (ret != 0)
+ return ret;
+
+ if (!hashes_equal(sha1_md, table->sha1sums[i]))
+ return WIM_INTEGRITY_NOT_OK;
+
+ offset += this_chunk_size;
+ if (progress_func) {
+ progress.integrity.completed_chunks++;
+ progress.integrity.completed_bytes += this_chunk_size;
+ progress_func(WIMLIB_PROGRESS_MSG_VERIFY_INTEGRITY,
+ &progress);
+ }
+ }
+ return WIM_INTEGRITY_OK;
+}
+
+
+/*
+ * Verifies the integrity of the WIM by making sure the SHA1 message digests of
+ * ~10 MiB chunks of the WIM match up with the values given in the integrity
+ * table.
+ *
+ * @w:
+ * The WIM, opened for reading, and with the header already read.
+ *
+ * @progress_func
+ * If non-NULL, a progress function that will be called after every
+ * verified chunk.
+ *
+ * Returns:
+ * > 0 (WIMLIB_ERR_*) on error
+ * 0 (WIM_INTEGRITY_OK) if the integrity was checked successfully and there
+ * were no inconsistencies.
+ * -1 (WIM_INTEGRITY_NOT_OK) if the WIM failed the integrity check.
+ * -2 (WIM_INTEGRITY_NONEXISTENT) if the WIM contains no integrity
+ * information.
+ */
+int check_wim_integrity(WIMStruct *w, wimlib_progress_func_t progress_func)
+{
+ int ret;
+ u64 bytes_to_check;
+ struct integrity_table *table;
+ u64 end_lookup_table_offset;
+
+ if (w->hdr.integrity.offset == 0) {
+ DEBUG("No integrity information.");
+ return WIM_INTEGRITY_NONEXISTENT;