* */
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)
*/
void free_dentry(struct dentry *dentry)
{
- wimlib_assert(dentry != NULL);
FREE(dentry->file_name);
FREE(dentry->file_name_utf8);
FREE(dentry->short_name);
void put_dentry(struct dentry *dentry)
{
- wimlib_assert(dentry != NULL);
wimlib_assert(dentry->refcnt != 0);
-
if (--dentry->refcnt == 0)
free_dentry(dentry);
}
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)
"%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 "
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.
goto out;
#endif
}
+ #endif
}
}
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;
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,
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");
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.
*/
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
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)
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");
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)
{
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));
* - 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;
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;
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)
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');
}
* 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);
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);
/* 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;
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);
}
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;
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
&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) {
"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;
}
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;
}
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);
}
/** 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
* ::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
* 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
* @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
* @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
* 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.
* @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.
* @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.
*/
* @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
* @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
* 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
/* %true iff any images have been deleted from this WIM. */
bool deletion_occurred;
+
+ bool all_images_verified;
+ bool full_verification_in_progress;
};
int, void *),
void *extra_arg,
wimlib_progress_func_t progress_func);
+extern int wim_run_full_verifications(WIMStruct *w);
/* ntfs-apply.c */
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;
}
}
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;
}
* 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) {
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;
}
{
int ret;
- if (!w || !path)
+ if (!path)
return WIMLIB_ERR_INVALID_PARAM;
write_flags &= WIMLIB_WRITE_MASK_PUBLIC;
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);
* 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,
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)) {
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);
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)
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;
!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,
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],