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;
lte->part_number = 1;
lte->refcnt = 1;
- lte->wim = wim;
INIT_LIST_HEAD(<e->lte_group_list);
return lte;
}
void free_lookup_table_entry(struct lookup_table_entry *lte)
{
if (lte) {
+#ifdef WITH_FUSE
if (lte->staging_list.next)
list_del(<e->staging_list);
- if (lte->resource_location != RESOURCE_IN_WIM &&
- lte->resource_location != RESOURCE_NONEXISTENT)
+#endif
+ switch (lte->resource_location) {
+ case RESOURCE_IN_STAGING_FILE:
+ case RESOURCE_IN_ATTACHED_BUFFER:
+ case RESOURCE_IN_FILE_ON_DISK:
+ wimlib_assert((<e->file_on_disk ==
+ <e->staging_file_name)
+ && (<e->file_on_disk ==
+ <e->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_utf8);
+ FREE(lte->ntfs_loc->stream_name_utf16);
+ FREE(lte->ntfs_loc);
+ }
+ break;
+#endif
+ default:
+ break;
+ }
FREE(lte);
}
}
wimlib_assert(lte->refcnt);
if (--lte->refcnt == 0) {
lookup_table_unlink(table, lte);
- if (lte->num_opened_fds == 0) {
+ #ifdef WITH_FUSE
+ if (lte->num_opened_fds == 0)
+ #endif
+ {
free_lookup_table_entry(lte);
lte = NULL;
}
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)) {
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;
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);
+
+ 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 "
+ "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;
+ FREE(cur_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;
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)
case RESOURCE_IN_STAGING_FILE:
printf("Staging File = `%s'\n", lte->staging_file_name);
break;
+ default:
+ break;
}
putchar('\n');
}
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;
&& 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)
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);
}