+ 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;
+ }
+
+ end_lookup_table_offset = w->hdr.lookup_table_res_entry.offset +
+ w->hdr.lookup_table_res_entry.size;
+
+ if (end_lookup_table_offset < WIM_HEADER_DISK_SIZE) {
+ ERROR("WIM lookup table ends before WIM header ends!");
+ return WIMLIB_ERR_INVALID_INTEGRITY_TABLE;
+ }
+
+ bytes_to_check = end_lookup_table_offset - WIM_HEADER_DISK_SIZE;
+
+ ret = read_integrity_table(&w->hdr.integrity, w->fp,
+ bytes_to_check, &table);
+ if (ret != 0)
+ return ret;
+ ret = verify_integrity(w->fp, w->filename, table,
+ bytes_to_check, progress_func);
+ FREE(table);