From: Eric Biggers Date: Fri, 17 May 2013 18:01:51 +0000 (-0500) Subject: header.c, lookup_table.c: Read/write data from structures X-Git-Tag: v1.4.0~26 X-Git-Url: https://wimlib.net/git/?p=wimlib;a=commitdiff_plain;h=30ba1eb06caca0b20a47d8dd75a117c82d730da7;hp=2e44f90c21db693058037f83f92ad136c818ce9d header.c, lookup_table.c: Read/write data from structures --- diff --git a/include/wimlib/header.h b/include/wimlib/header.h index 151d6c78..b250381c 100644 --- a/include/wimlib/header.h +++ b/include/wimlib/header.h @@ -4,12 +4,10 @@ #include "wimlib/resource.h" #include "wimlib/types.h" -#define WIM_MAGIC_LEN 8 #define WIM_GID_LEN 16 -#define WIM_UNUSED_LEN 60 /* Length of the WIM header on disk. */ -#define WIM_HEADER_DISK_SIZE (148 + WIM_UNUSED_LEN) +#define WIM_HEADER_DISK_SIZE 208 /* Compressed resources in the WIM are divided into separated compressed chunks * of this size. */ @@ -19,29 +17,13 @@ * yet. The differences between the versions are undocumented. */ #define WIM_VERSION 0x10d00 -/* Header at the very beginning of the WIM file. */ +/* Header at the very beginning of the WIM file. This is the in-memory + * representation and does not include all fields; see `struct wim_header_disk' + * for the on-disk structure. */ struct wim_header { - /* Identifies the file as WIM file. Must be exactly - * {'M', 'S', 'W', 'I', 'M', 0, 0, 0} */ - //u8 magic[WIM_MAGIC_LEN]; - - /* size of WIM header in bytes. */ - //u32 hdr_size; - - /* Version of the WIM file. Microsoft provides no documentation about - * exactly what this field affects about the file format, other than the - * fact that more recent versions have a higher value. */ - //u32 version; - /* Bitwise OR of one or more of the WIM_HDR_FLAG_* defined below. */ u32 flags; - /* The size of the pieces that the uncompressed files were split up into - * when they were compressed. This should be the same as - * WIM_CHUNK_SIZE. Microsoft incorrectly documents this as "the size of - * the compressed .wim file in bytes".*/ - //u32 chunk_size; - /* A unique identifier for the WIM file. */ u8 guid[WIM_GID_LEN]; @@ -72,9 +54,6 @@ struct wim_header { /* The location of the optional integrity table used to verify the * integrity WIM. Zeroed out if there is no integrity table.*/ struct resource_entry integrity; - - /* Reserved for future disuse */ - //u8 unused[WIM_UNUSED_LEN]; }; /* Flags for the `flags' field of the struct wim_header: */ diff --git a/include/wimlib/resource.h b/include/wimlib/resource.h index 757531c9..c7598611 100644 --- a/include/wimlib/resource.h +++ b/include/wimlib/resource.h @@ -23,6 +23,12 @@ struct resource_entry { u64 original_size; }; +struct resource_entry_disk { + u8 size[7]; + u8 flags; + le64 offset; + le64 original_size; +} _packed_attribute; /* Flags for the `flags' field of the struct resource_entry structure. */ @@ -84,11 +90,13 @@ read_resource_prefix(const struct wim_lookup_table_entry *lte, u64 size, consume_data_callback_t cb, void *ctx_or_buf, int flags); -extern const void * -get_resource_entry(const void *p, struct resource_entry *entry); +extern void +get_resource_entry(const struct resource_entry_disk *disk_entry, + struct resource_entry *entry); -extern void * -put_resource_entry(void *p, const struct resource_entry *entry); +extern void +put_resource_entry(const struct resource_entry *entry, + struct resource_entry_disk *disk_entry); extern int read_partial_wim_resource_into_buf(const struct wim_lookup_table_entry *lte, diff --git a/include/wimlib/sha1.h b/include/wimlib/sha1.h index 1f7c50f7..76e6d5e1 100644 --- a/include/wimlib/sha1.h +++ b/include/wimlib/sha1.h @@ -22,17 +22,16 @@ random_hash(u8 hash[SHA1_HASH_SIZE]) randomize_byte_array(hash, SHA1_HASH_SIZE); } -static inline bool -hashes_equal(const u8 h1[SHA1_HASH_SIZE], const u8 h2[SHA1_HASH_SIZE]) +static inline int +hashes_cmp(const u8 h1[SHA1_HASH_SIZE], const u8 h2[SHA1_HASH_SIZE]) { - return memcmp(h1, h2, SHA1_HASH_SIZE) == 0; + return memcmp(h1, h2, SHA1_HASH_SIZE); } -static inline int -hashes_cmp(const u8 h1[SHA1_HASH_SIZE], - const u8 h2[SHA1_HASH_SIZE]) +static inline bool +hashes_equal(const u8 h1[SHA1_HASH_SIZE], const u8 h2[SHA1_HASH_SIZE]) { - return memcmp(h1, h2, SHA1_HASH_SIZE); + return !hashes_cmp(h1, h2); } static inline void @@ -42,22 +41,19 @@ print_hash(const u8 hash[SHA1_HASH_SIZE], FILE *out) } static inline bool -is_zero_hash(const u8 hash[SHA1_HASH_SIZE]) +is_zero_hash(const u8 *hash) { - if (hash) - for (u8 i = 0; i < SHA1_HASH_SIZE / 4; i++) - if (((const u32*)hash)[i]) - return false; - return true; + if (!hash) + return true; + return hashes_equal(hash, zero_hash); } static inline void zero_out_hash(u8 hash[SHA1_HASH_SIZE]) { - memset(hash, 0, SHA1_HASH_SIZE); + copy_hash(hash, zero_hash); } - #ifdef WITH_LIBCRYPTO #include diff --git a/src/header.c b/src/header.c index c0518ecb..0066d75a 100644 --- a/src/header.c +++ b/src/header.c @@ -29,7 +29,7 @@ #include "wimlib.h" #include "wimlib/assert.h" -#include "wimlib/buffer_io.h" +#include "wimlib/endianness.h" #include "wimlib/error.h" #include "wimlib/file_io.h" #include "wimlib/header.h" @@ -37,73 +37,131 @@ #include "wimlib/wim.h" #include +#include + +/* WIM magic characters, translated to a single 64-bit little endian number. */ +#define WIM_MAGIC \ + cpu_to_le64(((u64)'M' << 0) | \ + ((u64)'S' << 8) | \ + ((u64)'W' << 16) | \ + ((u64)'I' << 24) | \ + ((u64)'M' << 32) | \ + ((u64)'\0' << 40) | \ + ((u64)'\0' << 48) | \ + ((u64)'\0' << 54)) + +/* On-disk format of the WIM header. */ +struct wim_header_disk { + + /* Magic characters "MSWIM\0\0\0" */ + le64 magic; + + /* Size of the WIM header, in bytes; WIM_HEADER_DISK_SIZE expected + * (currently the only supported value). */ + u32 hdr_size; + + /* Version of the WIM file; WIM_VERSION expected (currently the only + * supported value). */ + u32 wim_version; + + /* Flags for the WIM file (WIM_HDR_FLAG_*) */ + u32 wim_flags; + + /* Uncompressed chunk size of resources in the WIM. 0 if the WIM is + * uncompressed. If compressed, WIM_CHUNK_SIZE is expected (currently + * the only supported value). */ + u32 chunk_size; + + /* Globally unique identifier for the WIM file. Basically bunch of + * random bytes. */ + u8 guid[WIM_GID_LEN]; + + /* Number of this WIM part in the split WIM file, indexed from 1, or 1 + * if the WIM is not split. */ + u16 part_number; + + /* Total number of parts of the split WIM file, or 1 if the WIM is not + * split. */ + u16 total_parts; + + /* Number of images in the WIM. */ + u32 image_count; + + /* Location and size of the WIM's lookup table. */ + struct resource_entry_disk lookup_table_res_entry; + + /* Location and size of the WIM's XML data. */ + struct resource_entry_disk xml_data_res_entry; + + /* Location and size of metadata resource for the bootable image of the + * WIM, or all zeroes if no image is bootable. */ + struct resource_entry_disk boot_metadata_res_entry; + + /* 1-based index of the bootable image of the WIM, or 0 if no image is + * bootable. */ + u32 boot_idx; + + /* Location and size of the WIM's integrity table, or all zeroes if the + * WIM has no integrity table. */ + + /* Note the integrity_table_res_entry here is 4-byte aligned even though + * it would ordinarily be 8-byte aligned--- hence, the _packed_attribute + * on the `struct wim_header_disk' is essential. */ + struct resource_entry_disk integrity_table_res_entry; -/* First 8 bytes in every WIM file. */ -static const u8 wim_magic_chars[WIM_MAGIC_LEN] = { - 'M', 'S', 'W', 'I', 'M', '\0', '\0', '\0' }; + /* Unused bytes. */ + u8 unused[60]; +} _packed_attribute; /* Reads the header from a WIM file. */ int read_header(const tchar *filename, int in_fd, struct wim_header *hdr, int open_flags) { - size_t bytes_read; - u8 buf[WIM_HEADER_DISK_SIZE]; - const void *p; + struct wim_header_disk disk_hdr _aligned_attribute(8); - u32 hdr_size; - u32 wim_version; - u32 chunk_size; - - DEBUG("Reading WIM header from \"%"TS"\".", filename); + DEBUG("Reading WIM header from \"%"TS"\"", filename); - bytes_read = full_pread(in_fd, buf, WIM_HEADER_DISK_SIZE, 0); - - if (bytes_read != WIM_HEADER_DISK_SIZE) { + if (full_pread(in_fd, &disk_hdr, sizeof(disk_hdr), 0) != sizeof(disk_hdr)) { ERROR_WITH_ERRNO("\"%"TS"\": Error reading header", filename); return WIMLIB_ERR_READ; } - p = buf; - if (memcmp(p, wim_magic_chars, WIM_MAGIC_LEN)) { + if (disk_hdr.magic != WIM_MAGIC) { ERROR("\"%"TS"\": Invalid magic characters in header", filename); return WIMLIB_ERR_NOT_A_WIM_FILE; } - /* Byte 8 */ - p = get_u32(p + 8, &hdr_size); - if (hdr_size != WIM_HEADER_DISK_SIZE) { - ERROR("\"%"TS"\": Header is %u bytes (expected %u bytes)", - filename, hdr_size, WIM_HEADER_DISK_SIZE); + BUILD_BUG_ON(sizeof(struct wim_header_disk) != WIM_HEADER_DISK_SIZE); + if (le32_to_cpu(disk_hdr.hdr_size) != sizeof(struct wim_header_disk)) { + ERROR("\"%"TS"\": Header size is invalid (%u bytes)", + filename, le32_to_cpu(disk_hdr.hdr_size)); return WIMLIB_ERR_INVALID_HEADER_SIZE; } - /* Byte 12 */ - p = get_u32(buf + WIM_MAGIC_LEN + sizeof(u32), &wim_version); - if (wim_version != WIM_VERSION) { + if (le32_to_cpu(disk_hdr.wim_version) != WIM_VERSION) { ERROR("\"%"TS"\": The WIM header says the WIM version is %u, " "but wimlib only knows about version %u", - filename, wim_version, WIM_VERSION); + filename, le32_to_cpu(disk_hdr.wim_version), WIM_VERSION); return WIMLIB_ERR_UNKNOWN_VERSION; } - p = get_u32(p, &hdr->flags); - p = get_u32(p, &chunk_size); - if (chunk_size != WIM_CHUNK_SIZE && + hdr->flags = le32_to_cpu(disk_hdr.wim_flags); + if (le32_to_cpu(disk_hdr.chunk_size) != WIM_CHUNK_SIZE && (hdr->flags & WIM_HDR_FLAG_COMPRESSION)) { ERROR("\"%"TS"\": Unexpected chunk size of %u! Ask the author to " "implement support for other chunk sizes.", - filename, chunk_size); + filename, le32_to_cpu(disk_hdr.chunk_size)); ERROR("(Or it might just be that the WIM header is invalid.)"); return WIMLIB_ERR_INVALID_CHUNK_SIZE; } - p = get_bytes(p, WIM_GID_LEN, hdr->guid); - p = get_u16(p, &hdr->part_number); - p = get_u16(p, &hdr->total_parts); + memcpy(hdr->guid, disk_hdr.guid, WIM_GID_LEN); + + hdr->part_number = le16_to_cpu(disk_hdr.part_number); + hdr->total_parts = le16_to_cpu(disk_hdr.total_parts); - if (hdr->total_parts == 0 || - hdr->part_number == 0 || + if (hdr->total_parts == 0 || hdr->part_number == 0 || hdr->part_number > hdr->total_parts) { ERROR("\"%"TS"\": Invalid WIM part number: %hu of %hu", @@ -111,15 +169,14 @@ read_header(const tchar *filename, int in_fd, return WIMLIB_ERR_INVALID_PART_NUMBER; } - if (!(open_flags & WIMLIB_OPEN_FLAG_SPLIT_OK) && - hdr->total_parts != 1) + if (!(open_flags & WIMLIB_OPEN_FLAG_SPLIT_OK) && hdr->total_parts != 1) { ERROR("\"%"TS"\": This WIM is part %u of a %u-part WIM", filename, hdr->part_number, hdr->total_parts); return WIMLIB_ERR_SPLIT_UNSUPPORTED; } - p = get_u32(p, &hdr->image_count); + hdr->image_count = le32_to_cpu(disk_hdr.image_count); DEBUG("part_number = %u, total_parts = %u, image_count = %u", hdr->part_number, hdr->total_parts, hdr->image_count); @@ -130,26 +187,11 @@ read_header(const tchar *filename, int in_fd, return WIMLIB_ERR_IMAGE_COUNT; } - /* Byte 48 */ - - p = get_resource_entry(p, &hdr->lookup_table_res_entry); - p = get_resource_entry(p, &hdr->xml_res_entry); - p = get_resource_entry(p, &hdr->boot_metadata_res_entry); - - /* Byte 120 */ - - p = get_u32(p, &hdr->boot_idx); - - /* Byte 124 */ - - p = get_resource_entry(p, &hdr->integrity); - - /* Byte 148 */ - - /* 60 bytes of unused stuff. */ - - /* Byte 208 */ - + get_resource_entry(&disk_hdr.lookup_table_res_entry, &hdr->lookup_table_res_entry); + get_resource_entry(&disk_hdr.xml_data_res_entry, &hdr->xml_res_entry); + get_resource_entry(&disk_hdr.boot_metadata_res_entry, &hdr->boot_metadata_res_entry); + hdr->boot_idx = le32_to_cpu(disk_hdr.boot_idx); + get_resource_entry(&disk_hdr.integrity_table_res_entry, &hdr->integrity); return 0; } @@ -164,34 +206,28 @@ read_header(const tchar *filename, int in_fd, int write_header(const struct wim_header *hdr, int out_fd) { - u8 buf[WIM_HEADER_DISK_SIZE]; - u8 *p; + struct wim_header_disk disk_hdr _aligned_attribute(8); DEBUG("Writing WIM header."); - p = put_bytes(buf, WIM_MAGIC_LEN, wim_magic_chars); - p = put_u32(p, WIM_HEADER_DISK_SIZE); - p = put_u32(p, WIM_VERSION); - p = put_u32(p, hdr->flags); - p = put_u32(p, (hdr->flags & WIM_HDR_FLAG_COMPRESSION) ? - WIM_CHUNK_SIZE : 0); - /* Byte 24 */ - - p = put_bytes(p, WIM_GID_LEN, hdr->guid); - p = put_u16(p, hdr->part_number); - - /* Byte 40 */ - - p = put_u16(p, hdr->total_parts); - p = put_u32(p, hdr->image_count); - p = put_resource_entry(p, &hdr->lookup_table_res_entry); - p = put_resource_entry(p, &hdr->xml_res_entry); - p = put_resource_entry(p, &hdr->boot_metadata_res_entry); - p = put_u32(p, hdr->boot_idx); - p = put_resource_entry(p, &hdr->integrity); - p = put_zeroes(p, WIM_UNUSED_LEN); - wimlib_assert(p - buf == sizeof(buf)); - - if (full_pwrite(out_fd, buf, sizeof(buf), 0) != sizeof(buf)) { + disk_hdr.magic = WIM_MAGIC; + disk_hdr.hdr_size = cpu_to_le32(sizeof(struct wim_header_disk)); + disk_hdr.wim_version = cpu_to_le32(WIM_VERSION); + disk_hdr.wim_flags = cpu_to_le32(hdr->flags); + disk_hdr.chunk_size = cpu_to_le32((hdr->flags & WIM_HDR_FLAG_COMPRESSION) ? + WIM_CHUNK_SIZE : 0); + memcpy(disk_hdr.guid, hdr->guid, WIM_GID_LEN); + + disk_hdr.part_number = cpu_to_le16(hdr->part_number); + disk_hdr.total_parts = cpu_to_le16(hdr->total_parts); + disk_hdr.image_count = cpu_to_le32(hdr->image_count); + put_resource_entry(&hdr->lookup_table_res_entry, &disk_hdr.lookup_table_res_entry); + put_resource_entry(&hdr->xml_res_entry, &disk_hdr.xml_data_res_entry); + put_resource_entry(&hdr->boot_metadata_res_entry, &disk_hdr.boot_metadata_res_entry); + disk_hdr.boot_idx = cpu_to_le32(hdr->boot_idx); + put_resource_entry(&hdr->integrity, &disk_hdr.integrity_table_res_entry); + memset(disk_hdr.unused, 0, sizeof(disk_hdr.unused)); + + if (full_pwrite(out_fd, &disk_hdr, sizeof(disk_hdr), 0) != sizeof(disk_hdr)) { ERROR_WITH_ERRNO("Failed to write WIM header"); return WIMLIB_ERR_WRITE; } diff --git a/src/lookup_table.c b/src/lookup_table.c index 2e45f8f5..95708866 100644 --- a/src/lookup_table.c +++ b/src/lookup_table.c @@ -28,7 +28,7 @@ # include "config.h" #endif -#include "wimlib/buffer_io.h" +#include "wimlib/endianness.h" #include "wimlib/error.h" #include "wimlib/file_io.h" #include "wimlib/lookup_table.h" @@ -348,9 +348,22 @@ for_lookup_table_entry_pos_sorted(struct wim_lookup_table *table, return ret; } +/* On-disk format of a WIM lookup table entry (stream entry). */ +struct wim_lookup_table_entry_disk { + /* Location, offset, compression status, and metadata status of the + * stream. */ + struct resource_entry_disk resource_entry; -/* Size of each lookup table entry in the WIM file. */ -#define WIM_LOOKUP_TABLE_ENTRY_DISK_SIZE 50 + /* Which part of the split WIM this stream is in; indexed from 1. */ + u16 part_number; + + /* Reference count of this stream over all WIM images. */ + u32 refcnt; + + /* SHA1 message digest of the uncompressed data of this stream, or + * optionally all zeroes if this stream is of zero length. */ + u8 hash[SHA1_HASH_SIZE]; +} _packed_attribute; /* * Reads the lookup table from a WIM file. @@ -366,11 +379,12 @@ read_lookup_table(WIMStruct *w) size_t num_entries; struct wim_lookup_table *table; struct wim_lookup_table_entry *cur_entry, *duplicate_entry; - u8 table_buf[(BUFFER_SIZE / WIM_LOOKUP_TABLE_ENTRY_DISK_SIZE) * - WIM_LOOKUP_TABLE_ENTRY_DISK_SIZE]; - const u8 *p; + struct wim_lookup_table_entry_disk + table_buf[BUFFER_SIZE / sizeof(struct wim_lookup_table_entry_disk)] + _aligned_attribute(8); off_t offset; size_t buf_entries_remaining; + const struct wim_lookup_table_entry_disk *disk_entry; DEBUG("Reading lookup table: offset %"PRIu64", size %"PRIu64"", w->hdr.lookup_table_res_entry.offset, @@ -383,7 +397,7 @@ read_lookup_table(WIMStruct *w) } num_entries = w->hdr.lookup_table_res_entry.size / - WIM_LOOKUP_TABLE_ENTRY_DISK_SIZE; + sizeof(struct wim_lookup_table_entry_disk); table = new_lookup_table(num_entries * 2 + 1); if (!table) return WIMLIB_ERR_NOMEM; @@ -391,15 +405,14 @@ read_lookup_table(WIMStruct *w) w->current_image = 0; offset = w->hdr.lookup_table_res_entry.offset; buf_entries_remaining = 0; - for (; num_entries != 0; num_entries--, buf_entries_remaining--) { + for (; num_entries != 0; + num_entries--, buf_entries_remaining--, disk_entry++) + { if (buf_entries_remaining == 0) { size_t entries_to_read, bytes_to_read; - entries_to_read = min(sizeof(table_buf) / - WIM_LOOKUP_TABLE_ENTRY_DISK_SIZE, - num_entries); - bytes_to_read = entries_to_read * - WIM_LOOKUP_TABLE_ENTRY_DISK_SIZE; + entries_to_read = min(ARRAY_LEN(table_buf), num_entries); + bytes_to_read = entries_to_read * sizeof(struct wim_lookup_table_entry_disk); if (full_pread(w->in_fd, table_buf, bytes_to_read, offset) != bytes_to_read) { @@ -409,7 +422,7 @@ read_lookup_table(WIMStruct *w) goto out_free_lookup_table; } offset += bytes_to_read; - p = table_buf; + disk_entry = table_buf; buf_entries_remaining = entries_to_read; } cur_entry = new_lookup_table_entry(); @@ -420,10 +433,10 @@ read_lookup_table(WIMStruct *w) cur_entry->wim = w; cur_entry->resource_location = RESOURCE_IN_WIM; - p = get_resource_entry(p, &cur_entry->resource_entry); - p = get_u16(p, &cur_entry->part_number); - p = get_u32(p, &cur_entry->refcnt); - p = get_bytes(p, SHA1_HASH_SIZE, cur_entry->hash); + get_resource_entry(&disk_entry->resource_entry, &cur_entry->resource_entry); + cur_entry->part_number = le16_to_cpu(disk_entry->part_number); + cur_entry->refcnt = le32_to_cpu(disk_entry->refcnt); + copy_hash(cur_entry->hash, disk_entry->hash); if (cur_entry->part_number != w->hdr.part_number) { ERROR("A lookup table entry in part %hu of the WIM " @@ -534,14 +547,14 @@ out: } -static u8 * -write_lookup_table_entry(const struct wim_lookup_table_entry *lte, u8 *buf_p) +static void +write_lookup_table_entry(const struct wim_lookup_table_entry *lte, + struct wim_lookup_table_entry_disk *disk_entry) { - buf_p = put_resource_entry(buf_p, <e->output_resource_entry); - buf_p = put_u16(buf_p, lte->part_number); - buf_p = put_u32(buf_p, lte->out_refcnt); - buf_p = put_bytes(buf_p, SHA1_HASH_SIZE, lte->hash); - return buf_p; + put_resource_entry(<e->output_resource_entry, &disk_entry->resource_entry); + disk_entry->part_number = cpu_to_le16(lte->part_number); + disk_entry->refcnt = cpu_to_le32(lte->out_refcnt); + copy_hash(disk_entry->hash, lte->hash); } int @@ -551,32 +564,34 @@ write_lookup_table_from_stream_list(struct list_head *stream_list, { int ret; off_t start_offset; - u8 table_buf[(BUFFER_SIZE / WIM_LOOKUP_TABLE_ENTRY_DISK_SIZE) * - WIM_LOOKUP_TABLE_ENTRY_DISK_SIZE]; - u8 *buf_p; + struct wim_lookup_table_entry_disk + table_buf[BUFFER_SIZE / sizeof(struct wim_lookup_table_entry_disk)] + _aligned_attribute(8); size_t table_size; size_t bytes_to_write; struct wim_lookup_table_entry *lte; + size_t cur_idx; start_offset = filedes_offset(out_fd); if (start_offset == -1) goto write_error; - buf_p = table_buf; table_size = 0; + cur_idx = 0; list_for_each_entry(lte, stream_list, lookup_table_list) { - if (buf_p == table_buf + sizeof(table_buf)) { + if (cur_idx == ARRAY_LEN(table_buf)) { bytes_to_write = sizeof(table_buf); if (full_write(out_fd, table_buf, bytes_to_write) != bytes_to_write) goto write_error; table_size += bytes_to_write; - buf_p = table_buf; + cur_idx = 0; } - buf_p = write_lookup_table_entry(lte, buf_p); + write_lookup_table_entry(lte, &table_buf[cur_idx]); + cur_idx++; } - bytes_to_write = buf_p - table_buf; - if (bytes_to_write != 0) { + if (cur_idx != 0) { + bytes_to_write = cur_idx * sizeof(struct wim_lookup_table_entry_disk); if (full_write(out_fd, table_buf, bytes_to_write) != bytes_to_write) goto write_error; diff --git a/src/metadata_resource.c b/src/metadata_resource.c index 5b22ab6d..13ebf51f 100644 --- a/src/metadata_resource.c +++ b/src/metadata_resource.c @@ -59,7 +59,6 @@ read_metadata_resource(WIMStruct *wim, struct wim_image_metadata *imd) struct wim_dentry *root; const struct wim_lookup_table_entry *metadata_lte; u64 metadata_len; - struct wim_security_data *security_data; metadata_lte = imd->metadata_lte; metadata_len = wim_resource_size(metadata_lte); @@ -114,7 +113,7 @@ read_metadata_resource(WIMStruct *wim, struct wim_image_metadata *imd) * and calculate the offset in the metadata resource of the root dentry. * */ - ret = read_wim_security_data(buf, metadata_len, &security_data); + ret = read_wim_security_data(buf, metadata_len, &imd->security_data); if (ret) goto out_free_buf; @@ -128,7 +127,7 @@ read_metadata_resource(WIMStruct *wim, struct wim_image_metadata *imd) } ret = read_dentry(buf, metadata_len, - security_data->total_length, root); + imd->security_data->total_length, root); if (ret == 0 && root->length == 0) { ERROR("Metadata resource cannot begin with end-of-directory entry!"); @@ -157,6 +156,8 @@ read_metadata_resource(WIMStruct *wim, struct wim_image_metadata *imd) goto out_free_dentry_tree; if (!wim->all_images_verified) { + /* Note: verify_dentry() expects to access imd->security_data, + * so it needs to be set before here. */ DEBUG("Running miscellaneous verifications on the dentry tree"); for_lookup_table_entry(wim->lookup_table, lte_zero_real_refcnt, NULL); ret = for_dentry_in_tree(root, verify_dentry, wim); @@ -167,13 +168,13 @@ read_metadata_resource(WIMStruct *wim, struct wim_image_metadata *imd) DEBUG("Done reading image metadata"); imd->root_dentry = root; - imd->security_data = security_data; INIT_LIST_HEAD(&imd->unhashed_streams); goto out_free_buf; out_free_dentry_tree: free_dentry_tree(root, wim->lookup_table); out_free_security_data: - free_wim_security_data(security_data); + free_wim_security_data(imd->security_data); + imd->security_data = NULL; out_free_buf: FREE(buf); return ret; diff --git a/src/resource.c b/src/resource.c index 9192062f..38f005fa 100644 --- a/src/resource.c +++ b/src/resource.c @@ -27,8 +27,8 @@ #endif #include "wimlib.h" -#include "wimlib/buffer_io.h" #include "wimlib/dentry.h" +#include "wimlib/endianness.h" #include "wimlib/error.h" #include "wimlib/file_io.h" #include "wimlib/lookup_table.h" @@ -356,48 +356,63 @@ read_error: goto out; } -/* Reads the contents of a struct resource_entry, as represented in the on-disk - * format, from the memory pointed to by @p, and fills in the fields of @entry. - * A pointer to the byte after the memory read at @p is returned. */ -const void * -get_resource_entry(const void *p, struct resource_entry *entry) +/* Translates a WIM resource entry from the on-disk format to an in-memory + * format. */ +void +get_resource_entry(const struct resource_entry_disk *disk_entry, + struct resource_entry *entry) { - u64 size; - u8 flags; - - p = get_u56(p, &size); - p = get_u8(p, &flags); - entry->size = size; - entry->flags = flags; + /* Note: disk_entry may not be 8 byte aligned--- in that case, the + * offset and original_size members will be unaligned. (This should be + * okay since `struct resource_entry_disk' is declared as packed.) */ + + /* Read the size and flags into a bitfield portably... */ + entry->size = (((u64)disk_entry->size[0] << 0) | + ((u64)disk_entry->size[1] << 8) | + ((u64)disk_entry->size[2] << 16) | + ((u64)disk_entry->size[3] << 24) | + ((u64)disk_entry->size[4] << 32) | + ((u64)disk_entry->size[5] << 40) | + ((u64)disk_entry->size[6] << 48)); + entry->flags = disk_entry->flags; + entry->offset = le64_to_cpu(disk_entry->offset); + entry->original_size = le64_to_cpu(disk_entry->original_size); /* offset and original_size are truncated to 62 bits to avoid possible * overflows, when converting to a signed 64-bit integer (off_t) or when * adding size or original_size. This is okay since no one would ever * actually have a WIM bigger than 4611686018427387903 bytes... */ - p = get_u64(p, &entry->offset); if (entry->offset & 0xc000000000000000ULL) { WARNING("Truncating offset in resource entry"); entry->offset &= 0x3fffffffffffffffULL; } - p = get_u64(p, &entry->original_size); if (entry->original_size & 0xc000000000000000ULL) { WARNING("Truncating original_size in resource entry"); entry->original_size &= 0x3fffffffffffffffULL; } - return p; } -/* Copies the struct resource_entry @entry to the memory pointed to by @p in the - * on-disk format. A pointer to the byte after the memory written at @p is - * returned. */ -void * -put_resource_entry(void *p, const struct resource_entry *entry) +/* Translates a WIM resource entry from an in-memory format into the on-disk + * format. */ +void +put_resource_entry(const struct resource_entry *entry, + struct resource_entry_disk *disk_entry) { - p = put_u56(p, entry->size); - p = put_u8(p, entry->flags); - p = put_u64(p, entry->offset); - p = put_u64(p, entry->original_size); - return p; + /* Note: disk_entry may not be 8 byte aligned--- in that case, the + * offset and original_size members will be unaligned. (This should be + * okay since `struct resource_entry_disk' is declared as packed.) */ + u64 size = entry->size; + + disk_entry->size[0] = size >> 0; + disk_entry->size[1] = size >> 8; + disk_entry->size[2] = size >> 16; + disk_entry->size[3] = size >> 24; + disk_entry->size[4] = size >> 32; + disk_entry->size[5] = size >> 40; + disk_entry->size[6] = size >> 48; + disk_entry->flags = entry->flags; + disk_entry->offset = cpu_to_le64(entry->offset); + disk_entry->original_size = cpu_to_le64(entry->original_size); } static int diff --git a/src/split.c b/src/split.c index 05a7beeb..78dc8ab7 100644 --- a/src/split.c +++ b/src/split.c @@ -28,7 +28,7 @@ #endif #include "wimlib.h" -#include "wimlib/buffer_io.h" +#include "wimlib/endianness.h" #include "wimlib/error.h" #include "wimlib/file_io.h" #include "wimlib/lookup_table.h" @@ -224,7 +224,7 @@ wimlib_split(WIMStruct *w, const tchar *swm_name, for (int i = 1; i <= total_parts; i++) { const tchar *part_name; int part_fd; - u8 part_data_buf[4]; + le16 part_data[2]; size_t bytes_written; if (i == 1) { @@ -241,13 +241,13 @@ wimlib_split(WIMStruct *w, const tchar *swm_name, ret = WIMLIB_ERR_OPEN; goto out; } - put_u16(&part_data_buf[0], i); - put_u16(&part_data_buf[2], total_parts); + part_data[0] = cpu_to_le16(i); + part_data[1] = cpu_to_le16(total_parts); - bytes_written = full_pwrite(part_fd, part_data_buf, - sizeof(part_data_buf), 40); + bytes_written = full_pwrite(part_fd, part_data, + sizeof(part_data), 40); ret = close(part_fd); - if (bytes_written != sizeof(part_data_buf) || ret != 0) { + if (bytes_written != sizeof(part_data) || ret != 0) { ERROR_WITH_ERRNO("Error updating header of `%"TS"'", part_name); ret = WIMLIB_ERR_WRITE;