]> wimlib.net Git - wimlib/blobdiff - src/lookup_table.c
Do not add lookup table entry for empty files
[wimlib] / src / lookup_table.c
index e6b8fb2cbafcc86ee033b9d4dd5b579e0b9886d3..d15a3088d3675578227cfc82438f012242e7c5fe 100644 (file)
@@ -52,7 +52,7 @@ err:
        return NULL;
 }
 
-struct lookup_table_entry *new_lookup_table_entry(WIMStruct *wim)
+struct lookup_table_entry *new_lookup_table_entry()
 {
        struct lookup_table_entry *lte;
        
@@ -66,7 +66,6 @@ struct lookup_table_entry *new_lookup_table_entry(WIMStruct *wim)
 
        lte->part_number  = 1;
        lte->refcnt       = 1;
-       lte->wim          = wim;
        INIT_LIST_HEAD(&lte->lte_group_list);
        return lte;
 }
@@ -76,7 +75,9 @@ void free_lookup_table_entry(struct lookup_table_entry *lte)
        if (lte) {
                if (lte->staging_list.next)
                        list_del(&lte->staging_list);
-               FREE(lte->file_on_disk);
+               if (lte->resource_location != RESOURCE_IN_WIM &&
+                   lte->resource_location != RESOURCE_NONEXISTENT)
+                       FREE(lte->file_on_disk);
                FREE(lte);
        }
 }
@@ -195,7 +196,7 @@ int read_lookup_table(WIMStruct *w)
 
        while (num_entries--) {
                const u8 *p;
-               struct lookup_table_entry *cur_entry;
+               struct lookup_table_entry *cur_entry, *duplicate_entry;
 
                if (fread(buf, 1, sizeof(buf), w->fp) != sizeof(buf)) {
                        if (feof(w->fp)) {
@@ -207,7 +208,7 @@ int read_lookup_table(WIMStruct *w)
                        ret = WIMLIB_ERR_READ;
                        goto out;
                }
-               cur_entry = new_lookup_table_entry(w);
+               cur_entry = new_lookup_table_entry();
                if (!cur_entry) {
                        ret = WIMLIB_ERR_NOMEM;
                        goto out;
@@ -219,7 +220,31 @@ int read_lookup_table(WIMStruct *w)
                p = get_u16(p, &cur_entry->part_number);
                p = get_u32(p, &cur_entry->refcnt);
                p = get_bytes(p, SHA1_HASH_SIZE, cur_entry->hash);
+
+               duplicate_entry = __lookup_resource(table, cur_entry->hash);
+               if (duplicate_entry) {
+                       ERROR("The WIM lookup table contains two entries with the "
+                             "same SHA1 message digest!");
+                       ERROR("The first entry is:");
+                       print_lookup_table_entry(duplicate_entry);
+                       ERROR("The second entry is:");
+                       print_lookup_table_entry(cur_entry);
+                       ret = WIMLIB_ERR_INVALID_LOOKUP_TABLE_ENTRY;
+                       goto out;
+               }
                lookup_table_insert(table, cur_entry);
+
+               if (!(cur_entry->resource_entry.flags & WIM_RESHDR_FLAG_COMPRESSED)
+                   && (cur_entry->resource_entry.size !=
+                     cur_entry->resource_entry.original_size))
+               {
+                       ERROR("Found uncompressed resource with original size "
+                             "not the same as compressed size");
+                       ERROR("The lookup table entry for the resource is as follows:");
+                       print_lookup_table_entry(cur_entry);
+                       ret = WIMLIB_ERR_INVALID_LOOKUP_TABLE_ENTRY;
+                       goto out;
+               }
        }
        DEBUG("Done reading lookup table.");
        w->lookup_table = table;
@@ -241,10 +266,6 @@ int write_lookup_table_entry(struct lookup_table_entry *lte, void *__out)
 
        out = __out;
 
-       /* do not write lookup table entries for empty files */
-       if (lte->output_resource_entry.original_size == 0)
-               return 0;
-
        /* Don't write entries that have not had file resources or metadata
         * resources written for them. */
        if (lte->out_refcnt == 0)
@@ -273,7 +294,7 @@ int zero_out_refcnts(struct lookup_table_entry *entry, void *ignore)
        return 0;
 }
 
-void print_lookup_table_entry(struct lookup_table_entry *lte)
+void print_lookup_table_entry(const struct lookup_table_entry *lte)
 {
        if (!lte) {
                putchar('\n');
@@ -367,7 +388,20 @@ int lookup_resource(WIMStruct *w, const char *path,
        struct dentry *dentry;
        struct lookup_table_entry *lte;
        unsigned stream_idx;
+       const char *stream_name;
+       char *p = NULL;
+
+       if (lookup_flags & LOOKUP_FLAG_ADS_OK) {
+               stream_name = path_stream_name(path);
+               if (stream_name) {
+                       p = (char*)stream_name - 1;
+                       *p = '\0';
+               }
+       }
+
        dentry = get_dentry(w, path);
+       if (p)
+               *p = ':';
        if (!dentry)
                return -ENOENT;
 
@@ -378,22 +412,19 @@ int lookup_resource(WIMStruct *w, const char *path,
              && dentry_is_directory(dentry))
                return -EISDIR;
        stream_idx = 0;
-       if (lookup_flags & LOOKUP_FLAG_ADS_OK) {
-               const char *stream_name = path_stream_name(path);
-               if (stream_name) {
-                       size_t stream_name_len = strlen(stream_name);
-                       for (u16 i = 0; i < dentry->num_ads; i++) {
-                               if (ads_entry_has_name(&dentry->ads_entries[i],
-                                                      stream_name,
-                                                      stream_name_len))
-                               {
-                                       stream_idx = i + 1;
-                                       lte = dentry->ads_entries[i].lte;
-                                       goto out;
-                               }
+       if (stream_name) {
+               size_t stream_name_len = strlen(stream_name);
+               for (u16 i = 0; i < dentry->num_ads; i++) {
+                       if (ads_entry_has_name(&dentry->ads_entries[i],
+                                              stream_name,
+                                              stream_name_len))
+                       {
+                               stream_idx = i + 1;
+                               lte = dentry->ads_entries[i].lte;
+                               goto out;
                        }
-                       return -ENOENT;
                }
+               return -ENOENT;
        }
 out:
        if (dentry_ret)