]> wimlib.net Git - wimlib/blobdiff - src/resource.c
Various cleanups
[wimlib] / src / resource.c
index 9349c3ba0500384423f55daa223692e23db37195..49de59a482f3e5900dc14aa066101da918f344be 100644 (file)
@@ -401,7 +401,8 @@ int read_resource(FILE *fp, u64 resource_size, u64 resource_original_size,
                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, 
@@ -923,9 +924,8 @@ int read_metadata_resource(FILE *fp, int wim_ctype, struct image_metadata *imd)
        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;
 
@@ -965,12 +965,10 @@ int read_metadata_resource(FILE *fp, int wim_ctype, struct image_metadata *imd)
         * 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) {
@@ -993,27 +991,43 @@ 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;
 
-#ifdef ENABLE_SECURITY_DATA
+       DEBUG("Building link group table");
+       /* Build hash table that maps hard link group IDs to dentry sets */
+       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;
-#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;
@@ -1045,12 +1059,10 @@ int write_metadata_resource(WIMStruct *w)
        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;
@@ -1060,13 +1072,8 @@ int write_metadata_resource(WIMStruct *w)
                      "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);
@@ -1085,6 +1092,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);
@@ -1104,55 +1114,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) */
 
@@ -1165,14 +1176,12 @@ int write_file_resource(struct dentry *dentry, void *wim_p)
                        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) */
 
@@ -1202,3 +1211,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;
+}
+