From: Eric Biggers Date: Sun, 16 Dec 2012 07:44:00 +0000 (-0600) Subject: Various fixes and cleanups X-Git-Tag: v1.2.1~53 X-Git-Url: https://wimlib.net/git/?p=wimlib;a=commitdiff_plain;h=3fa7b7a033ce803accfd6758029114323f6a6865 Various fixes and cleanups --- diff --git a/src/dentry.c b/src/dentry.c index 54601493..4ff86029 100644 --- a/src/dentry.c +++ b/src/dentry.c @@ -953,8 +953,7 @@ void free_inode(struct inode *inode) * */ static void put_inode(struct inode *inode) { - wimlib_assert(inode); - wimlib_assert(inode->link_count); + wimlib_assert(inode->link_count != 0); if (--inode->link_count == 0) { #ifdef WITH_FUSE if (inode->num_opened_fds == 0) @@ -971,7 +970,6 @@ static void put_inode(struct inode *inode) */ void free_dentry(struct dentry *dentry) { - wimlib_assert(dentry != NULL); FREE(dentry->file_name); FREE(dentry->file_name_utf8); FREE(dentry->short_name); @@ -983,9 +981,7 @@ void free_dentry(struct dentry *dentry) void put_dentry(struct dentry *dentry) { - wimlib_assert(dentry != NULL); wimlib_assert(dentry->refcnt != 0); - if (--dentry->refcnt == 0) free_dentry(dentry); } @@ -1002,7 +998,7 @@ static int do_free_dentry(struct dentry *dentry, void *__lookup_table) if (lookup_table) { struct lookup_table_entry *lte; struct inode *inode = dentry->d_inode; - wimlib_assert(inode->link_count); + wimlib_assert(inode->link_count != 0); for (i = 0; i <= inode->num_ads; i++) { lte = inode_stream_lte(inode, i, lookup_table); if (lte) @@ -1126,7 +1122,15 @@ static int verify_inode(struct inode *inode, const WIMStruct *w) "%u of dentry `%s'", i, first_dentry->full_path_utf8); goto out; } - if (lte && (lte->real_refcnt += inode->link_count) > lte->refcnt) + if (lte) + lte->real_refcnt += inode->link_count; + + /* The following is now done when required by + * wim_run_full_verifications(). */ + + #if 0 + if (lte && !w->full_verification_in_progress && + lte->real_refcnt > lte->refcnt) { #ifdef ENABLE_ERROR_MESSAGES WARNING("The following lookup table entry " @@ -1140,9 +1144,9 @@ static int verify_inode(struct inode *inode, const WIMStruct *w) print_lookup_table_entry(lte); #endif /* Guess what! install.wim for Windows 8 - * contains a stream with 2 dentries referencing - * it, but the lookup table entry has reference - * count of 1. So we will need to handle this + * contains many streams referenced by more + * dentries than the refcnt stated in the lookup + * table entry. So we will need to handle this * case and not just make it be an error... I'm * just setting the reference count to the * number of references we found. @@ -1157,6 +1161,7 @@ static int verify_inode(struct inode *inode, const WIMStruct *w) goto out; #endif } + #endif } } diff --git a/src/extract.c b/src/extract.c index 8fbdd0d2..55508169 100644 --- a/src/extract.c +++ b/src/extract.c @@ -720,7 +720,7 @@ WIMLIBAPI int wimlib_extract_image(WIMStruct *w, int image, struct lookup_table *joined_tab, *w_tab_save; int ret; - if (!w || !target) + if (!target) return WIMLIB_ERR_INVALID_PARAM; extract_flags &= WIMLIB_EXTRACT_MASK_PUBLIC; diff --git a/src/hardlink.c b/src/hardlink.c index 007e744d..e3f9e27a 100644 --- a/src/hardlink.c +++ b/src/hardlink.c @@ -162,10 +162,12 @@ static void print_inode_dentries(const struct inode *inode) static void inconsistent_inode(const struct inode *inode) { - ERROR("An inconsistent hard link group that we cannot correct has been " - "detected"); + ERROR("An inconsistent hard link group that cannot be corrected has " + "been detected"); ERROR("The dentries are located at the following paths:"); +#ifdef ENABLE_ERROR_MESSAGES print_inode_dentries(inode); +#endif } static bool ref_inodes_consistent(const struct inode * restrict ref_inode_1, diff --git a/src/modify.c b/src/modify.c index 5b8fe415..42de5e92 100644 --- a/src/modify.c +++ b/src/modify.c @@ -511,9 +511,6 @@ WIMLIBAPI int wimlib_export_image(WIMStruct *src_wim, struct wim_security_data *sd; struct lookup_table *joined_tab, *src_wim_tab_save; - if (!src_wim || !dest_wim) - return WIMLIB_ERR_INVALID_PARAM; - if (dest_wim->hdr.total_parts != 1) { ERROR("Exporting an image to a split WIM is " "unsupported"); @@ -667,6 +664,56 @@ out: return ret; } +static int image_run_full_verifications(WIMStruct *w) +{ + return for_dentry_in_tree(wim_root_dentry(w), verify_dentry, w); +} + +static int lte_fix_refcnt(struct lookup_table_entry *lte, void *ctr) +{ + if (lte->refcnt != lte->real_refcnt) { + WARNING("The following lookup table entry has a reference " + "count of %u, but", lte->refcnt); + WARNING("We found %u references to it", + lte->real_refcnt); + print_lookup_table_entry(lte); + lte->refcnt = lte->real_refcnt; + ++*(unsigned long *)ctr; + } + return 0; +} + +/* Ideally this would be unnecessary... however, the WIMs for Windows 8 are + * screwed up because some lookup table entries are referenced more times than + * their stated reference counts. So theoretically, if we do the delete all the + * references to a stream and then remove it, it might still be referenced + * somewhere else... So, work around this problem by looking at ALL the images + * to re-calculate the reference count of EVERY lookup table entry. */ +int wim_run_full_verifications(WIMStruct *w) +{ + int ret; + + for_lookup_table_entry(w->lookup_table, lte_zero_real_refcnt, NULL); + w->all_images_verified = true; + w->full_verification_in_progress = true; + ret = for_image(w, WIMLIB_ALL_IMAGES, image_run_full_verifications); + w->full_verification_in_progress = false; + if (ret == 0) { + unsigned long num_ltes_with_bogus_refcnt = 0; + for_lookup_table_entry(w->lookup_table, lte_fix_refcnt, + &num_ltes_with_bogus_refcnt); + if (num_ltes_with_bogus_refcnt != 0) { + WARNING("A total of %lu entries in the WIM's stream " + "lookup table had to have\n" + " their reference counts fixed.", + num_ltes_with_bogus_refcnt); + } + } else { + w->all_images_verified = false; + } + return ret; +} + /* * Deletes an image from the WIM. */ @@ -689,6 +736,12 @@ WIMLIBAPI int wimlib_delete_image(WIMStruct *w, int image) return 0; } + if (!w->all_images_verified) { + ret = wim_run_full_verifications(w); + if (ret != 0) + return ret; + } + DEBUG("Deleting image %d", image); /* Even if the dentry tree is not allocated, we must select it (and diff --git a/src/mount.c b/src/mount.c index 0122d848..3c50c750 100644 --- a/src/mount.c +++ b/src/mount.c @@ -1921,6 +1921,12 @@ WIMLIBAPI int wimlib_mount_image(WIMStruct *wim, int image, const char *dir, wim->lookup_table = joined_tab; } + if (mount_flags & WIMLIB_MOUNT_FLAG_READWRITE) { + ret = wim_run_full_verifications(wim); + if (ret != 0) + goto out; + } + ret = select_wim_image(wim, image); if (ret != 0) diff --git a/src/resource.c b/src/resource.c index 86a2be6a..25761971 100644 --- a/src/resource.c +++ b/src/resource.c @@ -860,11 +860,13 @@ int read_metadata_resource(WIMStruct *w, struct image_metadata *imd) if (ret != 0) goto out_free_dentry_tree; - DEBUG("Running miscellaneous verifications on the dentry tree"); - for_lookup_table_entry(w->lookup_table, lte_zero_real_refcnt, NULL); - ret = for_dentry_in_tree(dentry, verify_dentry, w); - if (ret != 0) - goto out_free_dentry_tree; + if (!w->all_images_verified) { + DEBUG("Running miscellaneous verifications on the dentry tree"); + for_lookup_table_entry(w->lookup_table, lte_zero_real_refcnt, NULL); + ret = for_dentry_in_tree(dentry, verify_dentry, w); + if (ret != 0) + goto out_free_dentry_tree; + } DEBUG("Done reading image metadata"); @@ -881,6 +883,14 @@ out_free_buf: return ret; } +static void recalculate_security_data_length(struct wim_security_data *sd) +{ + u32 total_length = sizeof(u64) * sd->num_entries + 2 * sizeof(u32); + for (u32 i = 0; i < sd->num_entries; i++) + total_length += sd->sizes[i]; + sd->total_length = total_length; +} + /* Write the metadata resource for the current WIM image. */ int write_metadata_resource(WIMStruct *w) { @@ -891,7 +901,7 @@ int write_metadata_resource(WIMStruct *w) struct dentry *root; struct lookup_table_entry *lte; u64 metadata_original_size; - const struct wim_security_data *sd; + struct wim_security_data *sd; DEBUG("Writing metadata resource for image %d (offset = %"PRIu64")", w->current_image, ftello(w->out_fp)); @@ -906,6 +916,7 @@ int write_metadata_resource(WIMStruct *w) * - plus 8 bytes for an end-of-directory entry following the root * dentry (shouldn't really be needed, but just in case...) */ + recalculate_security_data_length(sd); subdir_offset = (((u64)sd->total_length + 7) & ~7) + dentry_correct_total_length(root) + 8; diff --git a/src/split.c b/src/split.c index 649a9bf2..50f15bf8 100644 --- a/src/split.c +++ b/src/split.c @@ -34,9 +34,9 @@ struct split_args { size_t swm_base_name_len; const char *swm_suffix; struct list_head lte_list; - int cur_part_number; - int write_flags; - long size_remaining; + int cur_part_number; + int write_flags; + long size_remaining; size_t part_size; wimlib_progress_func_t progress_func; union wimlib_progress_info progress; @@ -134,7 +134,7 @@ WIMLIBAPI int wimlib_split(WIMStruct *w, const char *swm_name, size_t swm_name_len; size_t swm_base_name_len; - if (!w || !swm_name || part_size == 0) + if (!swm_name || part_size == 0) return WIMLIB_ERR_INVALID_PARAM; if (w->hdr.total_parts != 1) diff --git a/src/wim.c b/src/wim.c index cbda0061..c76be36f 100644 --- a/src/wim.c +++ b/src/wim.c @@ -323,7 +323,7 @@ WIMLIBAPI void wimlib_print_wim_information(const WIMStruct *w) printf("Boot Index: %d\n", hdr->boot_idx); printf("Size: %"PRIu64" bytes\n", wim_info_get_total_bytes(w->wim_info)); - printf("Integrity Info: %s\n", (w->hdr.integrity.size != 0) ? "yes" : "no"); + printf("Integrity Info: %s\n", (w->hdr.integrity.offset != 0) ? "yes" : "no"); putchar('\n'); } @@ -363,8 +363,6 @@ WIMLIBAPI void wimlib_print_available_images(const WIMStruct *w, int image) * not WIMLIB_NO_IMAGE. */ WIMLIBAPI int wimlib_print_metadata(WIMStruct *w, int image) { - if (!w) - return WIMLIB_ERR_INVALID_PARAM; if (w->hdr.part_number != 1) { ERROR("Cannot show the metadata from part %hu of a %hu-part split WIM!", w->hdr.part_number, w->hdr.total_parts); @@ -376,8 +374,6 @@ WIMLIBAPI int wimlib_print_metadata(WIMStruct *w, int image) WIMLIBAPI int wimlib_print_files(WIMStruct *w, int image) { - if (!w) - return WIMLIB_ERR_INVALID_PARAM; if (w->hdr.part_number != 1) { ERROR("Cannot list the files from part %hu of a %hu-part split WIM!", w->hdr.part_number, w->hdr.total_parts); @@ -390,8 +386,6 @@ WIMLIBAPI int wimlib_print_files(WIMStruct *w, int image) /* Sets the index of the bootable image. */ WIMLIBAPI int wimlib_set_boot_idx(WIMStruct *w, int boot_idx) { - if (!w) - return WIMLIB_ERR_INVALID_PARAM; if (w->hdr.total_parts != 1) { ERROR("Cannot modify the boot index of a split WIM!"); return WIMLIB_ERR_SPLIT_UNSUPPORTED; @@ -458,15 +452,14 @@ static int begin_read(WIMStruct *w, const char *in_wim_path, int open_flags, if (!w->filename) { ERROR_WITH_ERRNO("Failed to resolve WIM filename"); if (errno == ENOMEM) - ret = WIMLIB_ERR_NOMEM; + return WIMLIB_ERR_NOMEM; else - ret = WIMLIB_ERR_OPEN; - goto out_close; + return WIMLIB_ERR_OPEN; } ret = read_header(w->fp, &w->hdr, open_flags); if (ret != 0) - goto out_close; + return ret; DEBUG("According to header, WIM contains %u images", w->hdr.image_count); @@ -479,45 +472,37 @@ static int begin_read(WIMStruct *w, const char *in_wim_path, int open_flags, } if (wimlib_get_compression_type(w) == WIMLIB_COMPRESSION_TYPE_INVALID) { - ERROR("Invalid compression type (WIM header flags = %x)", + ERROR("Invalid compression type (WIM header flags = 0x%x)", w->hdr.flags); - ret = WIMLIB_ERR_INVALID_COMPRESSION_TYPE; - goto out_close; + return WIMLIB_ERR_INVALID_COMPRESSION_TYPE; } if (open_flags & WIMLIB_OPEN_FLAG_CHECK_INTEGRITY) { ret = check_wim_integrity(w, progress_func); if (ret == WIM_INTEGRITY_NONEXISTENT) { WARNING("No integrity information for `%s'; skipping " - "integrity check.", w->filename); + "integrity check.", in_wim_path); } else if (ret == WIM_INTEGRITY_NOT_OK) { ERROR("WIM is not intact! (Failed integrity check)"); - ret = WIMLIB_ERR_INTEGRITY; - goto out_close; - } else if (ret != 0) { - goto out_close; + return WIMLIB_ERR_INTEGRITY; + } else if (ret != WIM_INTEGRITY_OK) { + return ret; } } - if (resource_is_compressed(&w->hdr.lookup_table_res_entry)) { - ERROR("Didn't expect a compressed lookup table!"); - ERROR("Ask the author to implement support for this."); - ret = WIMLIB_ERR_COMPRESSED_LOOKUP_TABLE; - goto out_close; - } - ret = read_lookup_table(w); if (ret != 0) - goto out_close; + return ret; - w->image_metadata = CALLOC(w->hdr.image_count, - sizeof(struct image_metadata)); + if (w->hdr.image_count != 0) { + w->image_metadata = CALLOC(w->hdr.image_count, + sizeof(struct image_metadata)); - if (!w->image_metadata) { - ERROR("Failed to allocate memory for %u metadata structures", - w->hdr.image_count); - ret = WIMLIB_ERR_NOMEM; - goto out_free_lookup_table; + if (!w->image_metadata) { + ERROR("Failed to allocate memory for %u image metadata structures", + w->hdr.image_count); + return WIMLIB_ERR_NOMEM; + } } w->current_image = 0; @@ -528,17 +513,16 @@ static int begin_read(WIMStruct *w, const char *in_wim_path, int open_flags, append_metadata_resource_entry, w); if (ret != 0) - goto out_free_image_metadata; + return ret; /* Make sure all the expected images were found. (We already have * returned false if *extra* images were found) */ if (w->current_image != w->hdr.image_count && w->hdr.part_number == 1) { - ERROR("Only found %u images in WIM, but expected %u", + ERROR("Only found %d images in WIM, but expected %u", w->current_image, w->hdr.image_count); - ret = WIMLIB_ERR_IMAGE_COUNT; - goto out_free_image_metadata; + return WIMLIB_ERR_IMAGE_COUNT; } /* Sort images by the position of their metadata resources. I'm @@ -555,7 +539,7 @@ static int begin_read(WIMStruct *w, const char *in_wim_path, int open_flags, &w->xml_data, &w->wim_info); if (ret != 0) - goto out_free_image_metadata; + return ret; xml_num_images = wim_info_get_num_images(w->wim_info); if (xml_num_images != w->hdr.image_count) { @@ -563,33 +547,11 @@ static int begin_read(WIMStruct *w, const char *in_wim_path, int open_flags, "in the XML data,", in_wim_path, xml_num_images); ERROR("but %u images in the WIM! There must be exactly one " " element per image.", w->hdr.image_count); - ret = WIMLIB_ERR_IMAGE_COUNT; - goto out_free_xml_data; + return WIMLIB_ERR_IMAGE_COUNT; } DEBUG("Done beginning read of WIM file `%s'.", in_wim_path); - /*return 0;*/ - - // - // Everything is freed in wimlib_free() anyway, so no need to roll back - // changes here. - // -out_free_xml_data: - /*FREE(w->xml_data);*/ - /*w->xml_data = NULL;*/ - /*free_wim_info(w->wim_info);*/ - /*w->wim_info = NULL;*/ -out_free_image_metadata: - /*FREE(w->image_metadata);*/ - /*w->image_metadata = NULL;*/ - /*w->current_image = WIMLIB_NO_IMAGE;*/ -out_free_lookup_table: - /*free_lookup_table(w->lookup_table);*/ - /*w->lookup_table = NULL;*/ -out_close: - /*fclose(w->fp);*/ - /*w->fp = NULL;*/ - return ret; + return 0; } @@ -605,19 +567,16 @@ WIMLIBAPI int wimlib_open_wim(const char *wim_file, int open_flags, if (!wim_file || !w_ret) return WIMLIB_ERR_INVALID_PARAM; + w = new_wim_struct(); - if (!w) { - ERROR("Failed to allocate memory for WIMStruct"); + if (!w) return WIMLIB_ERR_NOMEM; - } ret = begin_read(w, wim_file, open_flags, progress_func); - if (ret == 0) { + if (ret == 0) *w_ret = w; - } else { - DEBUG("Could not begin reading the WIM file `%s'", wim_file); + else wimlib_free(w); - } return ret; } @@ -650,7 +609,7 @@ WIMLIBAPI void wimlib_free(WIMStruct *w) FREE(w->xml_data); free_wim_info(w->wim_info); if (w->image_metadata) { - for (uint i = 0; i < w->hdr.image_count; i++) + for (unsigned i = 0; i < w->hdr.image_count; i++) destroy_image_metadata(&w->image_metadata[i], NULL); FREE(w->image_metadata); } diff --git a/src/wimlib.h b/src/wimlib.h index 084f7049..5265a396 100644 --- a/src/wimlib.h +++ b/src/wimlib.h @@ -503,9 +503,6 @@ union wimlib_progress_info { /** Number of split WIM parts. */ unsigned total_parts; - - /** Name of the joined WIM file being written. */ - const char *filename; } join; /** Valid on messages ::WIMLIB_PROGRESS_MSG_SPLIT_BEGIN_PART and @@ -982,8 +979,7 @@ extern int wimlib_delete_image(WIMStruct *wim, int image); * ::WIMLIB_ALL_IMAGES, @a src_wim contains multiple images, and no images in * @a src_wim are marked as bootable; or @a dest_name and/or @a * dest_description were non-NULL, @a src_image was - * ::WIMLIB_ALL_IMAGES, and @a src_wim contains multiple images; or @a src_wim - * or @a dest_wim was @c NULL. + * ::WIMLIB_ALL_IMAGES, and @a src_wim contains multiple images. * @retval ::WIMLIB_ERR_INVALID_RESOURCE_SIZE * The metadata resource for @a src_image in @a src_wim is invalid. * @retval ::WIMLIB_ERR_INVALID_SECURITY_DATA @@ -1085,11 +1081,11 @@ extern int wimlib_export_image(WIMStruct *src_wim, int src_image, * A directory entry in the metadata resource for @a image in @a wim is * invalid. * @retval ::WIMLIB_ERR_INVALID_PARAM - * @a wim was @c NULL, or @a target was @c NULL, or both - * ::WIMLIB_EXTRACT_FLAG_HARDLINK and ::WIMLIB_EXTRACT_FLAG_SYMLINK were - * specified in @a extract_flags, or both ::WIMLIB_EXTRACT_FLAG_NTFS and - * either ::WIMLIB_EXTRACT_FLAG_HARDLINK or ::WIMLIB_EXTRACT_FLAG_SYMLINK - * were specified in @a extract_flags, or ::WIMLIB_EXTRACT_FLAG_NTFS was + * @a target was @c NULL, or both ::WIMLIB_EXTRACT_FLAG_HARDLINK and + * ::WIMLIB_EXTRACT_FLAG_SYMLINK were specified in @a extract_flags, or + * both ::WIMLIB_EXTRACT_FLAG_NTFS and either + * ::WIMLIB_EXTRACT_FLAG_HARDLINK or ::WIMLIB_EXTRACT_FLAG_SYMLINK were + * specified in @a extract_flags, or ::WIMLIB_EXTRACT_FLAG_NTFS was * specified in @a extract_flags and @a image was ::WIMLIB_ALL_IMAGES. * @retval ::WIMLIB_ERR_INVALID_RESOURCE_HASH * The SHA1 message digest of an extracted stream did not match the SHA1 @@ -1646,8 +1642,6 @@ extern void wimlib_print_available_images(const WIMStruct *wim, int image); * @retval ::WIMLIB_ERR_INVALID_IMAGE * @a image does not specify a valid image in @a wim, and is not * ::WIMLIB_ALL_IMAGES. - * @retval ::WIMLIB_ERR_INVALID_PARAM - * @a wim was @c NULL. * @retval ::WIMLIB_ERR_INVALID_RESOURCE_SIZE * The metadata resource for one of the specified images is invalid. * @retval ::WIMLIB_ERR_INVALID_SECURITY_DATA @@ -1710,8 +1704,6 @@ extern void wimlib_print_lookup_table(WIMStruct *wim); * @retval ::WIMLIB_ERR_INVALID_IMAGE * @a image does not specify a valid image in @a wim, and is not * ::WIMLIB_ALL_IMAGES. - * @retval ::WIMLIB_ERR_INVALID_PARAM - * @a wim was @c NULL. * @retval ::WIMLIB_ERR_INVALID_RESOURCE_SIZE * The metadata resource for one of the specified images is invalid. * @retval ::WIMLIB_ERR_INVALID_SECURITY_DATA @@ -1777,8 +1769,6 @@ extern int wimlib_resolve_image(WIMStruct *wim, const char *image_name_or_num); * The number of the image to mark as bootable, or 0 to mark no image as * bootable. * @return 0 on success; nonzero on error. - * @retval ::WIMLIB_ERR_INVALID_PARAM - * @a wim was @c NULL. * @retval ::WIMLIB_ERR_INVALID_IMAGE * @a boot_idx does not specify an existing image in @a wim, and it was not * 0. @@ -1804,8 +1794,6 @@ extern int wimlib_set_boot_idx(WIMStruct *wim, int boot_idx); * @return 0 on success; nonzero on error. * @retval ::WIMLIB_ERR_INVALID_IMAGE * @a image does not specify a single existing image in @a wim. - * @retval ::WIMLIB_ERR_INVALID_PARAM - * @a wim was @c NULL. * @retval ::WIMLIB_ERR_NOMEM * Failed to allocate the memory needed to duplicate the @a description * string. @@ -1830,8 +1818,6 @@ extern int wimlib_set_image_descripton(WIMStruct *wim, int image, * @return 0 on success; nonzero on error. * @retval ::WIMLIB_ERR_INVALID_IMAGE * @a image does not specify a single existing image in @a wim. - * @retval ::WIMLIB_ERR_INVALID_PARAM - * @a wim was @c NULL. * @retval ::WIMLIB_ERR_NOMEM * Failed to allocate the memory needed to duplicate the @a flags string. */ @@ -1853,7 +1839,7 @@ extern int wimlib_set_image_flags(WIMStruct *wim, int image, const char *flags); * @retval ::WIMLIB_ERR_IMAGE_NAME_COLLISION * There is already an image named @a name in @a wim. * @retval ::WIMLIB_ERR_INVALID_PARAM - * @a name was @c NULL or the empty string, or @a wim was @c NULL. + * @a name was @c NULL or the empty string. * @retval ::WIMLIB_ERR_INVALID_IMAGE * @a image does not specify a single existing image in @a wim. * @retval ::WIMLIB_ERR_NOMEM @@ -1943,7 +1929,7 @@ extern int wimlib_set_print_errors(bool show_messages); * @retval ::WIMLIB_ERR_SPLIT_UNSUPPORTED: * @a wim is not part 1 of a stand-alone WIM. * @retval ::WIMLIB_ERR_INVALID_PARAM - * @a w was @c NULL, @a swm_name was @c NULL, or @a part_size was 0. + * @a swm_name was @c NULL, or @a part_size was 0. * * Note: the WIM's uncompressed and compressed resources are not checksummed * when they are copied from the joined WIM to the split WIM parts, nor are @@ -2062,7 +2048,7 @@ extern int wimlib_unmount_image(const char *dir, int unmount_flags, * wimlib_add_image() or wimlib_add_image_from_ntfs_volume() functions was * concurrently modified, so it failed the SHA1 message digest check. * @retval ::WIMLIB_ERR_INVALID_PARAM - * @a wim or @a path was @c NULL. + * @a path was @c NULL. * @retval ::WIMLIB_ERR_INVALID_RESOURCE_SIZE * The metadata resource for @a image in @a wim is invalid. * @retval ::WIMLIB_ERR_INVALID_SECURITY_DATA diff --git a/src/wimlib_internal.h b/src/wimlib_internal.h index 3828931d..474ca171 100644 --- a/src/wimlib_internal.h +++ b/src/wimlib_internal.h @@ -311,6 +311,9 @@ struct WIMStruct { /* %true iff any images have been deleted from this WIM. */ bool deletion_occurred; + + bool all_images_verified; + bool full_verification_in_progress; }; @@ -441,6 +444,7 @@ extern int do_add_image(WIMStruct *w, const char *dir, const char *name, int, void *), void *extra_arg, wimlib_progress_func_t progress_func); +extern int wim_run_full_verifications(WIMStruct *w); /* ntfs-apply.c */ diff --git a/src/write.c b/src/write.c index 36b82b45..1a5b50ec 100644 --- a/src/write.c +++ b/src/write.c @@ -1426,6 +1426,8 @@ int finish_write(WIMStruct *w, int image, int write_flags, memcpy(&checkpoint_hdr, &hdr, sizeof(struct wim_header)); memset(&checkpoint_hdr.integrity, 0, sizeof(struct resource_entry)); if (fseeko(out, 0, SEEK_SET) != 0) { + ERROR_WITH_ERRNO("Failed to seek to beginning " + "of WIM being written"); ret = WIMLIB_ERR_WRITE; goto out; } @@ -1440,6 +1442,8 @@ int finish_write(WIMStruct *w, int image, int write_flags, } if (fseeko(out, 0, SEEK_END) != 0) { + ERROR_WITH_ERRNO("Failed to seek to end " + "of WIM being written"); ret = WIMLIB_ERR_WRITE; goto out; } @@ -1474,16 +1478,6 @@ int finish_write(WIMStruct *w, int image, int write_flags, * it should be a copy of the resource entry for the image that is * marked as bootable. This is not well documented... */ - if (hdr.boot_idx == 0 || !w->image_metadata - || (image != WIMLIB_ALL_IMAGES && image != hdr.boot_idx)) { - memset(&hdr.boot_metadata_res_entry, 0, - sizeof(struct resource_entry)); - } else { - memcpy(&hdr.boot_metadata_res_entry, - &w->image_metadata[ - hdr.boot_idx - 1].metadata_lte->output_resource_entry, - sizeof(struct resource_entry)); - } /* Set image count and boot index correctly for single image writes */ if (image != WIMLIB_ALL_IMAGES) { @@ -1494,7 +1488,19 @@ int finish_write(WIMStruct *w, int image, int write_flags, hdr.boot_idx = 0; } + if (hdr.boot_idx == 0) { + memset(&hdr.boot_metadata_res_entry, 0, + sizeof(struct resource_entry)); + } else { + memcpy(&hdr.boot_metadata_res_entry, + &w->image_metadata[ + hdr.boot_idx - 1].metadata_lte->output_resource_entry, + sizeof(struct resource_entry)); + } + if (fseeko(out, 0, SEEK_SET) != 0) { + ERROR_WITH_ERRNO("Failed to seek to beginning of WIM " + "being written"); ret = WIMLIB_ERR_WRITE; goto out; } @@ -1597,7 +1603,7 @@ WIMLIBAPI int wimlib_write(WIMStruct *w, const char *path, { int ret; - if (!w || !path) + if (!path) return WIMLIB_ERR_INVALID_PARAM; write_flags &= WIMLIB_WRITE_MASK_PUBLIC; @@ -1647,10 +1653,12 @@ static int lte_overwrite_prepare(struct lookup_table_entry *lte, static int check_resource_offset(struct lookup_table_entry *lte, void *arg) { - off_t end_offset = *(u64*)arg; - - wimlib_assert(lte->out_refcnt <= lte->refcnt); - if (lte->out_refcnt < lte->refcnt) { + if (lte->out_refcnt > lte->refcnt) { + WARNING("Detected invalid stream reference count. " + "Forcing re-build of entire WIM."); + return WIMLIB_ERR_RESOURCE_ORDER; + } else if (lte->out_refcnt < lte->refcnt) { + off_t end_offset = *(u64*)arg; if (lte->resource_entry.offset + lte->resource_entry.size > end_offset) { ERROR("The following resource is after the XML data:"); print_lookup_table_entry(lte); @@ -1724,7 +1732,7 @@ static int find_new_streams(struct lookup_table_entry *lte, void *arg) * is is crash-safe except in the case of write re-ordering, but the * disadvantage is that a small hole is left in the WIM where the old lookup * table, xml data, and integrity table were. (These usually only take up a - * small amount of space compared to the streams, however. + * small amount of space compared to the streams, however.) */ static int overwrite_wim_inplace(WIMStruct *w, int write_flags, unsigned num_threads, @@ -1799,8 +1807,9 @@ static int overwrite_wim_inplace(WIMStruct *w, int write_flags, if (fseeko(w->out_fp, old_wim_end, SEEK_SET) != 0) { ERROR_WITH_ERRNO("Can't seek to end of WIM"); - ret = WIMLIB_ERR_WRITE; - goto out_ftruncate; + fclose(w->out_fp); + w->out_fp = NULL; + return WIMLIB_ERR_WRITE; } if (!list_empty(&stream_list)) { @@ -1827,7 +1836,7 @@ static int overwrite_wim_inplace(WIMStruct *w, int write_flags, progress_func); out_ftruncate: close_wim_writable(w); - if (ret != 0) { + if (ret != 0 && !(write_flags & WIMLIB_WRITE_FLAG_NO_LOOKUP_TABLE)) { WARNING("Truncating `%s' to its original size (%"PRIu64" bytes)", w->filename, old_wim_end); truncate(w->filename, old_wim_end); @@ -1907,9 +1916,6 @@ WIMLIBAPI int wimlib_overwrite(WIMStruct *w, int write_flags, unsigned num_threads, wimlib_progress_func_t progress_func) { - if (!w) - return WIMLIB_ERR_INVALID_PARAM; - write_flags &= WIMLIB_WRITE_MASK_PUBLIC; if (!w->filename) @@ -1923,7 +1929,10 @@ WIMLIBAPI int wimlib_overwrite(WIMStruct *w, int write_flags, if ((!w->deletion_occurred || (write_flags & WIMLIB_WRITE_FLAG_SOFT_DELETE)) && !(write_flags & WIMLIB_WRITE_FLAG_REBUILD)) { - int i, modified_image_idx; + int i; + int modified_image_idx; + int ret; + for (i = 0; i < w->hdr.image_count && !w->image_metadata[i].modified; i++) ; modified_image_idx = i; @@ -1931,9 +1940,13 @@ WIMLIBAPI int wimlib_overwrite(WIMStruct *w, int write_flags, !w->image_metadata[i].has_been_mounted_rw; i++) ; if (i == w->hdr.image_count) { - return overwrite_wim_inplace(w, write_flags, num_threads, - progress_func, - modified_image_idx); + ret = overwrite_wim_inplace(w, write_flags, num_threads, + progress_func, + modified_image_idx); + if (ret == WIMLIB_ERR_RESOURCE_ORDER) + WARNING("Falling back to re-building entire WIM"); + else + return ret; } } return overwrite_wim_via_tmpfile(w, write_flags, num_threads, diff --git a/src/xml.c b/src/xml.c index a1e6f596..fd5cddf1 100644 --- a/src/xml.c +++ b/src/xml.c @@ -950,9 +950,6 @@ void xml_delete_image(struct wim_info **wim_info_p, int image) wim_info = *wim_info_p; - wimlib_assert(wim_info != NULL); - wimlib_assert(image >= 1 && image <= wim_info->num_images); - destroy_image_info(&wim_info->images[image - 1]); memcpy(&wim_info->images[image - 1],