X-Git-Url: https://wimlib.net/git/?a=blobdiff_plain;f=src%2Fmodify.c;h=f4aadf9aed0b7a9be9c513fa3210919f52dd0bd7;hb=b1c4e6a269ae4c969060e33685db12f76a204a58;hp=fab9ee059d2558571363e8bb2698540d1b7027ed;hpb=da2c501c4ca54063126290c2103f607e926c9989;p=wimlib diff --git a/src/modify.c b/src/modify.c index fab9ee05..f4aadf9a 100644 --- a/src/modify.c +++ b/src/modify.c @@ -42,16 +42,16 @@ * the WIM. */ #define WIMLIB_ADD_IMAGE_FLAG_ROOT 0x80000000 -static void destroy_image_metadata(struct image_metadata *imd, - struct lookup_table *lt) +void destroy_image_metadata(struct image_metadata *imd,struct lookup_table *lt) { - free_dentry_tree(imd->root_dentry, lt, true); + free_dentry_tree(imd->root_dentry, lt); free_security_data(imd->security_data); free_link_group_table(imd->lgt); /* Get rid of the lookup table entry for this image's metadata resource * */ - lookup_table_remove(lt, imd->metadata_lte); + if (lt) + lookup_table_remove(lt, imd->metadata_lte); } /* @@ -60,9 +60,7 @@ static void destroy_image_metadata(struct image_metadata *imd, * * @root: A dentry that has already been created for the root of the dentry * tree. - * @source_path: The path to the root of the tree on disk. - * @root_stat: A pointer to a `struct stat' that contains the metadata for the - * root of the tree on disk. + * @root_disk_path: The path to the root of the tree on disk. * @lookup_table: The lookup table for the WIM file. For each file added to the * dentry tree being built, an entry is added to the lookup table, * unless an identical file is already in the lookup table. These @@ -78,9 +76,9 @@ static int build_dentry_tree(struct dentry *root, const char *root_disk_path, struct lookup_table* lookup_table, int add_flags) { - DEBUG("`%s'", root_disk_path); + DEBUG("%s", root_disk_path); struct stat root_stbuf; - int ret; + int ret = 0; int (*stat_fn)(const char *restrict, struct stat *restrict); if (add_flags & WIMLIB_ADD_IMAGE_FLAG_DEREFERENCE) @@ -100,8 +98,14 @@ static int build_dentry_tree(struct dentry *root, const char *root_disk_path, ERROR("`%s' is not a directory", root_disk_path); return WIMLIB_ERR_NOTDIR; } + if (!S_ISREG(root_stbuf.st_mode) && !S_ISDIR(root_stbuf.st_mode) + && !S_ISLNK(root_stbuf.st_mode)) { + ERROR("`%s' is not a regular file, directory, or symbolic link."); + return WIMLIB_ERR_SPECIAL_FILE; + } stbuf_to_dentry(&root_stbuf, root); add_flags &= ~WIMLIB_ADD_IMAGE_FLAG_ROOT; + root->resolved = true; if (dentry_is_directory(root)) { /* Open the directory on disk */ @@ -130,10 +134,8 @@ static int build_dentry_tree(struct dentry *root, const char *root_disk_path, continue; strcpy(name + len + 1, p->d_name); child = new_dentry(p->d_name); - if (!child) { - ERROR("No memory to allocate new dentry"); + if (!child) return WIMLIB_ERR_NOMEM; - } ret = build_dentry_tree(child, name, lookup_table, add_flags); link_dentry(child, root); @@ -145,68 +147,37 @@ static int build_dentry_tree(struct dentry *root, const char *root_disk_path, /* Archiving a symbolic link */ size_t symlink_buf_len; char deref_name_buf[4096]; - ssize_t ret = readlink(root_disk_path, deref_name_buf, - sizeof(deref_name_buf) - 1); - if (ret == -1) { + ssize_t deref_name_len; + + deref_name_len = readlink(root_disk_path, deref_name_buf, + sizeof(deref_name_buf) - 1); + if (deref_name_len == -1) { ERROR_WITH_ERRNO("Failed to read target of " "symbolic link `%s'", root_disk_path); - return WIMLIB_ERR_STAT; + return WIMLIB_ERR_READLINK; } - deref_name_buf[ret] = '\0'; + deref_name_buf[deref_name_len] = '\0'; DEBUG("Read symlink `%s'", deref_name_buf); - void *symlink_buf = make_symlink_reparse_data_buf(deref_name_buf, - &symlink_buf_len); - if (!symlink_buf) - return WIMLIB_ERR_NOMEM; - DEBUG("Made symlink reparse data buf (len = %zu, name len = %zu)", - symlink_buf_len, ret); - - u8 symlink_buf_hash[WIM_HASH_SIZE]; - sha1_buffer(symlink_buf, symlink_buf_len, symlink_buf_hash); - - ret = dentry_set_symlink_buf(root, symlink_buf_hash); - - if (ret != 0) { - FREE(symlink_buf); - return ret; - } - DEBUG("Created symlink buf"); - - struct lookup_table_entry *lte; - struct lookup_table_entry *existing_lte; - - existing_lte = __lookup_resource(lookup_table, symlink_buf_hash); - if (existing_lte) { - existing_lte->refcnt++; - } else { - DEBUG("Creating new lookup table entry"); - lte = new_lookup_table_entry(); - if (!lte) { - FREE(symlink_buf); - return WIMLIB_ERR_NOMEM; - } - lte->symlink_buf = symlink_buf; - lte->resource_entry.original_size = symlink_buf_len; - lte->resource_entry.size = symlink_buf_len; - lte->is_symlink = true; - memcpy(lte->hash, symlink_buf_hash, WIM_HASH_SIZE); - lookup_table_insert(lookup_table, lte); - } + ret = dentry_set_symlink(root, deref_name_buf, + lookup_table, NULL); } else { /* Regular file */ struct lookup_table_entry *lte; + u8 hash[SHA1_HASH_SIZE]; /* For each regular file, we must check to see if the file is in * the lookup table already; if it is, we increment its refcnt; * otherwise, we create a new lookup table entry and insert it. * */ - ret = sha1sum(root_disk_path, root->hash); + ret = sha1sum(root_disk_path, hash); if (ret != 0) return ret; - lte = __lookup_resource(lookup_table, root->hash); + lte = __lookup_resource(lookup_table, hash); if (lte) { lte->refcnt++; + DEBUG("Add lte reference %u for `%s'", lte->refcnt, + root_disk_path); } else { char *file_on_disk = STRDUP(root_disk_path); if (!file_on_disk) { @@ -221,9 +192,10 @@ static int build_dentry_tree(struct dentry *root, const char *root_disk_path, lte->file_on_disk = file_on_disk; lte->resource_entry.original_size = root_stbuf.st_size; lte->resource_entry.size = root_stbuf.st_size; - memcpy(lte->hash, root->hash, WIM_HASH_SIZE); + copy_hash(lte->hash, hash); lookup_table_insert(lookup_table, lte); } + root->lte = lte; } return ret; } @@ -241,40 +213,39 @@ struct wim_pair { * entry is created that references the location of the file resource in the * source WIM file through the other_wim_fp field of the lookup table entry. */ -static int add_lookup_table_entry_to_dest_wim(struct dentry *dentry, void *arg) +static int add_lte_to_dest_wim(struct dentry *dentry, void *arg) { WIMStruct *src_wim, *dest_wim; - struct lookup_table_entry *src_table_entry; - struct lookup_table_entry *dest_table_entry; src_wim = ((struct wim_pair*)arg)->src_wim; dest_wim = ((struct wim_pair*)arg)->dest_wim; - if (dentry_is_directory(dentry)) - return 0; - - /* XXX ADS */ - src_table_entry = __lookup_resource(src_wim->lookup_table, dentry->hash); - if (!src_table_entry) - return 0; - - /* XXX ADS */ - dest_table_entry = __lookup_resource(dest_wim->lookup_table, dentry->hash); - if (dest_table_entry) { - dest_table_entry->refcnt++; - } else { - dest_table_entry = new_lookup_table_entry(); - if (!dest_table_entry) - return WIMLIB_ERR_NOMEM; - dest_table_entry->other_wim_fp = src_wim->fp; - dest_table_entry->other_wim_ctype = - wimlib_get_compression_type(src_wim); - dest_table_entry->refcnt = 1; - memcpy(&dest_table_entry->resource_entry, - &src_table_entry->resource_entry, - sizeof(struct resource_entry)); - memcpy(dest_table_entry->hash, dentry->hash, WIM_HASH_SIZE); - lookup_table_insert(dest_wim->lookup_table, dest_table_entry); + wimlib_assert(!dentry->resolved); + + for (unsigned i = 0; i < (unsigned)dentry->num_ads + 1; i++) { + struct lookup_table_entry *src_lte, *dest_lte; + src_lte = dentry_stream_lte_unresolved(dentry, i, + src_wim->lookup_table); + if (!src_lte) + continue; + dest_lte = dentry_stream_lte_unresolved(dentry, i, + dest_wim->lookup_table); + if (dest_lte) { + dest_lte->refcnt++; + } else { + dest_lte = new_lookup_table_entry(); + if (!dest_lte) + return WIMLIB_ERR_NOMEM; + dest_lte->other_wim_fp = src_wim->fp; + dest_lte->other_wim_ctype = + wimlib_get_compression_type(src_wim); + memcpy(&dest_lte->resource_entry, + &src_lte->resource_entry, + sizeof(struct resource_entry)); + copy_hash(dest_lte->hash, + dentry_stream_hash_unresolved(dentry, i)); + lookup_table_insert(dest_wim->lookup_table, dest_lte); + } } return 0; } @@ -295,6 +266,7 @@ static int add_new_dentry_tree(WIMStruct *w, struct dentry *root_dentry) struct image_metadata *imd; struct image_metadata *new_imd; struct wim_security_data *sd; + struct link_group_table *lgt; DEBUG("Reallocating image metadata array for image_count = %u", w->hdr.image_count + 1); @@ -317,22 +289,30 @@ static int add_new_dentry_tree(WIMStruct *w, struct dentry *root_dentry) sd->refcnt = 1; sd->total_length = 8; + lgt = new_link_group_table(9001); + if (!lgt) + goto out_free_security_data; + metadata_lte->resource_entry.flags = WIM_RESHDR_FLAG_METADATA; - randomize_byte_array(metadata_lte->hash, WIM_HASH_SIZE); + random_hash(metadata_lte->hash); lookup_table_insert(w->lookup_table, metadata_lte); - w->hdr.image_count++; + new_imd = &imd[w->hdr.image_count]; - new_imd = &imd[w->hdr.image_count - 1]; - new_imd->metadata_lte = metadata_lte; - new_imd->modified = true; new_imd->root_dentry = root_dentry; + new_imd->metadata_lte = metadata_lte; new_imd->security_data = sd; + new_imd->lgt = lgt; + new_imd->modified = true; + FREE(w->image_metadata); w->image_metadata = imd; + w->hdr.image_count++; /* Change the current image to the new one. */ return wimlib_select_image(w, w->hdr.image_count); +out_free_security_data: + FREE(sd); out_free_metadata_lte: FREE(metadata_lte); out_free_imd: @@ -422,7 +402,7 @@ WIMLIBAPI int wimlib_export_image(WIMStruct *src_wim, /* Cleaning up here on failure would be hard. For example, we could - * fail to allocate memory in add_lookup_table_entry_to_dest_wim(), + * fail to allocate memory in add_lte_to_dest_wim(), * leaving the lookup table entries in the destination WIM in an * inconsistent state. Until these issues can be resolved, * wimlib_export_image() is documented as leaving dest_wim is an @@ -431,7 +411,7 @@ WIMLIBAPI int wimlib_export_image(WIMStruct *src_wim, for_dentry_in_tree(root, increment_dentry_refcnt, NULL); wims.src_wim = src_wim; wims.dest_wim = dest_wim; - ret = for_dentry_in_tree(root, add_lookup_table_entry_to_dest_wim, &wims); + ret = for_dentry_in_tree(root, add_lte_to_dest_wim, &wims); if (ret != 0) return ret; ret = add_new_dentry_tree(dest_wim, root); @@ -520,7 +500,6 @@ WIMLIBAPI int wimlib_add_image(WIMStruct *w, const char *dir, const char *flags_element, int flags) { struct dentry *root_dentry; - struct stat root_stat; struct image_metadata *imd; int ret; @@ -546,12 +525,6 @@ WIMLIBAPI int wimlib_add_image(WIMStruct *w, const char *dir, root_dentry = new_dentry(""); if (!root_dentry) return WIMLIB_ERR_NOMEM; - ret = calculate_dentry_full_path(root_dentry, NULL); - - if (ret != 0) - goto out_free_dentry_tree; - - root_dentry->attributes |= FILE_ATTRIBUTE_DIRECTORY; DEBUG("Building dentry tree."); ret = build_dentry_tree(root_dentry, dir, w->lookup_table, @@ -562,7 +535,7 @@ WIMLIBAPI int wimlib_add_image(WIMStruct *w, const char *dir, goto out_free_dentry_tree; } - DEBUG("Recalculating full paths of dentries."); + DEBUG("Calculating full paths of dentries."); ret = for_dentry_in_tree(root_dentry, calculate_dentry_full_path, NULL); if (ret != 0) goto out_free_dentry_tree; @@ -571,10 +544,12 @@ WIMLIBAPI int wimlib_add_image(WIMStruct *w, const char *dir, if (ret != 0) goto out_free_dentry_tree; + DEBUG("Inserting dentries into hard link group table"); ret = for_dentry_in_tree(root_dentry, link_group_table_insert, - &w->image_metadata[w->hdr.image_count - 1].lgt); + w->image_metadata[w->hdr.image_count - 1].lgt); if (ret != 0) goto out_destroy_imd; + DEBUG("Assigning hard link groups"); assign_link_groups(w->image_metadata[w->hdr.image_count - 1].lgt); if (flags & WIMLIB_ADD_IMAGE_FLAG_BOOT) @@ -588,8 +563,9 @@ WIMLIBAPI int wimlib_add_image(WIMStruct *w, const char *dir, out_destroy_imd: destroy_image_metadata(&w->image_metadata[w->hdr.image_count - 1], w->lookup_table); + w->hdr.image_count--; return ret; out_free_dentry_tree: - free_dentry_tree(root_dentry, w->lookup_table, true); + free_dentry_tree(root_dentry, w->lookup_table); return ret; }