From: Eric Biggers Date: Sat, 14 Dec 2013 05:06:07 +0000 (-0600) Subject: Split wim_resource_spec from wim_lookup_table_entry X-Git-Tag: v1.6.0~146 X-Git-Url: https://wimlib.net/git/?p=wimlib;a=commitdiff_plain;h=f24f8409b041727329e980fdc81e84a7c9b00e5b Split wim_resource_spec from wim_lookup_table_entry --- diff --git a/include/wimlib.h b/include/wimlib.h index 4e999d69..c7775416 100644 --- a/include/wimlib.h +++ b/include/wimlib.h @@ -425,6 +425,9 @@ enum wimlib_compression_type { /** Compressed resources in the WIM use XPRESS compression. */ WIMLIB_COMPRESSION_TYPE_XPRESS = 2, + + /** TODO */ + WIMLIB_COMPRESSION_TYPE_LZMS = 3, }; /** @} */ diff --git a/include/wimlib/header.h b/include/wimlib/header.h index f7c4b7ff..2fe76d4c 100644 --- a/include/wimlib/header.h +++ b/include/wimlib/header.h @@ -14,15 +14,16 @@ /* Version of the WIM file. There is an older version (used for prerelease * versions of Windows Vista), but wimlib doesn't support it. The differences * between the versions are undocumented. */ -#define WIM_VERSION 0x10d00 +#define WIM_VERSION_DEFAULT 0x10d00 /* Version number used for a different WIM format, which as of Windows 8 can be * created by passing 0x20000000 in dwFlagsAndAttributes to WIMGAPI's * WIMCreateFile() and specifying either NONE, XPRESS, or LZMS compression. - * This format is, however, currently undocumented by Microsoft and is seemingly - * incompatible with their own ImageX and Dism programs. wimlib does not yet - * support this format. */ -#define WIM_MYSTERY_VERSION 0xe00 + * This format is currently undocumented by Microsoft and is seemingly + * incompatible with their own ImageX and Dism programs; however, it seems to be + * used for Windows 8 updates. The format appears to feature a new flag (0x10) + * in resource entries, which I've named WIM_RESHDR_FLAG_CONCAT. */ +#define WIM_VERSION_STREAM_CONCAT 0xe00 /* WIM magic characters, translated to a single 64-bit little endian number. */ #define WIM_MAGIC \ @@ -57,8 +58,8 @@ struct wim_header_disk { * (currently the only supported value). */ u32 hdr_size; - /* Version of the WIM file; WIM_VERSION expected (currently the only - * supported value). */ + /* Version of the WIM file + * TODO */ u32 wim_version; /* Flags for the WIM file (WIM_HDR_FLAG_*) */ @@ -84,14 +85,14 @@ struct wim_header_disk { u32 image_count; /* Location and size of the WIM's lookup table. */ - struct resource_entry_disk lookup_table_res_entry; + struct wim_reshdr_disk lookup_table_reshdr; /* Location and size of the WIM's XML data. */ - struct resource_entry_disk xml_data_res_entry; + struct wim_reshdr_disk xml_data_reshdr; /* 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; + struct wim_reshdr_disk boot_metadata_reshdr; /* 1-based index of the bootable image of the WIM, or 0 if no image is * bootable. */ @@ -100,10 +101,10 @@ struct wim_header_disk { /* 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 + * Note the integrity_table_reshdr 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; + struct wim_reshdr_disk integrity_table_reshdr; /* Unused bytes. */ u8 unused[60]; @@ -118,6 +119,9 @@ struct wim_header { /* Magic characters: either WIM_MAGIC or PWM_MAGIC. */ le64 magic; + /* Version of the WIM file */ + u32 wim_version; + /* Bitwise OR of one or more of the WIM_HDR_FLAG_* defined below. */ u32 flags; @@ -137,15 +141,15 @@ struct wim_header { u32 image_count; /* Location, size, and flags of the lookup table of the WIM. */ - struct resource_entry lookup_table_res_entry; + struct wim_reshdr lookup_table_reshdr; /* Location, size, and flags for the XML data of the WIM. */ - struct resource_entry xml_res_entry; + struct wim_reshdr xml_data_reshdr; /* Location, size, and flags for the boot metadata. This means the * metadata resource for the image specified by boot_idx below. Should * be zeroed out if boot_idx is 0. */ - struct resource_entry boot_metadata_res_entry; + struct wim_reshdr boot_metadata_reshdr; /* The index of the bootable image in the WIM file. If 0, there are no * bootable images available. */ @@ -153,7 +157,7 @@ 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; + struct wim_reshdr integrity_table_reshdr; }; /* Flags for the `flags' field of the struct wim_header: */ diff --git a/include/wimlib/lookup_table.h b/include/wimlib/lookup_table.h index d1b980da..b5b3830f 100644 --- a/include/wimlib/lookup_table.h +++ b/include/wimlib/lookup_table.h @@ -114,24 +114,11 @@ struct wim_lookup_table_entry { /* List of lookup table entries in this hash bucket */ struct hlist_node hash_list; - /* Location and size of the stream in the WIM, whether it is compressed - * or not, and whether it's a metadata resource or not. This is an - * on-disk field. */ - struct resource_entry resource_entry; + /* Uncompressed size of the stream. */ + u64 size : 56; - /* Specifies which part of the split WIM the resource is located in. - * This is on on-disk field. - * - * In stand-alone WIMs, this must be 1. - * - * In split WIMs, every split WIM part has its own lookup table, and in - * read_lookup_table() it's currently expected that the part number of - * each lookup table entry in a split WIM part's lookup table is the - * same as the part number of that split WIM part. So this makes this - * field redundant since we store a pointer to the corresponding - * WIMStruct in the lookup table entry anyway. - */ - u16 part_number; + /* Stream flags (WIM_RESHDR_FLAG_*). */ + u64 flags : 8; /* One of the `enum resource_location' values documented above. */ u16 resource_location : 5; @@ -147,17 +134,6 @@ struct wim_lookup_table_entry { u16 no_progress : 1; - /* If resource_location == RESOURCE_IN_WIM, this will be a cached value - * that specifies the compression type of this stream as one of - * WIMLIB_COMPRESSION_TYPE_*. Otherwise this will be 0, which is the - * same as WIMLIB_COMPRESSION_TYPE_NONE. */ - u16 compression_type : 2; - - /* If resource_location == RESOURCE_IN_WIM, this flag will be set if the - * WIM is pipable and therefore the stream is in a slightly different - * format. See comment above write_pipable_wim(). */ - u16 is_pipable : 1; - /* Set to 1 when a metadata entry has its checksum changed; in such * cases the hash is no longer valid to verify the data if the metadata * resource is read again. */ @@ -209,7 +185,7 @@ struct wim_lookup_table_entry { /* Pointers to somewhere where the stream is actually located. See the * comments for the @resource_location field above. */ union { - WIMStruct *wim; + struct wim_resource_spec *rspec; tchar *file_on_disk; void *attached_buffer; #ifdef WITH_FUSE @@ -254,15 +230,9 @@ struct wim_lookup_table_entry { struct list_head being_compressed_list; }; - /* When a WIM file is written, @output_resource_entry is filled - * in with the resource entry for the output WIM. This will not - * necessarily be the same as the @resource_entry since: - * - The stream may have a different offset in the new WIM - * - The stream may have a different compressed size in the new - * WIM if the compression type changed - */ - struct resource_entry output_resource_entry; - + /* When a WIM file is written, @output_reshdr is filled in with + * the resource header for the output WIM. */ + struct wim_reshdr out_reshdr; /* Used temporarily during extraction */ union { @@ -290,37 +260,29 @@ struct wim_lookup_table_entry { /* Links streams that are still unhashed after being been added * to a WIM. */ struct list_head unhashed_list; + + struct list_head wim_resource_list; }; -static inline u64 -wim_resource_size(const struct wim_lookup_table_entry *lte) +static inline int +lte_ctype(const struct wim_lookup_table_entry *lte) { - return lte->resource_entry.original_size; + if (lte->resource_location == RESOURCE_IN_WIM) + return lte->rspec->ctype; + else + return WIMLIB_COMPRESSION_TYPE_NONE; } static inline u32 -wim_resource_chunk_size(const struct wim_lookup_table_entry * lte) +lte_cchunk_size(const struct wim_lookup_table_entry * lte) { if (lte->resource_location == RESOURCE_IN_WIM && - lte->compression_type != WIMLIB_COMPRESSION_TYPE_NONE) - return lte->wim->chunk_size; + lte->rspec->ctype != WIMLIB_COMPRESSION_TYPE_NONE) + return lte->rspec->cchunk_size; else return 32768; } - -static inline u64 -wim_resource_chunks(const struct wim_lookup_table_entry *lte) -{ - return DIV_ROUND_UP(wim_resource_size(lte), wim_resource_chunk_size(lte)); -} - -static inline int -wim_resource_compression_type(const struct wim_lookup_table_entry *lte) -{ - return lte->compression_type; -} - static inline bool lte_filename_valid(const struct wim_lookup_table_entry *lte) { @@ -342,7 +304,7 @@ read_wim_lookup_table(WIMStruct *wim); extern int write_wim_lookup_table(WIMStruct *wim, int image, int write_flags, - struct resource_entry *out_res_entry, + struct wim_reshdr *out_reshdr, struct list_head *stream_list_override); extern void @@ -369,8 +331,7 @@ clone_lookup_table_entry(const struct wim_lookup_table_entry *lte) _malloc_attribute; extern void -print_lookup_table_entry(const struct wim_lookup_table_entry *entry, - FILE *out); +print_lookup_table_entry(const struct wim_lookup_table_entry *lte, FILE *out); extern void free_lookup_table_entry(struct wim_lookup_table_entry *lte); @@ -413,16 +374,32 @@ lte_decrement_num_opened_fds(struct wim_lookup_table_entry *lte); #endif extern int -lte_zero_out_refcnt(struct wim_lookup_table_entry *entry, void *ignore); +lte_zero_out_refcnt(struct wim_lookup_table_entry *lte, void *ignore); extern int -lte_zero_real_refcnt(struct wim_lookup_table_entry *entry, void *ignore); +lte_zero_real_refcnt(struct wim_lookup_table_entry *lte, void *ignore); extern int lte_free_extracted_file(struct wim_lookup_table_entry *lte, void *ignore); -extern void -lte_init_wim(struct wim_lookup_table_entry *lte, WIMStruct *wim); +static inline void +lte_bind_wim_resource_spec(struct wim_lookup_table_entry *lte, + struct wim_resource_spec *rspec) +{ + lte->resource_location = RESOURCE_IN_WIM; + lte->rspec = rspec; + list_add(<e->wim_resource_list, &rspec->lte_list); + lte->flags = rspec->flags; + lte->size = rspec->uncompressed_size; +} + +static inline void +lte_unbind_wim_resource_spec(struct wim_lookup_table_entry *lte) +{ + list_del(<e->wim_resource_list); + lte->rspec = NULL; + lte->resource_location = RESOURCE_NONEXISTENT; +} extern int inode_resolve_ltes(struct wim_inode *inode, struct wim_lookup_table *table, @@ -530,10 +507,6 @@ inode_unnamed_lte(const struct wim_inode *inode, const struct wim_lookup_table * extern const u8 * inode_unnamed_stream_hash(const struct wim_inode *inode); -extern u64 -lookup_table_total_stream_size(struct wim_lookup_table *table); - - static inline void lookup_table_insert_unhashed(struct wim_lookup_table *table, struct wim_lookup_table_entry *lte, diff --git a/include/wimlib/resource.h b/include/wimlib/resource.h index 9bb67490..a717e494 100644 --- a/include/wimlib/resource.h +++ b/include/wimlib/resource.h @@ -5,43 +5,85 @@ #include "wimlib/endianness.h" #include "wimlib/callback.h" #include "wimlib/file_io.h" +#include "wimlib/list.h" #include "wimlib/sha1.h" struct wim_lookup_table_entry; struct wim_image_metadata; -/* Description of the location, size, and compression status of a WIM resource - * (stream). This is the in-memory version of `struct resource_entry_disk'. */ -struct resource_entry { - /* Size, in bytes, of the resource as it appears in the WIM file. If - * the resource is uncompressed, this will be the same as - * @original_size. If the resource is compressed, this will be the - * compressed size of the resource, including all compressed chunks as - * well as the chunk table. - * - * Note: if the WIM is "pipable", this value does not include the stream - * header. */ - u64 size : 56; - - /* Bitwise OR of one or more of the WIM_RESHDR_FLAG_* flags. */ - u64 flags : 8; +/* Specification of a resource in a WIM file. + * + * If a `struct wim_lookup_table_entry' lte has + * (lte->resource_location == RESOURCE_IN_WIM), then lte->wim_res_spec points to + * an instance of this structure. + * + * Normally, there is a one-to-one correspondence between WIM lookup table + * entries ("streams") and WIM resources. However, the flag + * WIM_RESHDR_FLAG_CONCAT can be used to specify that two streams be combined + * into the same resource and compressed together. Caveats about this flag are + * noted in the comment above the definition of WIM_VERSION_STREAM_CONCAT. */ +struct wim_resource_spec { + /* The WIM file containing this resource. */ + WIMStruct *wim; + + /* Offset, in bytes, from the start of WIM file at which this resource + * starts. */ + u64 offset_in_wim; + + /* The size of this resource in the WIM file. For compressed resources + * this is the compressed size. */ + u64 size_in_wim; + + /* Number of bytes of uncompressed data this resource uncompresses to. + */ + u64 uncompressed_size; + + /* List of streams this resource contains. */ + struct list_head lte_list; + + /* Resource flags. */ + u32 flags : 8; + + /* This flag will be set if the WIM is pipable and therefore the + * resource will be in a slightly different format if it is compressed + * (wimlib extension). */ + u32 is_pipable : 1; + + /* Compression type of this resource as one of WIMLIB_COMPRESSION_TYPE_* + * constants. */ + u32 ctype : 3; + + /* Compression chunk size. */ + u32 cchunk_size; +}; - /* Offset, in bytes, of the resource from the start of the WIM file. */ - u64 offset; - /* Uncompressed size, in bytes, of the resource (stream). */ - u64 original_size; -}; +/* On-disk version of a WIM resource header: This structure specifies the + * location, size, and flags (e.g. compressed or not compressed) for a resource + * in the WIM file. */ +struct wim_reshdr_disk { + /* Size of the resource as it appears in the WIM file (possibly + * compressed). */ + u8 size_in_wim[7]; -/* On-disk version of `struct resource_entry'. See `struct resource_entry' for - * description of fields. */ -struct resource_entry_disk { - u8 size[7]; + /* WIM_RESHDR_FLAG_* flags. */ u8 flags; - le64 offset; - le64 original_size; + + /* Offset of the resource from the start of the WIM file. */ + le64 offset_in_wim; + + /* Uncompressed size of the resource. */ + le64 uncompressed_size; } _packed_attribute; +/* In-memory version of wim_reshdr_disk. */ +struct wim_reshdr { + u64 size_in_wim : 56; + u64 flags : 8; + u64 offset_in_wim; + u64 uncompressed_size; +}; + /* Flags for the `flags' field of the struct resource_entry structure. */ /* I haven't seen this flag used in any of the WIMs I have examined. I assume @@ -65,34 +107,37 @@ struct resource_entry_disk { * Either way, wimlib doesn't actually use this flag for anything. */ #define WIM_RESHDR_FLAG_SPANNED 0x08 -/* Functions that operate directly on `struct resource_entry's. */ - -static inline int -resource_is_compressed(const struct resource_entry *entry) -{ - return (entry->flags & WIM_RESHDR_FLAG_COMPRESSED); -} +/* TODO */ +#define WIM_RESHDR_FLAG_CONCAT 0x10 static inline void -copy_resource_entry(struct resource_entry *dst, - const struct resource_entry *src) +copy_reshdr(struct wim_reshdr *dest, const struct wim_reshdr *src) { - memcpy(dst, src, sizeof(struct resource_entry)); + memcpy(dest, src, sizeof(struct wim_reshdr)); } static inline void -zero_resource_entry(struct resource_entry *entry) +zero_reshdr(struct wim_reshdr *reshdr) { - memset(entry, 0, sizeof(struct resource_entry)); + memset(reshdr, 0, sizeof(struct wim_reshdr)); } + +extern void +wim_res_hdr_to_spec(const struct wim_reshdr *reshdr, WIMStruct *wim, + struct wim_resource_spec *rspec); + extern void -get_resource_entry(const struct resource_entry_disk *disk_entry, - struct resource_entry *entry); +wim_res_spec_to_hdr(const struct wim_resource_spec *rspec, + struct wim_reshdr *reshdr); extern void -put_resource_entry(const struct resource_entry *entry, - struct resource_entry_disk *disk_entry); +get_wim_reshdr(const struct wim_reshdr_disk *disk_reshdr, + struct wim_reshdr *reshdr); + +void +put_wim_reshdr(const struct wim_reshdr *reshdr, + struct wim_reshdr_disk *disk_reshdr); /* wimlib internal flags used when reading or writing resources. */ #define WIMLIB_WRITE_RESOURCE_FLAG_RECOMPRESS 0x00000001 @@ -125,25 +170,14 @@ read_full_resource_into_alloc_buf(const struct wim_lookup_table_entry *lte, void **buf_ret); extern int -res_entry_to_data(const struct resource_entry *res_entry, - WIMStruct *wim, void **buf_ret); +wim_reshdr_to_data(const struct wim_reshdr *reshdr, + WIMStruct *wim, void **buf_ret); extern int read_resource_prefix(const struct wim_lookup_table_entry *lte, u64 size, consume_data_callback_t cb, u32 in_chunk_size, void *ctx_or_buf, int flags); -/* Functions to write a resource. */ - -extern int -write_wim_resource_from_buffer(const void *buf, size_t buf_size, - int reshdr_flags, struct filedes *out_fd, - int out_ctype, - u32 out_chunk_size, - struct resource_entry *out_res_entry, - u8 *hash_ret, int write_resource_flags, - struct wimlib_lzx_context **comp_ctx); - /* Functions to extract a resource. */ extern int diff --git a/include/wimlib/wim.h b/include/wimlib/wim.h index 4afa60eb..83b1dbcb 100644 --- a/include/wimlib/wim.h +++ b/include/wimlib/wim.h @@ -94,7 +94,7 @@ static inline bool wim_is_pipable(const WIMStruct *wim) static inline bool wim_has_integrity_table(const WIMStruct *wim) { - return (wim->hdr.integrity.offset != 0); + return (wim->hdr.integrity_table_reshdr.offset_in_wim != 0); } static inline bool wim_has_metadata(const WIMStruct *wim) @@ -112,8 +112,7 @@ extern int init_wim_header(struct wim_header *hdr, int ctype, u32 chunk_size); extern int -read_wim_header(const tchar *filename, struct filedes *in_fd, - struct wim_header *hdr); +read_wim_header(WIMStruct *wim, struct wim_header *hdr); extern int write_wim_header(const struct wim_header *hdr, struct filedes *out_fd); diff --git a/include/wimlib/write.h b/include/wimlib/write.h index eb73bed3..1240c89f 100644 --- a/include/wimlib/write.h +++ b/include/wimlib/write.h @@ -40,4 +40,13 @@ write_wim_part(WIMStruct *wim, struct list_head *stream_list_override, const u8 *guid); +int +write_wim_resource_from_buffer(const void *buf, size_t buf_size, + int reshdr_flags, struct filedes *out_fd, + int out_ctype, + u32 out_chunk_size, + struct wim_reshdr *out_reshdr, + u8 *hash_ret, int write_resource_flags, + struct wimlib_lzx_context **comp_ctx); + #endif /* _WIMLIB_WRITE_H */ diff --git a/include/wimlib/xml.h b/include/wimlib/xml.h index 0d09bf64..a4fd1152 100644 --- a/include/wimlib/xml.h +++ b/include/wimlib/xml.h @@ -5,7 +5,7 @@ #include "wimlib/file_io.h" struct wim_info; -struct resource_entry; +struct wim_reshdr; extern u64 wim_info_get_total_bytes(const struct wim_info *info); @@ -51,7 +51,7 @@ read_wim_xml_data(WIMStruct *wim); extern int write_wim_xml_data(WIMStruct *wim, int image, - u64 total_bytes, struct resource_entry *out_res_entry, + u64 total_bytes, struct wim_reshdr *out_reshdr, int write_resource_flags); extern void diff --git a/src/add_image.c b/src/add_image.c index 746c06a9..a06ee939 100644 --- a/src/add_image.c +++ b/src/add_image.c @@ -45,14 +45,14 @@ add_new_dentry_tree(WIMStruct *wim, struct wim_dentry *root_dentry, int ret; metadata_lte = new_lookup_table_entry(); - if (!metadata_lte) + if (metadata_lte == NULL) return WIMLIB_ERR_NOMEM; - metadata_lte->resource_entry.flags = WIM_RESHDR_FLAG_METADATA; + metadata_lte->flags = WIM_RESHDR_FLAG_METADATA; metadata_lte->unhashed = 1; new_imd = new_image_metadata(); - if (!new_imd) { + if (new_imd == NULL) { free_lookup_table_entry(metadata_lte); return WIMLIB_ERR_NOMEM; } @@ -92,7 +92,7 @@ wimlib_add_empty_image(WIMStruct *wim, const tchar *name, int *new_idx_ret) } sd = new_wim_security_data(); - if (!sd) { + if (sd == NULL) { ret = WIMLIB_ERR_NOMEM; goto out; } @@ -172,7 +172,7 @@ wimlib_add_image_multisource(WIMStruct *wim, /* Translate the "capture sources" into generic update commands. */ add_cmds = capture_sources_to_add_cmds(sources, num_sources, add_flags, config); - if (!add_cmds) { + if (add_cmds == NULL) { ret = WIMLIB_ERR_NOMEM; goto out_delete_image; } diff --git a/src/dentry.c b/src/dentry.c index b2bddf22..37405eb0 100644 --- a/src/dentry.c +++ b/src/dentry.c @@ -254,7 +254,7 @@ get_utf16le_name(const tchar *name, utf16lechar **name_utf16le_ret, #if TCHAR_IS_UTF16LE name_utf16le_nbytes = tstrlen(name) * sizeof(utf16lechar); name_utf16le = MALLOC(name_utf16le_nbytes + sizeof(utf16lechar)); - if (!name_utf16le) + if (name_utf16le == NULL) return WIMLIB_ERR_NOMEM; memcpy(name_utf16le, name, name_utf16le_nbytes + sizeof(utf16lechar)); ret = 0; @@ -443,7 +443,7 @@ for_dentry_in_tree(struct wim_dentry *root, { int ret; - if (!root) + if (root == NULL) return 0; ret = (*visitor)(root, arg); if (ret) @@ -461,7 +461,7 @@ for_dentry_in_tree_depth(struct wim_dentry *root, { int ret; - if (!root) + if (root == NULL) return 0; ret = for_dentry_tree_in_rbtree_depth(root->d_inode->i_children.rb_node, visitor, arg); @@ -485,7 +485,7 @@ calculate_dentry_full_path(struct wim_dentry *dentry) if (dentry_is_root(dentry)) { static const tchar _root_path[] = {WIM_PATH_SEPARATOR, T('\0')}; full_path = TSTRDUP(_root_path); - if (!full_path) + if (full_path == NULL) return WIMLIB_ERR_NOMEM; full_path_nbytes = 1 * sizeof(tchar); } else { @@ -499,7 +499,7 @@ calculate_dentry_full_path(struct wim_dentry *dentry) parent_full_path = T(""); parent_full_path_nbytes = 0; } else { - if (!parent->_full_path) { + if (parent->_full_path == NULL) { ret = calculate_dentry_full_path(parent); if (ret) return ret; @@ -525,7 +525,7 @@ calculate_dentry_full_path(struct wim_dentry *dentry) full_path_nbytes = parent_full_path_nbytes + sizeof(tchar) + filename_nbytes; full_path = MALLOC(full_path_nbytes + sizeof(tchar)); - if (!full_path) + if (full_path == NULL) return WIMLIB_ERR_NOMEM; memcpy(full_path, parent_full_path, parent_full_path_nbytes); full_path[parent_full_path_nbytes / sizeof(tchar)] = WIM_PATH_SEPARATOR; @@ -790,7 +790,7 @@ get_dentry_utf16le(WIMStruct *wim, const utf16lechar *path) const utf16lechar *p, *pp; cur_dentry = parent_dentry = wim_root_dentry(wim); - if (!cur_dentry) { + if (cur_dentry == NULL) { errno = ENOENT; return NULL; } @@ -1045,7 +1045,7 @@ new_dentry(const tchar *name, struct wim_dentry **dentry_ret) int ret; dentry = MALLOC(sizeof(struct wim_dentry)); - if (!dentry) + if (dentry == NULL) return WIMLIB_ERR_NOMEM; dentry_common_init(dentry); @@ -1077,7 +1077,7 @@ _new_dentry_with_inode(const tchar *name, struct wim_dentry **dentry_ret, dentry->d_inode = new_timeless_inode(); else dentry->d_inode = new_inode(); - if (!dentry->d_inode) { + if (dentry->d_inode == NULL) { free_dentry(dentry); return WIMLIB_ERR_NOMEM; } @@ -1139,7 +1139,7 @@ init_ads_entry(struct wim_ads_entry *ads_entry, const void *name, if (is_utf16le) { utf16lechar *p = MALLOC(name_nbytes + sizeof(utf16lechar)); - if (!p) + if (p == NULL) return WIMLIB_ERR_NOMEM; memcpy(p, name, name_nbytes); p[name_nbytes / 2] = cpu_to_le16(0); @@ -1455,7 +1455,7 @@ do_inode_add_ads(struct wim_inode *inode, const void *stream_name, num_ads = inode->i_num_ads + 1; ads_entries = REALLOC(inode->i_ads_entries, num_ads * sizeof(inode->i_ads_entries[0])); - if (!ads_entries) { + if (ads_entries == NULL) { ERROR("Failed to allocate memory for new alternate data stream"); return NULL; } @@ -1503,22 +1503,22 @@ add_stream_from_data_buffer(const void *buffer, size_t size, sha1_buffer(buffer, size, hash); existing_lte = lookup_resource(lookup_table, hash); if (existing_lte) { - wimlib_assert(wim_resource_size(existing_lte) == size); + wimlib_assert(existing_lte->size == size); lte = existing_lte; lte->refcnt++; } else { void *buffer_copy; lte = new_lookup_table_entry(); - if (!lte) + if (lte == NULL) return NULL; buffer_copy = memdup(buffer, size); - if (!buffer_copy) { + if (buffer_copy == NULL) { free_lookup_table_entry(lte); return NULL; } - lte->resource_location = RESOURCE_IN_ATTACHED_BUFFER; - lte->attached_buffer = buffer_copy; - lte->resource_entry.original_size = size; + lte->resource_location = RESOURCE_IN_ATTACHED_BUFFER; + lte->attached_buffer = buffer_copy; + lte->size = size; copy_hash(lte->hash, hash); lookup_table_insert(lookup_table, lte); } @@ -1535,12 +1535,12 @@ inode_add_ads_with_data(struct wim_inode *inode, const tchar *name, wimlib_assert(inode->i_resolved); new_ads_entry = inode_add_ads(inode, name); - if (!new_ads_entry) + if (new_ads_entry == NULL) return WIMLIB_ERR_NOMEM; new_ads_entry->lte = add_stream_from_data_buffer(value, size, lookup_table); - if (!new_ads_entry->lte) { + if (new_ads_entry->lte == NULL) { inode_remove_ads(inode, new_ads_entry - inode->i_ads_entries, lookup_table); return WIMLIB_ERR_NOMEM; @@ -1564,7 +1564,7 @@ inode_set_unnamed_stream(struct wim_inode *inode, const void *data, size_t len, struct wim_lookup_table *lookup_table) { inode->i_lte = add_stream_from_data_buffer(data, len, lookup_table); - if (!inode->i_lte) + if (inode->i_lte == NULL) return WIMLIB_ERR_NOMEM; inode->i_resolved = 1; return 0; @@ -1621,17 +1621,17 @@ inode_get_unix_data(const struct wim_inode *inode, ads_entry = inode_get_ads_entry((struct wim_inode*)inode, WIMLIB_UNIX_DATA_TAG, NULL); - if (!ads_entry) + if (ads_entry == NULL) return NO_UNIX_DATA; if (stream_idx_ret) *stream_idx_ret = ads_entry - inode->i_ads_entries; lte = ads_entry->lte; - if (!lte) + if (lte == NULL) return NO_UNIX_DATA; - size = wim_resource_size(lte); + size = lte->size; if (size != sizeof(struct wimlib_unix_data)) return BAD_UNIX_DATA; @@ -1714,7 +1714,7 @@ read_ads_entries(const u8 * restrict p, struct wim_inode * restrict inode, * data stream entries. */ num_ads = inode->i_num_ads; ads_entries = CALLOC(num_ads, sizeof(inode->i_ads_entries[0])); - if (!ads_entries) + if (ads_entries == NULL) goto out_of_memory; /* Read the entries into our newly allocated buffer. */ @@ -1769,7 +1769,7 @@ read_ads_entries(const u8 * restrict p, struct wim_inode * restrict inode, goto out_invalid; cur_entry->stream_name = MALLOC(cur_entry->stream_name_nbytes + 2); - if (!cur_entry->stream_name) + if (cur_entry->stream_name == NULL) goto out_of_memory; memcpy(cur_entry->stream_name, @@ -1908,7 +1908,7 @@ read_dentry(const u8 * restrict metadata_resource, u64 metadata_resource_len, /* Allocate a `struct wim_inode' for this `struct wim_dentry'. */ inode = new_timeless_inode(); - if (!inode) + if (inode == NULL) return WIMLIB_ERR_NOMEM; /* Read more fields; some into the dentry, and some into the inode. */ @@ -1976,7 +1976,7 @@ read_dentry(const u8 * restrict metadata_resource, u64 metadata_resource_len, * is no null terminator following it. */ if (file_name_nbytes) { file_name = MALLOC(file_name_nbytes + 2); - if (!file_name) { + if (file_name == NULL) { ERROR("Failed to allocate %d bytes for dentry file name", file_name_nbytes + 2); ret = WIMLIB_ERR_NOMEM; @@ -1994,7 +1994,7 @@ read_dentry(const u8 * restrict metadata_resource, u64 metadata_resource_len, * filename, there is no null terminator following it. */ if (short_name_nbytes) { short_name = MALLOC(short_name_nbytes + 2); - if (!short_name) { + if (short_name == NULL) { ERROR("Failed to allocate %d bytes for dentry short name", short_name_nbytes + 2); ret = WIMLIB_ERR_NOMEM; @@ -2131,7 +2131,7 @@ read_dentry_tree(const u8 * restrict metadata_resource, /* Not end of directory. Allocate this child permanently and * link it to the parent and previous child. */ child = memdup(&cur_child, sizeof(struct wim_dentry)); - if (!child) { + if (child == NULL) { ERROR("Failed to allocate new dentry!"); ret = WIMLIB_ERR_NOMEM; break; @@ -2523,7 +2523,7 @@ do_iterate_dir_tree(WIMStruct *wim, wdentry = CALLOC(1, sizeof(struct wimlib_dir_entry) + (1 + dentry->d_inode->i_num_ads) * sizeof(struct wimlib_stream_entry)); - if (!wdentry) + if (wdentry == NULL) goto out; ret = init_wimlib_dentry(wdentry, dentry, wim, flags); @@ -2568,7 +2568,7 @@ image_do_iterate_dir_tree(WIMStruct *wim) struct wim_dentry *dentry; dentry = get_dentry(wim, ctx->path); - if (!dentry) + if (dentry == NULL) return WIMLIB_ERR_PATH_DOES_NOT_EXIST; return do_iterate_dir_tree(wim, dentry, ctx->flags, ctx->cb, ctx->user_ctx); } @@ -2626,7 +2626,7 @@ inode_metadata_consistent(const struct wim_inode *inode, /* Compare stream sizes. */ if (lte && template_lte) { - if (wim_resource_size(lte) != wim_resource_size(template_lte)) + if (lte->size != template_lte->size) return false; /* If hash happens to be available, compare with template. */ @@ -2634,9 +2634,9 @@ inode_metadata_consistent(const struct wim_inode *inode, !hashes_equal(lte->hash, template_lte->hash)) return false; - } else if (lte && wim_resource_size(lte)) { + } else if (lte && lte->size) { return false; - } else if (template_lte && wim_resource_size(template_lte)) { + } else if (template_lte && template_lte->size) { return false; } } @@ -2673,7 +2673,7 @@ inode_copy_checksums(struct wim_inode *inode, /* Only take action if both entries exist, the entry for @inode * has no checksum calculated, but the entry for @template_inode * does. */ - if (!lte || !template_lte || + if (lte == NULL || template_lte == NULL || !lte->unhashed || template_lte->unhashed) continue; @@ -2736,7 +2736,7 @@ dentry_reference_template(struct wim_dentry *dentry, void *_args) return ret; template_dentry = get_dentry(template_wim, dentry->_full_path); - if (!template_dentry) { + if (template_dentry == NULL) { DEBUG("\"%"TS"\": newly added file", dentry->_full_path); return 0; } diff --git a/src/extract.c b/src/extract.c index 4448a6ea..549c92f7 100644 --- a/src/extract.c +++ b/src/extract.c @@ -129,7 +129,7 @@ ref_stream_to_extract(struct wim_lookup_table_entry *lte, (!is_linked_extraction(ctx) || (lte->out_refcnt == 0 && lte->extracted_file == NULL))) { - ctx->progress.extract.total_bytes += wim_resource_size(lte); + ctx->progress.extract.total_bytes += lte->size; ctx->progress.extract.num_streams++; } @@ -237,7 +237,7 @@ update_extract_progress(struct apply_ctx *ctx, wimlib_progress_func_t progress_func = ctx->progress_func; union wimlib_progress_info *progress = &ctx->progress; - progress->extract.completed_bytes += wim_resource_size(lte); + progress->extract.completed_bytes += lte->size; if (progress_func && progress->extract.completed_bytes >= ctx->next_progress) { @@ -1257,8 +1257,7 @@ extract_stream_instances(struct wim_lookup_table_entry *lte, goto out_free_lte_tmp; } filedes_init(&fd, raw_fd); - ret = extract_wim_resource_to_fd(lte, &fd, - wim_resource_size(lte)); + ret = extract_wim_resource_to_fd(lte, &fd, lte->size); if (filedes_close(&fd) && !ret) ret = WIMLIB_ERR_WRITE; if (ret) @@ -1327,12 +1326,14 @@ extract_stream_list(struct apply_ctx *ctx) /* Read the header from a stream in a pipable WIM. */ static int read_pwm_stream_header(WIMStruct *pwm, struct wim_lookup_table_entry *lte, + struct wim_resource_spec *rspec, int flags, struct wim_header_disk *hdr_ret) { union { struct pwm_stream_hdr stream_hdr; struct wim_header_disk pwm_hdr; } buf; + struct wim_reshdr reshdr; int ret; ret = full_read(&pwm->in_fd, &buf.stream_hdr, sizeof(buf.stream_hdr)); @@ -1356,20 +1357,14 @@ read_pwm_stream_header(WIMStruct *pwm, struct wim_lookup_table_entry *lte, return WIMLIB_ERR_INVALID_PIPABLE_WIM; } - lte->resource_entry.original_size = le64_to_cpu(buf.stream_hdr.uncompressed_size); copy_hash(lte->hash, buf.stream_hdr.hash); - lte->resource_entry.flags = le32_to_cpu(buf.stream_hdr.flags); - lte->resource_entry.offset = pwm->in_fd.offset; - lte->resource_location = RESOURCE_IN_WIM; - lte->wim = pwm; - if (lte->resource_entry.flags & WIM_RESHDR_FLAG_COMPRESSED) { - lte->compression_type = pwm->compression_type; - lte->resource_entry.size = 0; - } else { - lte->compression_type = WIMLIB_COMPRESSION_TYPE_NONE; - lte->resource_entry.size = lte->resource_entry.original_size; - } - lte->is_pipable = 1; + + reshdr.size_in_wim = 0; + reshdr.flags = le32_to_cpu(buf.stream_hdr.flags); + reshdr.offset_in_wim = pwm->in_fd.offset; + reshdr.uncompressed_size = le64_to_cpu(buf.stream_hdr.uncompressed_size); + wim_res_hdr_to_spec(&reshdr, pwm, rspec); + lte_bind_wim_resource_spec(lte, rspec); return 0; read_error: @@ -1389,9 +1384,9 @@ static int skip_pwm_stream(struct wim_lookup_table_entry *lte) { return read_partial_wim_resource(lte, - wim_resource_size(lte), + lte->size, skip_pwm_chunk_cb, - wim_resource_chunk_size(lte), + lte_cchunk_size(lte), NULL, WIMLIB_READ_RESOURCE_FLAG_RAW_CHUNKS, 0); @@ -1401,6 +1396,7 @@ static int extract_streams_from_pipe(struct apply_ctx *ctx) { struct wim_lookup_table_entry *found_lte; + struct wim_resource_spec *rspec; struct wim_lookup_table_entry *needed_lte; struct wim_lookup_table *lookup_table; struct wim_header_disk pwm_hdr; @@ -1409,9 +1405,13 @@ extract_streams_from_pipe(struct apply_ctx *ctx) ret = WIMLIB_ERR_NOMEM; found_lte = new_lookup_table_entry(); - if (!found_lte) + if (found_lte == NULL) goto out; + rspec = MALLOC(sizeof(struct wim_resource_spec)); + if (rspec == NULL) + goto out_free_found_lte; + lookup_table = ctx->wim->lookup_table; pwm_flags = PWM_ALLOW_WIM_HDR; if ((ctx->extract_flags & WIMLIB_EXTRACT_FLAG_RESUME)) @@ -1423,8 +1423,10 @@ extract_streams_from_pipe(struct apply_ctx *ctx) ctx->progress_func(WIMLIB_PROGRESS_MSG_EXTRACT_SPWM_PART_BEGIN, &ctx->progress); while (ctx->num_streams_remaining) { - ret = read_pwm_stream_header(ctx->wim, found_lte, pwm_flags, - &pwm_hdr); + if (found_lte->resource_location != RESOURCE_NONEXISTENT) + lte_unbind_wim_resource_spec(found_lte); + ret = read_pwm_stream_header(ctx->wim, found_lte, rspec, + pwm_flags, &pwm_hdr); if (ret) { if (ret == WIMLIB_ERR_UNEXPECTED_END_OF_FILE && (ctx->extract_flags & WIMLIB_EXTRACT_FLAG_RESUME)) @@ -1435,18 +1437,15 @@ extract_streams_from_pipe(struct apply_ctx *ctx) } if ((found_lte->resource_location != RESOURCE_NONEXISTENT) - && !(found_lte->resource_entry.flags & WIM_RESHDR_FLAG_METADATA) + && !(found_lte->flags & WIM_RESHDR_FLAG_METADATA) && (needed_lte = lookup_resource(lookup_table, found_lte->hash)) && (needed_lte->out_refcnt)) { - copy_resource_entry(&needed_lte->resource_entry, - &found_lte->resource_entry); - needed_lte->resource_location = found_lte->resource_location; - needed_lte->wim = found_lte->wim; - needed_lte->compression_type = found_lte->compression_type; - needed_lte->is_pipable = found_lte->is_pipable; - + lte_unbind_wim_resource_spec(found_lte); + lte_bind_wim_resource_spec(needed_lte, rspec); ret = extract_stream_instances(needed_lte, ctx, false); + lte_unbind_wim_resource_spec(needed_lte); + if (ret) goto out_free_found_lte; ctx->num_streams_remaining--; @@ -1478,6 +1477,8 @@ extract_streams_from_pipe(struct apply_ctx *ctx) } ret = 0; out_free_found_lte: + if (found_lte->resource_location != RESOURCE_IN_WIM) + FREE(rspec); free_lookup_table_entry(found_lte); out: return ret; @@ -1537,8 +1538,7 @@ extract_dentry_to_stdout(struct wim_dentry *dentry) if (lte) { struct filedes _stdout; filedes_init(&_stdout, STDOUT_FILENO); - ret = extract_wim_resource_to_fd(lte, &_stdout, - wim_resource_size(lte)); + ret = extract_wim_resource_to_fd(lte, &_stdout, lte->size); } } return ret; @@ -2649,7 +2649,7 @@ extract_single_image(WIMStruct *wim, int image, { int ret; tchar *target_copy = canonicalize_fs_path(target); - if (!target_copy) + if (target_copy == NULL) return WIMLIB_ERR_NOMEM; struct wimlib_extract_command cmd = { .wim_source_path = T(""), @@ -2821,11 +2821,12 @@ wimlib_extract_image_from_pipe(int pipe_fd, const tchar *image_num_or_name, * WIMs.) */ { struct wim_lookup_table_entry xml_lte; - ret = read_pwm_stream_header(pwm, &xml_lte, 0, NULL); + struct wim_resource_spec xml_rspec; + ret = read_pwm_stream_header(pwm, &xml_lte, &xml_rspec, 0, NULL); if (ret) goto out_wimlib_free; - if (!(xml_lte.resource_entry.flags & WIM_RESHDR_FLAG_METADATA)) + if (!(xml_lte.flags & WIM_RESHDR_FLAG_METADATA)) { ERROR("Expected XML data, but found non-metadata " "stream."); @@ -2833,12 +2834,12 @@ wimlib_extract_image_from_pipe(int pipe_fd, const tchar *image_num_or_name, goto out_wimlib_free; } - copy_resource_entry(&pwm->hdr.xml_res_entry, - &xml_lte.resource_entry); + wim_res_spec_to_hdr(&xml_rspec, &pwm->hdr.xml_data_reshdr); ret = read_wim_xml_data(pwm); if (ret) goto out_wimlib_free; + if (wim_info_get_num_images(pwm->wim_info) != pwm->hdr.image_count) { ERROR("Image count in XML data is not the same as in WIM header."); ret = WIMLIB_ERR_XML; @@ -2874,22 +2875,29 @@ wimlib_extract_image_from_pipe(int pipe_fd, const tchar *image_num_or_name, for (i = 1; i <= pwm->hdr.image_count; i++) { struct wim_lookup_table_entry *metadata_lte; struct wim_image_metadata *imd; + struct wim_resource_spec *metadata_rspec; metadata_lte = new_lookup_table_entry(); - if (!metadata_lte) { + if (metadata_lte == NULL) { ret = WIMLIB_ERR_NOMEM; goto out_wimlib_free; } + metadata_rspec = MALLOC(sizeof(struct wim_resource_spec)); + if (metadata_rspec == NULL) { + ret = WIMLIB_ERR_NOMEM; + free_lookup_table_entry(metadata_lte); + goto out_wimlib_free; + } - ret = read_pwm_stream_header(pwm, metadata_lte, 0, NULL); + ret = read_pwm_stream_header(pwm, metadata_lte, metadata_rspec, 0, NULL); imd = pwm->image_metadata[i - 1]; imd->metadata_lte = metadata_lte; - if (ret) + if (ret) { + FREE(metadata_rspec); goto out_wimlib_free; + } - if (!(metadata_lte->resource_entry.flags & - WIM_RESHDR_FLAG_METADATA)) - { + if (!(metadata_lte->flags & WIM_RESHDR_FLAG_METADATA)) { ERROR("Expected metadata resource, but found " "non-metadata stream."); ret = WIMLIB_ERR_INVALID_PIPABLE_WIM; diff --git a/src/header.c b/src/header.c index 4924b505..d3ab360c 100644 --- a/src/header.c +++ b/src/header.c @@ -48,18 +48,16 @@ /* * Reads the header from a WIM file. * - * @filename - * Name of the WIM file (for error/debug messages only), or NULL if reading - * directly from file descriptor. - * @in_fd - * File descriptor, positioned at offset 0, to read the header from. + * @wim + * WIM to read the header from; @wim->in_fd must be positioned at the + * offset at which to read the header. + * * @hdr * Structure to read the header into. * * Return values: * WIMLIB_ERR_SUCCESS (0) * WIMLIB_ERR_IMAGE_COUNT - * WIMLIB_ERR_INVALID_CHUNK_SIZE * WIMLIB_ERR_INVALID_PART_NUMBER * WIMLIB_ERR_NOT_A_WIM_FILE * WIMLIB_ERR_READ @@ -67,10 +65,11 @@ * WIMLIB_ERR_UNKNOWN_VERSION */ int -read_wim_header(const tchar *filename, struct filedes *in_fd, - struct wim_header *hdr) +read_wim_header(WIMStruct *wim, struct wim_header *hdr) { struct wim_header_disk disk_hdr _aligned_attribute(8); + struct filedes *in_fd = &wim->in_fd; + const tchar *filename = wim->filename; int ret; tchar *pipe_str; @@ -113,14 +112,11 @@ read_wim_header(const tchar *filename, struct filedes *in_fd, return WIMLIB_ERR_INVALID_HEADER; } - 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, le32_to_cpu(disk_hdr.wim_version), WIM_VERSION); - if (le32_to_cpu(disk_hdr.wim_flags) & WIM_HDR_FLAG_COMPRESS_LZMS) { - ERROR("\"%"TS"\": This WIM uses LZMS compression, " - "which is not supported by wimlib.", filename); - } + hdr->wim_version = le32_to_cpu(disk_hdr.wim_version); + if (hdr->wim_version != WIM_VERSION_DEFAULT && + hdr->wim_version != WIM_VERSION_STREAM_CONCAT) + { + ERROR("\"%"TS"\": Unknown WIM version: %u", hdr->wim_version); return WIMLIB_ERR_UNKNOWN_VERSION; } @@ -149,11 +145,11 @@ read_wim_header(const tchar *filename, struct filedes *in_fd, return WIMLIB_ERR_IMAGE_COUNT; } - 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); + get_wim_reshdr(&disk_hdr.lookup_table_reshdr, &hdr->lookup_table_reshdr); + get_wim_reshdr(&disk_hdr.xml_data_reshdr, &hdr->xml_data_reshdr); + get_wim_reshdr(&disk_hdr.boot_metadata_reshdr, &hdr->boot_metadata_reshdr); hdr->boot_idx = le32_to_cpu(disk_hdr.boot_idx); - get_resource_entry(&disk_hdr.integrity_table_res_entry, &hdr->integrity); + get_wim_reshdr(&disk_hdr.integrity_table_reshdr, &hdr->integrity_table_reshdr); return 0; read_error: @@ -177,7 +173,7 @@ write_wim_header_at_offset(const struct wim_header *hdr, struct filedes *out_fd, disk_hdr.magic = hdr->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_version = cpu_to_le32(hdr->wim_version); disk_hdr.wim_flags = cpu_to_le32(hdr->flags); if (hdr->flags & WIM_HDR_FLAG_COMPRESSION) disk_hdr.chunk_size = cpu_to_le32(hdr->chunk_size); @@ -188,11 +184,11 @@ write_wim_header_at_offset(const struct wim_header *hdr, struct filedes *out_fd, 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); + put_wim_reshdr(&hdr->lookup_table_reshdr, &disk_hdr.lookup_table_reshdr); + put_wim_reshdr(&hdr->xml_data_reshdr, &disk_hdr.xml_data_reshdr); + put_wim_reshdr(&hdr->boot_metadata_reshdr, &disk_hdr.boot_metadata_reshdr); disk_hdr.boot_idx = cpu_to_le32(hdr->boot_idx); - put_resource_entry(&hdr->integrity, &disk_hdr.integrity_table_res_entry); + put_wim_reshdr(&hdr->integrity_table_reshdr, &disk_hdr.integrity_table_reshdr); memset(disk_hdr.unused, 0, sizeof(disk_hdr.unused)); if (offset == out_fd->offset) @@ -256,6 +252,7 @@ init_wim_header(struct wim_header *hdr, int ctype, u32 chunk_size) { memset(hdr, 0, sizeof(struct wim_header)); hdr->magic = WIM_MAGIC; + hdr->wim_version = WIM_VERSION_DEFAULT; if (set_wim_hdr_cflags(ctype, hdr)) { ERROR("Invalid compression type specified (%d)", ctype); return WIMLIB_ERR_INVALID_COMPRESSION_TYPE; @@ -293,51 +290,51 @@ wimlib_print_header(const WIMStruct *wim) tprintf(T("Magic Characters = MSWIM\\000\\000\\000\n")); tprintf(T("Header Size = %u\n"), WIM_HEADER_DISK_SIZE); - tprintf(T("Version = 0x%x\n"), WIM_VERSION); + tprintf(T("Version = 0x%x\n"), hdr->wim_version); tprintf(T("Flags = 0x%x\n"), hdr->flags); for (size_t i = 0; i < ARRAY_LEN(hdr_flags); i++) if (hdr_flags[i].flag & hdr->flags) tprintf(T(" WIM_HDR_FLAG_%s is set\n"), hdr_flags[i].name); - tprintf(T("Chunk Size = %u\n"), wim->hdr.chunk_size); + tprintf(T("Chunk Size = %u\n"), hdr->chunk_size); tfputs (T("GUID = "), stdout); print_byte_field(hdr->guid, WIM_GID_LEN, stdout); tputchar(T('\n')); - tprintf(T("Part Number = %hu\n"), wim->hdr.part_number); - tprintf(T("Total Parts = %hu\n"), wim->hdr.total_parts); + tprintf(T("Part Number = %hu\n"), hdr->part_number); + tprintf(T("Total Parts = %hu\n"), hdr->total_parts); tprintf(T("Image Count = %u\n"), hdr->image_count); tprintf(T("Lookup Table Size = %"PRIu64"\n"), - (u64)hdr->lookup_table_res_entry.size); + (u64)hdr->lookup_table_reshdr.size_in_wim); tprintf(T("Lookup Table Flags = 0x%hhx\n"), - (u8)hdr->lookup_table_res_entry.flags); + (u8)hdr->lookup_table_reshdr.flags); tprintf(T("Lookup Table Offset = %"PRIu64"\n"), - hdr->lookup_table_res_entry.offset); + hdr->lookup_table_reshdr.offset_in_wim); tprintf(T("Lookup Table Original_size = %"PRIu64"\n"), - hdr->lookup_table_res_entry.original_size); + hdr->lookup_table_reshdr.uncompressed_size); tprintf(T("XML Data Size = %"PRIu64"\n"), - (u64)hdr->xml_res_entry.size); + (u64)hdr->xml_data_reshdr.size_in_wim); tprintf(T("XML Data Flags = 0x%hhx\n"), - (u8)hdr->xml_res_entry.flags); + (u8)hdr->xml_data_reshdr.flags); tprintf(T("XML Data Offset = %"PRIu64"\n"), - hdr->xml_res_entry.offset); + hdr->xml_data_reshdr.offset_in_wim); tprintf(T("XML Data Original Size = %"PRIu64"\n"), - hdr->xml_res_entry.original_size); + hdr->xml_data_reshdr.uncompressed_size); tprintf(T("Boot Metadata Size = %"PRIu64"\n"), - (u64)hdr->boot_metadata_res_entry.size); + (u64)hdr->boot_metadata_reshdr.size_in_wim); tprintf(T("Boot Metadata Flags = 0x%hhx\n"), - (u8)hdr->boot_metadata_res_entry.flags); + (u8)hdr->boot_metadata_reshdr.flags); tprintf(T("Boot Metadata Offset = %"PRIu64"\n"), - hdr->boot_metadata_res_entry.offset); + hdr->boot_metadata_reshdr.offset_in_wim); tprintf(T("Boot Metadata Original Size = %"PRIu64"\n"), - hdr->boot_metadata_res_entry.original_size); + hdr->boot_metadata_reshdr.uncompressed_size); tprintf(T("Boot Index = %u\n"), hdr->boot_idx); tprintf(T("Integrity Size = %"PRIu64"\n"), - (u64)hdr->integrity.size); + (u64)hdr->integrity_table_reshdr.size_in_wim); tprintf(T("Integrity Flags = 0x%hhx\n"), - (u8)hdr->integrity.flags); + (u8)hdr->integrity_table_reshdr.flags); tprintf(T("Integrity Offset = %"PRIu64"\n"), - hdr->integrity.offset); + hdr->integrity_table_reshdr.offset_in_wim); tprintf(T("Integrity Original_size = %"PRIu64"\n"), - hdr->integrity.original_size); + hdr->integrity_table_reshdr.uncompressed_size); } diff --git a/src/integrity.c b/src/integrity.c index 21bc2f15..8e1df189 100644 --- a/src/integrity.c +++ b/src/integrity.c @@ -37,6 +37,7 @@ #include "wimlib/resource.h" #include "wimlib/sha1.h" #include "wimlib/wim.h" +#include "wimlib/write.h" /* Size, in bytes, of each SHA1-summed chunk, when wimlib writes integrity * information. */ @@ -87,9 +88,8 @@ calculate_chunk_sha1(struct filedes *in_fd, size_t this_chunk_size, * read_integrity_table: - Reads the integrity table from a WIM file. * * @wim: - * WIMStruct for the WIM file; @wim->hdr.integrity specifies the location - * of the integrity table. The integrity table must exist (i.e. - * res_entry->offset must not be 0). @wim->in_fd is expected to be a + * WIMStruct for the WIM file; @wim->hdr.integrity_table_reshdr specifies + * the location of the integrity table. @wim->in_fd is expected to be a * seekable file descriptor to the WIM file opened for reading. * * @num_checked_bytes: @@ -114,14 +114,12 @@ read_integrity_table(WIMStruct *wim, u64 num_checked_bytes, struct integrity_table *table; int ret; - if (wim->hdr.integrity.size < 8) + if (wim->hdr.integrity_table_reshdr.uncompressed_size < 8) goto invalid; - DEBUG("Reading integrity table (offset %"PRIu64", " - "original_size %"PRIu64")", - wim->hdr.integrity.offset, wim->hdr.integrity.original_size); + DEBUG("Reading integrity table."); - ret = res_entry_to_data(&wim->hdr.integrity, wim, &buf); + ret = wim_reshdr_to_data(&wim->hdr.integrity_table_reshdr, wim, &buf); if (ret) return ret; table = buf; @@ -134,7 +132,7 @@ read_integrity_table(WIMStruct *wim, u64 num_checked_bytes, "table->chunk_size = %u", table->size, table->num_entries, table->chunk_size); - if (table->size != wim->hdr.integrity.original_size || + if (table->size != wim->hdr.integrity_table_reshdr.uncompressed_size || table->size != (u64)table->num_entries * SHA1_HASH_SIZE + 12 || table->chunk_size == 0 || table->num_entries != DIV_ROUND_UP(num_checked_bytes, table->chunk_size)) @@ -282,8 +280,8 @@ calculate_integrity_table(struct filedes *in_fd, * chunks of the file). * * This function can optionally re-use entries from an older integrity table. - * To do this, make @integrity_res_entry point to the resource entry for the - * older table (note: this is an input-output parameter), and set + * To do this, ensure that @wim->hdr.integrity_table_reshdr is the resource + * header for the older table (note: this is an input-output parameter), and set * @old_lookup_table_end to the offset of the byte directly following the last * byte checked by the old table. If the old integrity table is invalid or * cannot be read, a warning is printed and the integrity information is @@ -366,7 +364,7 @@ write_integrity_table(WIMStruct *wim, &wim->out_fd, WIMLIB_COMPRESSION_TYPE_NONE, 0, - &wim->hdr.integrity, + &wim->hdr.integrity_table_reshdr, NULL, 0, &wim->lzx_context); @@ -486,8 +484,8 @@ check_wim_integrity(WIMStruct *wim, wimlib_progress_func_t progress_func) return WIM_INTEGRITY_NONEXISTENT; } - end_lookup_table_offset = wim->hdr.lookup_table_res_entry.offset + - wim->hdr.lookup_table_res_entry.size; + end_lookup_table_offset = wim->hdr.lookup_table_reshdr.offset_in_wim + + wim->hdr.lookup_table_reshdr.size_in_wim; if (end_lookup_table_offset < WIM_HEADER_DISK_SIZE) { ERROR("WIM lookup table ends before WIM header ends!"); diff --git a/src/lookup_table.c b/src/lookup_table.c index 302b1750..d08498f8 100644 --- a/src/lookup_table.c +++ b/src/lookup_table.c @@ -74,16 +74,15 @@ new_lookup_table_entry(void) struct wim_lookup_table_entry *lte; lte = CALLOC(1, sizeof(struct wim_lookup_table_entry)); - if (lte) { - lte->part_number = 1; - lte->refcnt = 1; - BUILD_BUG_ON(RESOURCE_NONEXISTENT != 0); - BUILD_BUG_ON(WIMLIB_COMPRESSION_TYPE_NONE != 0); - } else { + if (lte == NULL) { ERROR("Out of memory (tried to allocate %zu bytes for " "lookup table entry)", sizeof(struct wim_lookup_table_entry)); + return NULL; } + lte->refcnt = 1; + BUILD_BUG_ON(RESOURCE_NONEXISTENT != 0); + BUILD_BUG_ON(WIMLIB_COMPRESSION_TYPE_NONE != 0); return lte; } @@ -98,6 +97,10 @@ clone_lookup_table_entry(const struct wim_lookup_table_entry *old) new->extracted_file = NULL; switch (new->resource_location) { + case RESOURCE_IN_WIM: + list_add(&new->wim_resource_list, &new->rspec->lte_list); + break; + case RESOURCE_IN_FILE_ON_DISK: #ifdef __WIN32__ case RESOURCE_WIN32_ENCRYPTED: @@ -112,8 +115,7 @@ clone_lookup_table_entry(const struct wim_lookup_table_entry *old) goto out_free; break; case RESOURCE_IN_ATTACHED_BUFFER: - new->attached_buffer = memdup(old->attached_buffer, - wim_resource_size(old)); + new->attached_buffer = memdup(old->attached_buffer, old->size); if (!new->attached_buffer) goto out_free; break; @@ -153,6 +155,11 @@ free_lookup_table_entry(struct wim_lookup_table_entry *lte) { if (lte) { switch (lte->resource_location) { + case RESOURCE_IN_WIM: + list_del(<e->wim_resource_list); + if (list_empty(<e->rspec->lte_list)) + FREE(lte->rspec); + break; case RESOURCE_IN_FILE_ON_DISK: #ifdef __WIN32__ case RESOURCE_WIN32_ENCRYPTED: @@ -303,6 +310,7 @@ cmp_streams_by_sequential_order(const void *p1, const void *p2) { const struct wim_lookup_table_entry *lte1, *lte2; int v; + WIMStruct *wim1, *wim2; lte1 = *(const struct wim_lookup_table_entry**)p1; lte2 = *(const struct wim_lookup_table_entry**)p2; @@ -315,24 +323,25 @@ cmp_streams_by_sequential_order(const void *p1, const void *p2) switch (lte1->resource_location) { case RESOURCE_IN_WIM: + wim1 = lte1->rspec->wim; + wim2 = lte2->rspec->wim; /* Different (possibly split) WIMs? */ - if (lte1->wim != lte2->wim) { - v = memcmp(lte1->wim->hdr.guid, lte2->wim->hdr.guid, - WIM_GID_LEN); + if (wim1 != wim2) { + v = memcmp(wim1->hdr.guid, wim2->hdr.guid, WIM_GID_LEN); if (v) return v; } /* Different part numbers in the same WIM? */ - v = (int)lte1->wim->hdr.part_number - (int)lte2->wim->hdr.part_number; + v = (int)wim1->hdr.part_number - (int)wim2->hdr.part_number; if (v) return v; /* Compare by offset. */ - if (lte1->resource_entry.offset < lte2->resource_entry.offset) + if (lte1->rspec->offset_in_wim < lte2->rspec->offset_in_wim) return -1; - else if (lte1->resource_entry.offset > lte2->resource_entry.offset) + if (lte1->rspec->offset_in_wim > lte2->rspec->offset_in_wim) return 1; return 0; case RESOURCE_IN_FILE_ON_DISK: @@ -439,9 +448,8 @@ for_lookup_table_entry_pos_sorted(struct wim_lookup_table *table, /* 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, offset, and flags of the stream. */ + struct wim_reshdr_disk reshdr; /* Which part of the split WIM this stream is in; indexed from 1. */ le16 part_number; @@ -456,20 +464,6 @@ struct wim_lookup_table_entry_disk { #define WIM_LOOKUP_TABLE_ENTRY_DISK_SIZE 50 -void -lte_init_wim(struct wim_lookup_table_entry *lte, WIMStruct *wim) -{ - lte->resource_location = RESOURCE_IN_WIM; - lte->wim = wim; - if (lte->resource_entry.flags & WIM_RESHDR_FLAG_COMPRESSED) - lte->compression_type = wim->compression_type; - else - lte->compression_type = WIMLIB_COMPRESSION_TYPE_NONE; - - if (wim_is_pipable(wim)) - lte->is_pipable = 1; -} - /* * Reads the lookup table from a WIM file. * @@ -491,21 +485,19 @@ read_wim_lookup_table(WIMStruct *wim) struct wim_lookup_table *table; struct wim_lookup_table_entry *cur_entry, *duplicate_entry; void *buf; + bool in_concat_run; BUILD_BUG_ON(sizeof(struct wim_lookup_table_entry_disk) != WIM_LOOKUP_TABLE_ENTRY_DISK_SIZE); - DEBUG("Reading lookup table: offset %"PRIu64", size %"PRIu64"", - wim->hdr.lookup_table_res_entry.offset, - wim->hdr.lookup_table_res_entry.size); + DEBUG("Reading lookup table."); /* Calculate number of entries in the lookup table. */ - num_entries = wim->hdr.lookup_table_res_entry.size / + num_entries = wim->hdr.lookup_table_reshdr.uncompressed_size / sizeof(struct wim_lookup_table_entry_disk); - /* Read the lookup table into a buffer. */ - ret = res_entry_to_data(&wim->hdr.lookup_table_res_entry, wim, &buf); + ret = wim_reshdr_to_data(&wim->hdr.lookup_table_reshdr, wim, &buf); if (ret) goto out; @@ -520,33 +512,32 @@ read_wim_lookup_table(WIMStruct *wim) /* Allocate and initalize `struct wim_lookup_table_entry's from the * on-disk lookup table. */ wim->current_image = 0; + in_concat_run = false; for (i = 0; i < num_entries; i++) { const struct wim_lookup_table_entry_disk *disk_entry = &((const struct wim_lookup_table_entry_disk*)buf)[i]; + u16 part_number; + struct wim_reshdr reshdr; + struct wim_resource_spec *cur_rspec; cur_entry = new_lookup_table_entry(); - if (!cur_entry) { + if (cur_entry == NULL) { ERROR("Not enough memory to read lookup table."); ret = WIMLIB_ERR_NOMEM; goto out_free_lookup_table; } - cur_entry->wim = wim; - cur_entry->resource_location = RESOURCE_IN_WIM; - get_resource_entry(&disk_entry->resource_entry, &cur_entry->resource_entry); - cur_entry->part_number = le16_to_cpu(disk_entry->part_number); + 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); - lte_init_wim(cur_entry, wim); - if (cur_entry->part_number != wim->hdr.part_number) { + if (part_number != wim->hdr.part_number) { WARNING("A lookup table entry in part %hu of the WIM " "points to part %hu (ignoring it)", - wim->hdr.part_number, cur_entry->part_number); + wim->hdr.part_number, part_number); free_lookup_table_entry(cur_entry); continue; } - if (is_zero_hash(cur_entry->hash)) { WARNING("The WIM lookup table contains an entry with a " "SHA1 message digest of all 0's (ignoring it)"); @@ -554,29 +545,18 @@ read_wim_lookup_table(WIMStruct *wim) continue; } - if (!(cur_entry->resource_entry.flags & WIM_RESHDR_FLAG_COMPRESSED) - && (cur_entry->resource_entry.size != - cur_entry->resource_entry.original_size)) - { - if (wimlib_print_errors) { - WARNING("Found uncompressed resource with " - "original size (%"PRIu64") not the same " - "as compressed size (%"PRIu64")", - cur_entry->resource_entry.original_size, - cur_entry->resource_entry.size); - if (cur_entry->resource_entry.original_size) { - WARNING("Overriding compressed size with original size."); - cur_entry->resource_entry.size = - cur_entry->resource_entry.original_size; - } else { - WARNING("Overriding original size with compressed size"); - cur_entry->resource_entry.original_size = - cur_entry->resource_entry.size; - } - } + cur_rspec = MALLOC(sizeof(struct wim_resource_spec)); + if (cur_rspec == NULL) { + ERROR("Not enough memory to read lookup table."); + ret = WIMLIB_ERR_NOMEM; + goto out_free_cur_entry; } - if (cur_entry->resource_entry.flags & WIM_RESHDR_FLAG_METADATA) { + get_wim_reshdr(&disk_entry->reshdr, &reshdr); + wim_res_hdr_to_spec(&reshdr, wim, cur_rspec); + lte_bind_wim_resource_spec(cur_entry, cur_rspec); + + if (cur_entry->flags & WIM_RESHDR_FLAG_METADATA) { /* Lookup table entry for a metadata resource */ if (cur_entry->refcnt != 1) { /* Metadata entries with no references must be @@ -619,7 +599,7 @@ read_wim_lookup_table(WIMStruct *wim) DEBUG("Found metadata resource for image %u at " "offset %"PRIu64".", wim->current_image + 1, - cur_entry->resource_entry.offset); + cur_entry->rspec->offset_in_wim); wim->image_metadata[ wim->current_image++]->metadata_lte = cur_entry; } else { @@ -657,6 +637,7 @@ read_wim_lookup_table(WIMStruct *wim) wim->lookup_table = table; ret = 0; goto out_free_buf; + out_free_cur_entry: FREE(cur_entry); out_free_lookup_table: @@ -671,10 +652,11 @@ out: static void write_wim_lookup_table_entry(const struct wim_lookup_table_entry *lte, - struct wim_lookup_table_entry_disk *disk_entry) + struct wim_lookup_table_entry_disk *disk_entry, + u16 part_number) { - put_resource_entry(<e->output_resource_entry, &disk_entry->resource_entry); - disk_entry->part_number = cpu_to_le16(lte->part_number); + put_wim_reshdr(<e->out_reshdr, &disk_entry->reshdr); + disk_entry->part_number = cpu_to_le16(part_number); disk_entry->refcnt = cpu_to_le32(lte->out_refcnt); copy_hash(disk_entry->hash, lte->hash); } @@ -682,7 +664,8 @@ write_wim_lookup_table_entry(const struct wim_lookup_table_entry *lte, static int write_wim_lookup_table_from_stream_list(struct list_head *stream_list, struct filedes *out_fd, - struct resource_entry *out_res_entry, + u16 part_number, + struct wim_reshdr *out_reshdr, int write_resource_flags, struct wimlib_lzx_context **comp_ctx) { @@ -707,7 +690,7 @@ write_wim_lookup_table_from_stream_list(struct list_head *stream_list, } table_buf_ptr = table_buf; list_for_each_entry(lte, stream_list, lookup_table_list) - write_wim_lookup_table_entry(lte, table_buf_ptr++); + write_wim_lookup_table_entry(lte, table_buf_ptr++, part_number); /* Write the lookup table uncompressed. Although wimlib can handle a * compressed lookup table, MS software cannot. */ @@ -717,7 +700,7 @@ write_wim_lookup_table_from_stream_list(struct list_head *stream_list, out_fd, WIMLIB_COMPRESSION_TYPE_NONE, 0, - out_res_entry, + out_reshdr, NULL, write_resource_flags, comp_ctx); @@ -746,10 +729,8 @@ append_lookup_table_entry(struct wim_lookup_table_entry *lte, void *_list) * needs to be copied from the resource information read originally. */ if (lte->out_refcnt != 0 && !(lte->filtered & FILTERED_EXTERNAL_WIM)) { - if (lte->filtered & FILTERED_SAME_WIM) { - copy_resource_entry(<e->output_resource_entry, - <e->resource_entry); - } + if (lte->filtered & FILTERED_SAME_WIM) + wim_res_spec_to_hdr(lte->rspec, <e->out_reshdr); list_add_tail(<e->lookup_table_list, (struct list_head*)_list); } return 0; @@ -757,7 +738,7 @@ append_lookup_table_entry(struct wim_lookup_table_entry *lte, void *_list) int write_wim_lookup_table(WIMStruct *wim, int image, int write_flags, - struct resource_entry *out_res_entry, + struct wim_reshdr *out_reshdr, struct list_head *stream_list_override) { int write_resource_flags; @@ -791,9 +772,7 @@ write_wim_lookup_table(WIMStruct *wim, int image, int write_flags, metadata_lte = wim->image_metadata[i - 1]->metadata_lte; metadata_lte->out_refcnt = 1; - metadata_lte->part_number = wim->hdr.part_number; - metadata_lte->output_resource_entry.flags |= WIM_RESHDR_FLAG_METADATA; - + metadata_lte->out_reshdr.flags |= WIM_RESHDR_FLAG_METADATA; list_add(&metadata_lte->lookup_table_list, stream_list); } } @@ -811,7 +790,8 @@ write_wim_lookup_table(WIMStruct *wim, int image, int write_flags, write_resource_flags |= WIMLIB_WRITE_RESOURCE_FLAG_PIPABLE; return write_wim_lookup_table_from_stream_list(stream_list, &wim->out_fd, - out_res_entry, + wim->hdr.part_number, + out_reshdr, write_resource_flags, &wim->lzx_context); } @@ -844,21 +824,21 @@ lte_free_extracted_file(struct wim_lookup_table_entry *lte, void *_ignore) void print_lookup_table_entry(const struct wim_lookup_table_entry *lte, FILE *out) { - if (!lte) { + if (lte == NULL) { tputc(T('\n'), out); return; } - tfprintf(out, T("Offset = %"PRIu64" bytes\n"), - lte->resource_entry.offset); - tfprintf(out, T("Size = %"PRIu64" bytes\n"), - (u64)lte->resource_entry.size); + tfprintf(out, T("Reference Count = %u\n"), lte->refcnt); + tfprintf(out, T("Uncompressed Size = %"PRIu64" bytes\n"), lte->size); - tfprintf(out, T("Original size = %"PRIu64" bytes\n"), - lte->resource_entry.original_size); + if (lte->resource_location == RESOURCE_IN_WIM) { + tfprintf(out, T("Offset in WIM = %"PRIu64" bytes\n"), + lte->rspec->offset_in_wim); - tfprintf(out, T("Part Number = %hu\n"), lte->part_number); - tfprintf(out, T("Reference Count = %u\n"), lte->refcnt); + tfprintf(out, T("Size in WIM = %"PRIu64" bytes\n"), + lte->rspec->size_in_wim); + } if (lte->unhashed) { tfprintf(out, T("(Unhashed: inode %p, stream_id = %u)\n"), @@ -870,7 +850,7 @@ print_lookup_table_entry(const struct wim_lookup_table_entry *lte, FILE *out) } tfprintf(out, T("Flags = ")); - u8 flags = lte->resource_entry.flags; + u8 flags = lte->flags; if (flags & WIM_RESHDR_FLAG_COMPRESSED) tfputs(T("WIM_RESHDR_FLAG_COMPRESSED, "), out); if (flags & WIM_RESHDR_FLAG_FREE) @@ -879,12 +859,14 @@ print_lookup_table_entry(const struct wim_lookup_table_entry *lte, FILE *out) tfputs(T("WIM_RESHDR_FLAG_METADATA, "), out); if (flags & WIM_RESHDR_FLAG_SPANNED) tfputs(T("WIM_RESHDR_FLAG_SPANNED, "), out); + if (flags & WIM_RESHDR_FLAG_CONCAT) + tfputs(T("WIM_RESHDR_FLAG_CONCAT, "), out); tputc(T('\n'), out); switch (lte->resource_location) { case RESOURCE_IN_WIM: - if (lte->wim->filename) { + if (lte->rspec->wim->filename) { tfprintf(out, T("WIM file = `%"TS"'\n"), - lte->wim->filename); + lte->rspec->wim->filename); } break; #ifdef __WIN32__ @@ -910,16 +892,23 @@ void lte_to_wimlib_resource_entry(const struct wim_lookup_table_entry *lte, struct wimlib_resource_entry *wentry) { - wentry->uncompressed_size = lte->resource_entry.original_size; - wentry->compressed_size = lte->resource_entry.size; - wentry->offset = lte->resource_entry.offset; + wentry->uncompressed_size = lte->size; + + if (lte->resource_location == RESOURCE_IN_WIM) { + wentry->compressed_size = lte->rspec->size_in_wim; + wentry->offset = lte->rspec->offset_in_wim; + wentry->part_number = lte->rspec->wim->hdr.part_number; + } else { + wentry->compressed_size = 0; + wentry->offset = 0; + wentry->part_number = 0; + } copy_hash(wentry->sha1_hash, lte->hash); - wentry->part_number = lte->part_number; wentry->reference_count = lte->refcnt; - wentry->is_compressed = (lte->resource_entry.flags & WIM_RESHDR_FLAG_COMPRESSED) != 0; - wentry->is_metadata = (lte->resource_entry.flags & WIM_RESHDR_FLAG_METADATA) != 0; - wentry->is_free = (lte->resource_entry.flags & WIM_RESHDR_FLAG_FREE) != 0; - wentry->is_spanned = (lte->resource_entry.flags & WIM_RESHDR_FLAG_SPANNED) != 0; + wentry->is_compressed = (lte->flags & WIM_RESHDR_FLAG_COMPRESSED) != 0; + wentry->is_metadata = (lte->flags & WIM_RESHDR_FLAG_METADATA) != 0; + wentry->is_free = (lte->flags & WIM_RESHDR_FLAG_FREE) != 0; + wentry->is_spanned = (lte->flags & WIM_RESHDR_FLAG_SPANNED) != 0; } struct iterate_lte_context { @@ -1257,22 +1246,6 @@ inode_unnamed_stream_hash(const struct wim_inode *inode) return zero_hash; } - -static int -lte_add_stream_size(struct wim_lookup_table_entry *lte, void *total_bytes_p) -{ - *(u64*)total_bytes_p += lte->resource_entry.size; - return 0; -} - -u64 -lookup_table_total_stream_size(struct wim_lookup_table *table) -{ - u64 total_size = 0; - for_lookup_table_entry(table, lte_add_stream_size, &total_size); - return total_size; -} - struct wim_lookup_table_entry ** retrieve_lte_pointer(struct wim_lookup_table_entry *lte) { diff --git a/src/metadata_resource.c b/src/metadata_resource.c index 5ee29664..b5ed165c 100644 --- a/src/metadata_resource.c +++ b/src/metadata_resource.c @@ -31,6 +31,7 @@ #include "wimlib/metadata.h" #include "wimlib/resource.h" #include "wimlib/security.h" +#include "wimlib/write.h" /* * Reads a metadata resource for an image in the WIM file. The metadata @@ -71,13 +72,13 @@ read_metadata_resource(WIMStruct *wim, struct wim_image_metadata *imd) struct wim_inode *inode; metadata_lte = imd->metadata_lte; - metadata_len = wim_resource_size(metadata_lte); + metadata_len = metadata_lte->size; DEBUG("Reading metadata resource: original_size = %"PRIu64", " "size = %"PRIu64", offset = %"PRIu64"", - metadata_lte->resource_entry.original_size, - metadata_lte->resource_entry.size, - metadata_lte->resource_entry.offset); + metadata_lte->rspec->uncompressed_size, + metadata_lte->rspec->size_in_wim, + metadata_lte->rspec->offset_in_wim); /* There is no way the metadata resource could possibly be less than (8 * + WIM_DENTRY_DISK_SIZE) bytes, where the 8 is for security data (with @@ -298,7 +299,7 @@ write_metadata_resource(WIMStruct *wim, int image, int write_resource_flags) &wim->out_fd, wim->out_compression_type, wim->out_chunk_size, - &imd->metadata_lte->output_resource_entry, + &imd->metadata_lte->out_reshdr, imd->metadata_lte->hash, write_resource_flags, &wim->lzx_context); diff --git a/src/mount_image.c b/src/mount_image.c index ce4a5843..b1a3f1c7 100644 --- a/src/mount_image.c +++ b/src/mount_image.c @@ -434,7 +434,7 @@ inode_to_stbuf(const struct wim_inode *inode, stbuf->st_ino = (ino_t)inode->i_ino; stbuf->st_nlink = inode->i_nlink; if (lte) - stbuf->st_size = wim_resource_size(lte); + stbuf->st_size = lte->size; else stbuf->st_size = 0; #ifdef HAVE_STAT_NANOSECOND_PRECISION @@ -568,7 +568,7 @@ extract_resource_to_staging_dir(struct wim_inode *inode, if (old_lte) { struct filedes wimlib_fd; filedes_init(&wimlib_fd, fd); - extract_size = min(wim_resource_size(old_lte), size); + extract_size = min(old_lte->size, size); ret = extract_wim_resource_to_fd(old_lte, &wimlib_fd, extract_size); } else { @@ -663,10 +663,10 @@ extract_resource_to_staging_dir(struct wim_inode *inode, } } - new_lte->refcnt = inode->i_nlink; - new_lte->resource_location = RESOURCE_IN_STAGING_FILE; - new_lte->staging_file_name = staging_file_name; - new_lte->resource_entry.original_size = size; + new_lte->refcnt = inode->i_nlink; + new_lte->resource_location = RESOURCE_IN_STAGING_FILE; + new_lte->staging_file_name = staging_file_name; + new_lte->size = size; lookup_table_insert_unhashed(ctx->wim->lookup_table, new_lte, inode, stream_id); @@ -825,7 +825,7 @@ rebuild_wim(struct wimfs_context *ctx, int write_flags, DEBUG("Freeing entries for zero-length streams"); image_for_each_unhashed_stream_safe(lte, tmp, imd) { wimlib_assert(lte->unhashed); - if (wim_resource_size(lte) == 0) { + if (lte->size == 0) { struct wim_lookup_table_entry **back_ptr; back_ptr = retrieve_lte_pointer(lte); *back_ptr = NULL; @@ -1606,7 +1606,7 @@ wimfs_ftruncate(const char *path, off_t size, struct fuse_file_info *fi) if (ret) return -errno; touch_inode(fd->f_inode); - fd->f_lte->resource_entry.original_size = size; + fd->f_lte->size = size; return 0; } @@ -1639,7 +1639,7 @@ wimfs_getxattr(const char *path, const char *name, char *value, int ret; struct wim_inode *inode; struct wim_ads_entry *ads_entry; - size_t res_size; + u64 stream_size; struct wim_lookup_table_entry *lte; struct wimfs_context *ctx = wimfs_get_context(); @@ -1659,12 +1659,12 @@ wimfs_getxattr(const char *path, const char *name, char *value, return -ENOATTR; lte = ads_entry->lte; - res_size = wim_resource_size(lte); + stream_size = lte->size; if (size == 0) - return res_size; + return stream_size; - if (res_size > size) + if (stream_size > size) return -ERANGE; ret = read_full_resource_into_buf(lte, value); @@ -1674,7 +1674,7 @@ wimfs_getxattr(const char *path, const char *name, char *value, else return -EIO; } - return res_size; + return stream_size; } #endif @@ -1857,7 +1857,7 @@ wimfs_open(const char *path, struct fuse_file_info *fi) if (flags_writable(fi->flags) && (!lte || lte->resource_location != RESOURCE_IN_STAGING_FILE)) { - u64 size = (lte) ? wim_resource_size(lte) : 0; + u64 size = (lte) ? lte->size : 0; ret = extract_resource_to_staging_dir(inode, stream_id, <e, size, ctx); if (ret) @@ -1915,7 +1915,7 @@ wimfs_read(const char *path, char *buf, size_t size, { struct wimfs_fd *fd = (struct wimfs_fd*)(uintptr_t)fi->fh; ssize_t ret; - u64 res_size; + u64 stream_size; if (!fd) return -EBADF; @@ -1924,14 +1924,14 @@ wimfs_read(const char *path, char *buf, size_t size, return 0; if (fd->f_lte) - res_size = wim_resource_size(fd->f_lte); + stream_size = fd->f_lte->size; else - res_size = 0; + stream_size = 0; - if (offset > res_size) + if (offset > stream_size) return -EOVERFLOW; - size = min(size, res_size - offset); + size = min(size, stream_size - offset); if (size == 0) return 0; @@ -2205,7 +2205,7 @@ wimfs_truncate(const char *path, off_t size) if (ret) ret = -errno; else - lte->resource_entry.original_size = size; + lte->size = size; } else { /* File in WIM. Extract it to the staging directory, but only * the first @size bytes of it. */ @@ -2325,11 +2325,10 @@ wimfs_write(const char *path, const char *buf, size_t size, return -errno; /* Update file size */ - if (offset + size > fd->f_lte->resource_entry.original_size) { + if (offset + size > fd->f_lte->size) { DEBUG("Update file size %"PRIu64 " => %"PRIu64"", - fd->f_lte->resource_entry.original_size, - offset + size); - fd->f_lte->resource_entry.original_size = offset + size; + fd->f_lte->size, offset + size); + fd->f_lte->size = offset + size; } /* Update timestamps */ diff --git a/src/ntfs-3g_apply.c b/src/ntfs-3g_apply.c index 356f5fe7..b49e53a7 100644 --- a/src/ntfs-3g_apply.c +++ b/src/ntfs-3g_apply.c @@ -261,13 +261,13 @@ ntfs_3g_extract_stream(file_spec_t file, const utf16lechar *raw_stream_name, * to skip even more useless work (for example it fills resized * attributes with 0's, then we just override it.) */ ret = WIMLIB_ERR_WRITE; - if (ntfs_attr_truncate_solid(na, wim_resource_size(lte))) + if (ntfs_attr_truncate_solid(na, lte->size)) goto out_attr_close; /* Extract stream data to the NTFS attribute. */ extract_ctx.na = na; extract_ctx.offset = 0; - ret = extract_wim_resource(lte, wim_resource_size(lte), + ret = extract_wim_resource(lte, lte->size, ntfs_3g_extract_wim_chunk, &extract_ctx); /* Clean up and return. */ out_attr_close: diff --git a/src/ntfs-3g_capture.c b/src/ntfs-3g_capture.c index 6daf0a54..829c41c9 100644 --- a/src/ntfs-3g_capture.c +++ b/src/ntfs-3g_capture.c @@ -258,14 +258,14 @@ capture_ntfs_streams(struct wim_inode *inode, goto out_free_lte; } lte->ntfs_loc->is_reparse_point = true; - lte->resource_entry.original_size = data_size - 8; + lte->size = data_size - 8; ret = read_reparse_tag(ni, lte->ntfs_loc, &inode->i_reparse_tag); if (ret) goto out_free_lte; } else { lte->ntfs_loc->is_reparse_point = false; - lte->resource_entry.original_size = data_size; + lte->size = data_size; } } if (name_length == 0) { @@ -275,8 +275,8 @@ capture_ntfs_streams(struct wim_inode *inode, if (lte) { ERROR("Found two un-named data streams for \"%s\" " "(sizes = %"PRIu64", %"PRIu64")", - path, wim_resource_size(inode->i_lte), - wim_resource_size(lte)); + path, inode->i_lte->size, + lte->size); ret = WIMLIB_ERR_NTFS_3G; goto out_free_lte; } diff --git a/src/reparse.c b/src/reparse.c index 1cbca56f..cbb3a08c 100644 --- a/src/reparse.c +++ b/src/reparse.c @@ -292,11 +292,11 @@ wim_inode_get_reparse_data(const struct wim_inode * restrict inode, lte = lte_override; } - if (wim_resource_size(lte) > REPARSE_POINT_MAX_SIZE - 8) { + if (lte->size > REPARSE_POINT_MAX_SIZE - 8) { ERROR("Reparse data is too long!"); return WIMLIB_ERR_INVALID_REPARSE_DATA; } - rpdatalen = wim_resource_size(lte); + rpdatalen = lte->size; /* Read the data from the WIM file */ ret = read_full_resource_into_buf(lte, rpbuf + 8); diff --git a/src/resource.c b/src/resource.c index 892aff18..d8897448 100644 --- a/src/resource.c +++ b/src/resource.c @@ -120,7 +120,7 @@ decompress(const void *cchunk, unsigned clen, /* Read data from a compressed WIM resource. Assumes parameters were already * verified by read_partial_wim_resource(). */ static int -read_compressed_wim_resource(const struct wim_lookup_table_entry * const lte, +read_compressed_wim_resource(const struct wim_resource_spec * const rspec, const u64 size, const consume_data_callback_t cb, const u32 cb_chunk_size, void * const ctx_or_buf, const int flags, const u64 offset) @@ -128,7 +128,7 @@ read_compressed_wim_resource(const struct wim_lookup_table_entry * const lte, int ret; int errno_save; - const u32 orig_chunk_size = wim_resource_chunk_size(lte); + const u32 orig_chunk_size = rspec->cchunk_size; const u32 orig_chunk_order = bsr32(orig_chunk_size); wimlib_assert(is_power_of_2(orig_chunk_size)); @@ -147,13 +147,13 @@ read_compressed_wim_resource(const struct wim_lookup_table_entry * const lte, bool compressed_buf_malloced = false; /* Get the file descriptor for the WIM. */ - struct filedes * const in_fd = <e->wim->in_fd; + struct filedes * const in_fd = &rspec->wim->in_fd; /* Determine if we're reading a pipable resource from a pipe or not. */ const bool is_pipe_read = !filedes_is_seekable(in_fd); /* Calculate the number of chunks the resource is divided into. */ - const u64 num_chunks = wim_resource_chunks(lte); + const u64 num_chunks = (rspec->uncompressed_size + orig_chunk_size - 1) >> orig_chunk_order; /* Calculate the 0-based index of the chunk at which the read starts. */ @@ -180,13 +180,13 @@ read_compressed_wim_resource(const struct wim_lookup_table_entry * const lte, /* Set the size of each chunk table entry based on the resource's * uncompressed size. */ - const u64 chunk_entry_size = (wim_resource_size(lte) > (1ULL << 32)) ? 8 : 4; + const u64 chunk_entry_size = (rspec->uncompressed_size > (1ULL << 32)) ? 8 : 4; /* Calculate the size, in bytes, of the full chunk table. */ const u64 chunk_table_size = num_chunk_entries * chunk_entry_size; /* Current offset to read from. */ - u64 cur_read_offset = lte->resource_entry.offset; + u64 cur_read_offset = rspec->offset_in_wim; if (!is_pipe_read) { /* Read the chunk table into memory. */ @@ -242,9 +242,9 @@ read_compressed_wim_resource(const struct wim_lookup_table_entry * const lte, * file is in the special "pipable" format, then the chunk table * is at the end of the resource, not the beginning. */ const u64 file_offset_of_needed_chunk_entries = - lte->resource_entry.offset + rspec->offset_in_wim + (start_table_idx * chunk_entry_size) - + (lte->is_pipable ? (lte->resource_entry.size - chunk_table_size) : 0); + + (rspec->is_pipable ? (rspec->size_in_wim - chunk_table_size) : 0); /* Read the needed chunk table entries into the end of the * chunk_offsets buffer. */ @@ -282,7 +282,7 @@ read_compressed_wim_resource(const struct wim_lookup_table_entry * const lte, /* Set offset to beginning of first chunk to read. */ cur_read_offset += chunk_offsets[0]; - if (lte->is_pipable) + if (rspec->is_pipable) cur_read_offset += start_chunk * sizeof(struct pwm_chunk_hdr); else cur_read_offset += chunk_table_size; @@ -330,7 +330,7 @@ read_compressed_wim_resource(const struct wim_lookup_table_entry * const lte, * chunks for which only part of the data is needed. */ if (start_offset_in_chunk != 0 || (end_offset_in_chunk != orig_chunk_size - 1 && - offset + size != wim_resource_size(lte))) + offset + size != rspec->uncompressed_size)) { if (orig_chunk_size <= STACK_MAX) { tmp_buf = alloca(orig_chunk_size); @@ -349,8 +349,8 @@ read_compressed_wim_resource(const struct wim_lookup_table_entry * const lte, /* Calculate uncompressed size of next chunk. */ u32 chunk_usize; - if ((i == num_chunks - 1) && (wim_resource_size(lte) & (orig_chunk_size - 1))) - chunk_usize = (wim_resource_size(lte) & (orig_chunk_size - 1)); + if ((i == num_chunks - 1) && (rspec->uncompressed_size & (orig_chunk_size - 1))) + chunk_usize = (rspec->uncompressed_size & (orig_chunk_size - 1)); else chunk_usize = orig_chunk_size; @@ -366,10 +366,10 @@ read_compressed_wim_resource(const struct wim_lookup_table_entry * const lte, chunk_csize = le32_to_cpu(chunk_hdr.compressed_size); } else { if (i == num_chunks - 1) { - chunk_csize = lte->resource_entry.size - + chunk_csize = rspec->size_in_wim - chunk_table_size - chunk_offsets[i - start_chunk]; - if (lte->is_pipable) + if (rspec->is_pipable) chunk_csize -= num_chunks * sizeof(struct pwm_chunk_hdr); } else { chunk_csize = chunk_offsets[i + 1 - start_chunk] - @@ -382,7 +382,7 @@ read_compressed_wim_resource(const struct wim_lookup_table_entry * const lte, ret = WIMLIB_ERR_DECOMPRESSION; goto out_free_memory; } - if (lte->is_pipable) + if (rspec->is_pipable) cur_read_offset += sizeof(struct pwm_chunk_hdr); if (i >= start_chunk) { @@ -435,7 +435,7 @@ read_compressed_wim_resource(const struct wim_lookup_table_entry * const lte, chunk_csize, target, chunk_usize, - wim_resource_compression_type(lte), + rspec->ctype, orig_chunk_size); if (ret) { ERROR("Failed to decompress data!"); @@ -484,7 +484,7 @@ read_compressed_wim_resource(const struct wim_lookup_table_entry * const lte, } if (is_pipe_read - && size == lte->resource_entry.original_size + && size == rspec->uncompressed_size && chunk_table_size) { u8 dummy; @@ -613,49 +613,52 @@ read_partial_wim_resource(const struct wim_lookup_table_entry *lte, u32 cb_chunk_size, void *ctx_or_buf, int flags, u64 offset) { + const struct wim_resource_spec *rspec; struct filedes *in_fd; /* Verify parameters. */ wimlib_assert(lte->resource_location == RESOURCE_IN_WIM); - in_fd = <e->wim->in_fd; + rspec = lte->rspec; + in_fd = &rspec->wim->in_fd; if (cb) wimlib_assert(is_power_of_2(cb_chunk_size)); if (flags & WIMLIB_READ_RESOURCE_FLAG_RAW_CHUNKS) { /* Raw chunks mode is subject to the restrictions noted. */ wimlib_assert(!(flags & WIMLIB_READ_RESOURCE_FLAG_RAW_FULL)); - wimlib_assert(cb_chunk_size == wim_resource_chunk_size(lte)); - wimlib_assert(size == lte->resource_entry.original_size); + wimlib_assert(cb_chunk_size == rspec->cchunk_size); + wimlib_assert(size == rspec->uncompressed_size); wimlib_assert(offset == 0); } else if (flags & WIMLIB_READ_RESOURCE_FLAG_RAW_FULL) { /* Raw full mode: read must not overrun end of store size. */ wimlib_assert(offset + size >= size && - offset + size <= lte->resource_entry.size); + offset + size <= rspec->size_in_wim); } else { /* Normal mode: read must not overrun end of original size. */ wimlib_assert(offset + size >= size && - offset + size <= lte->resource_entry.original_size); + offset + size <= rspec->uncompressed_size); } DEBUG("Reading WIM resource: %"PRIu64" @ +%"PRIu64" " "from %"PRIu64"(%"PRIu64") @ +%"PRIu64" " "(readflags 0x%08x, resflags 0x%02x%s)", size, offset, - lte->resource_entry.size, - lte->resource_entry.original_size, - lte->resource_entry.offset, - flags, lte->resource_entry.flags, - (lte->is_pipable ? ", pipable" : "")); + rspec->size_in_wim, + rspec->uncompressed_size, + rspec->offset_in_wim, + flags, lte->flags, + (rspec->is_pipable ? ", pipable" : "")); if ((flags & WIMLIB_READ_RESOURCE_FLAG_RAW_FULL) || - !resource_is_compressed(<e->resource_entry)) { + rspec->ctype == WIMLIB_COMPRESSION_TYPE_NONE) + { return read_raw_file_data(in_fd, size, cb, cb_chunk_size, ctx_or_buf, - offset + lte->resource_entry.offset); + offset + rspec->offset_in_wim); } else { - return read_compressed_wim_resource(lte, size, cb, + return read_compressed_wim_resource(rspec, size, cb, cb_chunk_size, ctx_or_buf, flags, offset); } @@ -702,7 +705,7 @@ read_file_on_disk_prefix(const struct wim_lookup_table_entry *lte, int raw_fd; struct filedes fd; - wimlib_assert(size <= wim_resource_size(lte)); + wimlib_assert(size <= lte->size); DEBUG("Reading %"PRIu64" bytes from \"%"TS"\"", size, lte->file_on_disk); raw_fd = open(lte->file_on_disk, O_BINARY | O_RDONLY); @@ -725,7 +728,7 @@ read_buffer_prefix(const struct wim_lookup_table_entry *lte, u32 cb_chunk_size, void *ctx_or_buf, int _ignored_flags) { - wimlib_assert(size <= wim_resource_size(lte)); + wimlib_assert(size <= lte->size); if (cb) { /* Feed the data into the callback function in @@ -820,8 +823,7 @@ int read_full_resource_into_buf(const struct wim_lookup_table_entry *lte, void *buf) { - return read_resource_prefix(lte, wim_resource_size(lte), - NULL, 0, buf, 0); + return read_resource_prefix(lte, lte->size, NULL, 0, buf, 0); } /* Read the full uncompressed data of the specified resource. A buffer @@ -833,15 +835,13 @@ read_full_resource_into_alloc_buf(const struct wim_lookup_table_entry *lte, int ret; void *buf; - if ((size_t)lte->resource_entry.original_size != - lte->resource_entry.original_size) - { + if ((size_t)lte->size != lte->size) { ERROR("Can't read %"PRIu64" byte resource into " - "memory", lte->resource_entry.original_size); + "memory", lte->size); return WIMLIB_ERR_NOMEM; } - buf = MALLOC(lte->resource_entry.original_size); + buf = MALLOC(lte->size); if (buf == NULL) return WIMLIB_ERR_NOMEM; @@ -857,9 +857,8 @@ read_full_resource_into_alloc_buf(const struct wim_lookup_table_entry *lte, /* Retrieve the full uncompressed data of the specified WIM resource, provided * as a raw `struct resource_entry'. */ -int -res_entry_to_data(const struct resource_entry *res_entry, - WIMStruct *wim, void **buf_ret) +static int +wim_resource_spec_to_data(struct wim_resource_spec *rspec, void **buf_ret) { int ret; struct wim_lookup_table_entry *lte; @@ -868,16 +867,28 @@ res_entry_to_data(const struct resource_entry *res_entry, if (lte == NULL) return WIMLIB_ERR_NOMEM; - copy_resource_entry(<e->resource_entry, res_entry); lte->unhashed = 1; - lte->part_number = wim->hdr.part_number; - lte_init_wim(lte, wim); + lte_bind_wim_resource_spec(lte, rspec); ret = read_full_resource_into_alloc_buf(lte, buf_ret); + + lte_unbind_wim_resource_spec(lte); free_lookup_table_entry(lte); return ret; } +int +wim_reshdr_to_data(const struct wim_reshdr *reshdr, WIMStruct *wim, void **buf_ret) +{ + DEBUG("offset_in_wim=%"PRIu64", size_in_wim=%"PRIu64", " + "uncompressed_size=%"PRIu64, + reshdr->offset_in_wim, reshdr->size_in_wim, reshdr->uncompressed_size); + + struct wim_resource_spec rspec; + wim_res_hdr_to_spec(reshdr, wim, &rspec); + return wim_resource_spec_to_data(&rspec, buf_ret); +} + struct extract_ctx { SHA_CTX sha_ctx; consume_data_callback_t extract_chunk; @@ -907,7 +918,7 @@ extract_wim_resource(const struct wim_lookup_table_entry *lte, void *extract_chunk_arg) { int ret; - if (size == wim_resource_size(lte)) { + if (size == lte->size) { /* Do SHA1 */ struct extract_ctx ctx; ctx.extract_chunk = extract_chunk; @@ -915,7 +926,7 @@ extract_wim_resource(const struct wim_lookup_table_entry *lte, sha1_init(&ctx.sha_ctx); ret = read_resource_prefix(lte, size, extract_chunk_sha1_wrapper, - wim_resource_chunk_size(lte), + lte_cchunk_size(lte), &ctx, 0); if (ret == 0) { u8 hash[SHA1_HASH_SIZE]; @@ -934,7 +945,7 @@ extract_wim_resource(const struct wim_lookup_table_entry *lte, } else { /* Don't do SHA1 */ ret = read_resource_prefix(lte, size, extract_chunk, - wim_resource_chunk_size(lte), + lte_cchunk_size(lte), extract_chunk_arg, 0); } return ret; @@ -976,8 +987,8 @@ sha1_resource(struct wim_lookup_table_entry *lte) SHA_CTX sha_ctx; sha1_init(&sha_ctx); - ret = read_resource_prefix(lte, wim_resource_size(lte), - sha1_chunk, wim_resource_chunk_size(lte), + ret = read_resource_prefix(lte, lte->size, + sha1_chunk, lte_cchunk_size(lte), &sha_ctx, 0); if (ret == 0) sha1_final(lte->hash, &sha_ctx); @@ -985,61 +996,87 @@ sha1_resource(struct wim_lookup_table_entry *lte) return ret; } -/* Translates a WIM resource entry from the on-disk format into an in-memory +/* Convert a WIM resource header to a stand-alone resource specification. */ +void +wim_res_hdr_to_spec(const struct wim_reshdr *reshdr, WIMStruct *wim, + struct wim_resource_spec *spec) +{ + spec->wim = wim; + spec->offset_in_wim = reshdr->offset_in_wim; + spec->size_in_wim = reshdr->size_in_wim; + spec->uncompressed_size = reshdr->uncompressed_size; + INIT_LIST_HEAD(&spec->lte_list); + spec->flags = reshdr->flags; + spec->is_pipable = wim_is_pipable(wim); + if (spec->flags & WIM_RESHDR_FLAG_COMPRESSED) { + spec->ctype = wim->compression_type; + spec->cchunk_size = wim->chunk_size; + } else { + spec->ctype = WIMLIB_COMPRESSION_TYPE_NONE; + spec->cchunk_size = 0; + } +} + +/* Convert a stand-alone resource specification to a WIM resource header. */ +void +wim_res_spec_to_hdr(const struct wim_resource_spec *rspec, + struct wim_reshdr *reshdr) +{ + reshdr->offset_in_wim = rspec->offset_in_wim; + reshdr->size_in_wim = rspec->size_in_wim; + reshdr->flags = rspec->flags; + reshdr->uncompressed_size = rspec->uncompressed_size; +} + +/* Translates a WIM resource header from the on-disk format into an in-memory * format. */ void -get_resource_entry(const struct resource_entry_disk *disk_entry, - struct resource_entry *entry) +get_wim_reshdr(const struct wim_reshdr_disk *disk_reshdr, + struct wim_reshdr *reshdr) { - /* Note: disk_entry may not be 8 byte aligned--- in that case, the + /* Note: disk_reshdr may not be 8 byte aligned--- in that case, the * offset and original_size members will be unaligned. (This is 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... */ - if (entry->offset & 0xc000000000000000ULL) { - WARNING("Truncating offset in resource entry"); - entry->offset &= 0x3fffffffffffffffULL; + * since `struct resource_reshdr_disk' is declared as packed.) */ + + reshdr->offset_in_wim = le64_to_cpu(disk_reshdr->offset_in_wim); + reshdr->size_in_wim = (((u64)disk_reshdr->size_in_wim[0] << 0) | + ((u64)disk_reshdr->size_in_wim[1] << 8) | + ((u64)disk_reshdr->size_in_wim[2] << 16) | + ((u64)disk_reshdr->size_in_wim[3] << 24) | + ((u64)disk_reshdr->size_in_wim[4] << 32) | + ((u64)disk_reshdr->size_in_wim[5] << 40) | + ((u64)disk_reshdr->size_in_wim[6] << 48)); + reshdr->uncompressed_size = le64_to_cpu(disk_reshdr->uncompressed_size); + reshdr->flags = disk_reshdr->flags; + + /* Truncate numbers to 62 bits to avoid possible overflows. */ + if (reshdr->offset_in_wim & 0xc000000000000000ULL) { + WARNING("Truncating offset in resource reshdr"); + reshdr->offset_in_wim &= 0x3fffffffffffffffULL; } - if (entry->original_size & 0xc000000000000000ULL) { - WARNING("Truncating original_size in resource entry"); - entry->original_size &= 0x3fffffffffffffffULL; + if (reshdr->uncompressed_size & 0xc000000000000000ULL) { + WARNING("Truncating original_size in resource reshdr"); + reshdr->uncompressed_size &= 0x3fffffffffffffffULL; } } -/* Translates a WIM resource entry from an in-memory format into the on-disk - * format. */ +/* Translates a WIM resource header 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) +put_wim_reshdr(const struct wim_reshdr *reshdr, + struct wim_reshdr_disk *disk_reshdr) { - /* Note: disk_entry may not be 8 byte aligned--- in that case, the + /* Note: disk_reshdr may not be 8 byte aligned--- in that case, the * offset and original_size members will be unaligned. (This is 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); + * since `struct resource_reshdr_disk' is declared as packed.) */ + disk_reshdr->size_in_wim[0] = reshdr->size_in_wim >> 0; + disk_reshdr->size_in_wim[1] = reshdr->size_in_wim >> 8; + disk_reshdr->size_in_wim[2] = reshdr->size_in_wim >> 16; + disk_reshdr->size_in_wim[3] = reshdr->size_in_wim >> 24; + disk_reshdr->size_in_wim[4] = reshdr->size_in_wim >> 32; + disk_reshdr->size_in_wim[5] = reshdr->size_in_wim >> 40; + disk_reshdr->size_in_wim[6] = reshdr->size_in_wim >> 48; + disk_reshdr->flags = reshdr->flags; + disk_reshdr->offset_in_wim = cpu_to_le64(reshdr->offset_in_wim); + disk_reshdr->uncompressed_size = cpu_to_le64(reshdr->uncompressed_size); } diff --git a/src/split.c b/src/split.c index dd4ba278..167105eb 100644 --- a/src/split.c +++ b/src/split.c @@ -148,7 +148,8 @@ add_stream_to_swm(struct wim_lookup_table_entry *lte, void *_swm_info) struct swm_info *swm_info = _swm_info; u64 stream_size; - stream_size = lte->resource_entry.size; + /* TODO */ + stream_size = lte->rspec->size_in_wim; /* - Start first part if no parts have been started so far; * - Start next part if adding this stream exceeds maximum part size, @@ -158,7 +159,7 @@ add_stream_to_swm(struct wim_lookup_table_entry *lte, void *_swm_info) if (swm_info->num_parts == 0 || ((swm_info->parts[swm_info->num_parts - 1].size + stream_size >= swm_info->max_part_size) - && !((lte->resource_entry.flags & WIM_RESHDR_FLAG_METADATA) || + && !((lte->flags & WIM_RESHDR_FLAG_METADATA) || swm_info->parts[swm_info->num_parts - 1].size == 0))) { if (swm_info->num_parts == swm_info->num_alloc_parts) { @@ -182,7 +183,7 @@ add_stream_to_swm(struct wim_lookup_table_entry *lte, void *_swm_info) swm_info->parts[swm_info->num_parts - 1].size = 0; } swm_info->parts[swm_info->num_parts - 1].size += stream_size; - if (!(lte->resource_entry.flags & WIM_RESHDR_FLAG_METADATA)) { + if (!(lte->flags & WIM_RESHDR_FLAG_METADATA)) { list_add_tail(<e->write_streams_list, &swm_info->parts[swm_info->num_parts - 1].stream_list); } diff --git a/src/unix_apply.c b/src/unix_apply.c index 86be081f..ca0f485c 100644 --- a/src/unix_apply.c +++ b/src/unix_apply.c @@ -122,7 +122,7 @@ unix_extract_unnamed_stream(file_spec_t file, if (raw_fd < 0) return WIMLIB_ERR_OPEN; filedes_init(&fd, raw_fd); - ret = extract_wim_resource_to_fd(lte, &fd, wim_resource_size(lte)); + ret = extract_wim_resource_to_fd(lte, &fd, lte->size); if (filedes_close(&fd) && !ret) ret = WIMLIB_ERR_WRITE; return ret; diff --git a/src/unix_capture.c b/src/unix_capture.c index ff9a6ac0..1d116d4b 100644 --- a/src/unix_capture.c +++ b/src/unix_capture.c @@ -64,7 +64,7 @@ unix_capture_regular_file(const char *path, } lte->file_on_disk = file_on_disk; lte->resource_location = RESOURCE_IN_FILE_ON_DISK; - lte->resource_entry.original_size = size; + lte->size = size; lookup_table_insert_unhashed(lookup_table, lte, inode, 0); inode->i_lte = lte; } diff --git a/src/wim.c b/src/wim.c index c0825687..a62be39e 100644 --- a/src/wim.c +++ b/src/wim.c @@ -138,6 +138,10 @@ wim_chunk_size_valid(u32 chunk_size, int ctype) * 2^15 = 32768 is the default value used for compatibility, but * wimlib can actually use up to 2^26. */ return order >= 15 && order <= 26; + + case WIMLIB_COMPRESSION_TYPE_LZMS: + /* TODO */ + return 131072; } return false; } @@ -371,7 +375,7 @@ wimlib_get_wim_info(WIMStruct *wim, struct wimlib_wim_info *info) memcpy(info->guid, wim->hdr.guid, WIMLIB_GUID_LEN); info->image_count = wim->hdr.image_count; info->boot_index = wim->hdr.boot_idx; - info->wim_version = WIM_VERSION; + info->wim_version = wim->hdr.wim_version; info->chunk_size = wim->hdr.chunk_size; info->part_number = wim->hdr.part_number; info->total_parts = wim->hdr.total_parts; @@ -535,7 +539,6 @@ begin_read(WIMStruct *wim, const void *wim_filename_or_fd, wim->in_fd.is_pipe = 1; } else { wimfile = wim_filename_or_fd; - DEBUG("Reading the WIM file `%"TS"'", wimfile); ret = do_open_wim(wimfile, &wim->in_fd); if (ret) return ret; @@ -562,7 +565,7 @@ begin_read(WIMStruct *wim, const void *wim_filename_or_fd, } } - ret = read_wim_header(wim->filename, &wim->in_fd, &wim->hdr); + ret = read_wim_header(wim, &wim->hdr); if (ret) return ret; @@ -596,17 +599,17 @@ begin_read(WIMStruct *wim, const void *wim_filename_or_fd, /* Check and cache the compression type */ if (wim->hdr.flags & WIM_HDR_FLAG_COMPRESSION) { if (wim->hdr.flags & WIM_HDR_FLAG_COMPRESS_LZX) { - if (wim->hdr.flags & WIM_HDR_FLAG_COMPRESS_XPRESS) { - ERROR("Multiple compression flags are set in \"%"TS"\"", - wimfile); - return WIMLIB_ERR_INVALID_COMPRESSION_TYPE; - } wim->compression_type = WIMLIB_COMPRESSION_TYPE_LZX; } else if (wim->hdr.flags & WIM_HDR_FLAG_COMPRESS_XPRESS) { wim->compression_type = WIMLIB_COMPRESSION_TYPE_XPRESS; + #if 0 + /* TODO */ + } else if (wim->hdr.flags & WIM_HDR_FLAG_COMPRESS_LZMS) { + wim->compression_type = WIMLIB_COMPRESSION_TYPE_LZMS; + #endif } else { ERROR("The compression flag is set on \"%"TS"\", but " - "neither the XPRESS nor LZX flag is set", + "a flag for a recognized format is not", wimfile); return WIMLIB_ERR_INVALID_COMPRESSION_TYPE; } @@ -677,6 +680,11 @@ open_wim_as_WIMStruct(const void *wim_filename_or_fd, int open_flags, WIMStruct *wim; int ret; + if (open_flags & WIMLIB_OPEN_FLAG_FROM_PIPE) + DEBUG("Opening pipable WIM from file descriptor %d.", *(const int*)wim_filename_or_fd); + else + DEBUG("Opening WIM file \"%"TS"\"", (const tchar*)wim_filename_or_fd); + wimlib_global_init(WIMLIB_INIT_FLAG_ASSUME_UTF8); if (wim_ret == NULL) @@ -692,6 +700,7 @@ open_wim_as_WIMStruct(const void *wim_filename_or_fd, int open_flags, return ret; } + DEBUG("Successfully opened WIM and created WIMStruct."); *wim_ret = wim; return 0; } diff --git a/src/win32_apply.c b/src/win32_apply.c index 55757233..1a4adf5c 100644 --- a/src/win32_apply.c +++ b/src/win32_apply.c @@ -195,8 +195,7 @@ win32_extract_stream(const wchar_t *path, const wchar_t *stream_name, ret = 0; if (!lte) goto out_close_handle; - ret = extract_wim_resource(lte, wim_resource_size(lte), - win32_extract_wim_chunk, h); + ret = extract_wim_resource(lte, lte->size, win32_extract_wim_chunk, h); out_close_handle: if (!CloseHandle(h)) goto error; @@ -239,7 +238,7 @@ win32_encrypted_import_cb(unsigned char *data, void *_import_ctx, unsigned long len = *len_p; const struct wim_lookup_table_entry *lte = import_ctx->lte; - len = min(len, wim_resource_size(lte) - import_ctx->offset); + len = min(len, lte->size - import_ctx->offset); if (read_partial_wim_resource_into_buf(lte, len, import_ctx->offset, data)) return ERROR_READ_FAULT; diff --git a/src/write.c b/src/write.c index ce301063..80a3b096 100644 --- a/src/write.c +++ b/src/write.c @@ -74,8 +74,8 @@ static bool can_raw_copy(const struct wim_lookup_table_entry *lte, int write_resource_flags, int out_ctype, u32 out_chunk_size) { - return (out_ctype == wim_resource_compression_type(lte) - && out_chunk_size == wim_resource_chunk_size(lte) + return (out_ctype == lte_ctype(lte) + && out_chunk_size == lte_cchunk_size(lte) && out_ctype != WIMLIB_COMPRESSION_TYPE_NONE); } @@ -150,7 +150,7 @@ begin_wim_resource_chunk_tab(const struct wim_lookup_table_entry *lte, struct chunk_table *chunk_tab; int ret; - size = wim_resource_size(lte); + size = lte->size; num_chunks = DIV_ROUND_UP(size, out_chunk_size); bytes_per_chunk_entry = (size > (1ULL << 32)) ? 8 : 4; alloc_size = sizeof(struct chunk_table) + num_chunks * sizeof(u64); @@ -245,7 +245,7 @@ write_pwm_stream_header(const struct wim_lookup_table_entry *lte, int ret; stream_hdr.magic = PWM_STREAM_MAGIC; - stream_hdr.uncompressed_size = cpu_to_le64(lte->resource_entry.original_size); + stream_hdr.uncompressed_size = cpu_to_le64(lte->size); if (additional_reshdr_flags & PWM_RESHDR_FLAG_UNHASHED) { zero_out_hash(stream_hdr.hash); } else { @@ -253,7 +253,7 @@ write_pwm_stream_header(const struct wim_lookup_table_entry *lte, copy_hash(stream_hdr.hash, lte->hash); } - reshdr_flags = lte->resource_entry.flags & ~WIM_RESHDR_FLAG_COMPRESSED; + reshdr_flags = lte->flags & ~WIM_RESHDR_FLAG_COMPRESSED; reshdr_flags |= additional_reshdr_flags; stream_hdr.flags = cpu_to_le32(reshdr_flags); ret = full_write(out_fd, &stream_hdr, sizeof(stream_hdr)); @@ -397,7 +397,7 @@ error: * @out_chunk_size: * Compressed chunk size to use. * - * @out_res_entry: + * @out_reshdr: * On success, this is filled in with the offset, flags, compressed size, * and uncompressed size of the resource in the output WIM. * @@ -421,7 +421,7 @@ static int write_wim_resource(struct wim_lookup_table_entry *lte, struct filedes *out_fd, int out_ctype, u32 out_chunk_size, - struct resource_entry *out_res_entry, + struct wim_reshdr *out_reshdr, int resource_flags, struct wimlib_lzx_context **comp_ctx) { @@ -450,20 +450,20 @@ write_wim_resource(struct wim_lookup_table_entry *lte, * needs to be requested so that the written resource can be * appropriately formatted. However, in neither case is any * actual decompression needed. */ - if (lte->is_pipable == !!(resource_flags & - WIMLIB_WRITE_RESOURCE_FLAG_PIPABLE)) + if (lte->rspec->is_pipable == !!(resource_flags & + WIMLIB_WRITE_RESOURCE_FLAG_PIPABLE)) { resource_flags |= WIMLIB_READ_RESOURCE_FLAG_RAW_FULL; - read_size = lte->resource_entry.size; + read_size = lte->rspec->size_in_wim; } else { resource_flags |= WIMLIB_READ_RESOURCE_FLAG_RAW_CHUNKS; - read_size = lte->resource_entry.original_size; + read_size = lte->size; } write_ctx.doing_sha = false; } else { write_ctx.doing_sha = true; sha1_init(&write_ctx.sha_ctx); - read_size = lte->resource_entry.original_size; + read_size = lte->size; } /* Set the output compression mode and initialize chunk table if needed. @@ -513,7 +513,7 @@ write_wim_resource(struct wim_lookup_table_entry *lte, write_ctx.resource_flags = resource_flags; try_write_again: if (write_ctx.out_ctype == WIMLIB_COMPRESSION_TYPE_NONE) - in_chunk_size = wim_resource_chunk_size(lte); + in_chunk_size = lte_cchunk_size(lte); else in_chunk_size = out_chunk_size; ret = read_resource_prefix(lte, read_size, @@ -540,27 +540,27 @@ try_write_again: goto out_free_chunk_tab; } - /* Fill in out_res_entry with information about the newly written + /* Fill in out_reshdr with information about the newly written * resource. */ - out_res_entry->size = out_fd->offset - res_start_offset; - out_res_entry->flags = lte->resource_entry.flags; + out_reshdr->size_in_wim = out_fd->offset - res_start_offset; + out_reshdr->flags = lte->flags; if (out_ctype == WIMLIB_COMPRESSION_TYPE_NONE) - out_res_entry->flags &= ~WIM_RESHDR_FLAG_COMPRESSED; + out_reshdr->flags &= ~WIM_RESHDR_FLAG_COMPRESSED; else - out_res_entry->flags |= WIM_RESHDR_FLAG_COMPRESSED; - out_res_entry->offset = res_start_offset; - out_res_entry->original_size = wim_resource_size(lte); + out_reshdr->flags |= WIM_RESHDR_FLAG_COMPRESSED; + out_reshdr->offset_in_wim = res_start_offset; + out_reshdr->uncompressed_size = lte->size; /* Check for resources compressed to greater than their original size * and write them uncompressed instead. (But never do this if writing * to a pipe, and don't bother if we did a raw copy.) */ - if (out_res_entry->size > out_res_entry->original_size && + if (out_reshdr->size_in_wim > out_reshdr->uncompressed_size && !(resource_flags & (WIMLIB_WRITE_RESOURCE_FLAG_PIPABLE | WIMLIB_READ_RESOURCE_FLAG_RAW))) { DEBUG("Compressed %"PRIu64" => %"PRIu64" bytes; " "writing uncompressed instead", - out_res_entry->original_size, out_res_entry->size); + out_reshdr->uncompressed_size, out_reshdr->size_in_wim); ret = seek_and_truncate(out_fd, res_start_offset); if (ret) goto out_free_chunk_tab; @@ -574,18 +574,18 @@ try_write_again: if (resource_flags & WIMLIB_READ_RESOURCE_FLAG_RAW) { DEBUG("Copied raw compressed data " "(%"PRIu64" => %"PRIu64" bytes @ +%"PRIu64", flags=0x%02x)", - out_res_entry->original_size, out_res_entry->size, - out_res_entry->offset, out_res_entry->flags); + out_reshdr->uncompressed_size, out_reshdr->size_in_wim, + out_reshdr->offset_in_wim, out_reshdr->flags); } else if (out_ctype != WIMLIB_COMPRESSION_TYPE_NONE) { DEBUG("Wrote compressed resource " "(%"PRIu64" => %"PRIu64" bytes @ +%"PRIu64", flags=0x%02x)", - out_res_entry->original_size, out_res_entry->size, - out_res_entry->offset, out_res_entry->flags); + out_reshdr->uncompressed_size, out_reshdr->size_in_wim, + out_reshdr->offset_in_wim, out_reshdr->flags); } else { DEBUG("Wrote uncompressed resource " "(%"PRIu64" bytes @ +%"PRIu64", flags=0x%02x)", - out_res_entry->original_size, - out_res_entry->offset, out_res_entry->flags); + out_reshdr->uncompressed_size, + out_reshdr->offset_in_wim, out_reshdr->flags); } ret = 0; out_free_chunk_tab: @@ -602,7 +602,7 @@ write_wim_resource_from_buffer(const void *buf, size_t buf_size, int reshdr_flags, struct filedes *out_fd, int out_ctype, u32 out_chunk_size, - struct resource_entry *out_res_entry, + struct wim_reshdr *out_reshdr, u8 *hash_ret, int write_resource_flags, struct wimlib_lzx_context **comp_ctx) { @@ -616,10 +616,10 @@ write_wim_resource_from_buffer(const void *buf, size_t buf_size, if (lte == NULL) return WIMLIB_ERR_NOMEM; - lte->resource_location = RESOURCE_IN_ATTACHED_BUFFER; - lte->attached_buffer = (void*)buf; - lte->resource_entry.original_size = buf_size; - lte->resource_entry.flags = reshdr_flags; + lte->resource_location = RESOURCE_IN_ATTACHED_BUFFER; + lte->attached_buffer = (void*)buf; + lte->size = buf_size; + lte->flags = reshdr_flags; if (write_resource_flags & WIMLIB_WRITE_RESOURCE_FLAG_PIPABLE) { sha1_buffer(buf, buf_size, lte->hash); @@ -629,7 +629,7 @@ write_wim_resource_from_buffer(const void *buf, size_t buf_size, } ret = write_wim_resource(lte, out_fd, out_ctype, out_chunk_size, - out_res_entry, write_resource_flags, comp_ctx); + out_reshdr, write_resource_flags, comp_ctx); if (ret) goto out_free_lte; if (hash_ret) @@ -821,24 +821,24 @@ do_write_streams_progress(struct write_streams_progress_data *progress_data, bool new_wim_part; if (stream_discarded) { - progress->write_streams.total_bytes -= wim_resource_size(lte); + progress->write_streams.total_bytes -= lte->size; if (progress_data->next_progress != ~(uint64_t)0 && progress_data->next_progress > progress->write_streams.total_bytes) { progress_data->next_progress = progress->write_streams.total_bytes; } } else { - progress->write_streams.completed_bytes += wim_resource_size(lte); + progress->write_streams.completed_bytes += lte->size; } new_wim_part = false; if (lte->resource_location == RESOURCE_IN_WIM && - lte->wim != progress_data->prev_wim_part) + lte->rspec->wim != progress_data->prev_wim_part) { if (progress_data->prev_wim_part) { new_wim_part = true; progress->write_streams.completed_parts++; } - progress_data->prev_wim_part = lte->wim; + progress_data->prev_wim_part = lte->rspec->wim; } progress->write_streams.completed_streams++; if (progress_data->progress_func @@ -873,7 +873,7 @@ serial_write_stream(struct wim_lookup_table_entry *lte, void *_ctx) return write_wim_resource(lte, ctx->out_fd, ctx->out_ctype, ctx->out_chunk_size, - <e->output_resource_entry, + <e->out_reshdr, ctx->write_resource_flags, ctx->comp_ctx); } @@ -929,7 +929,7 @@ do_write_stream_list(struct list_head *stream_list, lte->filtered) { DEBUG("Discarding duplicate stream of " "length %"PRIu64, - wim_resource_size(lte)); + lte->size); lte->no_progress = 0; stream_discarded = true; goto skip_to_progress; @@ -1290,12 +1290,12 @@ receive_compressed_chunks(struct main_writer_thread_ctx *ctx) * equal to their original size and write them * uncompressed instead. (But never do this if writing * to a pipe.) */ - if (res_csize >= wim_resource_size(cur_lte) && + if (res_csize >= cur_lte->size && !(ctx->write_resource_flags & WIMLIB_WRITE_RESOURCE_FLAG_PIPABLE)) { DEBUG("Compressed %"PRIu64" => %"PRIu64" bytes; " "writing uncompressed instead", - wim_resource_size(cur_lte), res_csize); + cur_lte->size, res_csize); ret = seek_and_truncate(ctx->out_fd, ctx->res_start_offset); if (ret) return ret; @@ -1303,31 +1303,31 @@ receive_compressed_chunks(struct main_writer_thread_ctx *ctx) ctx->out_fd, WIMLIB_COMPRESSION_TYPE_NONE, 0, - &cur_lte->output_resource_entry, + &cur_lte->out_reshdr, ctx->write_resource_flags, ctx->comp_ctx); if (ret) return ret; } else { - cur_lte->output_resource_entry.size = + cur_lte->out_reshdr.size_in_wim = res_csize; - cur_lte->output_resource_entry.original_size = - cur_lte->resource_entry.original_size; + cur_lte->out_reshdr.uncompressed_size = + cur_lte->size; - cur_lte->output_resource_entry.offset = + cur_lte->out_reshdr.offset_in_wim = ctx->res_start_offset; - cur_lte->output_resource_entry.flags = - cur_lte->resource_entry.flags | + cur_lte->out_reshdr.flags = + cur_lte->flags | WIM_RESHDR_FLAG_COMPRESSED; DEBUG("Wrote compressed resource " "(%"PRIu64" => %"PRIu64" bytes @ +%"PRIu64", flags=0x%02x)", - cur_lte->output_resource_entry.original_size, - cur_lte->output_resource_entry.size, - cur_lte->output_resource_entry.offset, - cur_lte->output_resource_entry.flags); + cur_lte->out_reshdr.uncompressed_size, + cur_lte->out_reshdr.size_in_wim, + cur_lte->out_reshdr.offset_in_wim, + cur_lte->out_reshdr.flags); } do_write_streams_progress(ctx->progress_data, @@ -1462,12 +1462,11 @@ submit_stream_for_compression(struct wim_lookup_table_entry *lte, * when @lte is already hashed. */ sha1_init(&ctx->next_sha_ctx); ctx->next_chunk = 0; - ctx->next_num_chunks = DIV_ROUND_UP(wim_resource_size(lte), - ctx->out_chunk_size); + ctx->next_num_chunks = DIV_ROUND_UP(lte->size, ctx->out_chunk_size); ctx->next_lte = lte; INIT_LIST_HEAD(<e->msg_list); list_add_tail(<e->being_compressed_list, &ctx->outstanding_streams); - ret = read_resource_prefix(lte, wim_resource_size(lte), + ret = read_resource_prefix(lte, lte->size, main_writer_thread_cb, ctx->out_chunk_size, ctx, 0); if (ret) @@ -1482,7 +1481,7 @@ main_thread_process_next_stream(struct wim_lookup_table_entry *lte, void *_ctx) struct main_writer_thread_ctx *ctx = _ctx; int ret; - if (wim_resource_size(lte) < 1000 || + if (lte->size < 1000 || !must_compress_stream(lte, ctx->write_resource_flags, ctx->out_ctype, ctx->out_chunk_size)) { @@ -1754,13 +1753,13 @@ write_stream_list(struct list_head *stream_list, prev_wim_part = NULL; list_for_each_entry(lte, stream_list, write_streams_list) { num_streams++; - total_bytes += wim_resource_size(lte); + total_bytes += lte->size; if (must_compress_stream(lte, write_resource_flags, out_ctype, out_chunk_size)) - total_compression_bytes += wim_resource_size(lte); + total_compression_bytes += lte->size; if (lte->resource_location == RESOURCE_IN_WIM) { - if (prev_wim_part != lte->wim) { - prev_wim_part = lte->wim; + if (prev_wim_part != lte->rspec->wim) { + prev_wim_part = lte->rspec->wim; total_parts++; } } @@ -1840,10 +1839,10 @@ stream_size_table_insert(struct wim_lookup_table_entry *lte, void *_tab) struct wim_lookup_table_entry *same_size_lte; struct hlist_node *tmp; - pos = hash_u64(wim_resource_size(lte)) % tab->capacity; + pos = hash_u64(lte->size) % tab->capacity; lte->unique_size = 1; hlist_for_each_entry(same_size_lte, tmp, &tab->array[pos], hash_list_2) { - if (wim_resource_size(same_size_lte) == wim_resource_size(lte)) { + if (same_size_lte->size == lte->size) { lte->unique_size = 0; same_size_lte->unique_size = 0; break; @@ -1949,7 +1948,6 @@ prepare_logical_stream_list(WIMStruct *wim, int image, bool streams_ok, struct find_streams_ctx *ctx) { int ret; - struct wim_lookup_table_entry *lte; if (streams_ok && (image == WIMLIB_ALL_IMAGES || (image == 1 && wim->hdr.image_count == 1))) @@ -1977,8 +1975,6 @@ prepare_logical_stream_list(WIMStruct *wim, int image, bool streams_ok, return ret; } - list_for_each_entry(lte, &ctx->stream_list, write_streams_list) - lte->part_number = wim->hdr.part_number; return 0; } @@ -1990,10 +1986,10 @@ process_filtered_stream(struct wim_lookup_table_entry *lte, void *_ctx) /* Calculate and set lte->filtered. */ if (lte->resource_location == RESOURCE_IN_WIM) { - if (lte->wim == ctx->wim && + if (lte->rspec->wim == ctx->wim && (ctx->write_flags & WIMLIB_WRITE_FLAG_OVERWRITE)) filtered |= FILTERED_SAME_WIM; - if (lte->wim != ctx->wim && + if (lte->rspec->wim != ctx->wim && (ctx->write_flags & WIMLIB_WRITE_FLAG_SKIP_EXTERNAL_WIMS)) filtered |= FILTERED_EXTERNAL_WIM; } @@ -2112,10 +2108,8 @@ write_wim_streams(WIMStruct *wim, int image, int write_flags, * use stream list already explicitly provided. Use existing * reference counts. */ stream_list = stream_list_override; - list_for_each_entry(lte, stream_list, write_streams_list) { + list_for_each_entry(lte, stream_list, write_streams_list) lte->out_refcnt = (lte->refcnt ? lte->refcnt : 1); - lte->part_number = wim->hdr.part_number; - } } return write_stream_list(stream_list, @@ -2174,8 +2168,8 @@ write_wim_metadata_resources(WIMStruct *wim, int image, int write_flags, } else if (write_flags & WIMLIB_WRITE_FLAG_OVERWRITE) { DEBUG("Image %u was not modified; re-using existing " "metadata resource.", i); - copy_resource_entry(&imd->metadata_lte->output_resource_entry, - &imd->metadata_lte->resource_entry); + wim_res_spec_to_hdr(imd->metadata_lte->rspec, + &imd->metadata_lte->out_reshdr); ret = 0; } else { DEBUG("Image %u was not modified; copying existing " @@ -2184,7 +2178,7 @@ write_wim_metadata_resources(WIMStruct *wim, int image, int write_flags, &wim->out_fd, wim->out_compression_type, wim->out_chunk_size, - &imd->metadata_lte->output_resource_entry, + &imd->metadata_lte->out_reshdr, write_resource_flags, &wim->lzx_context); } @@ -2294,19 +2288,19 @@ finish_write(WIMStruct *wim, int image, int write_flags, * it should be a copy of the resource entry for the image that is * marked as bootable. This is not well documented... */ if (wim->hdr.boot_idx == 0) { - zero_resource_entry(&wim->hdr.boot_metadata_res_entry); + zero_reshdr(&wim->hdr.boot_metadata_reshdr); } else { - copy_resource_entry(&wim->hdr.boot_metadata_res_entry, + copy_reshdr(&wim->hdr.boot_metadata_reshdr, &wim->image_metadata[wim->hdr.boot_idx- 1 - ]->metadata_lte->output_resource_entry); + ]->metadata_lte->out_reshdr); } /* Write lookup table. (Save old position first.) */ - old_lookup_table_end = wim->hdr.lookup_table_res_entry.offset + - wim->hdr.lookup_table_res_entry.size; + old_lookup_table_end = wim->hdr.lookup_table_reshdr.offset_in_wim + + wim->hdr.lookup_table_reshdr.size_in_wim; if (!(write_flags & WIMLIB_WRITE_FLAG_NO_LOOKUP_TABLE)) { ret = write_wim_lookup_table(wim, image, write_flags, - &wim->hdr.lookup_table_res_entry, + &wim->hdr.lookup_table_reshdr, stream_list_override); if (ret) return ret; @@ -2317,7 +2311,7 @@ finish_write(WIMStruct *wim, int image, int write_flags, if (write_flags & WIMLIB_WRITE_FLAG_USE_EXISTING_TOTALBYTES) xml_totalbytes = WIM_TOTALBYTES_USE_EXISTING; ret = write_wim_xml_data(wim, image, xml_totalbytes, - &wim->hdr.xml_res_entry, + &wim->hdr.xml_data_reshdr, write_resource_flags); if (ret) return ret; @@ -2327,7 +2321,7 @@ finish_write(WIMStruct *wim, int image, int write_flags, if (write_flags & WIMLIB_WRITE_FLAG_CHECKPOINT_AFTER_XML) { struct wim_header checkpoint_hdr; memcpy(&checkpoint_hdr, &wim->hdr, sizeof(struct wim_header)); - zero_resource_entry(&checkpoint_hdr.integrity); + zero_reshdr(&checkpoint_hdr.integrity_table_reshdr); checkpoint_hdr.flags |= WIM_HDR_FLAG_WRITE_IN_PROGRESS; ret = write_wim_header_at_offset(&checkpoint_hdr, &wim->out_fd, 0); @@ -2338,8 +2332,8 @@ finish_write(WIMStruct *wim, int image, int write_flags, if (!(write_flags & WIMLIB_WRITE_FLAG_REUSE_INTEGRITY_TABLE)) old_lookup_table_end = 0; - new_lookup_table_end = wim->hdr.lookup_table_res_entry.offset + - wim->hdr.lookup_table_res_entry.size; + new_lookup_table_end = wim->hdr.lookup_table_reshdr.offset_in_wim + + wim->hdr.lookup_table_reshdr.size_in_wim; ret = write_integrity_table(wim, new_lookup_table_end, @@ -2349,7 +2343,7 @@ finish_write(WIMStruct *wim, int image, int write_flags, return ret; } else { /* No integrity table. */ - zero_resource_entry(&wim->hdr.integrity); + zero_reshdr(&wim->hdr.integrity_table_reshdr); } /* Now that all information in the WIM header has been determined, the @@ -2497,7 +2491,7 @@ write_pipable_wim(WIMStruct *wim, int image, int write_flags, struct list_head *stream_list_override) { int ret; - struct resource_entry xml_res_entry; + struct wim_reshdr xml_reshdr; WARNING("Creating a pipable WIM, which will " "be incompatible\n" @@ -2520,7 +2514,7 @@ write_pipable_wim(WIMStruct *wim, int image, int write_flags, /* Write extra copy of the XML data. */ ret = write_wim_xml_data(wim, image, WIM_TOTALBYTES_OMIT, - &xml_res_entry, + &xml_reshdr, WIMLIB_WRITE_RESOURCE_FLAG_PIPABLE); if (ret) return ret; @@ -2682,10 +2676,10 @@ write_wim_part(WIMStruct *wim, randomize_byte_array(wim->hdr.guid, WIMLIB_GUID_LEN); /* Clear references to resources that have not been written yet. */ - zero_resource_entry(&wim->hdr.lookup_table_res_entry); - zero_resource_entry(&wim->hdr.xml_res_entry); - zero_resource_entry(&wim->hdr.boot_metadata_res_entry); - zero_resource_entry(&wim->hdr.integrity); + zero_reshdr(&wim->hdr.lookup_table_reshdr); + zero_reshdr(&wim->hdr.xml_data_reshdr); + zero_reshdr(&wim->hdr.boot_metadata_reshdr); + zero_reshdr(&wim->hdr.integrity_table_reshdr); /* Set image count and boot index correctly for single image writes. */ if (image != WIMLIB_ALL_IMAGES) { @@ -2838,8 +2832,8 @@ check_resource_offset(struct wim_lookup_table_entry *lte, void *_wim) const WIMStruct *wim = _wim; off_t end_offset = *(const off_t*)wim->private; - if (lte->resource_location == RESOURCE_IN_WIM && lte->wim == wim && - lte->resource_entry.offset + lte->resource_entry.size > end_offset) + if (lte->resource_location == RESOURCE_IN_WIM && lte->rspec->wim == wim && + lte->rspec->offset_in_wim + lte->rspec->size_in_wim > end_offset) return WIMLIB_ERR_RESOURCE_ORDER; return 0; } @@ -2950,11 +2944,12 @@ overwrite_wim_inplace(WIMStruct *wim, int write_flags, * data, and that there are no stream resources, metadata resources, or * lookup tables after the XML data. Otherwise, these data would be * overwritten. */ - old_xml_begin = wim->hdr.xml_res_entry.offset; - old_xml_end = old_xml_begin + wim->hdr.xml_res_entry.size; - old_lookup_table_end = wim->hdr.lookup_table_res_entry.offset + - wim->hdr.lookup_table_res_entry.size; - if (wim->hdr.integrity.offset != 0 && wim->hdr.integrity.offset < old_xml_end) { + old_xml_begin = wim->hdr.xml_data_reshdr.offset_in_wim; + old_xml_end = old_xml_begin + wim->hdr.xml_data_reshdr.size_in_wim; + old_lookup_table_end = wim->hdr.lookup_table_reshdr.offset_in_wim + + wim->hdr.lookup_table_reshdr.size_in_wim; + if (wim->hdr.integrity_table_reshdr.offset_in_wim != 0 && + wim->hdr.integrity_table_reshdr.offset_in_wim < old_xml_end) { WARNING("Didn't expect the integrity table to be before the XML data"); return WIMLIB_ERR_RESOURCE_ORDER; } @@ -2979,10 +2974,11 @@ overwrite_wim_inplace(WIMStruct *wim, int write_flags, old_wim_end = old_lookup_table_end; write_flags |= WIMLIB_WRITE_FLAG_NO_LOOKUP_TABLE | WIMLIB_WRITE_FLAG_CHECKPOINT_AFTER_XML; - } else if (wim->hdr.integrity.offset) { + } else if (wim->hdr.integrity_table_reshdr.offset_in_wim != 0) { /* Old WIM has an integrity table; begin writing new streams * after it. */ - old_wim_end = wim->hdr.integrity.offset + wim->hdr.integrity.size; + old_wim_end = wim->hdr.integrity_table_reshdr.offset_in_wim + + wim->hdr.integrity_table_reshdr.size_in_wim; } else { /* No existing integrity table; begin writing new streams after * the old XML data. */ diff --git a/src/xml.c b/src/xml.c index cd335e07..4a8bda9a 100644 --- a/src/xml.c +++ b/src/xml.c @@ -36,6 +36,7 @@ #include "wimlib/resource.h" #include "wimlib/timestamp.h" #include "wimlib/xml.h" +#include "wimlib/write.h" #include #include @@ -1153,9 +1154,9 @@ calculate_dentry_statistics(struct wim_dentry *dentry, void *arg) */ lte = inode_unnamed_lte(inode, info->lookup_table); if (lte) { - info->total_bytes += wim_resource_size(lte); + info->total_bytes += lte->size; if (!dentry_is_first_in_inode(dentry)) - info->hard_link_bytes += wim_resource_size(lte); + info->hard_link_bytes += lte->size; } if (inode->i_nlink >= 2 && dentry_is_first_in_inode(dentry)) { @@ -1164,7 +1165,7 @@ calculate_dentry_statistics(struct wim_dentry *dentry, void *arg) lte = inode_stream_lte(inode, i + 1, info->lookup_table); if (lte) { info->hard_link_bytes += inode->i_nlink * - wim_resource_size(lte); + lte->size; } } } @@ -1311,23 +1312,18 @@ int read_wim_xml_data(WIMStruct *wim) { void *buf; + size_t bufsize; u8 *xml_data; xmlDoc *doc; xmlNode *root; int ret; - const struct resource_entry *res_entry; - - res_entry = &wim->hdr.xml_res_entry; - - DEBUG("Reading XML data: %"PRIu64" bytes at offset %"PRIu64"", - (u64)res_entry->size, res_entry->offset); - ret = res_entry_to_data(res_entry, wim, &buf); + ret = wimlib_get_xml_data(wim, &buf, &bufsize); if (ret) goto out; xml_data = buf; - doc = xmlReadMemory((const char *)xml_data, res_entry->original_size, + doc = xmlReadMemory((const char *)xml_data, bufsize, NULL, "UTF-16LE", 0); if (!doc) { ERROR("Failed to parse XML data"); @@ -1500,7 +1496,7 @@ out_write_error: /* Writes the XML data to a WIM file. */ int write_wim_xml_data(WIMStruct *wim, int image, u64 total_bytes, - struct resource_entry *out_res_entry, + struct wim_reshdr *out_reshdr, int write_resource_flags) { int ret; @@ -1523,7 +1519,7 @@ write_wim_xml_data(WIMStruct *wim, int image, u64 total_bytes, &wim->out_fd, WIMLIB_COMPRESSION_TYPE_NONE, 0, - out_res_entry, + out_reshdr, NULL, write_resource_flags, &wim->lzx_context); @@ -1567,14 +1563,19 @@ wimlib_image_name_in_use(const WIMStruct *wim, const tchar *name) WIMLIBAPI int wimlib_get_xml_data(WIMStruct *wim, void **buf_ret, size_t *bufsize_ret) { - if (wim->filename == NULL) + const struct wim_reshdr *xml_reshdr; + + if (wim->filename == NULL && filedes_is_seekable(&wim->in_fd)) return WIMLIB_ERR_INVALID_PARAM; if (buf_ret == NULL || bufsize_ret == NULL) return WIMLIB_ERR_INVALID_PARAM; - *bufsize_ret = wim->hdr.xml_res_entry.original_size; - return res_entry_to_data(&wim->hdr.xml_res_entry, wim, buf_ret); + xml_reshdr = &wim->hdr.xml_data_reshdr; + + DEBUG("Reading XML data."); + *bufsize_ret = xml_reshdr->uncompressed_size; + return wim_reshdr_to_data(xml_reshdr, wim, buf_ret); } WIMLIBAPI int