From 40beb80283a2df7af88c8359ca41adb814585e9a Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 16 Dec 2012 12:30:19 -0600 Subject: [PATCH] Re-organize code --- Makefile.am | 26 +- src/{modify.c => add_image.c} | 548 +++---------------- src/{comp.c => compress.c} | 4 +- src/{comp.h => compress.h} | 8 +- src/{decomp.c => decompress.c} | 4 +- src/{decomp.h => decompress.h} | 2 +- src/delete_image.c | 92 ++++ src/export_image.c | 346 ++++++++++++ src/{extract.c => extract_image.c} | 4 +- src/{lz.c => lz77.c} | 2 +- src/{lzx-comp.c => lzx-compress.c} | 7 +- src/{lzx-decomp.c => lzx-decompress.c} | 4 +- src/{mount.c => mount_image.c} | 2 +- src/wim.c | 14 + src/wimlib_internal.h | 26 +- src/{xpress-comp.c => xpress-compress.c} | 6 +- src/{xpress-decomp.c => xpress-decompress.c} | 9 +- src/xpress.h | 2 +- tests/test-imagex | 12 +- tests/test-imagex-mount | 16 +- 20 files changed, 586 insertions(+), 548 deletions(-) rename src/{modify.c => add_image.c} (64%) rename src/{comp.c => compress.c} (99%) rename src/{comp.h => compress.h} (95%) rename src/{decomp.c => decompress.c} (99%) rename src/{decomp.h => decompress.h} (99%) create mode 100644 src/delete_image.c create mode 100644 src/export_image.c rename src/{extract.c => extract_image.c} (99%) rename src/{lz.c => lz77.c} (99%) rename src/{lzx-comp.c => lzx-compress.c} (99%) rename src/{lzx-decomp.c => lzx-decompress.c} (99%) rename src/{mount.c => mount_image.c} (99%) rename src/{xpress-comp.c => xpress-compress.c} (98%) rename src/{xpress-decomp.c => xpress-decompress.c} (97%) diff --git a/Makefile.am b/Makefile.am index da603f21..b0320835 100644 --- a/Makefile.am +++ b/Makefile.am @@ -10,14 +10,17 @@ lib_LTLIBRARIES = libwim.la libwim_la_LDFLAGS = -version-info 1:0:0 libwim_la_SOURCES = \ - src/comp.c \ - src/comp.h \ - src/decomp.c \ - src/decomp.h \ + src/add_image.c \ + src/compress.c \ + src/compress.h \ + src/decompress.c \ + src/decompress.h \ + src/delete_image.c \ src/dentry.c \ src/dentry.h \ src/endianness.h \ - src/extract.c \ + src/export_image.c \ + src/extract_image.c \ src/hardlink.c \ src/header.c \ src/integrity.c \ @@ -26,13 +29,12 @@ libwim_la_SOURCES = \ src/list.h \ src/lookup_table.c \ src/lookup_table.h \ - src/lz.c \ + src/lz77.c \ src/lzx-common.c \ - src/lzx-comp.c \ - src/lzx-decomp.c \ + src/lzx-compress.c \ + src/lzx-decompress.c \ src/lzx.h \ - src/modify.c \ - src/mount.c \ + src/mount_image.c \ src/resource.c \ src/rbtree.c \ src/rbtree.h \ @@ -52,8 +54,8 @@ libwim_la_SOURCES = \ src/write.c \ src/xml.c \ src/xml.h \ - src/xpress-comp.c \ - src/xpress-decomp.c \ + src/xpress-compress.c \ + src/xpress-decompress.c \ src/xpress.h if WITH_NTFS_3G diff --git a/src/modify.c b/src/add_image.c similarity index 64% rename from src/modify.c rename to src/add_image.c index 2697a3d7..085fd044 100644 --- a/src/modify.c +++ b/src/add_image.c @@ -1,10 +1,5 @@ /* - * modify.c - * - * Support for modifying WIM files with image-level operations (delete an image, - * add an image, export an image from one WIM to another.) There is nothing - * here that lets you change individual files in the WIM; for that you will need - * to look at the filesystem implementation in mount.c. + * add_image.c */ /* @@ -27,38 +22,91 @@ */ #include "wimlib_internal.h" -#include "util.h" -#include "sha1.h" #include "dentry.h" -#include "xml.h" -#include "lookup_table.h" #include "timestamp.h" -#include -#include +#include "lookup_table.h" +#include "xml.h" #include -#include #include #include +#include +#include +#include #include /** Private flag: Used to mark that we currently adding the root directory of * the WIM image. */ #define WIMLIB_ADD_IMAGE_FLAG_ROOT 0x80000000 -void destroy_image_metadata(struct image_metadata *imd, - struct lookup_table *table) +/* + * Adds an image (given by its dentry tree) to the image metadata array of a WIM + * file, adds an entry to the lookup table for the image metadata, updates the + * image count in the header, and selects the new image. + * + * Does not update the XML data. + * + * On failure, WIMLIB_ERR_NOMEM is returned and no changes are made. Otherwise, + * 0 is returned and the image metadata array of @w is modified. + * + * @w: The WIMStruct for the WIM file. + * @root_dentry: The root of the directory tree for the image. + * @sd: The security data for the image. + */ +int add_new_dentry_tree(WIMStruct *w, struct dentry *root_dentry, + struct wim_security_data *sd) { - free_dentry_tree(imd->root_dentry, table); - free_security_data(imd->security_data); - - /* Get rid of the lookup table entry for this image's metadata resource - * */ - if (table) { - lookup_table_unlink(table, imd->metadata_lte); - free_lookup_table_entry(imd->metadata_lte); + struct lookup_table_entry *metadata_lte; + struct image_metadata *imd; + struct image_metadata *new_imd; + int ret; + + wimlib_assert(root_dentry != NULL); + + DEBUG("Reallocating image metadata array for image_count = %u", + w->hdr.image_count + 1); + imd = CALLOC((w->hdr.image_count + 1), sizeof(struct image_metadata)); + + if (!imd) { + ERROR("Failed to allocate memory for new image metadata array"); + goto err; } + + memcpy(imd, w->image_metadata, + w->hdr.image_count * sizeof(struct image_metadata)); + + metadata_lte = new_lookup_table_entry(); + if (!metadata_lte) + goto err_free_imd; + + metadata_lte->resource_entry.flags = WIM_RESHDR_FLAG_METADATA; + random_hash(metadata_lte->hash); + lookup_table_insert(w->lookup_table, metadata_lte); + + new_imd = &imd[w->hdr.image_count]; + + new_imd->root_dentry = root_dentry; + new_imd->metadata_lte = metadata_lte; + new_imd->security_data = sd; + new_imd->modified = true; + + FREE(w->image_metadata); + w->image_metadata = imd; + w->hdr.image_count++; + + /* Change the current image to the new one. There should not be any + * ways for this to fail, since the image is valid and the dentry tree + * is already in memory. */ + ret = select_wim_image(w, w->hdr.image_count); + wimlib_assert(ret == 0); + return ret; +err_free_imd: + FREE(imd); +err: + return WIMLIB_ERR_NOMEM; + } + /* * Recursively builds a dentry tree from a directory tree on disk, outside the * WIM file. @@ -331,458 +379,6 @@ out: return ret; } -struct wim_pair { - WIMStruct *src_wim; - WIMStruct *dest_wim; - struct list_head lte_list_head; -}; - -static int allocate_lte_if_needed(struct dentry *dentry, void *arg) -{ - const WIMStruct *src_wim, *dest_wim; - struct list_head *lte_list_head; - struct inode *inode; - - src_wim = ((struct wim_pair*)arg)->src_wim; - dest_wim = ((struct wim_pair*)arg)->dest_wim; - lte_list_head = &((struct wim_pair*)arg)->lte_list_head; - inode = dentry->d_inode; - - wimlib_assert(!inode->resolved); - - for (unsigned i = 0; i <= inode->num_ads; i++) { - struct lookup_table_entry *src_lte, *dest_lte; - src_lte = inode_stream_lte_unresolved(inode, i, - src_wim->lookup_table); - - if (src_lte && ++src_lte->out_refcnt == 1) { - dest_lte = inode_stream_lte_unresolved(inode, i, - dest_wim->lookup_table); - - if (!dest_lte) { - dest_lte = clone_lookup_table_entry(src_lte); - if (!dest_lte) - return WIMLIB_ERR_NOMEM; - list_add_tail(&dest_lte->staging_list, lte_list_head); - } - } - } - return 0; -} - -/* - * This function takes in a dentry that was previously located only in image(s) - * in @src_wim, but now is being added to @dest_wim. For each stream associated - * with the dentry, if there is already a lookup table entry for that stream in - * the lookup table of the destination WIM file, its reference count is - * incrementej. Otherwise, a new lookup table entry is created that points back - * to the stream in the source WIM file (through the @hash field combined with - * the @wim field of the lookup table entry.) - */ -static int add_lte_to_dest_wim(struct dentry *dentry, void *arg) -{ - WIMStruct *src_wim, *dest_wim; - struct inode *inode; - - src_wim = ((struct wim_pair*)arg)->src_wim; - dest_wim = ((struct wim_pair*)arg)->dest_wim; - inode = dentry->d_inode; - - wimlib_assert(!inode->resolved); - - for (unsigned i = 0; i <= inode->num_ads; i++) { - struct lookup_table_entry *src_lte, *dest_lte; - src_lte = inode_stream_lte_unresolved(inode, i, - src_wim->lookup_table); - - if (!src_lte) /* Empty or nonexistent stream. */ - continue; - - dest_lte = inode_stream_lte_unresolved(inode, i, - dest_wim->lookup_table); - if (dest_lte) { - dest_lte->refcnt++; - } else { - struct list_head *lte_list_head; - struct list_head *next; - - lte_list_head = &((struct wim_pair*)arg)->lte_list_head; - wimlib_assert(!list_empty(lte_list_head)); - - next = lte_list_head->next; - list_del(next); - dest_lte = container_of(next, struct lookup_table_entry, - staging_list); - dest_lte->part_number = 1; - dest_lte->refcnt = 1; - wimlib_assert(hashes_equal(dest_lte->hash, src_lte->hash)); - - lookup_table_insert(dest_wim->lookup_table, dest_lte); - } - } - return 0; -} - -/* - * Adds an image (given by its dentry tree) to the image metadata array of a WIM - * file, adds an entry to the lookup table for the image metadata, updates the - * image count in the header, and selects the new image. - * - * Does not update the XML data. - * - * On failure, WIMLIB_ERR_NOMEM is returned and no changes are made. Otherwise, - * 0 is returned and the image metadata array of @w is modified. - * - * @w: The WIMStruct for the WIM file. - * @root_dentry: The root of the directory tree for the image. - * @sd: The security data for the image. - */ -static int add_new_dentry_tree(WIMStruct *w, struct dentry *root_dentry, - struct wim_security_data *sd) -{ - struct lookup_table_entry *metadata_lte; - struct image_metadata *imd; - struct image_metadata *new_imd; - int ret; - - wimlib_assert(root_dentry != NULL); - - DEBUG("Reallocating image metadata array for image_count = %u", - w->hdr.image_count + 1); - imd = CALLOC((w->hdr.image_count + 1), sizeof(struct image_metadata)); - - if (!imd) { - ERROR("Failed to allocate memory for new image metadata array"); - goto err; - } - - memcpy(imd, w->image_metadata, - w->hdr.image_count * sizeof(struct image_metadata)); - - metadata_lte = new_lookup_table_entry(); - if (!metadata_lte) - goto err_free_imd; - - metadata_lte->resource_entry.flags = WIM_RESHDR_FLAG_METADATA; - random_hash(metadata_lte->hash); - lookup_table_insert(w->lookup_table, metadata_lte); - - new_imd = &imd[w->hdr.image_count]; - - new_imd->root_dentry = root_dentry; - new_imd->metadata_lte = metadata_lte; - new_imd->security_data = sd; - new_imd->modified = true; - - FREE(w->image_metadata); - w->image_metadata = imd; - w->hdr.image_count++; - - /* Change the current image to the new one. There should not be any - * ways for this to fail, since the image is valid and the dentry tree - * is already in memory. */ - ret = select_wim_image(w, w->hdr.image_count); - wimlib_assert(ret == 0); - return ret; -err_free_imd: - FREE(imd); -err: - return WIMLIB_ERR_NOMEM; - -} - -/* - * Copies an image, or all the images, from a WIM file, into another WIM file. - */ -WIMLIBAPI int wimlib_export_image(WIMStruct *src_wim, - int src_image, - WIMStruct *dest_wim, - const char *dest_name, - const char *dest_description, - int export_flags, - WIMStruct **additional_swms, - unsigned num_additional_swms, - wimlib_progress_func_t progress_func) -{ - int i; - int ret; - struct dentry *root; - struct wim_pair wims; - struct wim_security_data *sd; - struct lookup_table *joined_tab, *src_wim_tab_save; - - if (dest_wim->hdr.total_parts != 1) { - ERROR("Exporting an image to a split WIM is " - "unsupported"); - return WIMLIB_ERR_SPLIT_UNSUPPORTED; - } - - if (src_image == WIMLIB_ALL_IMAGES) { - if (src_wim->hdr.image_count > 1) { - - /* multi-image export. */ - - if ((export_flags & WIMLIB_EXPORT_FLAG_BOOT) && - (src_wim->hdr.boot_idx == 0)) - { - /* Specifying the boot flag on a multi-image - * source WIM makes the boot index default to - * the bootable image in the source WIM. It is - * an error if there is no such bootable image. - * */ - ERROR("Cannot specify `boot' flag when " - "exporting multiple images from a WIM " - "with no bootable images"); - return WIMLIB_ERR_INVALID_PARAM; - } - if (dest_name || dest_description) { - ERROR("Image name or image description was " - "specified, but we are exporting " - "multiple images"); - return WIMLIB_ERR_INVALID_PARAM; - } - for (i = 1; i <= src_wim->hdr.image_count; i++) { - int new_flags = export_flags; - - if (i != src_wim->hdr.boot_idx) - new_flags &= ~WIMLIB_EXPORT_FLAG_BOOT; - - ret = wimlib_export_image(src_wim, i, dest_wim, - NULL, NULL, - new_flags, - additional_swms, - num_additional_swms, - progress_func); - if (ret != 0) - return ret; - } - return 0; - } else if (src_wim->hdr.image_count == 1) { - src_image = 1; - } else { - return 0; - } - } - - if (!dest_name) { - dest_name = wimlib_get_image_name(src_wim, src_image); - DEBUG("Using name `%s' for source image %d", - dest_name, src_image); - } - - if (!dest_description) { - dest_description = wimlib_get_image_description(src_wim, - src_image); - DEBUG("Using description `%s' for source image %d", - dest_description, src_image); - } - - DEBUG("Exporting image %d from `%s'", src_image, src_wim->filename); - - if (wimlib_image_name_in_use(dest_wim, dest_name)) { - ERROR("There is already an image named `%s' in the " - "destination WIM", dest_name); - return WIMLIB_ERR_IMAGE_NAME_COLLISION; - } - - ret = verify_swm_set(src_wim, additional_swms, num_additional_swms); - if (ret != 0) - return ret; - - if (num_additional_swms) { - ret = new_joined_lookup_table(src_wim, additional_swms, - num_additional_swms, - &joined_tab); - if (ret != 0) - return ret; - src_wim_tab_save = src_wim->lookup_table; - src_wim->lookup_table = joined_tab; - } - - ret = select_wim_image(src_wim, src_image); - if (ret != 0) { - ERROR("Could not select image %d from the WIM `%s' " - "to export it", src_image, src_wim->filename); - goto out; - } - - /* Pre-allocate the new lookup table entries that will be needed. This - * way, it's not possible to run out of memory part-way through - * modifying the lookup table of the destination WIM. */ - wims.src_wim = src_wim; - wims.dest_wim = dest_wim; - INIT_LIST_HEAD(&wims.lte_list_head); - for_lookup_table_entry(src_wim->lookup_table, lte_zero_out_refcnt, NULL); - root = wim_root_dentry(src_wim); - for_dentry_in_tree(root, dentry_unresolve_ltes, NULL); - ret = for_dentry_in_tree(root, allocate_lte_if_needed, &wims); - if (ret != 0) - goto out_free_ltes; - - ret = xml_export_image(src_wim->wim_info, src_image, - &dest_wim->wim_info, dest_name, dest_description); - if (ret != 0) - goto out_free_ltes; - - sd = wim_security_data(src_wim); - ret = add_new_dentry_tree(dest_wim, root, sd); - if (ret != 0) - goto out_xml_delete_image; - - - /* All memory allocations have been taken care of, so it's no longer - * possible for this function to fail. Go ahead and increment the - * reference counts of the dentry tree and security data, then update - * the lookup table of the destination WIM and the boot index, if - * needed. */ - for_dentry_in_tree(root, increment_dentry_refcnt, NULL); - sd->refcnt++; - for_dentry_in_tree(root, add_lte_to_dest_wim, &wims); - wimlib_assert(list_empty(&wims.lte_list_head)); - - if (export_flags & WIMLIB_EXPORT_FLAG_BOOT) { - DEBUG("Setting boot_idx to %d", dest_wim->hdr.image_count); - wimlib_set_boot_idx(dest_wim, dest_wim->hdr.image_count); - } - ret = 0; - goto out; - -out_xml_delete_image: - xml_delete_image(&dest_wim->wim_info, dest_wim->hdr.image_count); -out_free_ltes: - { - struct lookup_table_entry *lte, *tmp; - list_for_each_entry_safe(lte, tmp, &wims.lte_list_head, staging_list) - free_lookup_table_entry(lte); - } - -out: - if (num_additional_swms) { - free_lookup_table(src_wim->lookup_table); - src_wim->lookup_table = src_wim_tab_save; - } - 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 delete all the - * references to a stream and then remove it, it might still be referenced - * somewhere else, making a file be missing from the WIM... So, work around this - * problem by looking at ALL the images to re-calculate the reference count of - * EVERY lookup table entry. This only absolutely has to be done before an image - * is deleted or before an image is mounted read-write. */ -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 (int i = 0; i < w->hdr.image_count; i++) - w->image_metadata[i].metadata_lte->real_refcnt++; - 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. - */ -WIMLIBAPI int wimlib_delete_image(WIMStruct *w, int image) -{ - int i; - int ret; - - if (w->hdr.total_parts != 1) { - ERROR("Deleting an image from a split WIM is not supported."); - return WIMLIB_ERR_SPLIT_UNSUPPORTED; - } - - if (image == WIMLIB_ALL_IMAGES) { - for (i = w->hdr.image_count; i >= 1; i--) { - ret = wimlib_delete_image(w, i); - if (ret != 0) - return ret; - } - 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 - * therefore allocate it) so that we can decrement the reference counts - * in the lookup table. */ - ret = select_wim_image(w, image); - if (ret != 0) - return ret; - - /* Free the dentry tree, any lookup table entries that have their - * refcnt decremented to 0, and the security data. */ - destroy_image_metadata(&w->image_metadata[image - 1], w->lookup_table); - - /* Get rid of the empty slot in the image metadata array. */ - memmove(&w->image_metadata[image - 1], &w->image_metadata[image], - (w->hdr.image_count - image) * sizeof(struct image_metadata)); - - /* Decrement the image count. */ - if (--w->hdr.image_count == 0) { - FREE(w->image_metadata); - w->image_metadata = NULL; - } - - /* Fix the boot index. */ - if (w->hdr.boot_idx == image) - w->hdr.boot_idx = 0; - else if (w->hdr.boot_idx > image) - w->hdr.boot_idx--; - - w->current_image = WIMLIB_NO_IMAGE; - - /* Remove the image from the XML information. */ - xml_delete_image(&w->wim_info, image); - - w->deletion_occurred = true; - return 0; -} enum pattern_type { NONE = 0, @@ -1061,7 +657,7 @@ WIMLIBAPI int wimlib_add_image(WIMStruct *w, const char *source, ERROR("Must specify a non-empty string for the image name"); return WIMLIB_ERR_INVALID_PARAM; } - if (!source) { + if (!source || !*source) { ERROR("Must specify the name of a directory or NTFS volume"); return WIMLIB_ERR_INVALID_PARAM; } diff --git a/src/comp.c b/src/compress.c similarity index 99% rename from src/comp.c rename to src/compress.c index ab3040d8..02ff35dd 100644 --- a/src/comp.c +++ b/src/compress.c @@ -1,5 +1,5 @@ /* - * comp.c + * compress.c * * Functions used for compression. */ @@ -23,7 +23,7 @@ * along with wimlib; if not, see http://www.gnu.org/licenses/. */ -#include "comp.h" +#include "compress.h" #include #include diff --git a/src/comp.h b/src/compress.h similarity index 95% rename from src/comp.h rename to src/compress.h index 37b1f992..37ab23d3 100644 --- a/src/comp.h +++ b/src/compress.h @@ -1,11 +1,11 @@ /* - * comp.h + * compress.h * * Functions useful for compression, mainly bitstreams. */ -#ifndef _WIMLIB_COMP_H -#define _WIMLIB_COMP_H +#ifndef _WIMLIB_COMPRESS_H +#define _WIMLIB_COMPRESS_H #include "util.h" #include "endianness.h" @@ -92,4 +92,4 @@ extern void make_canonical_huffman_code(unsigned num_syms, u8 lens[], u16 codewords[]); -#endif /* _WIMLIB_COMP_H */ +#endif /* _WIMLIB_COMPRESS_H */ diff --git a/src/decomp.c b/src/decompress.c similarity index 99% rename from src/decomp.c rename to src/decompress.c index b1a7043e..47ce9943 100644 --- a/src/decomp.c +++ b/src/decompress.c @@ -1,5 +1,5 @@ /* - * decomp.c + * decompress.c * * Functions used for decompression. */ @@ -23,7 +23,7 @@ * along with wimlib; if not, see http://www.gnu.org/licenses/. */ -#include "decomp.h" +#include "decompress.h" #include /* Reads @n bytes from the bitstream @stream into the location pointed to by @dest. diff --git a/src/decomp.h b/src/decompress.h similarity index 99% rename from src/decomp.h rename to src/decompress.h index 0bd2a69f..b4c45795 100644 --- a/src/decomp.h +++ b/src/decompress.h @@ -1,5 +1,5 @@ /* - * decomp.h + * decompress.h * * Functions useful for decompression, mainly bitstreams. */ diff --git a/src/delete_image.c b/src/delete_image.c new file mode 100644 index 00000000..ecd80478 --- /dev/null +++ b/src/delete_image.c @@ -0,0 +1,92 @@ +/* + * delete_image.c + */ + +/* + * Copyright (C) 2012 Eric Biggers + * + * 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 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 General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with wimlib; if not, see http://www.gnu.org/licenses/. + */ + +#include "wimlib_internal.h" +#include "xml.h" +#include + +/* + * Deletes an image from the WIM. + */ +WIMLIBAPI int wimlib_delete_image(WIMStruct *w, int image) +{ + int i; + int ret; + + if (w->hdr.total_parts != 1) { + ERROR("Deleting an image from a split WIM is not supported."); + return WIMLIB_ERR_SPLIT_UNSUPPORTED; + } + + if (image == WIMLIB_ALL_IMAGES) { + for (i = w->hdr.image_count; i >= 1; i--) { + ret = wimlib_delete_image(w, i); + if (ret != 0) + return ret; + } + 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 + * therefore allocate it) so that we can decrement the reference counts + * in the lookup table. */ + ret = select_wim_image(w, image); + if (ret != 0) + return ret; + + /* Free the dentry tree, any lookup table entries that have their + * refcnt decremented to 0, and the security data. */ + destroy_image_metadata(&w->image_metadata[image - 1], w->lookup_table); + + /* Get rid of the empty slot in the image metadata array. */ + memmove(&w->image_metadata[image - 1], &w->image_metadata[image], + (w->hdr.image_count - image) * sizeof(struct image_metadata)); + + /* Decrement the image count. */ + if (--w->hdr.image_count == 0) { + FREE(w->image_metadata); + w->image_metadata = NULL; + } + + /* Fix the boot index. */ + if (w->hdr.boot_idx == image) + w->hdr.boot_idx = 0; + else if (w->hdr.boot_idx > image) + w->hdr.boot_idx--; + + w->current_image = WIMLIB_NO_IMAGE; + + /* Remove the image from the XML information. */ + xml_delete_image(&w->wim_info, image); + + w->deletion_occurred = true; + return 0; +} diff --git a/src/export_image.c b/src/export_image.c new file mode 100644 index 00000000..9b9304ce --- /dev/null +++ b/src/export_image.c @@ -0,0 +1,346 @@ +/* + * export_image.c + */ + +/* + * Copyright (C) 2012 Eric Biggers + * + * 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 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 General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with wimlib; if not, see http://www.gnu.org/licenses/. + */ + +#include "wimlib_internal.h" +#include "dentry.h" +#include "lookup_table.h" +#include "xml.h" + +struct wim_pair { + WIMStruct *src_wim; + WIMStruct *dest_wim; + struct list_head lte_list_head; +}; + +static int allocate_lte_if_needed(struct dentry *dentry, void *arg) +{ + const WIMStruct *src_wim, *dest_wim; + struct list_head *lte_list_head; + struct inode *inode; + + src_wim = ((struct wim_pair*)arg)->src_wim; + dest_wim = ((struct wim_pair*)arg)->dest_wim; + lte_list_head = &((struct wim_pair*)arg)->lte_list_head; + inode = dentry->d_inode; + + wimlib_assert(!inode->resolved); + + for (unsigned i = 0; i <= inode->num_ads; i++) { + struct lookup_table_entry *src_lte, *dest_lte; + src_lte = inode_stream_lte_unresolved(inode, i, + src_wim->lookup_table); + + if (src_lte && ++src_lte->out_refcnt == 1) { + dest_lte = inode_stream_lte_unresolved(inode, i, + dest_wim->lookup_table); + + if (!dest_lte) { + dest_lte = clone_lookup_table_entry(src_lte); + if (!dest_lte) + return WIMLIB_ERR_NOMEM; + list_add_tail(&dest_lte->staging_list, lte_list_head); + } + } + } + return 0; +} + +/* + * This function takes in a dentry that was previously located only in image(s) + * in @src_wim, but now is being added to @dest_wim. For each stream associated + * with the dentry, if there is already a lookup table entry for that stream in + * the lookup table of the destination WIM file, its reference count is + * incrementej. Otherwise, a new lookup table entry is created that points back + * to the stream in the source WIM file (through the @hash field combined with + * the @wim field of the lookup table entry.) + */ +static int add_lte_to_dest_wim(struct dentry *dentry, void *arg) +{ + WIMStruct *src_wim, *dest_wim; + struct inode *inode; + + src_wim = ((struct wim_pair*)arg)->src_wim; + dest_wim = ((struct wim_pair*)arg)->dest_wim; + inode = dentry->d_inode; + + wimlib_assert(!inode->resolved); + + for (unsigned i = 0; i <= inode->num_ads; i++) { + struct lookup_table_entry *src_lte, *dest_lte; + src_lte = inode_stream_lte_unresolved(inode, i, + src_wim->lookup_table); + + if (!src_lte) /* Empty or nonexistent stream. */ + continue; + + dest_lte = inode_stream_lte_unresolved(inode, i, + dest_wim->lookup_table); + if (dest_lte) { + dest_lte->refcnt++; + } else { + struct list_head *lte_list_head; + struct list_head *next; + + lte_list_head = &((struct wim_pair*)arg)->lte_list_head; + wimlib_assert(!list_empty(lte_list_head)); + + next = lte_list_head->next; + list_del(next); + dest_lte = container_of(next, struct lookup_table_entry, + staging_list); + dest_lte->part_number = 1; + dest_lte->refcnt = 1; + wimlib_assert(hashes_equal(dest_lte->hash, src_lte->hash)); + + lookup_table_insert(dest_wim->lookup_table, dest_lte); + } + } + return 0; +} + +/* + * Copies an image, or all the images, from a WIM file, into another WIM file. + */ +WIMLIBAPI int wimlib_export_image(WIMStruct *src_wim, + int src_image, + WIMStruct *dest_wim, + const char *dest_name, + const char *dest_description, + int export_flags, + WIMStruct **additional_swms, + unsigned num_additional_swms, + wimlib_progress_func_t progress_func) +{ + int i; + int ret; + struct dentry *root; + struct wim_pair wims; + struct wim_security_data *sd; + struct lookup_table *joined_tab, *src_wim_tab_save; + + if (dest_wim->hdr.total_parts != 1) { + ERROR("Exporting an image to a split WIM is " + "unsupported"); + return WIMLIB_ERR_SPLIT_UNSUPPORTED; + } + + if (src_image == WIMLIB_ALL_IMAGES) { + if (src_wim->hdr.image_count > 1) { + + /* multi-image export. */ + + if ((export_flags & WIMLIB_EXPORT_FLAG_BOOT) && + (src_wim->hdr.boot_idx == 0)) + { + /* Specifying the boot flag on a multi-image + * source WIM makes the boot index default to + * the bootable image in the source WIM. It is + * an error if there is no such bootable image. + * */ + ERROR("Cannot specify `boot' flag when " + "exporting multiple images from a WIM " + "with no bootable images"); + return WIMLIB_ERR_INVALID_PARAM; + } + if (dest_name || dest_description) { + ERROR("Image name or image description was " + "specified, but we are exporting " + "multiple images"); + return WIMLIB_ERR_INVALID_PARAM; + } + for (i = 1; i <= src_wim->hdr.image_count; i++) { + int new_flags = export_flags; + + if (i != src_wim->hdr.boot_idx) + new_flags &= ~WIMLIB_EXPORT_FLAG_BOOT; + + ret = wimlib_export_image(src_wim, i, dest_wim, + NULL, NULL, + new_flags, + additional_swms, + num_additional_swms, + progress_func); + if (ret != 0) + return ret; + } + return 0; + } else if (src_wim->hdr.image_count == 1) { + src_image = 1; + } else { + return 0; + } + } + + if (!dest_name) { + dest_name = wimlib_get_image_name(src_wim, src_image); + DEBUG("Using name `%s' for source image %d", + dest_name, src_image); + } + + if (!dest_description) { + dest_description = wimlib_get_image_description(src_wim, + src_image); + DEBUG("Using description `%s' for source image %d", + dest_description, src_image); + } + + DEBUG("Exporting image %d from `%s'", src_image, src_wim->filename); + + if (wimlib_image_name_in_use(dest_wim, dest_name)) { + ERROR("There is already an image named `%s' in the " + "destination WIM", dest_name); + return WIMLIB_ERR_IMAGE_NAME_COLLISION; + } + + ret = verify_swm_set(src_wim, additional_swms, num_additional_swms); + if (ret != 0) + return ret; + + if (num_additional_swms) { + ret = new_joined_lookup_table(src_wim, additional_swms, + num_additional_swms, + &joined_tab); + if (ret != 0) + return ret; + src_wim_tab_save = src_wim->lookup_table; + src_wim->lookup_table = joined_tab; + } + + ret = select_wim_image(src_wim, src_image); + if (ret != 0) { + ERROR("Could not select image %d from the WIM `%s' " + "to export it", src_image, src_wim->filename); + goto out; + } + + /* Pre-allocate the new lookup table entries that will be needed. This + * way, it's not possible to run out of memory part-way through + * modifying the lookup table of the destination WIM. */ + wims.src_wim = src_wim; + wims.dest_wim = dest_wim; + INIT_LIST_HEAD(&wims.lte_list_head); + for_lookup_table_entry(src_wim->lookup_table, lte_zero_out_refcnt, NULL); + root = wim_root_dentry(src_wim); + for_dentry_in_tree(root, dentry_unresolve_ltes, NULL); + ret = for_dentry_in_tree(root, allocate_lte_if_needed, &wims); + if (ret != 0) + goto out_free_ltes; + + ret = xml_export_image(src_wim->wim_info, src_image, + &dest_wim->wim_info, dest_name, dest_description); + if (ret != 0) + goto out_free_ltes; + + sd = wim_security_data(src_wim); + ret = add_new_dentry_tree(dest_wim, root, sd); + if (ret != 0) + goto out_xml_delete_image; + + + /* All memory allocations have been taken care of, so it's no longer + * possible for this function to fail. Go ahead and increment the + * reference counts of the dentry tree and security data, then update + * the lookup table of the destination WIM and the boot index, if + * needed. */ + for_dentry_in_tree(root, increment_dentry_refcnt, NULL); + sd->refcnt++; + for_dentry_in_tree(root, add_lte_to_dest_wim, &wims); + wimlib_assert(list_empty(&wims.lte_list_head)); + + if (export_flags & WIMLIB_EXPORT_FLAG_BOOT) { + DEBUG("Setting boot_idx to %d", dest_wim->hdr.image_count); + wimlib_set_boot_idx(dest_wim, dest_wim->hdr.image_count); + } + ret = 0; + goto out; + +out_xml_delete_image: + xml_delete_image(&dest_wim->wim_info, dest_wim->hdr.image_count); +out_free_ltes: + { + struct lookup_table_entry *lte, *tmp; + list_for_each_entry_safe(lte, tmp, &wims.lte_list_head, staging_list) + free_lookup_table_entry(lte); + } + +out: + if (num_additional_swms) { + free_lookup_table(src_wim->lookup_table); + src_wim->lookup_table = src_wim_tab_save; + } + 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 delete all the + * references to a stream and then remove it, it might still be referenced + * somewhere else, making a file be missing from the WIM... So, work around this + * problem by looking at ALL the images to re-calculate the reference count of + * EVERY lookup table entry. This only absolutely has to be done before an image + * is deleted or before an image is mounted read-write. */ +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 (int i = 0; i < w->hdr.image_count; i++) + w->image_metadata[i].metadata_lte->real_refcnt++; + 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; +} diff --git a/src/extract.c b/src/extract_image.c similarity index 99% rename from src/extract.c rename to src/extract_image.c index 55508169..22b12ba1 100644 --- a/src/extract.c +++ b/src/extract_image.c @@ -1,5 +1,5 @@ /* - * extract.c + * extract_image.c * * Support for extracting WIM files. * @@ -10,7 +10,6 @@ */ /* - * Copyright (C) 2010 Carl Thijssen * Copyright (C) 2012 Eric Biggers * * This file is part of wimlib, a library for working with WIM files. @@ -44,7 +43,6 @@ #include #endif - #include #include "dentry.h" diff --git a/src/lz.c b/src/lz77.c similarity index 99% rename from src/lz.c rename to src/lz77.c index c248acf5..2926c128 100644 --- a/src/lz.c +++ b/src/lz77.c @@ -26,7 +26,7 @@ * along with wimlib; if not, see http://www.gnu.org/licenses/. */ -#include "comp.h" +#include "compress.h" #include #define LZ_MIN_MATCH 3 diff --git a/src/lzx-comp.c b/src/lzx-compress.c similarity index 99% rename from src/lzx-comp.c rename to src/lzx-compress.c index f96d90c3..b1800468 100644 --- a/src/lzx-comp.c +++ b/src/lzx-compress.c @@ -1,5 +1,5 @@ /* - * lzx-comp.c + * lzx-compress.c * * LZX compression routines, originally based on code written by Matthew T. * Russotto (liblzxcomp), but heavily modified. @@ -30,7 +30,7 @@ * This file provides lzx_compress(), a function to compress an in-memory buffer * of data using LZX compression, as used in the WIM file format. * - * Please see the comments in lzx-decomp.c for more information about this + * Please see the comments in lzx-decompress.c for more information about this * compression format. * * One thing to keep in mind is that there is no sliding window, since the @@ -58,8 +58,7 @@ */ #include "lzx.h" -#include "comp.h" -#include +#include "compress.h" #include #include diff --git a/src/lzx-decomp.c b/src/lzx-decompress.c similarity index 99% rename from src/lzx-decomp.c rename to src/lzx-decompress.c index 73e68127..6e4098ff 100644 --- a/src/lzx-decomp.c +++ b/src/lzx-decompress.c @@ -1,5 +1,5 @@ /* - * lzx-decomp.c + * lzx-decompress.c * * LZX decompression routines, originally based on code taken from cabextract * v0.5, which was, itself, a modified version of the lzx decompression code @@ -108,7 +108,7 @@ #include "util.h" #include "lzx.h" -#include "decomp.h" +#include "decompress.h" #include /* Huffman decoding tables and maps from symbols to code lengths. */ diff --git a/src/mount.c b/src/mount_image.c similarity index 99% rename from src/mount.c rename to src/mount_image.c index 3c50c750..ea44f220 100644 --- a/src/mount.c +++ b/src/mount_image.c @@ -1,5 +1,5 @@ /* - * mount.c + * mount_image.c * * This file implements mounting of WIM files using FUSE, which stands for * Filesystem in Userspace. FUSE allows a filesystem to be implemented in a diff --git a/src/wim.c b/src/wim.c index c76be36f..c7264841 100644 --- a/src/wim.c +++ b/src/wim.c @@ -580,6 +580,20 @@ WIMLIBAPI int wimlib_open_wim(const char *wim_file, int open_flags, return ret; } +void destroy_image_metadata(struct image_metadata *imd, + struct lookup_table *table) +{ + free_dentry_tree(imd->root_dentry, table); + free_security_data(imd->security_data); + + /* Get rid of the lookup table entry for this image's metadata resource + * */ + if (table) { + lookup_table_unlink(table, imd->metadata_lte); + free_lookup_table_entry(imd->metadata_lte); + } +} + /* Frees the memory for the WIMStruct, including all internal memory; also * closes all files associated with the WIMStruct. */ WIMLIBAPI void wimlib_free(WIMStruct *w) diff --git a/src/wimlib_internal.h b/src/wimlib_internal.h index 474ca171..71a7a593 100644 --- a/src/wimlib_internal.h +++ b/src/wimlib_internal.h @@ -369,6 +369,13 @@ struct capture_config { size_t prefix_len; }; +/* add_image.c */ +extern bool exclude_path(const char *path, + const struct capture_config *config, + bool exclude_prefix); +extern int add_new_dentry_tree(WIMStruct *dest_wim, struct dentry *root, + struct wim_security_data *sd); + /* hardlink.c */ /* Hash table to find inodes, identified by their inode ID. @@ -402,7 +409,6 @@ extern int inode_table_insert(struct dentry *dentry, void *__table); extern u64 assign_inode_numbers(struct hlist_head *inode_list); extern int fix_inodes(struct inode_table *table, struct hlist_head *inode_list); - /* header.c */ extern int read_header(FILE *fp, struct wim_header *hdr, int split_ok); extern int write_header(const struct wim_header *hdr, FILE *out); @@ -428,22 +434,6 @@ extern int new_joined_lookup_table(WIMStruct *w, extern int verify_swm_set(WIMStruct *w, WIMStruct **additional_swms, unsigned num_additional_swms); -/* modify.c */ -extern void destroy_image_metadata(struct image_metadata *imd, - struct lookup_table *lt); -extern bool exclude_path(const char *path, - const struct capture_config *config, - bool exclude_prefix); -extern int do_add_image(WIMStruct *w, const char *dir, const char *name, - const char *config_str, size_t config_len, - int flags, - int (*capture_tree)(struct dentry **, const char *, - struct lookup_table *, - struct wim_security_data *, - const struct capture_config *, - int, void *), - void *extra_arg, - wimlib_progress_func_t progress_func); extern int wim_run_full_verifications(WIMStruct *w); /* ntfs-apply.c */ @@ -531,6 +521,8 @@ extern WIMStruct *new_wim_struct(); extern int select_wim_image(WIMStruct *w, int image); extern int wim_hdr_flags_compression_type(int wim_hdr_flags); extern int for_image(WIMStruct *w, int image, int (*visitor)(WIMStruct *)); +extern void destroy_image_metadata(struct image_metadata *imd, + struct lookup_table *lt); /* Internal use only */ #define WIMLIB_WRITE_FLAG_NO_LOOKUP_TABLE 0x80000000 diff --git a/src/xpress-comp.c b/src/xpress-compress.c similarity index 98% rename from src/xpress-comp.c rename to src/xpress-compress.c index 31bd370c..77df5279 100644 --- a/src/xpress-comp.c +++ b/src/xpress-compress.c @@ -1,9 +1,9 @@ /* - * xpress-comp.c + * xpress-compress.c * * XPRESS compression routines. * - * See the comments in xpress-decomp.c about the XPRESS format. + * See the comments in xpress-decompress.c about the XPRESS format. */ /* @@ -26,7 +26,7 @@ */ #include "xpress.h" -#include "comp.h" +#include "compress.h" #include #include diff --git a/src/xpress-decomp.c b/src/xpress-decompress.c similarity index 97% rename from src/xpress-decomp.c rename to src/xpress-decompress.c index ce240a09..87205543 100644 --- a/src/xpress-decomp.c +++ b/src/xpress-decompress.c @@ -1,5 +1,5 @@ /* - * xpress-decomp.c + * xpress-decompress.c * * XPRESS decompression routines. */ @@ -67,8 +67,8 @@ * the end. Otherwise Microsoft's software will fail to decompress the * XPRESS-compressed data. * - * Howeve, wimlib's decompressor in xpress-decomp.c currently does not care if - * this extra symbol is there or not. + * However, wimlib's decompressor in this file currently does not care if this + * extra symbol is there or not. */ #include "util.h" @@ -76,8 +76,7 @@ #include "wimlib.h" #define XPRESS_DECOMP -#include "decomp.h" - +#include "decompress.h" /* * Decodes a symbol @huffsym that begins an XPRESS match. diff --git a/src/xpress.h b/src/xpress.h index d792a480..d438c81c 100644 --- a/src/xpress.h +++ b/src/xpress.h @@ -3,7 +3,7 @@ #include "util.h" -/* See the comments in xpress-decomp.c about the XPRESS format. */ +/* See the comments in xpress-decompress.c about the XPRESS format. */ //#define ENABLE_XPRESS_DEBUG #ifdef ENABLE_XPRESS_DEBUG diff --git a/tests/test-imagex b/tests/test-imagex index 25ed8e03..46697673 100755 --- a/tests/test-imagex +++ b/tests/test-imagex @@ -289,13 +289,13 @@ fi if ! diff -q -r tmp/dir tmp/myname || ! diff -q -r dir tmp/dir; then error "Recursive diff of applied WIM with original directory failed" fi -if test "`get_link_count tmp/dir/lz.c`" != 1; then +if test "`get_link_count tmp/dir/lz77.c`" != 1; then error "Incorrect link count on extracted file" fi -if test "`get_link_count tmp/myname/lz.c`" != 1; then +if test "`get_link_count tmp/myname/lz77.c`" != 1; then error "Incorrect link count on extracted file" fi -if test "`get_inode_number tmp/myname/lz.c`" = "`get_inode_number tmp/dir/lz.c`"; then +if test "`get_inode_number tmp/myname/lz77.c`" = "`get_inode_number tmp/dir/lz77.c`"; then error "Incorrect inode number" fi rm -rf tmp @@ -306,13 +306,13 @@ fi if ! diff -q -r tmp/dir tmp/myname || ! diff -q -r dir tmp/dir; then error "Recursive diff of applied WIM with original directory failed" fi -if test "`get_link_count tmp/dir/lz.c`" != 2; then +if test "`get_link_count tmp/dir/lz77.c`" != 2; then error "Incorrect link count on extracted file" fi -if test "`get_link_count tmp/myname/lz.c`" != 2; then +if test "`get_link_count tmp/myname/lz77.c`" != 2; then error "Incorrect link count on extracted file" fi -if test "`get_inode_number tmp/myname/lz.c`" != "`get_inode_number tmp/dir/lz.c`"; then +if test "`get_inode_number tmp/myname/lz77.c`" != "`get_inode_number tmp/dir/lz77.c`"; then error "Incorrect inode number" fi rm -rf tmp diff --git a/tests/test-imagex-mount b/tests/test-imagex-mount index 22ad6609..3be51a11 100755 --- a/tests/test-imagex-mount +++ b/tests/test-imagex-mount @@ -86,24 +86,24 @@ for flag in "--compress=none" "--compress=maximum" "--compress=fast"; do "loaded, or you aren't a member of the FUSE group?" fi echo "Testing extracting file from mounted read-only WIM" - if ! cp tmp/lz.c lz.c; then + if ! cp tmp/lz77.c lz77.c; then error "Failed to extract file from read-only mounted WIM" fi - if ! diff -q dir/lz.c lz.c; then + if ! diff -q dir/lz77.c lz77.c; then error "Extracted file does not match copy in mounted WIM" fi - if ! diff -q tmp/lz.c dir/lz.c; then + if ! diff -q tmp/lz77.c dir/lz77.c; then error "Extractef file does not match original" fi - rm -f lz.c + rm -f lz77.c echo "Testing modifying mounted read-only WIM (should fail)" - if rm tmp/lz.c; then + if rm tmp/lz77.c; then error "Removing file from read-only mounted WIM didn't fail" fi if touch tmp/newfile; then error "Creating file on read-only mounted WIM didn't fail" fi - if echo 3 > tmp/lz.c; then + if echo 3 > tmp/lz77.c; then error "Writing to file on read-only mounted WIM didn't fail" fi echo "Testing diff of mounted read-only WIM with original directory" @@ -148,10 +148,10 @@ echo "Testing removing file from mounted WIM" if ! imagex mountrw dir.wim dir tmp; then error "Failed to re-mount test WIM read-write" fi -if ! rm tmp/lz.c; then +if ! rm tmp/lz77.c; then error "Failed to remove file from read-write mounted WIM" fi -if test -f tmp/lz.c; then +if test -f tmp/lz77.c; then error "Removing file from read-write mounted WIM failed" fi echo "Testing making directory in mounted WIM" -- 2.43.0