+/*
+ * verify_integrity():
+ *
+ * Checks a WIM for consistency with the integrity table.
+ *
+ * @in_fd:
+ * File descriptor 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).
+ *
+ * Returns:
+ * > 0 (WIMLIB_ERR_READ, WIMLIB_ERR_UNEXPECTED_END_OF_FILE) 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(struct filedes *in_fd, const tchar *filename,
+ const struct integrity_table *table,
+ u64 bytes_to_check,
+ wimlib_progress_func_t progfunc, void *progctx)
+{
+ int ret;
+ u64 offset = WIM_HEADER_DISK_SIZE;
+ u8 sha1_md[SHA1_HASH_SIZE];
+ union wimlib_progress_info progress;
+
+ 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;
+
+ ret = call_progress(progfunc, WIMLIB_PROGRESS_MSG_VERIFY_INTEGRITY,
+ &progress, progctx);
+ if (ret)
+ return ret;
+
+ 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(in_fd, this_chunk_size, offset, sha1_md);
+ if (ret)
+ return ret;
+
+ if (!hashes_equal(sha1_md, table->sha1sums[i]))
+ return WIM_INTEGRITY_NOT_OK;
+
+ offset += this_chunk_size;
+ progress.integrity.completed_chunks++;
+ progress.integrity.completed_bytes += this_chunk_size;
+
+ ret = call_progress(progfunc, WIMLIB_PROGRESS_MSG_VERIFY_INTEGRITY,
+ &progress, progctx);
+ if (ret)
+ return ret;
+ }
+ return WIM_INTEGRITY_OK;
+}