]> wimlib.net Git - wimlib/blobdiff - src/blob_table.c
mount_image.c: add fallback definitions of RENAME_* constants
[wimlib] / src / blob_table.c
index 39193b42651dde1fee6eaf54236f8d7732b5ba2d..386155031c264ab87f799228966002db836d85cd 100644 (file)
@@ -9,7 +9,7 @@
  */
 
 /*
- * Copyright (C) 2012, 2013, 2014, 2015 Eric Biggers
+ * Copyright (C) 2012-2016 Eric Biggers
  *
  * This file is free software; you can redistribute it and/or modify it under
  * the terms of the GNU Lesser General Public License as published by the Free
@@ -22,7 +22,7 @@
  * details.
  *
  * You should have received a copy of the GNU Lesser General Public License
- * along with this file; if not, see http://www.gnu.org/licenses/.
+ * along with this file; if not, see https://www.gnu.org/licenses/.
  */
 
 #ifdef HAVE_CONFIG_H
@@ -36,6 +36,7 @@
 #include "wimlib/assert.h"
 #include "wimlib/bitops.h"
 #include "wimlib/blob_table.h"
+#include "wimlib/dentry.h"
 #include "wimlib/encoding.h"
 #include "wimlib/endianness.h"
 #include "wimlib/error.h"
@@ -44,6 +45,7 @@
 #include "wimlib/resource.h"
 #include "wimlib/unaligned.h"
 #include "wimlib/util.h"
+#include "wimlib/win32.h"
 #include "wimlib/write.h"
 
 /* A hash table mapping SHA-1 message digests to blob descriptors  */
@@ -53,21 +55,13 @@ struct blob_table {
        size_t mask; /* capacity - 1; capacity is a power of 2  */
 };
 
