]> wimlib.net Git - wimlib/blobdiff - src/resource.c
wimfs_write(), dentry_to_stbuf()
[wimlib] / src / resource.c
index 5e6707d97dee941d1514bf7a3accad3bac4ece7d..48f54804576a3d68fdb25d308fe4d8d26dc61e01 100644 (file)
@@ -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 = &lte->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 = &lte->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;
+}
+