+ tchar expected_hashstr[SHA1_HASH_SIZE * 2 + 1];
+ tchar actual_hashstr[SHA1_HASH_SIZE * 2 + 1];
+
+ wimlib_assert(blob->blob_location != BLOB_NONEXISTENT);
+ wimlib_assert(blob->blob_location != BLOB_IN_ATTACHED_BUFFER);
+
+ sprint_hash(blob->hash, expected_hashstr);
+ sprint_hash(actual_hash, actual_hashstr);
+
+ if (blob_is_in_file(blob)) {
+ ERROR("A file was concurrently modified!\n"
+ " Path: \"%"TS"\"\n"
+ " Expected SHA-1: %"TS"\n"
+ " Actual SHA-1: %"TS"\n",
+ blob_file_path(blob), expected_hashstr, actual_hashstr);
+ return WIMLIB_ERR_CONCURRENT_MODIFICATION_DETECTED;
+ } else if (blob->blob_location == BLOB_IN_WIM) {
+ const struct wim_resource_descriptor *rdesc = blob->rdesc;
+ ERROR("A WIM resource is corrupted!\n"
+ " WIM file: \"%"TS"\"\n"
+ " Blob uncompressed size: %"PRIu64"\n"
+ " Resource offset in WIM: %"PRIu64"\n"
+ " Resource uncompressed size: %"PRIu64"\n"
+ " Resource size in WIM: %"PRIu64"\n"
+ " Resource flags: 0x%x%"TS"\n"
+ " Resource compression type: %"TS"\n"
+ " Resource compression chunk size: %"PRIu32"\n"
+ " Expected SHA-1: %"TS"\n"
+ " Actual SHA-1: %"TS"\n",
+ rdesc->wim->filename,
+ blob->size,
+ rdesc->offset_in_wim,
+ rdesc->uncompressed_size,
+ rdesc->size_in_wim,
+ (unsigned int)rdesc->flags,
+ (rdesc->is_pipable ? T(", pipable") : T("")),
+ wimlib_get_compression_type_string(
+ rdesc->compression_type),
+ rdesc->chunk_size,
+ expected_hashstr, actual_hashstr);
+ return WIMLIB_ERR_INVALID_RESOURCE_HASH;
+ } else {
+ ERROR("File data was concurrently modified!\n"
+ " Location ID: %d\n"
+ " Expected SHA-1: %"TS"\n"
+ " Actual SHA-1: %"TS"\n",
+ (int)blob->blob_location,
+ expected_hashstr, actual_hashstr);
+ return WIMLIB_ERR_CONCURRENT_MODIFICATION_DETECTED;
+ }