]> wimlib.net Git - wimlib/blobdiff - src/lookup_table.c
Fix various issues
[wimlib] / src / lookup_table.c
index 0546f958a3108f41dc2b3dffc884a576567b8ea3..007cd9eae689d655ec4580b7d2a00bfcf9fb84f2 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;
 }
@@ -209,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;
@@ -222,6 +221,14 @@ int read_lookup_table(WIMStruct *w)
                p = get_u32(p, &cur_entry->refcnt);
                p = get_bytes(p, SHA1_HASH_SIZE, cur_entry->hash);
 
+               if (is_zero_hash(cur_entry->hash)) {
+                       ERROR("The WIM lookup table contains an entry with a "
+                             "SHA1 message digest of all 0's");
+                       ret = WIMLIB_ERR_INVALID_LOOKUP_TABLE_ENTRY;
+                       FREE(cur_entry);
+                       goto out;
+               }
+
                duplicate_entry = __lookup_resource(table, cur_entry->hash);
                if (duplicate_entry) {
                        ERROR("The WIM lookup table contains two entries with the "
@@ -231,6 +238,7 @@ int read_lookup_table(WIMStruct *w)
                        ERROR("The second entry is:");
                        print_lookup_table_entry(cur_entry);
                        ret = WIMLIB_ERR_INVALID_LOOKUP_TABLE_ENTRY;
+                       FREE(cur_entry);
                        goto out;
                }
                lookup_table_insert(table, cur_entry);
@@ -267,10 +275,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)
@@ -340,6 +344,8 @@ void print_lookup_table_entry(const struct lookup_table_entry *lte)
        case RESOURCE_IN_STAGING_FILE:
                printf("Staging File      = `%s'\n", lte->staging_file_name);
                break;
+       default:
+               break;
        }
        putchar('\n');
 }
@@ -393,7 +399,20 @@ int lookup_resource(WIMStruct *w, const char *path,
        struct dentry *dentry;
        struct lookup_table_entry *lte;
        unsigned stream_idx;
+       const char *stream_name = NULL;
+       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;
 
@@ -404,22 +423,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)
@@ -476,12 +492,29 @@ int dentry_resolve_ltes(struct dentry *dentry, void *__table)
        return 0;
 }
 
+/* Return the lookup table entry for the unnamed data stream of a dentry, or
+ * NULL if there is none.
+ *
+ * You'd think this would be easier than it actually is, since the unnamed data
+ * stream should be the one referenced from the dentry itself.  Alas, if there
+ * are named data streams, Microsoft's "imagex.exe" program will put the unnamed
+ * data stream in one of the alternate data streams instead of inside the
+ * dentry.  So we need to check the alternate data streams too.
+ *
+ * Also, note that a dentry may appear to have than one unnamed stream, but if
+ * the SHA1 message digest is all 0's then the corresponding stream does not
+ * really "count" (this is the case for the dentry's own file stream when the
+ * file stream that should be there is actually in one of the alternate stream
+ * entries.).  This is despite the fact that we may need to extract such a
+ * missing entry as an empty file or empty named data stream.
+ */
 struct lookup_table_entry *
-dentry_first_lte(const struct dentry *dentry, const struct lookup_table *table)
+dentry_unnamed_lte(const struct dentry *dentry,
+                  const struct lookup_table *table)
 {
        if (dentry->resolved)
-               return dentry_first_lte_resolved(dentry);
+               return dentry_unnamed_lte_resolved(dentry);
        else
-               return dentry_first_lte_unresolved(dentry, table);
+               return dentry_unnamed_lte_unresolved(dentry, table);
 }