* @sd: The security data for the image.
*/
int add_new_dentry_tree(WIMStruct *w, struct dentry *root_dentry,
- struct wim_security_data *sd)
+ struct wim_security_data *sd)
{
struct lookup_table_entry *metadata_lte;
struct image_metadata *imd;
new_imd->root_dentry = root_dentry;
new_imd->metadata_lte = metadata_lte;
new_imd->security_data = sd;
- new_imd->modified = true;
+ new_imd->modified = 1;
FREE(w->image_metadata);
- w->image_metadata = imd;
+ w->image_metadata = imd;
w->hdr.image_count++;
-
- /* Change the current image to the new one. There should not be any
- * ways for this to fail, since the image is valid and the dentry tree
- * is already in memory. */
- ret = select_wim_image(w, w->hdr.image_count);
- wimlib_assert(ret == 0);
- return ret;
+ return 0;
err_free_imd:
FREE(imd);
err:
struct dentry *root_dentry = NULL;
struct wim_security_data *sd;
struct capture_config config;
- struct inode_table inode_tab;
struct hlist_head inode_list;
int ret;
if (ret != 0)
goto out_free_dentry_tree;
- DEBUG("Inserting dentries into inode table");
- ret = init_inode_table(&inode_tab, 9001);
- if (ret != 0)
- goto out_destroy_imd;
-
- for_dentry_in_tree(root_dentry, inode_table_insert, &inode_tab);
- DEBUG("Cleaning up the hard link groups");
- ret = fix_inodes(&inode_tab, &inode_list);
- destroy_inode_table(&inode_tab);
+ ret = dentry_tree_fix_inodes(root_dentry, &inode_list);
if (ret != 0)
goto out_destroy_imd;
#include "lookup_table.h"
#include "xml.h"
-struct wim_pair {
- WIMStruct *src_wim;
- WIMStruct *dest_wim;
- struct list_head lte_list_head;
-};
-
-static int allocate_lte_if_needed(struct dentry *dentry, void *arg)
+static int inode_allocate_needed_ltes(struct inode *inode,
+ struct lookup_table *src_lookup_table,
+ struct lookup_table *dest_lookup_table,
+ struct list_head *lte_list_head)
{
- const WIMStruct *src_wim, *dest_wim;
- struct list_head *lte_list_head;
- struct inode *inode;
-
- src_wim = ((struct wim_pair*)arg)->src_wim;
- dest_wim = ((struct wim_pair*)arg)->dest_wim;
- lte_list_head = &((struct wim_pair*)arg)->lte_list_head;
- inode = dentry->d_inode;
+ struct lookup_table_entry *src_lte, *dest_lte;
+ unsigned i;
- wimlib_assert(!inode->resolved);
-
- for (unsigned i = 0; i <= inode->num_ads; i++) {
- struct lookup_table_entry *src_lte, *dest_lte;
+ inode_unresolve_ltes(inode);
+ for (i = 0; i <= inode->num_ads; i++) {
src_lte = inode_stream_lte_unresolved(inode, i,
- src_wim->lookup_table);
-
- if (src_lte && ++src_lte->out_refcnt == 1) {
+ src_lookup_table);
+ if (src_lte && src_lte->out_refcnt == 0) {
+ src_lte->out_refcnt = 1;
dest_lte = inode_stream_lte_unresolved(inode, i,
- dest_wim->lookup_table);
-
+ dest_lookup_table);
if (!dest_lte) {
dest_lte = clone_lookup_table_entry(src_lte);
if (!dest_lte)
return 0;
}
-/*
- * This function takes in a dentry that was previously located only in image(s)
- * in @src_wim, but now is being added to @dest_wim. For each stream associated
- * with the dentry, if there is already a lookup table entry for that stream in
- * the lookup table of the destination WIM file, its reference count is
- * incrementej. Otherwise, a new lookup table entry is created that points back
- * to the stream in the source WIM file (through the @hash field combined with
- * the @wim field of the lookup table entry.)
- */
-static int add_lte_to_dest_wim(struct dentry *dentry, void *arg)
+static void inode_move_ltes_to_table(struct inode *inode,
+ struct lookup_table *src_lookup_table,
+ struct lookup_table *dest_lookup_table,
+ struct list_head *lte_list_head)
{
- WIMStruct *src_wim, *dest_wim;
- struct inode *inode;
-
- src_wim = ((struct wim_pair*)arg)->src_wim;
- dest_wim = ((struct wim_pair*)arg)->dest_wim;
- inode = dentry->d_inode;
-
- wimlib_assert(!inode->resolved);
-
- for (unsigned i = 0; i <= inode->num_ads; i++) {
- struct lookup_table_entry *src_lte, *dest_lte;
- src_lte = inode_stream_lte_unresolved(inode, i,
- src_wim->lookup_table);
-
- if (!src_lte) /* Empty or nonexistent stream. */
- continue;
+ struct lookup_table_entry *src_lte, *dest_lte;
+ unsigned i;
+ struct dentry *dentry;
- dest_lte = inode_stream_lte_unresolved(inode, i,
- dest_wim->lookup_table);
- if (dest_lte) {
- dest_lte->refcnt++;
- } else {
- struct list_head *lte_list_head;
- struct list_head *next;
-
- lte_list_head = &((struct wim_pair*)arg)->lte_list_head;
- wimlib_assert(!list_empty(lte_list_head));
+ inode_for_each_dentry(dentry, inode)
+ dentry->refcnt++;
- next = lte_list_head->next;
- list_del(next);
- dest_lte = container_of(next, struct lookup_table_entry,
- staging_list);
- dest_lte->part_number = 1;
- dest_lte->refcnt = 1;
- wimlib_assert(hashes_equal(dest_lte->hash, src_lte->hash));
-
- lookup_table_insert(dest_wim->lookup_table, dest_lte);
+ for (i = 0; i <= inode->num_ads; i++) {
+ src_lte = inode_stream_lte_unresolved(inode, i, src_lookup_table);
+ if (src_lte) {
+ dest_lte = inode_stream_lte_unresolved(inode, i,
+ dest_lookup_table);
+ if (!dest_lte) {
+ struct list_head *next;
+
+ wimlib_assert(!list_empty(lte_list_head));
+ next = lte_list_head->next;
+ list_del(next);
+ dest_lte = container_of(next,
+ struct lookup_table_entry,
+ staging_list);
+ dest_lte->part_number = 1;
+ dest_lte->refcnt = 0;
+ wimlib_assert(hashes_equal(dest_lte->hash, src_lte->hash));
+ lookup_table_insert(dest_lookup_table, dest_lte);
+ }
+ dest_lte->refcnt += inode->link_count;
}
}
- return 0;
}
/*
unsigned num_additional_swms,
wimlib_progress_func_t progress_func)
{
- int i;
int ret;
- struct dentry *root;
- struct wim_pair wims;
struct wim_security_data *sd;
struct lookup_table *joined_tab, *src_wim_tab_save;
+ struct image_metadata *src_imd;
+ struct hlist_node *cur_node;
+ struct list_head lte_list_head;
+ struct inode *inode;
if (dest_wim->hdr.total_parts != 1) {
ERROR("Exporting an image to a split WIM is "
"multiple images");
return WIMLIB_ERR_INVALID_PARAM;
}
- for (i = 1; i <= src_wim->hdr.image_count; i++) {
+ for (int i = 1; i <= src_wim->hdr.image_count; i++) {
int new_flags = export_flags;
if (i != src_wim->hdr.boot_idx)
/* Pre-allocate the new lookup table entries that will be needed. This
* way, it's not possible to run out of memory part-way through
* modifying the lookup table of the destination WIM. */
- wims.src_wim = src_wim;
- wims.dest_wim = dest_wim;
- INIT_LIST_HEAD(&wims.lte_list_head);
+ INIT_LIST_HEAD(<e_list_head);
for_lookup_table_entry(src_wim->lookup_table, lte_zero_out_refcnt, NULL);
- root = wim_root_dentry(src_wim);
- for_dentry_in_tree(root, dentry_unresolve_ltes, NULL);
- ret = for_dentry_in_tree(root, allocate_lte_if_needed, &wims);
- if (ret != 0)
- goto out_free_ltes;
+ src_imd = wim_get_current_image_metadata(src_wim);
+
+ hlist_for_each_entry(inode, cur_node, &src_imd->inode_list, hlist) {
+ ret = inode_allocate_needed_ltes(inode,
+ src_wim->lookup_table,
+ dest_wim->lookup_table,
+ <e_list_head);
+ if (ret != 0)
+ goto out_free_ltes;
+ }
ret = xml_export_image(src_wim->wim_info, src_image,
&dest_wim->wim_info, dest_name,
if (ret != 0)
goto out_free_ltes;
- sd = wim_security_data(src_wim);
- ret = add_new_dentry_tree(dest_wim, root, sd);
+ sd = src_imd->security_data;
+ ret = add_new_dentry_tree(dest_wim, src_imd->root_dentry, sd);
if (ret != 0)
goto out_xml_delete_image;
+ dest_wim->image_metadata[
+ dest_wim->hdr.image_count - 1].inode_list = src_imd->inode_list;
/* All memory allocations have been taken care of, so it's no longer
* possible for this function to fail. Go ahead and increment the
* reference counts of the dentry tree and security data, then update
* the lookup table of the destination WIM and the boot index, if
* needed. */
- for_dentry_in_tree(root, increment_dentry_refcnt, NULL);
sd->refcnt++;
- for_dentry_in_tree(root, add_lte_to_dest_wim, &wims);
- wimlib_assert(list_empty(&wims.lte_list_head));
+ hlist_for_each_entry(inode, cur_node, &src_imd->inode_list, hlist) {
+ inode_move_ltes_to_table(inode,
+ src_wim->lookup_table,
+ dest_wim->lookup_table,
+ <e_list_head);
+ }
if (export_flags & WIMLIB_EXPORT_FLAG_BOOT)
wimlib_set_boot_idx(dest_wim, dest_wim->hdr.image_count);
out_free_ltes:
{
struct lookup_table_entry *lte, *tmp;
- list_for_each_entry_safe(lte, tmp, &wims.lte_list_head, staging_list)
+ list_for_each_entry_safe(lte, tmp, <e_list_head, staging_list)
free_lookup_table_entry(lte);
}
* -----------------
*/
+/* Hash table to find inodes, identified by their inode ID.
+ * */
+struct inode_table {
+ /* Fields for the hash table */
+ struct hlist_head *array;
+ u64 num_entries;
+ u64 capacity;
+
+ /*
+ * Linked list of "extra" inodes. These may be:
+ *
+ * - inodes with link count 1, which are all allowed to have 0 for their
+ * inode number, meaning we cannot insert them into the hash table
+ * before calling assign_inode_numbers().
+ *
+ * - Groups we create ourselves by splitting a nominal inode due to
+ * inconsistencies in the dentries. These inodes will share a inode
+ * ID with some other inode until assign_inode_numbers() is called.
+ */
+ struct hlist_head extra_inodes;
+};
+
+static inline void destroy_inode_table(struct inode_table *table)
+{
+ FREE(table->array);
+}
-int init_inode_table(struct inode_table *table, size_t capacity)
+static int init_inode_table(struct inode_table *table, size_t capacity)
{
table->array = CALLOC(capacity, sizeof(table->array[0]));
if (!table->array) {
return 0;
}
-
static inline size_t inode_link_count(const struct inode *inode)
{
const struct list_head *cur;
* we keep a linked list of the single dentries, and assign them inode
* numbers later.
*/
-int inode_table_insert(struct dentry *dentry, void *__table)
+static int inode_table_insert(struct dentry *dentry, void *__table)
{
struct inode_table *table = __table;
struct inode *d_inode = dentry->d_inode;
* inodes'. There will be just one `struct inode' for each hard link group
* remaining.
*/
-static int
-fix_nominal_inode(struct inode *inode, struct hlist_head *inode_list)
+static int fix_nominal_inode(struct inode *inode,
+ struct hlist_head *inode_list)
{
struct dentry *dentry;
struct hlist_node *cur, *tmp;
* split inodes as well as the inodes that were good before, is returned in the
* list @inode_list.
*/
-int fix_inodes(struct inode_table *table, struct hlist_head *inode_list)
+static int fix_inodes(struct inode_table *table, struct hlist_head *inode_list)
{
struct inode *inode;
struct hlist_node *cur, *tmp;
hlist_add_head(cur, inode_list);
return 0;
}
+
+int dentry_tree_fix_inodes(struct dentry *root, struct hlist_head *inode_list)
+{
+ struct inode_table inode_tab;
+ int ret;
+
+ DEBUG("Inserting dentries into inode table");
+ ret = init_inode_table(&inode_tab, 9001);
+ if (ret != 0)
+ return ret;
+
+ for_dentry_in_tree(root, inode_table_insert, &inode_tab);
+
+ DEBUG("Cleaning up the hard link groups");
+ ret = fix_inodes(&inode_tab, inode_list);
+ destroy_inode_table(&inode_tab);
+ return ret;
+}
void inode_resolve_ltes(struct inode *inode, struct lookup_table *table)
{
- struct lookup_table_entry *lte;
-
- wimlib_assert(!inode->resolved);
- /* Resolve the default file stream */
- lte = __lookup_resource(table, inode->hash);
- inode->lte = lte;
- inode->resolved = 1;
-
- /* Resolve the alternate data streams */
- for (u16 i = 0; i < inode->num_ads; i++) {
- struct ads_entry *cur_entry = &inode->ads_entries[i];
- lte = __lookup_resource(table, cur_entry->hash);
- cur_entry->lte = lte;
+ if (!inode->resolved) {
+ struct lookup_table_entry *lte;
+ /* Resolve the default file stream */
+ lte = __lookup_resource(table, inode->hash);
+ inode->lte = lte;
+ inode->resolved = 1;
+
+ /* Resolve the alternate data streams */
+ for (u16 i = 0; i < inode->num_ads; i++) {
+ struct ads_entry *cur_entry = &inode->ads_entries[i];
+ lte = __lookup_resource(table, cur_entry->hash);
+ cur_entry->lte = lte;
+ }
}
}
-static void inode_unresolve_ltes(struct inode *inode)
+void inode_unresolve_ltes(struct inode *inode)
{
- wimlib_assert(inode->resolved);
- if (inode->lte)
- copy_hash(inode->hash, inode->lte->hash);
- else
- zero_out_hash(inode->hash);
-
- for (u16 i = 0; i < inode->num_ads; i++) {
- if (inode->ads_entries[i].lte)
- copy_hash(inode->ads_entries[i].hash,
- inode->ads_entries[i].lte->hash);
+ if (inode->resolved) {
+ if (inode->lte)
+ copy_hash(inode->hash, inode->lte->hash);
else
- zero_out_hash(inode->ads_entries[i].hash);
+ zero_out_hash(inode->hash);
+
+ for (u16 i = 0; i < inode->num_ads; i++) {
+ if (inode->ads_entries[i].lte)
+ copy_hash(inode->ads_entries[i].hash,
+ inode->ads_entries[i].lte->hash);
+ else
+ zero_out_hash(inode->ads_entries[i].hash);
+ }
+ inode->resolved = 0;
}
- inode->resolved = 0;
}
/* Resolve a dentry's lookup table entries
*/
int dentry_resolve_ltes(struct dentry *dentry, void *table)
{
- if (!dentry->d_inode->resolved)
- inode_resolve_ltes(dentry->d_inode, table);
+ wimlib_assert(dentry->refcnt == 1);
+ inode_resolve_ltes(dentry->d_inode, table);
return 0;
}
int dentry_unresolve_ltes(struct dentry *dentry, void *ignore)
{
- if (dentry->d_inode->resolved)
- inode_unresolve_ltes(dentry->d_inode);
+ inode_unresolve_ltes(dentry->d_inode);
return 0;
}
struct lookup_table *table);
extern int dentry_resolve_ltes(struct dentry *dentry, void *__table);
+
+extern void inode_unresolve_ltes(struct inode *inode);
extern int dentry_unresolve_ltes(struct dentry *dentry, void *ignore);
int write_lookup_table(struct lookup_table *table, FILE *out,
u32 dentry_offset;
int ret;
struct dentry *dentry;
- struct inode_table inode_tab;
const struct lookup_table_entry *metadata_lte;
u64 metadata_len;
struct hlist_head inode_list;
goto out_free_dentry_tree;
/* Build hash table that maps hard link group IDs to dentry sets */
- DEBUG("Building link group table");
- ret = init_inode_table(&inode_tab, 9001);
- if (ret != 0)
- goto out_free_dentry_tree;
-
- for_dentry_in_tree(dentry, inode_table_insert, &inode_tab);
-
- DEBUG("Fixing inconsistencies in the hard link groups");
- ret = fix_inodes(&inode_tab, &inode_list);
- destroy_inode_table(&inode_tab);
+ ret = dentry_tree_fix_inodes(dentry, &inode_list);
if (ret != 0)
goto out_free_dentry_tree;
struct lookup_table *joined_tab, *wim_tab_save;
struct image_metadata *imd;
struct wimfs_context ctx;
+ struct hlist_node *cur_node;
+ struct inode *inode;
DEBUG("Mount: wim = %p, image = %d, dir = %s, flags = %d, ",
wim, image, dir, mount_flags);
imd->has_been_mounted_rw = 1;
}
- /* Resolve all the lookup table entries of the dentry tree */
- DEBUG("Resolving lookup table entries");
- for_dentry_in_tree(imd->root_dentry, dentry_resolve_ltes,
- wim->lookup_table);
+ /* Resolve the lookup table entries for every inode in the image, and
+ * assign inode numbers */
+ DEBUG("Resolving lookup table entries and assigning inode numbers");
- ctx.next_ino = assign_inode_numbers(&imd->inode_list);
+ ctx.next_ino = 1;
+ hlist_for_each_entry(inode, cur_node, &imd->inode_list, hlist) {
+ inode_resolve_ltes(inode, wim->lookup_table);
+ inode->ino = ctx.next_ino++;
+ }
+ /*ctx.next_ino = assign_inode_numbers(&imd->inode_list);*/
DEBUG("(next_ino = %"PRIu64")", ctx.next_ino);
-
DEBUG("Calling fuse_main()");
ret = fuse_main(argc, argv, &wimfs_operations, &ctx);
#include "lookup_table.h"
#include "xml.h"
-static inline struct image_metadata *
-wim_get_current_image_metadata(WIMStruct *w)
-{
- return &w->image_metadata[w->current_image - 1];
-}
-
static int print_metadata(WIMStruct *w)
{
DEBUG("Printing metadata for image %d", w->current_image);
return w->image_metadata[w->current_image - 1].security_data;
}
+static inline struct image_metadata *
+wim_get_current_image_metadata(WIMStruct *w)
+{
+ return &w->image_metadata[w->current_image - 1];
+}
+
/* Nonzero if a struct resource_entry indicates a compressed resource. */
static inline int resource_is_compressed(const struct resource_entry *entry)
{
/* hardlink.c */
-/* Hash table to find inodes, identified by their inode ID.
- * */
-struct inode_table {
- /* Fields for the hash table */
- struct hlist_head *array;
- u64 num_entries;
- u64 capacity;
-
- /*
- * Linked list of "extra" inodes. These may be:
- *
- * - inodes with link count 1, which are all allowed to have 0 for their
- * inode number, meaning we cannot insert them into the hash table
- * before calling assign_inode_numbers().
- *
- * - Groups we create ourselves by splitting a nominal inode due to
- * inconsistencies in the dentries. These inodes will share a inode
- * ID with some other inode until assign_inode_numbers() is called.
- */
- struct hlist_head extra_inodes;
-};
-
-extern int init_inode_table(struct inode_table *table, size_t capacity);
-static inline void destroy_inode_table(struct inode_table *table)
-{
- FREE(table->array);
-}
-extern int inode_table_insert(struct dentry *dentry, void *__table);
extern u64 assign_inode_numbers(struct hlist_head *inode_list);
-extern int fix_inodes(struct inode_table *table, struct hlist_head *inode_list);
+
+extern int dentry_tree_fix_inodes(struct dentry *root,
+ struct hlist_head *inode_list);
/* header.c */
extern int read_header(FILE *fp, struct wim_header *hdr, int split_ok);