]> wimlib.net Git - wimlib/blobdiff - src/resource.c
WIMBoot: Update WimOverlay.dat directly when WOF not running
[wimlib] / src / resource.c
index 6e47dff71da9c932f73d1cc89c14412d314f530c..b45db5973a9e261dfb316e0c355dbee04ce5f130 100644 (file)
 #endif
 
 #include "wimlib.h"
+#include "wimlib/assert.h"
 #include "wimlib/endianness.h"
 #include "wimlib/error.h"
 #include "wimlib/file_io.h"
 #include "wimlib/lookup_table.h"
 #include "wimlib/resource.h"
 #include "wimlib/sha1.h"
+#include "wimlib/wim.h"
 
 #ifdef __WIN32__
 /* for read_win32_file_prefix(), read_win32_encrypted_file_prefix() */
@@ -175,37 +177,21 @@ read_compressed_wim_resource(const struct wim_resource_spec * const rspec,
 
        /* Get the maximum size of uncompressed chunks in this resource, which
         * we require be a power of 2.  */
-       u32 chunk_size = 0;
        u64 cur_read_offset = rspec->offset_in_wim;
-       int ctype = WIMLIB_COMPRESSION_TYPE_NONE;
+       int ctype = rspec->compression_type;
+       u32 chunk_size = rspec->chunk_size;
        if (alt_chunk_table) {
                /* Alternate chunk table format.  Its header specifies the chunk
-                * size and compression format.  */
-               struct alt_chunk_table_header_disk hdr;
-
-               ret = full_pread(in_fd, &hdr, sizeof(hdr), cur_read_offset);
-               if (ret)
-                       goto read_error;
-               cur_read_offset += sizeof(hdr);
-
-               chunk_size = le32_to_cpu(hdr.chunk_size);
-               ctype = le32_to_cpu(hdr.compression_format);
-
-               /* Format numbers must be the same as in WIMGAPI to be
-                * compatible.  */
-               BUILD_BUG_ON(WIMLIB_COMPRESSION_TYPE_NONE != 0);
-               BUILD_BUG_ON(WIMLIB_COMPRESSION_TYPE_LZX != 1);
-               BUILD_BUG_ON(WIMLIB_COMPRESSION_TYPE_XPRESS != 2);
-               BUILD_BUG_ON(WIMLIB_COMPRESSION_TYPE_LZMS != 3);
-       } else {
-               /* "Normal" format: the maximum uncompressed chunk size and the
-                * compression format default to those of the WIM itself.  */
-               chunk_size = rspec->wim->chunk_size;
-               ctype = rspec->wim->compression_type;
+                * size and compression format.  Note: it could be read here;
+                * however, the relevant data was already loaded into @rspec by
+                * read_wim_lookup_table().  */
+               cur_read_offset += sizeof(struct alt_chunk_table_header_disk);
        }
+
        if (!is_power_of_2(chunk_size)) {
                ERROR("Invalid compressed resource: "
-                     "expected power-of-2 chunk size (got %u)", chunk_size);
+                     "expected power-of-2 chunk size (got %"PRIu32")",
+                     chunk_size);
                ret = WIMLIB_ERR_INVALID_CHUNK_SIZE;
                goto out_free_memory;
        }
@@ -892,6 +878,34 @@ wim_reshdr_to_data(const struct wim_reshdr *reshdr, WIMStruct *wim, void **buf_r
        return wim_resource_spec_to_data(&rspec, buf_ret);
 }
 
+int
+wim_reshdr_to_hash(const struct wim_reshdr *reshdr, WIMStruct *wim,
+                  u8 hash[SHA1_HASH_SIZE])
+{
+       struct wim_resource_spec rspec;
+       int ret;
+       struct wim_lookup_table_entry *lte;
+
+       wim_res_hdr_to_spec(reshdr, wim, &rspec);
+
+       lte = new_lookup_table_entry();
+       if (lte == NULL)
+               return WIMLIB_ERR_NOMEM;
+
+       lte_bind_wim_resource_spec(lte, &rspec);
+       lte->flags = rspec.flags;
+       lte->size = rspec.uncompressed_size;
+       lte->offset_in_res = 0;
+       lte->unhashed = 1;
+
+       ret = sha1_stream(lte);
+
+       lte_unbind_wim_resource_spec(lte);
+       copy_hash(hash, lte->hash);
+       free_lookup_table_entry(lte);
+       return ret;
+}
+
 struct streamifier_context {
        struct read_stream_list_callbacks cbs;
        struct wim_lookup_table_entry *cur_stream;
@@ -1005,6 +1019,13 @@ hasher_consume_chunk(const void *chunk, size_t size, void *_ctx)
                return (*ctx->cbs.consume_chunk)(chunk, size, ctx->cbs.consume_chunk_ctx);
 }
 
+static void
+get_sha1_string(const u8 md[SHA1_HASH_SIZE], tchar *str)
+{
+       for (size_t i = 0; i < SHA1_HASH_SIZE; i++)
+               str += tsprintf(str, T("%02x"), md[i]);
+}
+
 /* Callback for finishing reading a stream while calculating its SHA1 message
  * digest.  */
 static int
@@ -1037,9 +1058,14 @@ hasher_end_stream(struct wim_lookup_table_entry *lte, int status, void *_ctx)
                         * that it is the same as the calculated value.  */
                        if (!hashes_equal(hash, lte->hash)) {
                                if (wimlib_print_errors) {
-                                       ERROR("Invalid SHA1 message digest "
-                                             "on the following WIM stream:");
-                                       print_lookup_table_entry(lte, stderr);
+                                       tchar expected_hashstr[SHA1_HASH_SIZE * 2 + 1];
+                                       tchar actual_hashstr[SHA1_HASH_SIZE * 2 + 1];
+                                       get_sha1_string(lte->hash, expected_hashstr);
+                                       get_sha1_string(hash, actual_hashstr);
+                                       ERROR("The stream is corrupted!\n"
+                                             "        (Expected SHA1=%"TS",\n"
+                                             "              got SHA1=%"TS")",
+                                             expected_hashstr, actual_hashstr);
                                }
                                ret = WIMLIB_ERR_INVALID_RESOURCE_HASH;
                                errno = EINVAL;
@@ -1377,7 +1403,10 @@ sha1_stream(struct wim_lookup_table_entry *lte)
 }
 
 /* Convert a short WIM resource header to a stand-alone WIM resource
- * specification.  */
+ * specification.
+ *
+ * Note: for packed resources some fields still need to be overridden.
+ */
 void
 wim_res_hdr_to_spec(const struct wim_reshdr *reshdr, WIMStruct *wim,
                    struct wim_resource_spec *rspec)
@@ -1389,6 +1418,13 @@ wim_res_hdr_to_spec(const struct wim_reshdr *reshdr, WIMStruct *wim,
        INIT_LIST_HEAD(&rspec->stream_list);
        rspec->flags = reshdr->flags;
        rspec->is_pipable = wim_is_pipable(wim);
+       if (rspec->flags & WIM_RESHDR_FLAG_COMPRESSED) {
+               rspec->compression_type = wim->compression_type;
+               rspec->chunk_size = wim->chunk_size;
+       } else {
+               rspec->compression_type = WIMLIB_COMPRESSION_TYPE_NONE;
+               rspec->chunk_size = 0;
+       }
 }
 
 /* Convert a stand-alone resource specification to a WIM resource header.  */