Various fixes and cleanups
authorEric Biggers <ebiggers3@gmail.com>
Sun, 16 Dec 2012 07:44:00 +0000 (01:44 -0600)
committerEric Biggers <ebiggers3@gmail.com>
Sun, 16 Dec 2012 07:44:00 +0000 (01:44 -0600)
12 files changed:
src/dentry.c
src/extract.c
src/hardlink.c
src/modify.c
src/mount.c
src/resource.c
src/split.c
src/wim.c
src/wimlib.h
src/wimlib_internal.h
src/write.c
src/xml.c

index 5460149..4ff8602 100644 (file)
@@ -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
                }
        }
 
index 8fbdd0d..5550816 100644 (file)
@@ -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;
index 007e744..e3f9e27 100644 (file)
@@ -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,
index 5b8fe41..42de5e9 100644 (file)
@@ -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
index 0122d84..3c50c75 100644 (file)
@@ -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)
index 86a2be6..2576197 100644 (file)
@@ -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;
 
index 649a9bf..50f15bf 100644 (file)
@@ -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)
index cbda006..c76be36 100644 (file)
--- 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 "
                      "<IMAGE> 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);
        }
index 084f704..5265a39 100644 (file)
@@ -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-<code>NULL</code>, @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
index 3828931..474ca17 100644 (file)
@@ -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 */
 
index 36b82b4..1a5b50e 100644 (file)
@@ -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,
index a1e6f59..fd5cddf 100644 (file)
--- 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],