]> wimlib.net Git - wimlib/commitdiff
Limit can_modify_wim() calls; remove can_delete_from_wim()
authorEric Biggers <ebiggers3@gmail.com>
Tue, 14 Oct 2014 00:42:16 +0000 (19:42 -0500)
committerEric Biggers <ebiggers3@gmail.com>
Tue, 14 Oct 2014 01:33:19 +0000 (20:33 -0500)
It isn't necessary to check for permission to modify a WIM for in-memory
operations such as wimlib_add_image(), wimlib_update_image(), and
wimlib_delete_image().  It is only when the user attempts to modify an
on-disk WIM file using wimlib_overwrite() --- or when the user explicitly
opens an on-disk WIM file for write access --- that write permissions
need to be checked.

This change prevents the library from getting in the way of "unusual" use
cases, such as making last-minute changes to a WIM before extracting it
even when the underlying file is located on read-only media, which
otherwise are fully supported by the existing code.

Also part of this change is the removal of can_delete_from_wim().  This
function did a lot of work (decompressing each metadata resource) that
usually turns out to be a waste of time.  And it turns out that it really
needs to be called for any 'wimlib_update_command', including "add" and
"rename", because both "add" and "rename" can cause files to be deleted
(specifically, replaced).  But this is gone too far.  Instead, just get
rid of can_delete_from_wim() completely: it's not needed if we retain
0-reference streams when not recalculating reference counts as part of
wimlib_write() anyway.

13 files changed:
include/wimlib.h
include/wimlib/lookup_table.h
include/wimlib/wim.h
programs/imagex.c
src/add_image.c
src/delete_image.c
src/export_image.c
src/lookup_table.c
src/mount_image.c
src/update_image.c
src/verify.c
src/wim.c
src/xml.c

index 529de43765e4d079fa90a67300c1b29ed338fca5..59e4fb6852487223b53287a272a8411e3710849f 100644 (file)
@@ -1248,14 +1248,15 @@ struct wimlib_capture_source {
        long reserved;
 };
 
        long reserved;
 };
 
-/** Set or unset the WIM header flag that marks it read-only
- * (WIM_HDR_FLAG_READONLY in Microsoft's documentation), based on the
- * ::wimlib_wim_info.is_marked_readonly member of the @p info parameter.  This
- * is distinct from basic file permissions; this flag can be set on a WIM file
- * that is physically writable.  If this flag is set, all further operations to
- * modify the WIM will fail, except calling wimlib_overwrite() with
- * ::WIMLIB_WRITE_FLAG_IGNORE_READONLY_FLAG specified, which is a loophole that
- * allows you to set this flag persistently on the underlying WIM file.
+/** Set or unset the "readonly" WIM header flag (WIM_HDR_FLAG_READONLY in
+ * Microsoft's documentation), based on the ::wimlib_wim_info.is_marked_readonly
+ * member of the @p info parameter.  This is distinct from basic file
+ * permissions; this flag can be set on a WIM file that is physically writable.
+ *
+ * wimlib disallows modifying on-disk WIM files with the readonly flag set.
+ * However, wimlib_overwrite() with ::WIMLIB_WRITE_FLAG_IGNORE_READONLY_FLAG
+ * will override this --- and in fact, this is necessary to set the readonly
+ * flag persistently on an existing WIM file.
  */
 #define WIMLIB_CHANGE_READONLY_FLAG            0x00000001
 
  */
 #define WIMLIB_CHANGE_READONLY_FLAG            0x00000001
 
