if (resource_size != resource_original_size) {
ERROR("Resource with original size %"PRIu64" bytes is "
"marked as uncompressed, but its actual size is "
- "%"PRIu64" bytes", resource_size);
+ "%"PRIu64" bytes",
+ resource_original_size, resource_size);
return WIMLIB_ERR_INVALID_RESOURCE_SIZE;
}
return read_uncompressed_resource(fp,
int ret;
const struct resource_entry *res_entry;
struct dentry *dentry;
-#ifdef ENABLE_SECURITY_DATA
struct wim_security_data *sd;
-#endif
+ struct link_group_table *lgt;
res_entry = &imd->metadata_lte->resource_entry;
* The security data starts with a 4-byte integer giving its total
* length. */
-#ifdef ENABLE_SECURITY_DATA
/* Read the security data into a wim_security_data structure. */
ret = read_security_data(buf, res_entry->original_size, &sd);
if (ret != 0)
goto out_free_buf;
-#endif
dentry = MALLOC(sizeof(struct dentry));
if (!dentry) {
if (ret != 0)
goto out_free_dentry_tree;
-#ifdef ENABLE_SECURITY_DATA
+ 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;
+
+ imd->lgt = lgt;
imd->security_data = sd;
-#endif
- imd->root_dentry = dentry;
+ imd->root_dentry = dentry;
goto out_free_buf;
-out_free_security_data:
-#ifdef ENABLE_SECURITY_DATA
- free_security_data(sd);
-#endif
+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;
if (metadata_offset == -1)
return WIMLIB_ERR_WRITE;
- #ifdef ENABLE_SECURITY_DATA
struct wim_security_data *sd = wim_security_data(w);
if (sd)
subdir_offset = sd->total_length + root->length + 8;
else
- #endif
subdir_offset = 8 + root->length + 8;
calculate_subdir_offsets(root, &subdir_offset);
metadata_original_size = subdir_offset;
"metadata resource", metadata_original_size);
return WIMLIB_ERR_NOMEM;
}
- #ifdef ENABLE_SECURITY_DATA
- /* Write the security data. */
+
p = write_security_data(sd, buf);
- #else
- p = put_u32(buf, 8); /* Total length of security data. */
- p = put_u32(p, 0); /* Number of security data entries. */
- #endif
DEBUG("Writing dentry tree.");
p = write_dentry_tree(root, p);
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;
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;
+
+ 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) */
return WIMLIB_ERR_OPEN;
}
- if (w->verbose)
- puts(lte->file_on_disk);
-
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) */
}
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;
+}
+