/* * 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; }
/* * Reads and parses a metadata resource for an image in the WIM file. * * @imd: * Pointer to the image metadata structure for the image whose metadata * resource we are reading. Its `metadata_blob' member specifies the blob * table entry for the metadata resource. The rest of the image metadata * entry will be filled in by this function. * * Return values: * WIMLIB_ERR_SUCCESS (0) * WIMLIB_ERR_INVALID_METADATA_RESOURCE * WIMLIB_ERR_NOMEM * WIMLIB_ERR_READ * WIMLIB_ERR_UNEXPECTED_END_OF_FILE * WIMLIB_ERR_DECOMPRESSION */ int read_metadata_resource(struct wim_image_metadata *imd) { const struct blob_descriptor *metadata_blob; void *buf; int ret; u8 hash[SHA1_HASH_SIZE]; struct wim_security_data *sd; struct wim_dentry *root; metadata_blob = imd->metadata_blob; /* Read the metadata resource into memory. (It may be compressed.) */ ret = read_blob_into_alloc_buf(metadata_blob, &buf); if (ret) return ret; /* Checksum the metadata resource. */ sha1_buffer(buf, metadata_blob->size, hash); if (!hashes_equal(metadata_blob->hash, hash)) { ERROR("Metadata resource is corrupted " "(invalid SHA-1 message digest)!"); ret = WIMLIB_ERR_INVALID_METADATA_RESOURCE; goto out_free_buf; } /* Parse the metadata resource. * * Notes: The metadata resource consists of the security data, followed * by the directory entry for the root directory, followed by all the * other directory entries in the filesystem. The subdir offset field * of each directory entry gives the start of its child entries from the * beginning of the metadata resource. An end-of-directory is signaled * by a directory entry of length '0', really of length 8, because * that's how long the 'length' field is. */ ret = read_wim_security_data(buf, metadata_blob->size, &sd); if (ret) goto out_free_buf; ret = read_dentry_tree(buf, metadata_blob->size, sd->total_length, &root); if (ret) goto out_free_security_data; /* We have everything we need from the buffer now. */ FREE(buf); buf = NULL; /* Calculate and validate inodes. */ ret = dentry_tree_fix_inodes(root, &imd->inode_list); if (ret) goto out_free_dentry_tree; fix_security_ids(imd, sd->num_entries); /* Success; fill in the image_metadata structure. */ imd->root_dentry = root; imd->security_data = sd; INIT_LIST_HEAD(&imd->unhashed_blobs); return 0; out_free_dentry_tree: free_dentry_tree(root, NULL); out_free_security_data: free_wim_security_data(sd); out_free_buf: FREE(buf); return ret; }