X-Git-Url: https://wimlib.net/git/?a=blobdiff_plain;f=src%2Fintegrity.c;h=f1e208f17d2a4a1fc26363ddba8580a8aae55b90;hb=79b64b516e5bdb486832f88788362dbe9deb1b61;hp=e310716130bfa79084a0a6b789286d623441a8c6;hpb=b1c4e6a269ae4c969060e33685db12f76a204a58;p=wimlib diff --git a/src/integrity.c b/src/integrity.c index e3107161..f1e208f1 100644 --- a/src/integrity.c +++ b/src/integrity.c @@ -12,16 +12,16 @@ * This file is part of wimlib, a library for working with WIM files. * * wimlib is free software; you can redistribute it and/or modify it under the - * terms of the GNU Lesser General Public License as published by the Free - * Software Foundation; either version 2.1 of the License, or (at your option) + * terms of the GNU General Public License as published by the Free + * Software Foundation; either version 3 of the License, or (at your option) * any later version. * * wimlib is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * A PARTICULAR PURPOSE. See the GNU General Public License for more * details. * - * You should have received a copy of the GNU Lesser General Public License + * You should have received a copy of the GNU General Public License * along with wimlib; if not, see http://www.gnu.org/licenses/. */ @@ -34,22 +34,22 @@ #define INTEGRITY_CHUNK_SIZE 10485760 /* - * Verifies the integrity of a WIM. + * Verifies the integrity of a WIM. * - * @fp: FILE* of the WIM, currently positioned at the end of the header. + * @fp: FILE* of the WIM, currently positioned at the end of the header. * @num_bytes: Number of bytes to verify the integrity of. * @chunk_size: Chunk size per SHA1 message digest. * @sha1sums: Array of SHA1 message digests; 20 bytes each, one per chunk. * @show_progress: Nonzero if the percent complete is to be printed after every * chunk. - * @status: On success, set to WIM_INTEGRITY_OK or WIM_INTEGRITY_NOT_OK + * @status: On success, set to WIM_INTEGRITY_OK or WIM_INTEGRITY_NOT_OK * based on whether the WIM is intact or not. */ -static int verify_integrity(FILE *fp, u64 num_bytes, u32 chunk_size, +static int verify_integrity(FILE *fp, u64 num_bytes, u32 chunk_size, const u8 *sha1sums, int show_progress, int *status) { - char *chunk_buf; + u8 *chunk_buf; u8 resblock[SHA1_HASH_SIZE]; u64 bytes_remaining; size_t bytes_to_read; @@ -65,10 +65,10 @@ static int verify_integrity(FILE *fp, u64 num_bytes, u32 chunk_size, bytes_remaining = num_bytes; while (bytes_remaining != 0) { if (show_progress) { - percent_done = (num_bytes - bytes_remaining) * 100 / + percent_done = (num_bytes - bytes_remaining) * 100 / num_bytes; printf("Verifying integrity of WIM (%"PRIu64" bytes " - "remaining, %u%% done) \r", + "remaining, %u%% done) \r", bytes_remaining, percent_done); fflush(stdout); } @@ -103,7 +103,7 @@ verify_integrity_error: } /* - * Verifies the integrity of the WIM. + * Verifies the integrity of the WIM. * * @show_progress: Nonzero if the percent complete is to be printed after every * chunk. @@ -117,7 +117,6 @@ int check_wim_integrity(WIMStruct *w, int show_progress, int *status) { struct resource_entry *res_entry; - int ctype; u8 *buf = NULL; int ret; u32 integrity_table_size; @@ -135,11 +134,14 @@ int check_wim_integrity(WIMStruct *w, int show_progress, int *status) *status = WIM_INTEGRITY_NONEXISTENT; return 0; } - ctype = wim_resource_compression_type(w, res_entry); if (res_entry->original_size < 12) { ERROR("Integrity table is too short"); return WIMLIB_ERR_INVALID_INTEGRITY_TABLE; } + if (res_entry->flags & WIM_RESHDR_FLAG_COMPRESSED) { + ERROR("Didn't expect a compressed integrity table"); + return WIMLIB_ERR_INVALID_INTEGRITY_TABLE; + } /* Read the integrity table into memory. */ buf = MALLOC(res_entry->original_size); @@ -149,15 +151,14 @@ int check_wim_integrity(WIMStruct *w, int show_progress, int *status) ret = WIMLIB_ERR_NOMEM; goto out; } - ret = read_full_resource(w->fp, res_entry->size, - res_entry->original_size, - res_entry->offset, ctype, buf); + ret = read_uncompressed_resource(w->fp, res_entry->offset, + res_entry->original_size, buf); if (ret != 0) { ERROR("Failed to read integrity table (size = %"PRIu64", " "original_size = %"PRIu64", offset = " - "%"PRIu64", ctype = %d", + "%"PRIu64")", (u64)res_entry->size, res_entry->original_size, - res_entry->offset, ctype); + res_entry->offset); goto out; } @@ -185,7 +186,7 @@ int check_wim_integrity(WIMStruct *w, int show_progress, int *status) if (integrity_table_size != expected_size) { ERROR("Integrity table is %u bytes, but expected %"PRIu64" " - "bytes to hold %u entries", + "bytes to hold %u entries", integrity_table_size, expected_size, num_entries); ret = WIMLIB_ERR_INVALID_INTEGRITY_TABLE; goto out; @@ -200,6 +201,12 @@ int check_wim_integrity(WIMStruct *w, int show_progress, int *status) 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???"); + ret = WIMLIB_ERR_INVALID_INTEGRITY_TABLE; + goto out; + } + bytes_to_check = end_lookup_table_offset - WIM_HEADER_DISK_SIZE; expected_num_entries = (bytes_to_check + chunk_size - 1) / chunk_size; @@ -225,36 +232,36 @@ int check_wim_integrity(WIMStruct *w, int show_progress, int *status) } /* call verify_integrity(), which does the actual checking of the SHA1 * message digests. */ - ret = verify_integrity(w->fp, bytes_to_check, chunk_size, p, + ret = verify_integrity(w->fp, bytes_to_check, chunk_size, p, show_progress, status); out: FREE(buf); return ret; } -/* +/* * Writes integrity information to the output stream for a WIM file being - * written. + * written. * * @end_header_offset is the offset of the byte after the header, which is the * beginning of the region that is checksummed. * * @end_lookup_table_offset is the offset of the byte after the lookup table, - * which is the end of the region that is checksummed. + * which is the end of the region that is checksummed. */ -int write_integrity_table(FILE *out, u64 end_header_offset, +int write_integrity_table(FILE *out, u64 end_header_offset, u64 end_lookup_table_offset, int show_progress) { - u64 bytes_to_check; - u64 bytes_remaining; - u8 *buf; - u8 *p; - char *chunk_buf; - u32 num_entries; - u32 integrity_table_size; - int ret; - - DEBUG("Writing integrity table"); + u64 bytes_to_check; + u64 bytes_remaining; + u8 *buf; + u8 *p; + u8 *chunk_buf; + u32 num_entries; + u32 integrity_table_size; + int ret; + + DEBUG("Calculating integrity table"); if (fseeko(out, end_header_offset, SEEK_SET) != 0) { ERROR_WITH_ERRNO("Failed to seek to byte %"PRIu64" of WIM to " "calculate integrity data", end_header_offset); @@ -262,12 +269,11 @@ int write_integrity_table(FILE *out, u64 end_header_offset, } bytes_to_check = end_lookup_table_offset - end_header_offset; - num_entries = bytes_to_check / INTEGRITY_CHUNK_SIZE + - (bytes_to_check % INTEGRITY_CHUNK_SIZE != 0); + num_entries = (bytes_to_check + INTEGRITY_CHUNK_SIZE - 1) / + INTEGRITY_CHUNK_SIZE; integrity_table_size = num_entries * SHA1_HASH_SIZE + 3 * sizeof(u32); - DEBUG("integrity table size = %u", integrity_table_size); - + DEBUG("integrity_table_size = %u", integrity_table_size); buf = MALLOC(integrity_table_size); if (!buf) { @@ -285,7 +291,7 @@ int write_integrity_table(FILE *out, u64 end_header_offset, ERROR("Failed to allocate %u bytes for integrity chunk buffer", INTEGRITY_CHUNK_SIZE); ret = WIMLIB_ERR_NOMEM; - goto err2; + goto out_free_buf; } bytes_remaining = bytes_to_check; @@ -294,13 +300,13 @@ int write_integrity_table(FILE *out, u64 end_header_offset, while (bytes_remaining != 0) { - uint percent_done = (bytes_to_check - bytes_remaining) * + uint percent_done = (bytes_to_check - bytes_remaining) * 100 / bytes_to_check; if (show_progress) { printf("Calculating integrity checksums for WIM " "(%"PRIu64" bytes remaining, %u%% " - "done) \r", + "done) \r", bytes_remaining, percent_done); fflush(stdout); } @@ -318,7 +324,7 @@ int write_integrity_table(FILE *out, u64 end_header_offset, "checksums"); } ret = WIMLIB_ERR_READ; - goto err2; + goto out_free_chunk_buf; } sha1_buffer(chunk_buf, bytes_read, p); p += SHA1_HASH_SIZE; @@ -333,19 +339,19 @@ int write_integrity_table(FILE *out, u64 end_header_offset, ERROR_WITH_ERRNO("Failed to seek to end of WIM to write " "integrity table"); ret = WIMLIB_ERR_WRITE; - goto err1; + goto out_free_chunk_buf; } if (fwrite(buf, 1, integrity_table_size, out) != integrity_table_size) { ERROR_WITH_ERRNO("Failed to write integrity table to end of " "WIM"); ret = WIMLIB_ERR_WRITE; - goto err1; + goto out_free_chunk_buf; } ret = 0; -err1: +out_free_chunk_buf: FREE(chunk_buf); -err2: +out_free_buf: FREE(buf); return ret; }