-/* Write the metadata resource for the current image. */
-int write_metadata_resource(WIMStruct *w)
-{
- FILE *out;
- u8 *buf;
- u8 *p;
- int ret;
- u64 subdir_offset;
- struct dentry *root;
- struct lookup_table_entry *lte;
- struct resource_entry *res_entry;
- off_t metadata_offset;
- u64 metadata_original_size;
- u64 metadata_compressed_size;
- int metadata_ctype;
- u8 hash[WIM_HASH_SIZE];
-
- DEBUG("Writing metadata resource for image %d", w->current_image);
-
- out = w->out_fp;
- root = wim_root_dentry(w);
- metadata_ctype = wimlib_get_compression_type(w);
- metadata_offset = ftello(out);
- if (metadata_offset == -1)
- return WIMLIB_ERR_WRITE;
-
- struct wim_security_data *sd = wim_security_data(w);
- if (sd)
- subdir_offset = sd->total_length + root->length + 8;
- else
- subdir_offset = 8 + root->length + 8;
- calculate_subdir_offsets(root, &subdir_offset);
- metadata_original_size = subdir_offset;
- buf = MALLOC(metadata_original_size);
- if (!buf) {
- ERROR("Failed to allocate %"PRIu64" bytes for "
- "metadata resource", metadata_original_size);
- return WIMLIB_ERR_NOMEM;
- }
-
- p = write_security_data(sd, buf);
-
- DEBUG("Writing dentry tree.");
- p = write_dentry_tree(root, p);
-
- /* Like file resources, the lookup table entry for a metadata resource
- * uses for the hash code a SHA1 message digest of its uncompressed
- * contents. */
- sha1_buffer(buf, metadata_original_size, hash);
-
- ret = write_resource_from_memory(buf,
- metadata_ctype,
- metadata_original_size,
- out,
- &metadata_compressed_size);
- FREE(buf);
- if (ret != 0)
- return ret;
-
- /* 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);
- res_entry = <e->output_resource_entry;
- lte->out_refcnt++;
- if (memcmp(hash, lte->hash, WIM_HASH_SIZE) != 0) {
- lookup_table_unlink(w->lookup_table, lte);
- memcpy(lte->hash, hash, WIM_HASH_SIZE);
- lookup_table_insert(w->lookup_table, lte);
- }
- res_entry->original_size = metadata_original_size;
- res_entry->offset = metadata_offset;
- res_entry->size = metadata_compressed_size;
- res_entry->flags = WIM_RESHDR_FLAG_METADATA;
- if (metadata_ctype != WIM_COMPRESSION_TYPE_NONE)
- res_entry->flags |= WIM_RESHDR_FLAG_COMPRESSED;
- return 0;
-}
-
-static int write_file_resource(WIMStruct *w, const u8 hash[])
-{
- /* Get the lookup entry for the file resource. */
- 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.) */
- if (++lte->out_refcnt != 1)
- return 0;
-
- /* 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, 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;
-
- recompress_resource(in_fp, 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) */
-
- len = lte->resource_entry.original_size;
-
- in_fp = fopen(lte->file_on_disk, "rb");
- if (!in_fp) {
- ERROR_WITH_ERRNO("Failed to open the file `%s'",
- lte->file_on_disk);
- return WIMLIB_ERR_OPEN;
- }
-
- ret = transfer_file_resource(in_fp, len, len, 0,
- WIM_COMPRESSION_TYPE_NONE, out_fp,
- out_wim_ctype, output_res_entry);
- fclose(in_fp);
- } else {
- int in_wim_ctype;
-
- /* Read from input WIM (possibly compressed) */
-
- /* It may be a different WIM file, in the case of
- * exporting images from one WIM file to another */
- if (lte->other_wim_fp) {
- /* Different WIM file. */
- in_fp = lte->other_wim_fp;
- in_wim_ctype = lte->other_wim_ctype;
- } else {
- /* Same WIM file. */
- in_fp = w->fp;
- in_wim_ctype = out_wim_ctype;
- }
- int input_res_ctype = resource_compression_type(
- in_wim_ctype,
- lte->resource_entry.flags);
-
- ret = transfer_file_resource(in_fp,
- lte->resource_entry.size,
- lte->resource_entry.original_size,
- lte->resource_entry.offset,
- input_res_ctype,
- out_fp,
- out_wim_ctype,
- output_res_entry);
- }
- 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.