]> wimlib.net Git - wimlib/blobdiff - src/resource.c
Update version to 1.4.2
[wimlib] / src / resource.c
index 38f005fa682246036fafb783551f134183a65db0..8705cb1d582d01e19741052fb8e6154216f77ddc 100644 (file)
@@ -97,8 +97,8 @@ read_compressed_resource(int in_fd,
 
        /* Calculate how many chunks the resource consists of in its entirety.
         * */
-       u64 num_chunks = (resource_uncompressed_size + WIM_CHUNK_SIZE - 1) /
-                                                               WIM_CHUNK_SIZE;
+       u64 num_chunks = DIV_ROUND_UP(resource_uncompressed_size, WIM_CHUNK_SIZE);
+
        /* As mentioned, the first chunk has no entry in the chunk table. */
        u64 num_chunk_entries = num_chunks - 1;
 
@@ -123,11 +123,20 @@ read_compressed_resource(int in_fd,
        if (end_chunk != num_chunks - 1)
                num_needed_chunks++;
 
+       /* According to M$'s documentation, if the uncompressed size of
+        * the file is greater than 4 GB, the chunk entries are 8-byte
+        * integers.  Otherwise, they are 4-byte integers. */
+       u64 chunk_entry_size = (resource_uncompressed_size >
+                               (u64)1 << 32) ?  8 : 4;
+
+       /* Size of the full chunk table in the WIM file. */
+       u64 chunk_table_size = chunk_entry_size * num_chunk_entries;
+
        /* Allocate the chunk table.  It will only contain offsets for the
         * chunks that are actually needed for this read. */
        u64 *chunk_offsets;
        bool chunk_offsets_malloced;
-       if (num_needed_chunks < 1000) {
+       if (num_needed_chunks < 1024) {
                chunk_offsets = alloca(num_needed_chunks * sizeof(u64));
                chunk_offsets_malloced = false;
        } else {
@@ -151,14 +160,6 @@ read_compressed_resource(int in_fd,
        if (start_chunk == 0)
                chunk_offsets[0] = 0;
 
-       /* According to M$'s documentation, if the uncompressed size of
-        * the file is greater than 4 GB, the chunk entries are 8-byte
-        * integers.  Otherwise, they are 4-byte integers. */
-       u64 chunk_entry_size = (resource_uncompressed_size >= (u64)1 << 32) ?
-                                                                       8 : 4;
-
-       /* Size of the full chunk table in the WIM file. */
-       u64 chunk_table_size = chunk_entry_size * num_chunk_entries;
 
        /* Read the needed chunk offsets from the table in the WIM file. */
 
@@ -175,12 +176,30 @@ read_compressed_resource(int in_fd,
        u64 file_offset_of_needed_chunk_entries = resource_offset +
                                start_table_idx * chunk_entry_size;
 
+       /* Allocate a buffer into which to read the raw chunk entries. */
+       void *chunk_tab_buf;
+       bool chunk_tab_buf_malloced = false;
+
        /* Number of bytes we need to read from the chunk table. */
        size_t size = num_needed_chunk_entries * chunk_entry_size;
+       if ((u64)size != num_needed_chunk_entries * chunk_entry_size) {
+               ERROR("Compressed read request too large to fit into memory!");
+               ret = WIMLIB_ERR_NOMEM;
+               goto out;
+       }
 
-       /* Read the raw data into the end of the chunk_offsets array to
-        * avoid allocating another array. */
-       void *chunk_tab_buf = (void*)&chunk_offsets[num_needed_chunks] - size;
+       if (size < 4096) {
+               chunk_tab_buf = alloca(size);
+       } else {
+               chunk_tab_buf = malloc(size);
+               if (!chunk_tab_buf) {
+                       ERROR("Failed to allocate chunk table buffer of "
+                             "size %zu bytes", size);
+                       ret = WIMLIB_ERR_NOMEM;
+                       goto out;
+               }
+               chunk_tab_buf_malloced = true;
+       }
 
        if (full_pread(in_fd, chunk_tab_buf, size,
                       file_offset_of_needed_chunk_entries) != size)
@@ -194,17 +213,17 @@ read_compressed_resource(int in_fd,
                chunk_tab_p++;
 
        if (chunk_entry_size == 4) {
-               u32 *entries = (u32*)chunk_tab_buf;
+               le32 *entries = (le32*)chunk_tab_buf;
                while (num_needed_chunk_entries--)
                        *chunk_tab_p++ = le32_to_cpu(*entries++);
        } else {
-               u64 *entries = (u64*)chunk_tab_buf;
+               le64 *entries = (le64*)chunk_tab_buf;
                while (num_needed_chunk_entries--)
                        *chunk_tab_p++ = le64_to_cpu(*entries++);
        }
 
-       /* Done with the chunk table now.  We must now seek to the first chunk
-        * that is needed for the read. */
+       /* Done reading the chunk table now.  Now calculate the file offset for
+        * the first byte of compressed data we need to read. */
 
        u64 cur_read_offset = resource_offset + chunk_table_size + chunk_offsets[0];
 
@@ -348,6 +367,8 @@ read_compressed_resource(int in_fd,
 out:
        if (chunk_offsets_malloced)
                FREE(chunk_offsets);
+       if (chunk_tab_buf_malloced)
+               FREE(chunk_tab_buf);
        return ret;
 
 read_error:
@@ -439,7 +460,7 @@ read_partial_wim_resource(const struct wim_lookup_table_entry *lte,
                                               lte->resource_entry.size,
                                               lte->resource_entry.original_size,
                                               lte->resource_entry.offset,
-                                              wimlib_get_compression_type(wim),
+                                              wim->compression_type,
                                               size,
                                               offset,
                                               cb,
@@ -670,13 +691,13 @@ extract_wim_resource(const struct wim_lookup_table_entry *lte,
                        u8 hash[SHA1_HASH_SIZE];
                        sha1_final(hash, &ctx.sha_ctx);
                        if (!hashes_equal(hash, lte->hash)) {
-                       #ifdef ENABLE_ERROR_MESSAGES
-                               ERROR("Invalid SHA1 message digest "
-                                     "on the following WIM resource:");
-                               print_lookup_table_entry(lte, stderr);
-                               if (lte->resource_location == RESOURCE_IN_WIM)
-                                       ERROR("The WIM file appears to be corrupt!");
-                       #endif
+                               if (wimlib_print_errors) {
+                                       ERROR("Invalid SHA1 message digest "
+                                             "on the following WIM resource:");
+                                       print_lookup_table_entry(lte, stderr);
+                                       if (lte->resource_location == RESOURCE_IN_WIM)
+                                               ERROR("The WIM file appears to be corrupt!");
+                               }
                                ret = WIMLIB_ERR_INVALID_RESOURCE_HASH;
                        }
                }
@@ -733,8 +754,8 @@ sha1_resource(struct wim_lookup_table_entry *lte)
 
 /*
  * Copies the file resource specified by the lookup table entry @lte from the
- * input WIM to the output WIM that has its FILE * given by
- * ((WIMStruct*)wim)->out_fp.
+ * input WIM to the output WIM that has its output file descriptor given by
+ * ((WIMStruct*)_wim)->out_fd.
  *
  * The output_resource_entry, out_refcnt, and part_number fields of @lte are
  * updated.
@@ -742,17 +763,17 @@ sha1_resource(struct wim_lookup_table_entry *lte)
  * (This function is confusing and should be refactored somehow.)
  */
 int
-copy_resource(struct wim_lookup_table_entry *lte, void *wim)
+copy_resource(struct wim_lookup_table_entry *lte, void *_wim)
 {
-       WIMStruct *w = wim;
+       WIMStruct *wim = _wim;
        int ret;
 
-       ret = write_wim_resource(lte, w->out_fd,
+       ret = write_wim_resource(lte, wim->out_fd,
                                 wim_resource_compression_type(lte),
                                 &lte->output_resource_entry, 0);
        if (ret == 0) {
                lte->out_refcnt = lte->refcnt;
-               lte->part_number = w->hdr.part_number;
+               lte->part_number = wim->hdr.part_number;
        }
        return ret;
 }