#include "wimlib_internal.h"
#include "lookup_table.h"
#include "io.h"
+#include <errno.h>
struct lookup_table *new_lookup_table(size_t capacity)
{
lte->part_number = 1;
lte->refcnt = 1;
+ INIT_LIST_HEAD(<e->lte_group_list);
return lte;
}
+void free_lookup_table_entry(struct lookup_table_entry *lte)
+{
+ if (lte) {
+ if (lte->staging_list.next)
+ list_del(<e->staging_list);
+ FREE(lte->file_on_disk);
+ FREE(lte);
+ }
+}
/*
* Inserts an entry into the lookup table.
/* Decrement the reference count for the dentry having hash value @hash in the
* lookup table. The lookup table entry is unlinked and freed if there are no
* references to in remaining. */
-bool lookup_table_decrement_refcnt(struct lookup_table* table, const u8 hash[])
+struct lookup_table_entry *
+lookup_table_decrement_refcnt(struct lookup_table* table, const u8 hash[])
{
size_t pos = *(size_t*)hash % table->capacity;
struct lookup_table_entry *prev = NULL;
if (memcmp(hash, entry->hash, WIM_HASH_SIZE) == 0) {
wimlib_assert(entry->refcnt != 0);
if (--entry->refcnt == 0) {
- if (entry->staging_num_times_opened == 0)
+ if (entry->num_opened_fds == 0) {
free_lookup_table_entry(entry);
+ entry = NULL;
+ }
if (prev)
prev->next = next;
else
table->array[pos] = next;
- return true;
+ break;
}
}
prev = entry;
entry = next;
}
- return false;
+ return entry;
}
+/* Like lookup_table_decrement_refcnt(), but for when we already know the lookup
+ * table entry. */
+struct lookup_table_entry *
+lte_decrement_refcnt(struct lookup_table_entry *lte, struct lookup_table *table)
+{
+ if (lte) {
+ wimlib_assert(lte->refcnt);
+ if (--lte->refcnt == 0) {
+ lookup_table_unlink(table, lte);
+ if (lte->num_opened_fds == 0) {
+ free_lookup_table_entry(lte);
+ lte = NULL;
+ }
+ }
+ }
+ return lte;
+}
/*
* Calls a function on all the entries in the lookup table. Stop early and
return 0;
if (lte->output_resource_entry.flags & WIM_RESHDR_FLAG_METADATA)
- DEBUG("Writing metadata entry at %lu", ftello(out));
+ DEBUG("Writing metadata entry at %lu (orig size = %zu)",
+ ftello(out), lte->output_resource_entry.original_size);
p = put_resource_entry(buf, <e->output_resource_entry);
p = put_u16(p, lte->part_number);
return NULL;
}
+/*
+ * Finds the dentry, lookup table entry, and stream index for a WIM file stream,
+ * given a path name.
+ *
+ * This is only for pre-resolved dentries.
+ */
int lookup_resource(WIMStruct *w, const char *path,
int lookup_flags,
struct dentry **dentry_ret,
struct lookup_table_entry **lte_ret,
- u8 **hash_ret)
+ unsigned *stream_idx_ret)
{
- struct dentry *dentry = get_dentry(w, path);
+ struct dentry *dentry;
struct lookup_table_entry *lte;
- const u8 *hash;
+ unsigned stream_idx;
+ dentry = get_dentry(w, path);
if (!dentry)
return -ENOENT;
+
+ wimlib_assert(dentry->resolved);
+
+ lte = dentry->lte;
if (!(lookup_flags & LOOKUP_FLAG_DIRECTORY_OK)
&& 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 (strcmp(stream_name, dentry->ads_entries[i].stream_name) == 0) {
- hash = dentry->ads_entries[i].hash;
- goto do_lookup;
+ 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;
}
}
- hash = dentry->hash;
-do_lookup:
- lte = __lookup_resource(w->lookup_table, hash);
+out:
if (dentry_ret)
*dentry_ret = dentry;
if (lte_ret)
*lte_ret = lte;
- if (hash_ret)
- *hash_ret = hash;
+ if (stream_idx_ret)
+ *stream_idx_ret = stream_idx;
+ return 0;
+}
+
+/* Resolve a dentry's lookup table entries
+ *
+ * This replaces the SHA1 hash fields (which are used to lookup an entry in the
+ * lookup table) with pointers directly to the lookup table entries. A circular
+ * linked list of streams sharing the same lookup table entry is created.
+ *
+ * This function always succeeds; unresolved lookup table entries are given a
+ * NULL pointer.
+ */
+int dentry_resolve_ltes(struct dentry *dentry, void *__table)
+{
+ struct lookup_table *table = __table;
+ struct lookup_table_entry *lte;
+
+ wimlib_assert(!dentry->resolved);
+
+ /* Resolve the default file stream */
+ lte = __lookup_resource(table, dentry->hash);
+ if (lte)
+ list_add(&dentry->lte_group_list.list, <e->lte_group_list);
+ else
+ INIT_LIST_HEAD(&dentry->lte_group_list.list);
+ dentry->lte = lte;
+ dentry->lte_group_list.type = STREAM_TYPE_NORMAL;
+ dentry->resolved = true;
+
+ /* Resolve the alternate data streams */
+ if (dentry->ads_entries_status != ADS_ENTRIES_USER) {
+ for (u16 i = 0; i < dentry->num_ads; i++) {
+ struct ads_entry *cur_entry = &dentry->ads_entries[i];
+
+ lte = __lookup_resource(table, cur_entry->hash);
+ if (lte)
+ list_add(&cur_entry->lte_group_list.list,
+ <e->lte_group_list);
+ else
+ INIT_LIST_HEAD(&cur_entry->lte_group_list.list);
+ cur_entry->lte = lte;
+ cur_entry->lte_group_list.type = STREAM_TYPE_ADS;
+ }
+ }
return 0;
}