-static size_t
-next_power_of_2(size_t n)
-{
-       if (n <= 1)
-               return 1;
-       return (size_t)1 << (1 + flsw(n - 1));
-}
-
 struct blob_table *
 new_blob_table(size_t capacity)
 {
        struct blob_table *table;
        struct hlist_head *array;
 
-       capacity = next_power_of_2(capacity);
+       capacity = roundup_pow_of_2(capacity);
 
        table = MALLOC(sizeof(struct blob_table));
        if (table == NULL)
@@ -129,10 +123,6 @@ clone_blob_descriptor(const struct blob_descriptor *old)
                break;
 
        case BLOB_IN_FILE_ON_DISK:
-#ifdef __WIN32__
-       case BLOB_IN_WINNT_FILE_ON_DISK:
-       case BLOB_WIN32_ENCRYPTED:
-#endif
 #ifdef WITH_FUSE
        case BLOB_IN_STAGING_FILE:
                STATIC_ASSERT((void*)&old->file_on_disk ==
@@ -142,6 +132,11 @@ clone_blob_descriptor(const struct blob_descriptor *old)
                if (new->file_on_disk == NULL)
                        goto out_free;
                break;
+#ifdef _WIN32
+       case BLOB_IN_WINDOWS_FILE:
+               new->windows_file = clone_windows_file(old->windows_file);
+               break;
+#endif
        case BLOB_IN_ATTACHED_BUFFER:
                new->attached_buffer = memdup(old->attached_buffer, old->size);
                if (new->attached_buffer == NULL)
@@ -168,16 +163,17 @@ void
 blob_release_location(struct blob_descriptor *blob)
 {
        switch (blob->blob_location) {
-       case BLOB_IN_WIM:
+       case BLOB_IN_WIM: {
+               struct wim_resource_descriptor *rdesc = blob->rdesc;
+
                list_del(&blob->rdesc_node);
-               if (list_empty(&blob->rdesc->blob_list))
-                       FREE(blob->rdesc);
+               if (list_empty(&rdesc->blob_list)) {
+                       wim_decrement_refcnt(rdesc->wim);
+                       FREE(rdesc);
+               }
                break;
+       }
        case BLOB_IN_FILE_ON_DISK:
-#ifdef __WIN32__
-       case BLOB_IN_WINNT_FILE_ON_DISK:
-       case BLOB_WIN32_ENCRYPTED:
-#endif
 #ifdef WITH_FUSE
        case BLOB_IN_STAGING_FILE:
                STATIC_ASSERT((void*)&blob->file_on_disk ==
@@ -188,10 +184,14 @@ blob_release_location(struct blob_descriptor *blob)
                              (void*)&blob->attached_buffer);
                FREE(blob->file_on_disk);
                break;
+#ifdef _WIN32
+       case BLOB_IN_WINDOWS_FILE:
+               free_windows_file(blob->windows_file);
+               break;
+#endif
 #ifdef WITH_NTFS_3G
        case BLOB_IN_NTFS_VOLUME:
-               if (blob->ntfs_loc)
-                       free_ntfs_location(blob->ntfs_loc);
+               free_ntfs_location(blob->ntfs_loc);
                break;
 #endif
        }
@@ -458,18 +458,14 @@ cmp_blobs_by_sequential_order(const void *p1, const void *p2)
        case BLOB_IN_FILE_ON_DISK:
 #ifdef WITH_FUSE
        case BLOB_IN_STAGING_FILE:
-#endif
-#ifdef __WIN32__
-       case BLOB_IN_WINNT_FILE_ON_DISK:
-       case BLOB_WIN32_ENCRYPTED:
-               /* Windows: compare by starting LCN (logical cluster number)  */
-               v = cmp_u64(blob1->sort_key, blob2->sort_key);
-               if (v)
-                       return v;
 #endif
                /* Compare files by path: just a heuristic that will place files
                 * in the same directory next to each other.  */
                return tstrcmp(blob1->file_on_disk, blob2->file_on_disk);
+#ifdef _WIN32
+       case BLOB_IN_WINDOWS_FILE:
+               return cmp_windows_files(blob1->windows_file, blob2->windows_file);
+#endif
 #ifdef WITH_NTFS_3G
        case BLOB_IN_NTFS_VOLUME:
                return cmp_ntfs_locations(blob1->ntfs_loc, blob2->ntfs_loc);
@@ -589,7 +585,7 @@ struct blob_descriptor_disk {
        /* SHA-1 message digest of the uncompressed data of this blob, or all
         * zeroes if this blob is of zero length.  */
        u8 hash[SHA1_HASH_SIZE];
-} _packed_attribute;
+} __attribute__((packed));
 
 /* Given a nonempty run of consecutive blob descriptors with the SOLID flag set,
  * count how many specify resources (as opposed to blobs within those
@@ -710,6 +706,8 @@ load_solid_info(WIMStruct *wim,
        if (ret)
                goto out_free_rdescs;
 
+       wim->refcnt += num_rdescs;
+
        *rdescs_ret = rdescs;
        *num_rdescs_ret = num_rdescs;
        return 0;
@@ -750,9 +748,12 @@ static void
 free_solid_rdescs(struct wim_resource_descriptor **rdescs, size_t num_rdescs)
 {
        if (rdescs) {
-               for (size_t i = 0; i < num_rdescs; i++)
-                       if (list_empty(&rdescs[i]->blob_list))
+               for (size_t i = 0; i < num_rdescs; i++) {
+                       if (list_empty(&rdescs[i]->blob_list)) {
+                               rdescs[i]->wim->refcnt--;
                                FREE(rdescs[i]);
+                       }
+               }
                FREE(rdescs);
        }
 }
@@ -900,7 +901,7 @@ read_blob_table(WIMStruct *wim)
        if (!table)
                goto oom;
 
-       /* Allocate and initalize blob descriptors from the raw blob table
+       /* Allocate and initialize blob descriptors from the raw blob table
         * buffer.  */
        for (size_t i = 0; i < num_entries; i++) {
                const struct blob_descriptor_disk *disk_entry =
@@ -984,6 +985,7 @@ read_blob_table(WIMStruct *wim)
                                goto oom;
 
                        wim_reshdr_to_desc_and_blob(&reshdr, wim, rdesc, cur_blob);
+                       wim->refcnt++;
                }
 
                /* cur_blob is now a blob bound to a resource.  */
@@ -1006,9 +1008,6 @@ read_blob_table(WIMStruct *wim)
                }
 
                if (reshdr.flags & WIM_RESHDR_FLAG_METADATA) {
-
-                       cur_blob->is_metadata = 1;
-
                        /* Blob table entry for a metadata resource.  */
 
                        /* Metadata entries with no references must be ignored.
@@ -1055,7 +1054,10 @@ read_blob_table(WIMStruct *wim)
                         * this overrides the actual locations of the metadata
                         * resources themselves in the WIM file as well as any
                         * information written in the XML data.  */
-                       wim->image_metadata[image_index++]->metadata_blob = cur_blob;
+                       wim->image_metadata[image_index] = new_unloaded_image_metadata(cur_blob);
+                       if (!wim->image_metadata[image_index])
+                               goto oom;
+                       image_index++;
                } else {
                        /* Blob table entry for a non-metadata blob.  */
 
@@ -1090,8 +1092,6 @@ read_blob_table(WIMStruct *wim)
 
        if (wim->hdr.part_number == 1 && image_index != wim->hdr.image_count) {
                WARNING("Could not find metadata resources for all images");
-               for (u32 i = image_index; i < wim->hdr.image_count; i++)
-                       put_image_metadata(wim->image_metadata[i], NULL);
                wim->hdr.image_count = image_index;
        }
 
@@ -1236,7 +1236,7 @@ new_blob_from_data_buffer(const void *buffer, size_t size,
        struct blob_descriptor *blob;
        void *buffer_copy;
 
-       sha1_buffer(buffer, size, hash);
+       sha1(buffer, size, hash);
 
        blob = lookup_blob(blob_table, hash);
        if (blob)
@@ -1260,7 +1260,7 @@ new_blob_from_data_buffer(const void *buffer, size_t size,
 struct blob_descriptor *
 after_blob_hashed(struct blob_descriptor *blob,
                  struct blob_descriptor **back_ptr,
-                 struct blob_table *blob_table)
+                 struct blob_table *blob_table, struct wim_inode *inode)
 {
        struct blob_descriptor *duplicate_blob;
 
@@ -1274,7 +1274,16 @@ after_blob_hashed(struct blob_descriptor *blob,
                 * this blob to the duplicate and update the reference to this
                 * blob (from a stream) to point to the duplicate.  The caller
                 * is responsible for freeing @blob if needed.  */
-               wimlib_assert(duplicate_blob->size == blob->size);
+               if (duplicate_blob->size != blob->size) {
+                       tchar hash_str[SHA1_HASH_STRING_LEN];
+
+                       sprint_hash(blob->hash, hash_str);
+                       WARNING("SHA-1 collision at \"%"TS"\"\n"
+                               "          (hash=%"TS", size=%"PRIu64", other_size=%"PRIu64").\n"
+                               "          File will be corrupted!",
+                               inode_any_full_path(inode), hash_str,
+                               blob->size, duplicate_blob->size);
+               }
                duplicate_blob->refcnt += blob->refcnt;
                blob->refcnt = 0;
                *back_ptr = duplicate_blob;
@@ -1308,15 +1317,17 @@ hash_unhashed_blob(struct blob_descriptor *blob, struct blob_table *blob_table,
                   struct blob_descriptor **blob_ret)
 {
        struct blob_descriptor **back_ptr;
+       struct wim_inode *inode;
        int ret;
 
        back_ptr = retrieve_pointer_to_unhashed_blob(blob);
+       inode = blob->back_inode;
 
        ret = sha1_blob(blob);
        if (ret)
                return ret;
 
-       *blob_ret = after_blob_hashed(blob, back_ptr, blob_table);
+       *blob_ret = after_blob_hashed(blob, back_ptr, blob_table, inode);
        return 0;
 }