]> wimlib.net Git - wimlib/blobdiff - src/lookup_table.c
read_wim_lookup_table(): Warn only once for all duplicate streams
[wimlib] / src / lookup_table.c
index c76823d14e4cacc3b4be3f620a14cadcb9dd13ec..889013e0ae4912a382354e08e6d4ce406830e0d5 100644 (file)
@@ -190,41 +190,47 @@ out_free:
 }
 
 void
-free_lookup_table_entry(struct wim_lookup_table_entry *lte)
+lte_put_resource(struct wim_lookup_table_entry *lte)
 {
-       if (lte) {
-               switch (lte->resource_location) {
-               case RESOURCE_IN_WIM:
-                       list_del(&lte->rspec_node);
-                       if (list_empty(&lte->rspec->stream_list))
-                               FREE(lte->rspec);
-                       break;
-               case RESOURCE_IN_FILE_ON_DISK:
-       #ifdef __WIN32__
-               case RESOURCE_WIN32_ENCRYPTED:
-       #endif
-       #ifdef WITH_FUSE
-               case RESOURCE_IN_STAGING_FILE:
-                       BUILD_BUG_ON((void*)&lte->file_on_disk !=
-                                    (void*)&lte->staging_file_name);
-       #endif
-               case RESOURCE_IN_ATTACHED_BUFFER:
-                       BUILD_BUG_ON((void*)&lte->file_on_disk !=
-                                    (void*)&lte->attached_buffer);
-                       FREE(lte->file_on_disk);
-                       break;
-#ifdef WITH_NTFS_3G
-               case RESOURCE_IN_NTFS_VOLUME:
-                       if (lte->ntfs_loc) {
-                               FREE(lte->ntfs_loc->path);
-                               FREE(lte->ntfs_loc->stream_name);
-                               FREE(lte->ntfs_loc);
-                       }
-                       break;
+       switch (lte->resource_location) {
+       case RESOURCE_IN_WIM:
+               list_del(&lte->rspec_node);
+               if (list_empty(&lte->rspec->stream_list))
+                       FREE(lte->rspec);
+               break;
+       case RESOURCE_IN_FILE_ON_DISK:
+#ifdef __WIN32__
+       case RESOURCE_WIN32_ENCRYPTED:
 #endif
-               default:
-                       break;
+#ifdef WITH_FUSE
+       case RESOURCE_IN_STAGING_FILE:
+               BUILD_BUG_ON((void*)&lte->file_on_disk !=
+                            (void*)&lte->staging_file_name);
+#endif
+       case RESOURCE_IN_ATTACHED_BUFFER:
+               BUILD_BUG_ON((void*)&lte->file_on_disk !=
+                            (void*)&lte->attached_buffer);
+               FREE(lte->file_on_disk);
+               break;
+#ifdef WITH_NTFS_3G
+       case RESOURCE_IN_NTFS_VOLUME:
+               if (lte->ntfs_loc) {
+                       FREE(lte->ntfs_loc->path);
+                       FREE(lte->ntfs_loc->stream_name);
+                       FREE(lte->ntfs_loc);
                }
+               break;
+#endif
+       default:
+               break;
+       }
+}
+
+void
+free_lookup_table_entry(struct wim_lookup_table_entry *lte)
+{
+       if (lte) {
+               lte_put_resource(lte);
                FREE(lte);
        }
 }
@@ -609,6 +615,7 @@ read_wim_lookup_table(WIMStruct *wim)
        struct wim_resource_spec *cur_rspec;
        void *buf;
        bool back_to_back_pack;
+       size_t num_duplicate_entries = 0;
 
        DEBUG("Reading lookup table.");
 
@@ -678,9 +685,27 @@ read_wim_lookup_table(WIMStruct *wim)
                if (!(reshdr.flags & (WIM_RESHDR_FLAG_PACKED_STREAMS |
                                      WIM_RESHDR_FLAG_COMPRESSED))) {
                        if (reshdr.uncompressed_size != reshdr.size_in_wim) {
-                               ERROR("Invalid resource entry!");
-                               ret = WIMLIB_ERR_INVALID_LOOKUP_TABLE_ENTRY;
-                               goto err;
+                               /* So ... This is an uncompressed resource, but
+                                * its uncompressed size is NOT the same as its
+                                * "compressed" size (size_in_wim).  What to do
+                                * with it?
+                                *
+                                * Based on a simple test, WIMGAPI seems to
+                                * handle this as follows:
+                                *
+                                * if (size_in_wim > uncompressed_size) {
+                                *      Ignore uncompressed_size; use
+                                *      size_in_wim instead.
+                                * } else {
+                                *      Honor uncompressed_size, but treat the
+                                *      part of the file data above size_in_wim
+                                *      as all zeros.
+                                * }
+                                *
+                                * So we will do the same.
+                                */
+                               if (reshdr.size_in_wim > reshdr.uncompressed_size)
+                                       reshdr.uncompressed_size = reshdr.size_in_wim;
                        }
                }
 
@@ -768,8 +793,8 @@ read_wim_lookup_table(WIMStruct *wim)
                        /* Compression format numbers must be the same as in
                         * WIMGAPI to be compatible here.  */
                        BUILD_BUG_ON(WIMLIB_COMPRESSION_TYPE_NONE != 0);
-                       BUILD_BUG_ON(WIMLIB_COMPRESSION_TYPE_LZX != 1);
-                       BUILD_BUG_ON(WIMLIB_COMPRESSION_TYPE_XPRESS != 2);
+                       BUILD_BUG_ON(WIMLIB_COMPRESSION_TYPE_XPRESS != 1);
+                       BUILD_BUG_ON(WIMLIB_COMPRESSION_TYPE_LZX != 2);
                        BUILD_BUG_ON(WIMLIB_COMPRESSION_TYPE_LZMS != 3);
                        cur_rspec->compression_type = le32_to_cpu(hdr.compression_format);
 
@@ -867,8 +892,7 @@ read_wim_lookup_table(WIMStruct *wim)
                 * resource.  */
                duplicate_entry = lookup_stream(table, cur_entry->hash);
                if (duplicate_entry) {
-                       WARNING("The WIM lookup table contains two entries "
-                               "with the same SHA1 message digest!");
+                       num_duplicate_entries++;
                        free_lookup_table_entry(cur_entry);
                        continue;
                }
@@ -896,6 +920,12 @@ read_wim_lookup_table(WIMStruct *wim)
                        put_image_metadata(wim->image_metadata[i], NULL);
                wim->hdr.image_count = wim->current_image;
        }
+
+       if (num_duplicate_entries > 0) {
+               WARNING("Ignoring %zu duplicate streams in the WIM lookup table",
+                       num_duplicate_entries);
+       }
+
        DEBUG("Done reading lookup table.");
        wim->lookup_table = table;
        ret = 0;
@@ -1181,6 +1211,9 @@ wimlib_iterate_lookup_table(WIMStruct *wim, int flags,
                            wimlib_iterate_lookup_table_callback_t cb,
                            void *user_ctx)
 {
+       if (flags != 0)
+               return WIMLIB_ERR_INVALID_PARAM;
+
        struct iterate_lte_context ctx = {
                .cb = cb,
                .user_ctx = user_ctx,