@@ -1973,8 +1974,8 @@ typedef int (*wimlib_iterate_lookup_table_callback_t)(const struct wimlib_resour
  * only if it is writable at the filesystem level, does not have the
  * WIM_HDR_FLAG_READONLY flag set in its header, and is not part of a spanned
  * set.  It is not required to provide this flag before attempting to make
  * only if it is writable at the filesystem level, does not have the
  * WIM_HDR_FLAG_READONLY flag set in its header, and is not part of a spanned
  * set.  It is not required to provide this flag before attempting to make
- * changes to the WIM, but with this flag you get an error sooner rather than
- * later.  */
+ * changes to the WIM, but with this flag you get an error immediately rather
+ * than potentially much later, when wimlib_overwrite() is finally called.  */
 #define WIMLIB_OPEN_FLAG_WRITE_ACCESS                  0x00000004
 
 /** @} */
 #define WIMLIB_OPEN_FLAG_WRITE_ACCESS                  0x00000004
 
 /** @} */
@@ -2468,10 +2469,6 @@ enum wimlib_error_code {
  *     There is already an image in @p wim named @p name.
  * @retval ::WIMLIB_ERR_NOMEM
  *     Failed to allocate the memory needed to add the new image.
  *     There is already an image in @p wim named @p name.
  * @retval ::WIMLIB_ERR_NOMEM
  *     Failed to allocate the memory needed to add the new image.
- * @retval ::WIMLIB_ERR_WIM_IS_READONLY
- *     The WIM file is considered read-only because of any of the reasons
- *     mentioned in the documentation for the ::WIMLIB_OPEN_FLAG_WRITE_ACCESS
- *     flag.
  */
 extern int
 wimlib_add_empty_image(WIMStruct *wim,
  */
 extern int
 wimlib_add_empty_image(WIMStruct *wim,
@@ -2634,10 +2631,6 @@ wimlib_create_new_wim(int ctype, WIMStruct **wim_ret);
  *
  * @retval ::WIMLIB_ERR_INVALID_IMAGE
  *     @p image does not exist in the WIM and is not ::WIMLIB_ALL_IMAGES.
  *
  * @retval ::WIMLIB_ERR_INVALID_IMAGE
  *     @p image does not exist in the WIM and is not ::WIMLIB_ALL_IMAGES.
- * @retval ::WIMLIB_ERR_WIM_IS_READONLY
- *     The WIM file is considered read-only because of any of the reasons
- *     mentioned in the documentation for the ::WIMLIB_OPEN_FLAG_WRITE_ACCESS
- *     flag.
  *
  * This function can additionally return ::WIMLIB_ERR_DECOMPRESSION,
  * ::WIMLIB_ERR_INVALID_METADATA_RESOURCE, ::WIMLIB_ERR_METADATA_NOT_FOUND,
  *
  * This function can additionally return ::WIMLIB_ERR_DECOMPRESSION,
  * ::WIMLIB_ERR_INVALID_METADATA_RESOURCE, ::WIMLIB_ERR_METADATA_NOT_FOUND,
@@ -2728,10 +2721,6 @@ wimlib_delete_path(WIMStruct *wim, int image,
  *     WIM parts were not referenced with wimlib_reference_resources() or
  *     wimlib_reference_resource_files() before the call to
  *     wimlib_export_image().
  *     WIM parts were not referenced with wimlib_reference_resources() or
  *     wimlib_reference_resource_files() before the call to
  *     wimlib_export_image().
- * @retval ::WIMLIB_ERR_WIM_IS_READONLY
- *     @p dest_wim is considered read-only because of any of the reasons
- *     mentioned in the documentation for the ::WIMLIB_OPEN_FLAG_WRITE_ACCESS
- *     flag.
  *
  * This function can additionally return ::WIMLIB_ERR_DECOMPRESSION,
  * ::WIMLIB_ERR_INVALID_METADATA_RESOURCE, ::WIMLIB_ERR_METADATA_NOT_FOUND,
  *
  * This function can additionally return ::WIMLIB_ERR_DECOMPRESSION,
  * ::WIMLIB_ERR_INVALID_METADATA_RESOURCE, ::WIMLIB_ERR_METADATA_NOT_FOUND,
@@ -3962,9 +3951,6 @@ wimlib_set_error_file_by_name(const wimlib_tchar *path);
  * @retval ::WIMLIB_ERR_NOMEM
  *     Failed to allocate the memory needed to duplicate the @p description
  *     string.
  * @retval ::WIMLIB_ERR_NOMEM
  *     Failed to allocate the memory needed to duplicate the @p description
  *     string.
- * @retval ::WIMLIB_ERR_WIM_IS_READONLY
- *     @p wim is considered read-only because of any of the reasons mentioned
- *     in the documentation for the ::WIMLIB_OPEN_FLAG_WRITE_ACCESS flag.
  */
 extern int
 wimlib_set_image_descripton(WIMStruct *wim, int image,
  */
 extern int
 wimlib_set_image_descripton(WIMStruct *wim, int image,
@@ -4056,12 +4042,6 @@ wimlib_set_output_pack_compression_type(WIMStruct *wim, int ctype);
  *     ::WIMLIB_CHANGE_BOOT_INDEX, and/or ::WIMLIB_CHANGE_RPFIX_FLAG.
  *
  * @return 0 on success; nonzero on failure.
  *     ::WIMLIB_CHANGE_BOOT_INDEX, and/or ::WIMLIB_CHANGE_RPFIX_FLAG.
  *
  * @return 0 on success; nonzero on failure.
- * @retval ::WIMLIB_ERR_WIM_IS_READONLY
- *     The WIM file is considered read-only because of any of the reasons
- *     mentioned in the documentation for the ::WIMLIB_OPEN_FLAG_WRITE_ACCESS
- *     flag.  However, as a special case, if you are using
- *     ::WIMLIB_CHANGE_READONLY_FLAG to unset the readonly flag, then this
- *     function will not fail due to the readonly flag being previously set.
  * @retval ::WIMLIB_ERR_IMAGE_COUNT
  *     ::WIMLIB_CHANGE_BOOT_INDEX was specified, but
  *     ::wimlib_wim_info.boot_index did not specify 0 or a valid 1-based image
  * @retval ::WIMLIB_ERR_IMAGE_COUNT
  *     ::WIMLIB_CHANGE_BOOT_INDEX was specified, but
  *     ::wimlib_wim_info.boot_index did not specify 0 or a valid 1-based image
@@ -4090,9 +4070,6 @@ wimlib_set_wim_info(WIMStruct *wim, const struct wimlib_wim_info *info,
  *     @p image does not specify a single existing image in @p wim.
  * @retval ::WIMLIB_ERR_NOMEM
  *     Failed to allocate the memory needed to duplicate the @p flags string.
  *     @p image does not specify a single existing image in @p wim.
  * @retval ::WIMLIB_ERR_NOMEM
  *     Failed to allocate the memory needed to duplicate the @p flags string.
- * @retval ::WIMLIB_ERR_WIM_IS_READONLY
- *     @p wim is considered read-only because of any of the reasons mentioned
- *     in the documentation for the ::WIMLIB_OPEN_FLAG_WRITE_ACCESS flag.
  */
 extern int
 wimlib_set_image_flags(WIMStruct *wim, int image, const wimlib_tchar *flags);
  */
 extern int
 wimlib_set_image_flags(WIMStruct *wim, int image, const wimlib_tchar *flags);
@@ -4118,9 +4095,6 @@ wimlib_set_image_flags(WIMStruct *wim, int image, const wimlib_tchar *flags);
  *     @p image does not specify a single existing image in @p wim.
  * @retval ::WIMLIB_ERR_NOMEM
  *     Failed to allocate the memory needed to duplicate the @p name string.
  *     @p image does not specify a single existing image in @p wim.
  * @retval ::WIMLIB_ERR_NOMEM
  *     Failed to allocate the memory needed to duplicate the @p name string.
- * @retval ::WIMLIB_ERR_WIM_IS_READONLY
- *     @p wim is considered read-only because of any of the reasons mentioned
- *     in the documentation for the ::WIMLIB_OPEN_FLAG_WRITE_ACCESS flag.
  */
 extern int
 wimlib_set_image_name(WIMStruct *wim, int image, const wimlib_tchar *name);
  */
 extern int
 wimlib_set_image_name(WIMStruct *wim, int image, const wimlib_tchar *name);
@@ -4405,10 +4379,6 @@ wimlib_unmount_image_with_progress(const wimlib_tchar *dir,
  *     a supported file type (e.g. a device file).  Only if
  *     ::WIMLIB_ADD_FLAG_NO_UNSUPPORTED_EXCLUDE specified in @p the add_flags
  *     for an update command.
  *     a supported file type (e.g. a device file).  Only if
  *     ::WIMLIB_ADD_FLAG_NO_UNSUPPORTED_EXCLUDE specified in @p the add_flags
  *     for an update command.
- * @retval ::WIMLIB_ERR_WIM_IS_READONLY
- *     The WIM file is considered read-only because of any of the reasons
- *     mentioned in the documentation for the ::WIMLIB_OPEN_FLAG_WRITE_ACCESS
- *     flag.
  *
  * This function can additionally return ::WIMLIB_ERR_DECOMPRESSION,
  * ::WIMLIB_ERR_INVALID_METADATA_RESOURCE, ::WIMLIB_ERR_METADATA_NOT_FOUND,
  *
  * This function can additionally return ::WIMLIB_ERR_DECOMPRESSION,
  * ::WIMLIB_ERR_INVALID_METADATA_RESOURCE, ::WIMLIB_ERR_METADATA_NOT_FOUND,
index 8857fd8386fc6f28ead85b2274ce68306fad756a..bfd219c85434b627cd2023a07899927052a59a01 100644 (file)
@@ -134,10 +134,10 @@ struct wim_lookup_table_entry {
 
        /* Number of times this lookup table entry is referenced by dentries in
         * the WIM.  When a WIM's lookup table is read, this field is
 
        /* Number of times this lookup table entry is referenced by dentries in
         * the WIM.  When a WIM's lookup table is read, this field is
-        * initialized from a corresponding entry; while it should be correct,
-        * in general it may not be.  wim_recalculate_refcnts() recalculates the
-        * reference counts for all streams and is run before doing any
-        * deletions.  */
+        * initialized from a corresponding entry.
+        *
+        * However, see lte_decrement_refcnt() for information about the
+        * limitations of this field.  */
        u32 refcnt;
 
        /* When a WIM file is written, this is set to the number of references
        u32 refcnt;
 
        /* When a WIM file is written, this is set to the number of references
@@ -228,10 +228,6 @@ struct wim_lookup_table_entry {
                                u32 alloc_stream_owners;
                        };
                };
                                u32 alloc_stream_owners;
                        };
                };
-
-               /* Actual reference count to this stream (only used while
-                * verifying an image).  */
-               u32 real_refcnt;
        };
 
        /* Temporary list fields.  */
        };
 
        /* Temporary list fields.  */
@@ -346,9 +342,6 @@ sort_stream_list_by_sequential_order(struct list_head *stream_list,
 extern int
 lte_zero_out_refcnt(struct wim_lookup_table_entry *lte, void *ignore);
 
 extern int
 lte_zero_out_refcnt(struct wim_lookup_table_entry *lte, void *ignore);
 
-extern int
-lte_zero_real_refcnt(struct wim_lookup_table_entry *lte, void *ignore);
-
 static inline bool
 lte_is_partial(const struct wim_lookup_table_entry * lte)
 {
 static inline bool
 lte_is_partial(const struct wim_lookup_table_entry * lte)
 {
index 587e2f694bf4b595594f27dcbc6c870a08eab62f..50db70d7005ddfa3c66f51ffbce0ff066578ed8b 100644 (file)
@@ -59,13 +59,6 @@ struct WIMStruct {
        /* Have any images been deleted? */
        u8 deletion_occurred : 1;
 
        /* Have any images been deleted? */
        u8 deletion_occurred : 1;
 
-       /* Do we know that all the stream reference counts in the WIM are
-        * correct?  If so, this is set to 1 and deletions are safe; otherwise
-        * this is set to 0 and deletions are not safe until reference counts
-        * are recalculated.  (This is due to a bug in M$'s software that
-        * generates WIMs with invalid reference counts.)  */
-       u8 refcnts_ok : 1;
-
        /* Has the underlying WIM file been locked for appending?  */
        u8 locked_for_append : 1;
 
        /* Has the underlying WIM file been locked for appending?  */
        u8 locked_for_append : 1;
 
@@ -115,9 +108,6 @@ static inline bool wim_has_metadata(const WIMStruct *wim)
        return (wim->image_metadata != NULL || wim->hdr.image_count == 0);
 }
 
        return (wim->image_metadata != NULL || wim->hdr.image_count == 0);
 }
 
-extern int
-wim_recalculate_refcnts(WIMStruct *wim);
-
 extern int
 set_wim_hdr_cflags(int ctype, struct wim_header *hdr);
 
 extern int
 set_wim_hdr_cflags(int ctype, struct wim_header *hdr);
 
@@ -158,7 +148,4 @@ open_wim_as_WIMStruct(const void *wim_filename_or_fd, int open_flags,
 extern int
 can_modify_wim(WIMStruct *wim);
 
 extern int
 can_modify_wim(WIMStruct *wim);
 
-extern int
-can_delete_from_wim(WIMStruct *wim);
-
 #endif /* _WIMLIB_WIM_H */
 #endif /* _WIMLIB_WIM_H */
index eec90698e7477d8b6ae81a6031a5b32e0f355317..f2414af7a3a5729f818f3ad69a4588bd2b4d84b2 100644 (file)
@@ -1713,7 +1713,7 @@ static int
 imagex_capture_or_append(int argc, tchar **argv, int cmd)
 {
        int c;
 imagex_capture_or_append(int argc, tchar **argv, int cmd)
 {
        int c;
-       int open_flags = WIMLIB_OPEN_FLAG_WRITE_ACCESS;
+       int open_flags = 0;
        int add_image_flags = WIMLIB_ADD_IMAGE_FLAG_EXCLUDE_VERBOSE |
                              WIMLIB_ADD_IMAGE_FLAG_WINCONFIG |
                              WIMLIB_ADD_IMAGE_FLAG_VERBOSE;
        int add_image_flags = WIMLIB_ADD_IMAGE_FLAG_EXCLUDE_VERBOSE |
                              WIMLIB_ADD_IMAGE_FLAG_WINCONFIG |
                              WIMLIB_ADD_IMAGE_FLAG_VERBOSE;
@@ -2007,8 +2007,11 @@ imagex_capture_or_append(int argc, tchar **argv, int cmd)
 
        /* Open the existing WIM, or create a new one.  */
        if (cmd == CMD_APPEND) {
 
        /* Open the existing WIM, or create a new one.  */
        if (cmd == CMD_APPEND) {
-               ret = wimlib_open_wim_with_progress(wimfile, open_flags, &wim,
-                                                   imagex_progress_func, NULL);
+               ret = wimlib_open_wim_with_progress(wimfile,
+                                                   open_flags | WIMLIB_OPEN_FLAG_WRITE_ACCESS,
+                                                   &wim,
+                                                   imagex_progress_func,
+                                                   NULL);
                if (ret)
                        goto out_free_capture_sources;
        } else {
                if (ret)
                        goto out_free_capture_sources;
        } else {
@@ -2090,8 +2093,7 @@ imagex_capture_or_append(int argc, tchar **argv, int cmd)
 
                for (size_t i = 0; i < base_wimfiles.num_strings; i++) {
                        ret = wimlib_open_wim_with_progress(
 
                for (size_t i = 0; i < base_wimfiles.num_strings; i++) {
                        ret = wimlib_open_wim_with_progress(
-                                   base_wimfiles.strings[i],
-                                   open_flags & ~WIMLIB_OPEN_FLAG_WRITE_ACCESS,
+                                   base_wimfiles.strings[i], open_flags,
                                    &base_wims[i], imagex_progress_func, NULL);
                        if (ret)
                                goto out_free_base_wims;
                                    &base_wims[i], imagex_progress_func, NULL);
                        if (ret)
                                goto out_free_base_wims;
@@ -2127,7 +2129,7 @@ imagex_capture_or_append(int argc, tchar **argv, int cmd)
                        template_wim = wim;
                } else {
                        ret = wimlib_open_wim_with_progress(template_wimfile,
                        template_wim = wim;
                } else {
                        ret = wimlib_open_wim_with_progress(template_wimfile,
-                                                           open_flags & ~WIMLIB_OPEN_FLAG_WRITE_ACCESS,
+                                                           open_flags,
                                                            &template_wim,
                                                            imagex_progress_func,
                                                            NULL);
                                                            &template_wim,
                                                            imagex_progress_func,
                                                            NULL);
index e01f80a8095e1bfc18787158358d2aec28d056bd..0aed1deb3a11d5ce2bd868783b641f32f8672742 100644 (file)
@@ -88,10 +88,6 @@ wimlib_add_empty_image(WIMStruct *wim, const tchar *name, int *new_idx_ret)
 {
        int ret;
 
 {
        int ret;
 
-       ret = can_modify_wim(wim);
-       if (ret)
-               return ret;
-
        if (!name)
                name = T("");
 
        if (!name)
                name = T("");
 
index 131ec8d94f83525b2e3833406dea69ca94f54db4..7e33ea3cebbcf59dcc6435ca242f1513583b0541 100644 (file)
@@ -37,10 +37,6 @@ wimlib_delete_image(WIMStruct *wim, int image)
        int ret;
        int first, last;
 
        int ret;
        int first, last;
 
-       ret = can_delete_from_wim(wim);
-       if (ret)
-               return ret;
-
        if (image == WIMLIB_ALL_IMAGES) {
                last = wim->hdr.image_count;
                first = 1;
        if (image == WIMLIB_ALL_IMAGES) {
                last = wim->hdr.image_count;
                first = 1;
@@ -52,16 +48,16 @@ wimlib_delete_image(WIMStruct *wim, int image)
        for (image = last; image >= first; image--) {
                DEBUG("Deleting image %d", image);
 
        for (image = last; image >= first; image--) {
                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.  */
+               /* Even if the dentry tree is not allocated, we must select it
+                * (and therefore allocate it) so that we can decrement stream
+                * reference counts.  */
                ret = select_wim_image(wim, image);
                if (ret)
                        return ret;
 
                ret = select_wim_image(wim, image);
                if (ret)
                        return ret;
 
-               /* Unless the image metadata is shared by another WIMStruct, free the
-                * dentry tree, any lookup table entries that have their refcnt
-                * decremented to 0, and the security data. */
+               /* Unless the image metadata is shared by another WIMStruct,
+                * free the dentry tree, free the security data, and decrement
+                * stream reference counts.  */
                put_image_metadata(wim->image_metadata[image - 1], wim->lookup_table);
 
                /* Get rid of the empty slot in the image metadata array. */
                put_image_metadata(wim->image_metadata[image - 1], wim->lookup_table);
 
                /* Get rid of the empty slot in the image metadata array. */
index 77e9e5414c39c87e2384c604613f080b98c23862..54532dd19d2d38f4232d388ad1d10b86413e66f2 100644 (file)
@@ -131,11 +131,6 @@ wimlib_export_image(WIMStruct *src_wim,
        if (!wim_has_metadata(dest_wim))
                return WIMLIB_ERR_METADATA_NOT_FOUND;
 
        if (!wim_has_metadata(dest_wim))
                return WIMLIB_ERR_METADATA_NOT_FOUND;
 
-       /* Destination WIM must be writable.  */
-       ret = can_modify_wim(dest_wim);
-       if (ret)
-               return ret;
-
        if (src_image == WIMLIB_ALL_IMAGES) {
                /* Multi-image export.  */
                if ((!(export_flags & WIMLIB_EXPORT_FLAG_NO_NAMES) &&
        if (src_image == WIMLIB_ALL_IMAGES) {
                /* Multi-image export.  */
                if ((!(export_flags & WIMLIB_EXPORT_FLAG_NO_NAMES) &&
index 08612f6565b21b36975565555614aa4c12bb41d0..882e7dd7048cd979f81dde2a9a611f630d3d12da 100644 (file)
@@ -243,20 +243,34 @@ finalize_lte(struct wim_lookup_table_entry *lte)
 }
 
 /*
 }
 
 /*
- * Decrements the reference count for the lookup table entry @lte, which must be
- * inserted in the stream lookup table @table.
+ * Decrements the reference count of the single-instance stream @lte, which must
+ * be inserted in the stream lookup table @table.
  *
  *
- * If the reference count reaches 0, this may cause @lte to be destroyed.
- * However, we may retain entries with 0 reference count.  This does not affect
- * correctness, but it prevents the entries for valid streams in a WIM archive,
- * which will continue to be present after appending to the file, from being
- * lost merely because we dropped all references to them.
+ * If the stream's reference count reaches 0, we may unlink it from @table and
+ * free it.  However, we retain streams with 0 reference count that originated
+ * from WIM files (RESOURCE_IN_WIM).  We do this for two reasons:
+ *
+ * 1. This prevents information about valid streams in a WIM file --- streams
+ *    which will continue to be present after appending to the WIM file --- from
+ *    being lost merely because we dropped all references to them.
+ *
+ * 2. Stream reference counts we read from WIM files can't be trusted.  It's
+ *    possible that a WIM has reference counts that are too low; WIMGAPI
+ *    sometimes creates WIMs where this is the case.  It's also possible that
+ *    streams have been referenced from an external WIM; those streams can
+ *    potentially have any reference count at all, either lower or higher than
+ *    would be expected for this WIM ("this WIM" meaning the owner of @table) if
+ *    it were a standalone WIM.
+ *
+ * So we can't take the reference counts too seriously.  But at least, we do
+ * recalculate by default when writing a new WIM file.
  */
 void
 lte_decrement_refcnt(struct wim_lookup_table_entry *lte,
                     struct wim_lookup_table *table)
 {
  */
 void
 lte_decrement_refcnt(struct wim_lookup_table_entry *lte,
                     struct wim_lookup_table *table)
 {
-       wimlib_assert(lte->refcnt != 0);
+       if (unlikely(lte->refcnt == 0))  /* See comment above  */
+               return;
 
        if (--lte->refcnt == 0) {
                if (lte->unhashed) {
 
        if (--lte->refcnt == 0) {
                if (lte->unhashed) {
@@ -563,7 +577,8 @@ struct wim_lookup_table_entry_disk {
        /* Which part of the split WIM this stream is in; indexed from 1. */
        le16 part_number;
 
        /* Which part of the split WIM this stream is in; indexed from 1. */
        le16 part_number;
 
-       /* Reference count of this stream over all WIM images. */
+       /* Reference count of this stream over all WIM images.  (But see comment
+        * above lte_decrement_refcnt().)  */
        le32 refcnt;
 
        /* SHA1 message digest of the uncompressed data of this stream, or
        le32 refcnt;
 
        /* SHA1 message digest of the uncompressed data of this stream, or
@@ -1256,13 +1271,6 @@ write_wim_lookup_table_from_stream_list(struct list_head *stream_list,
        return ret;
 }
 
        return ret;
 }
 
-int
-lte_zero_real_refcnt(struct wim_lookup_table_entry *lte, void *_ignore)
-{
-       lte->real_refcnt = 0;
-       return 0;
-}
-
 int
 lte_zero_out_refcnt(struct wim_lookup_table_entry *lte, void *_ignore)
 {
 int
 lte_zero_out_refcnt(struct wim_lookup_table_entry *lte, void *_ignore)
 {
index 1133ad7d36ec71e037d97ac712746604fcd07ba7..18db8571fbd270eafe43e46ad27cae5153d40d91 100644 (file)
@@ -2100,7 +2100,7 @@ wimlib_mount_image(WIMStruct *wim, int image, const char *dir,
        if (mount_flags & WIMLIB_MOUNT_FLAG_READWRITE) {
                if (!wim->filename)
                        return WIMLIB_ERR_NO_FILENAME;
        if (mount_flags & WIMLIB_MOUNT_FLAG_READWRITE) {
                if (!wim->filename)
                        return WIMLIB_ERR_NO_FILENAME;
-               ret = can_delete_from_wim(wim);
+               ret = can_modify_wim(wim);
                if (ret)
                        return ret;
        }
                if (ret)
                        return ret;
        }
index 81c17244141baf42f9a48890a7422a0b5835c59a..fc149f0a415cd6e5771783634abc91dab89b9200 100644 (file)
@@ -1433,14 +1433,6 @@ wimlib_update_image(WIMStruct *wim,
 
        DEBUG("Updating image %d with %zu commands", image, num_cmds);
 
 
        DEBUG("Updating image %d with %zu commands", image, num_cmds);
 
-       if (have_command_type(cmds, num_cmds, WIMLIB_UPDATE_OP_DELETE))
-               ret = can_delete_from_wim(wim);
-       else
-               ret = can_modify_wim(wim);
-
-       if (ret)
-               goto out;
-
        /* Load the metadata for the image to modify (if not loaded already) */
        ret = select_wim_image(wim, image);
        if (ret)
        /* Load the metadata for the image to modify (if not loaded already) */
        ret = select_wim_image(wim, image);
        if (ret)
index 6ee918f4c04bb4188a7f32dfdccc52121672b423..c06e7029d6cb145f43bbc9ea18eba0ac3c1c6236 100644 (file)
 #include "wimlib/progress.h"
 #include "wimlib/security.h"
 
 #include "wimlib/progress.h"
 #include "wimlib/security.h"
 
-static int
-lte_fix_refcnt(struct wim_lookup_table_entry *lte, void *ctr)
-{
-       if (lte->refcnt != lte->real_refcnt) {
-               lte->refcnt = lte->real_refcnt;
-               ++*(unsigned long *)ctr;
-       }
-       return 0;
-}
-
-static void
-tally_inode_refcnts(const struct wim_inode *inode,
-                   const struct wim_lookup_table *lookup_table)
-{
-       for (unsigned i = 0; i <= inode->i_num_ads; i++) {
-               struct wim_lookup_table_entry *lte;
-               lte = inode_stream_lte(inode, i, lookup_table);
-               if (lte)
-                       lte->real_refcnt += inode->i_nlink;
-       }
-}
-
-
-static int
-tally_image_refcnts(WIMStruct *wim)
-{
-       const struct wim_image_metadata *imd;
-       const struct wim_inode *inode;
-
-       imd = wim_get_current_image_metadata(wim);
-       image_for_each_inode(inode, imd)
-               tally_inode_refcnts(inode, wim->lookup_table);
-       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_recalculate_refcnts(WIMStruct *wim)
-{
-       unsigned long num_ltes_with_bogus_refcnt = 0;
-       int ret;
-
-       for_lookup_table_entry(wim->lookup_table, lte_zero_real_refcnt, NULL);
-       ret = for_image(wim, WIMLIB_ALL_IMAGES, tally_image_refcnts);
-       if (ret)
-               return ret;
-       num_ltes_with_bogus_refcnt = 0;
-       for_lookup_table_entry(wim->lookup_table, lte_fix_refcnt,
-                              &num_ltes_with_bogus_refcnt);
-       if (num_ltes_with_bogus_refcnt != 0) {
-               WARNING("%lu stream(s) had incorrect reference count.",
-                       num_ltes_with_bogus_refcnt);
-       }
-       wim->refcnts_ok = 1;
-       return 0;
-}
-
 static int
 append_lte_to_list(struct wim_lookup_table_entry *lte, void *_list)
 {
 static int
 append_lte_to_list(struct wim_lookup_table_entry *lte, void *_list)
 {
index e7025daf03e0badcf094cdcc1f33e48df1e85231..7b1347dd93379ccc29726ad57d9d4c7f8a3fa689 100644 (file)
--- a/src/wim.c
+++ b/src/wim.c
@@ -203,7 +203,6 @@ wimlib_create_new_wim(int ctype, WIMStruct **wim_ret)
                goto out_free_wim;
        }
        wim->lookup_table = table;
                goto out_free_wim;
        }
        wim->lookup_table = table;
-       wim->refcnts_ok = 1;
        wim->compression_type = ctype;
        wim->out_compression_type = ctype;
        wim->chunk_size = wim->hdr.chunk_size;
        wim->compression_type = ctype;
        wim->out_compression_type = ctype;
        wim->chunk_size = wim->hdr.chunk_size;
@@ -472,14 +471,16 @@ wimlib_get_wim_info(WIMStruct *wim, struct wimlib_wim_info *info)
 WIMLIBAPI int
 wimlib_set_wim_info(WIMStruct *wim, const struct wimlib_wim_info *info, int which)
 {
 WIMLIBAPI int
 wimlib_set_wim_info(WIMStruct *wim, const struct wimlib_wim_info *info, int which)
 {
-       int ret;
-
        if (which & ~(WIMLIB_CHANGE_READONLY_FLAG |
                      WIMLIB_CHANGE_GUID |
                      WIMLIB_CHANGE_BOOT_INDEX |
                      WIMLIB_CHANGE_RPFIX_FLAG))
                return WIMLIB_ERR_INVALID_PARAM;
 
        if (which & ~(WIMLIB_CHANGE_READONLY_FLAG |
                      WIMLIB_CHANGE_GUID |
                      WIMLIB_CHANGE_BOOT_INDEX |
                      WIMLIB_CHANGE_RPFIX_FLAG))
                return WIMLIB_ERR_INVALID_PARAM;
 
+       if ((which & WIMLIB_CHANGE_BOOT_INDEX) &&
+           info->boot_index > wim->hdr.image_count)
+               return WIMLIB_ERR_INVALID_IMAGE;
+
        if (which & WIMLIB_CHANGE_READONLY_FLAG) {
                if (info->is_marked_readonly)
                        wim->hdr.flags |= WIM_HDR_FLAG_READONLY;
        if (which & WIMLIB_CHANGE_READONLY_FLAG) {
                if (info->is_marked_readonly)
                        wim->hdr.flags |= WIM_HDR_FLAG_READONLY;
@@ -487,21 +488,11 @@ wimlib_set_wim_info(WIMStruct *wim, const struct wimlib_wim_info *info, int whic
                        wim->hdr.flags &= ~WIM_HDR_FLAG_READONLY;
        }
 
                        wim->hdr.flags &= ~WIM_HDR_FLAG_READONLY;
        }
 
-       if ((which & ~WIMLIB_CHANGE_READONLY_FLAG) == 0)
-               return 0;
-
-       ret = can_modify_wim(wim);
-       if (ret)
-               return ret;
-
        if (which & WIMLIB_CHANGE_GUID)
                memcpy(wim->hdr.guid, info->guid, WIM_GUID_LEN);
 
        if (which & WIMLIB_CHANGE_GUID)
                memcpy(wim->hdr.guid, info->guid, WIM_GUID_LEN);
 
-       if (which & WIMLIB_CHANGE_BOOT_INDEX) {
-               if (info->boot_index > wim->hdr.image_count)
-                       return WIMLIB_ERR_INVALID_IMAGE;
+       if (which & WIMLIB_CHANGE_BOOT_INDEX)
                wim->hdr.boot_idx = info->boot_index;
                wim->hdr.boot_idx = info->boot_index;
-       }
 
        if (which & WIMLIB_CHANGE_RPFIX_FLAG) {
                if (info->has_rpfix)
 
        if (which & WIMLIB_CHANGE_RPFIX_FLAG) {
                if (info->has_rpfix)
@@ -872,33 +863,6 @@ can_modify_wim(WIMStruct *wim)
        return 0;
 }
 
        return 0;
 }
 
-/*
- * can_delete_from_wim - Check if files or images can be deleted from a given
- * WIM file.
- *
- * This theoretically should be exactly the same as can_modify_wim(), but
- * unfortunately, due to bugs in Microsoft's software that generate incorrect
- * reference counts for some WIM resources, we need to run expensive
- * verifications to make sure the reference counts are correct on all WIM
- * resources.  Otherwise we might delete a WIM resource whose reference count
- * has fallen to 0, but is actually still referenced somewhere.
- */
-int
-can_delete_from_wim(WIMStruct *wim)
-{
-       int ret;
-
-       ret = can_modify_wim(wim);
-       if (ret)
-               return ret;
-       if (!wim->refcnts_ok) {
-               ret = wim_recalculate_refcnts(wim);
-               if (ret)
-                       return ret;
-       }
-       return 0;
-}
-
 /* API function documented in wimlib.h  */
 WIMLIBAPI void
 wimlib_free(WIMStruct *wim)
 /* API function documented in wimlib.h  */
 WIMLIBAPI void
 wimlib_free(WIMStruct *wim)
index 383e20342dfddadabae9196380d9e866057e0dba..ecb73b221454227e2175abfa1fa888438f0cde93 100644 (file)
--- a/src/xml.c
+++ b/src/xml.c
@@ -1667,14 +1667,9 @@ wimlib_set_image_name(WIMStruct *wim, int image, const tchar *name)
 {
        tchar *p;
        int i;
 {
        tchar *p;
        int i;
-       int ret;
 
        DEBUG("Setting the name of image %d to %"TS, image, name);
 
 
        DEBUG("Setting the name of image %d to %"TS, image, name);
 
-       ret = can_modify_wim(wim);
-       if (ret)
-               return ret;
-
        if (name == NULL)
                name = T("");
 
        if (name == NULL)
                name = T("");
 
@@ -1708,11 +1703,6 @@ do_set_image_info_str(WIMStruct *wim, int image, const tchar *tstr,
 {
        tchar *tstr_copy;
        tchar **dest_tstr_p;
 {
        tchar *tstr_copy;
        tchar **dest_tstr_p;
-       int ret;
-
-       ret = can_modify_wim(wim);
-       if (ret)
-               return ret;
 
        if (image < 1 || image > wim->hdr.image_count) {
                ERROR("%d is not a valid image", image);
 
        if (image < 1 || image > wim->hdr.image_count) {
                ERROR("%d is not a valid image", image);