X-Git-Url: https://wimlib.net/git/?a=blobdiff_plain;f=src%2Fresource.c;h=48f54804576a3d68fdb25d308fe4d8d26dc61e01;hb=8a7aa1e0e77c5fadb2ee4d062b90532f709f7883;hp=5e6707d97dee941d1514bf7a3accad3bac4ece7d;hpb=ef8f45b98b5c4db398321cd36d052ccbb9c3784a;p=wimlib diff --git a/src/resource.c b/src/resource.c index 5e6707d9..48f54804 100644 --- a/src/resource.c +++ b/src/resource.c @@ -925,6 +925,7 @@ int read_metadata_resource(FILE *fp, int wim_ctype, struct image_metadata *imd) const struct resource_entry *res_entry; struct dentry *dentry; struct wim_security_data *sd; + struct link_group_table *lgt; res_entry = &imd->metadata_lte->resource_entry; @@ -990,23 +991,42 @@ int read_metadata_resource(FILE *fp, int wim_ctype, struct image_metadata *imd) if (ret != 0) goto out_free_dentry_tree; + DEBUG("Reading dentry tree"); /* Now read the entire directory entry tree. */ ret = read_dentry_tree(buf, res_entry->original_size, dentry); if (ret != 0) goto out_free_dentry_tree; + DEBUG("Calculating dentry full paths"); /* Calculate the full paths in the dentry tree. */ ret = for_dentry_in_tree(dentry, calculate_dentry_full_path, NULL); if (ret != 0) goto out_free_dentry_tree; + DEBUG("Building link group table"); + lgt = new_link_group_table(9001); + if (!lgt) + goto out_free_dentry_tree; + ret = for_dentry_in_tree(dentry, link_group_table_insert, lgt); + if (ret != 0) + goto out_free_lgt; + + DEBUG("Freeing duplicate ADS entries in link group table"); + ret = link_groups_free_duplicate_data(lgt); + if (ret != 0) + goto out_free_lgt; + DEBUG("Done reading image metadata"); + + imd->lgt = lgt; imd->security_data = sd; - imd->root_dentry = dentry; + imd->root_dentry = dentry; goto out_free_buf; -out_free_security_data: - free_security_data(sd); +out_free_lgt: + free_link_group_table(lgt); out_free_dentry_tree: free_dentry_tree(dentry, NULL, false); +out_free_security_data: + free_security_data(sd); out_free_buf: FREE(buf); return ret; @@ -1071,6 +1091,9 @@ int write_metadata_resource(WIMStruct *w) if (ret != 0) return ret; + DEBUG("Updating metadata lookup table entry (size %zu)", + metadata_original_size); + /* Update the lookup table entry, including the hash and output resource * entry fields, for this image's metadata resource. */ lte = wim_metadata_lookup_table_entry(w); @@ -1090,55 +1113,56 @@ int write_metadata_resource(WIMStruct *w) return 0; } -/* - * Writes a file resource to the output file. - * - * @dentry: The dentry for the file resource. - * @wim_p: A pointer to the WIMStruct. The fields of interest to this - * function are the input and output file streams and the lookup - * table. - * - * @return zero on success, nonzero on failure. - */ -int write_file_resource(struct dentry *dentry, void *wim_p) +static int write_file_resource(WIMStruct *w, const u8 hash[]) { - WIMStruct *w; - FILE *out_fp; - FILE *in_fp; - struct lookup_table_entry *lte; - int in_wim_ctype; - int out_wim_ctype; - struct resource_entry *output_res_entry; - u64 len; - int ret; - - w = wim_p; - out_fp = w->out_fp; - - /* Directories don't need file resources. */ - if (dentry_is_directory(dentry)) - return 0; - /* Get the lookup entry for the file resource. */ - lte = wim_lookup_resource(w, dentry); + struct lookup_table_entry *lte; + + lte = __lookup_resource(w->lookup_table, hash); if (!lte) return 0; - /* No need to write file resources twice. (This indicates file - * resources that are part of a hard link set.) */ + /* No need to write file resources twice. */ if (++lte->out_refcnt != 1) return 0; - out_wim_ctype = wimlib_get_compression_type(w); - output_res_entry = <e->output_resource_entry; - /* do not write empty resources */ if (lte->resource_entry.original_size == 0) return 0; + int out_wim_ctype = wimlib_get_compression_type(w); + struct resource_entry *output_res_entry = <e->output_resource_entry; + u64 len; + FILE *in_fp; + FILE *out_fp = w->out_fp; + int ret = 0; + /* Figure out if we can read the resource from the WIM file, or - * if we have to read it from the filesystem outside. */ - if (lte->file_on_disk) { + * if we have to read it from the filesystem outside, or if it's a + * symbolic link with the data already in memory pointed to by a field + * of the lookup table entry. */ + if (lte->is_symlink) { + off_t offset = ftello(w->out_fp); + u64 new_size; + + if (offset == -1) { + ERROR_WITH_ERRNO("Could not get position in output " + "file"); + return WIMLIB_ERR_WRITE; + } + + wimlib_assert(lte->symlink_buf); + + len = lte->resource_entry.original_size; + + ret = recompress_resource(NULL, lte->symlink_buf, len, len, 0, + 0, out_fp, out_wim_ctype, &new_size); + output_res_entry->size = new_size; + output_res_entry->original_size = len; + output_res_entry->offset = offset; + output_res_entry->flags = (out_wim_ctype == WIM_COMPRESSION_TYPE_NONE) + ? 0 : WIM_RESHDR_FLAG_COMPRESSED; + } else if (lte->file_on_disk) { /* Read from disk (uncompressed) */ @@ -1156,6 +1180,7 @@ int write_file_resource(struct dentry *dentry, void *wim_p) out_wim_ctype, output_res_entry); fclose(in_fp); } else { + int in_wim_ctype; /* Read from input WIM (possibly compressed) */ @@ -1185,3 +1210,34 @@ int write_file_resource(struct dentry *dentry, void *wim_p) } return ret; } + +/* + * Writes a dentry's resources to the output file. + * + * @dentry: The dentry for the file resource. + * @wim_p: A pointer to the WIMStruct. The fields of interest to this + * function are the input and output file streams and the lookup + * table, and the alternate data streams. + * + * @return zero on success, nonzero on failure. + */ +int write_dentry_resources(struct dentry *dentry, void *wim_p) +{ + WIMStruct *w = wim_p; + int ret; + + /* Directories don't need file resources. */ + if (dentry_is_directory(dentry)) + return 0; + + ret = write_file_resource(w, dentry->hash); + if (ret != 0) + return ret; + for (u16 i = 0; i < dentry->num_ads; i++) { + ret = write_file_resource(w, dentry->ads_entries[i].hash); + if (ret != 0) + return ret; + } + return 0; +} +