X-Git-Url: https://wimlib.net/git/?p=wimlib;a=blobdiff_plain;f=include%2Fwimlib%2Fresource.h;h=2fea2f579048759ce3d9b5c9784603b316694ce8;hp=c75986117643fd8c7c788baccc3070b8fbbc7117;hb=011502c8756394066172b3164567a8b9835cc280;hpb=30ba1eb06caca0b20a47d8dd75a117c82d730da7 diff --git a/include/wimlib/resource.h b/include/wimlib/resource.h index c7598611..2fea2f57 100644 --- a/include/wimlib/resource.h +++ b/include/wimlib/resource.h @@ -1,135 +1,309 @@ #ifndef _WIMLIB_RESOURCE_H #define _WIMLIB_RESOURCE_H +#include "wimlib/list.h" +#include "wimlib/sha1.h" #include "wimlib/types.h" -#include "wimlib/callback.h" -struct wim_lookup_table_entry; +struct blob_descriptor; +struct filedes; struct wim_image_metadata; -/* Metadata for a resource in a WIM file. */ -struct resource_entry { - /* Size, in bytes, of the resource in the WIM file. */ - u64 size : 56; +/* + * Description of a "resource" in a WIM file. A "resource" is a standalone, + * possibly compressed region of data. Normally, there is a one-to-one + * correspondence between "blobs" (each of which may be the contents of a file, + * for example) and resources. However, a resource with the + * WIM_RESHDR_FLAG_SOLID flag set is a "solid" resource that contains multiple + * blobs compressed together. + */ +struct wim_resource_descriptor { + /* The WIM containing this resource. @wim->in_fd is expected to be a + * file descriptor to the underlying WIM file, opened for reading. */ + WIMStruct *wim; - /* Bitwise or of one or more of the WIM_RESHDR_FLAG_* flags. */ - u64 flags : 8; + /* The 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, including overhead such as the chunk + * table. */ + u64 size_in_wim; + + /* The number of bytes of uncompressed data this resource decompresses + * to. */ + u64 uncompressed_size; + + /* The list of blobs this resource contains. */ + struct list_head blob_list; + + /* Flags for this resource (WIM_RESHDR_FLAG_*). */ + u32 flags : 8; - /* Offset, in bytes, of the resource in the WIM file. */ - u64 offset; + /* [wimlib extension] This flag will be set if the WIM is pipable. In + * such cases, the resource will be in a slightly different format if it + * is compressed. */ + u32 is_pipable : 1; - /* Uncompressed size of the resource in the WIM file. Is the same as - * @size if the resource is uncompressed. */ - u64 original_size; + /* Temporary flag. */ + u32 raw_copy_ok : 1; + + /* Compression type of this resource. */ + u32 compression_type : 22; + + /* Compression chunk size of this resource. Irrelevant if the resource + * is uncompressed. */ + u32 chunk_size; }; -struct resource_entry_disk { - u8 size[7]; +/* On-disk version of a WIM resource header. */ +struct wim_reshdr_disk { + /* Size of the resource as it appears in the WIM file (possibly + * compressed). */ + u8 size_in_wim[7]; + + /* Zero or more of the WIM_RESHDR_FLAG_* flags. These indicate, for + * example, whether the resource is compressed or not. */ u8 flags; - le64 offset; - le64 original_size; + + /* Offset of the resource from the start of the WIM file, in bytes. */ + le64 offset_in_wim; + + /* Uncompressed size of the resource, in bytes. */ + le64 uncompressed_size; } _packed_attribute; -/* Flags for the `flags' field of the struct resource_entry structure. */ +/* In-memory version of a WIM resource header (`struct 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 WIM resource headers (`struct wim_reshdr'). + */ -/* I haven't seen this flag used in any of the WIMs I have examined. I assume - * it means that there are no references to the stream, so the space is free. - * However, even after deleting files from a WIM mounted with `imagex.exe - * /mountrw', I could not see this flag being used. Either way, we don't - * actually use this flag for anything. */ +/* Unknown meaning; currently ignored by wimlib. */ #define WIM_RESHDR_FLAG_FREE 0x01 -/* Indicates that the stream is a metadata resource for a WIM image. */ +/* The resource is a metadata resource for a WIM image, or is the blob table or + * XML data for the WIM. */ #define WIM_RESHDR_FLAG_METADATA 0x02 -/* Indicates that the stream is compressed. */ +/* The resource is a non-solid resource compressed using the WIM's default + * compression type. */ #define WIM_RESHDR_FLAG_COMPRESSED 0x04 -/* I haven't seen this flag used in any of the WIMs I have examined. Perhaps it - * means that a stream could possibly be split among multiple split WIM parts. - * However, `imagex.exe /split' does not seem to create any WIMs like this. - * Either way, we don't actually use this flag for anything. */ +/* Unknown meaning; currently ignored by wimlib. */ #define WIM_RESHDR_FLAG_SPANNED 0x08 -/* Nonzero if a struct resource_entry indicates a compressed resource. */ -static inline int -resource_is_compressed(const struct resource_entry *entry) -{ - return (entry->flags & WIM_RESHDR_FLAG_COMPRESSED); -} +/* The resource is a solid compressed resource which may contain multiple blobs. + * This flag is only allowed if the WIM version number is WIM_VERSION_SOLID. */ +#define WIM_RESHDR_FLAG_SOLID 0x10 + +/* Magic number in the 'uncompressed_size' field of the resource header that + * identifies the main entry for a solid resource. */ +#define SOLID_RESOURCE_MAGIC_NUMBER 0x100000000ULL -#if 1 -# define copy_resource_entry(dst, src) memcpy(dst, src, sizeof(struct resource_entry)) -# define zero_resource_entry(entry) memset(entry, 0, sizeof(struct resource_entry)) -#else 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) { - BUILD_BUG_ON(sizeof(struct resource_entry) != 24); - ((u64*)dst)[0] = ((u64*)src)[0]; - ((u64*)dst)[1] = ((u64*)src)[1]; - ((u64*)dst)[2] = ((u64*)src)[2]; + memcpy(dest, src, sizeof(struct wim_reshdr)); } static inline void -zero_resource_entry(struct resource_entry *entry) +zero_reshdr(struct wim_reshdr *reshdr) { - BUILD_BUG_ON(sizeof(struct resource_entry) != 24); - ((u64*)entry)[0] = 0; - ((u64*)entry)[1] = 0; - ((u64*)entry)[2] = 0; + memset(reshdr, 0, sizeof(struct wim_reshdr)); } -#endif -#define WIMLIB_RESOURCE_FLAG_RAW 0x1 -#define WIMLIB_RESOURCE_FLAG_RECOMPRESS 0x2 +extern void +wim_reshdr_to_desc(const struct wim_reshdr *reshdr, WIMStruct *wim, + struct wim_resource_descriptor *rdesc); -extern int -read_resource_prefix(const struct wim_lookup_table_entry *lte, - u64 size, consume_data_callback_t cb, void *ctx_or_buf, - int flags); +extern void +wim_reshdr_to_desc_and_blob(const struct wim_reshdr *reshdr, WIMStruct *wim, + struct wim_resource_descriptor *rdesc, + struct blob_descriptor *blob); extern 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); extern 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); + +/* Alternate chunk table format for resources with WIM_RESHDR_FLAG_SOLID set. + */ +struct alt_chunk_table_header_disk { + /* Uncompressed size of the resource in bytes. */ + le64 res_usize; + + /* Number of bytes each compressed chunk decompresses into, except + * possibly the last which decompresses into the remainder. This + * overrides the chunk size specified by the WIM header. */ + le32 chunk_size; + + /* Compression format used for compressed chunks: + * 0 = None + * 1 = XPRESS + * 2 = LZX + * 3 = LZMS + * + * This overrides the compression type specified by the WIM header. */ + le32 compression_format; + + /* This header is directly followed by a table of compressed sizes of + * the chunks (4 bytes per entry). */ +} _packed_attribute; + +static inline unsigned int +get_chunk_entry_size(u64 res_size, bool is_alt) +{ + if (res_size <= UINT32_MAX || is_alt) + return 4; + else + return 8; +} + +/* Functions to read blobs */ extern int -read_partial_wim_resource_into_buf(const struct wim_lookup_table_entry *lte, - size_t size, u64 offset, void *buf); +read_partial_wim_blob_into_buf(const struct blob_descriptor *blob, + u64 offset, size_t size, void *buf); + extern int -read_full_resource_into_buf(const struct wim_lookup_table_entry *lte, void *buf); +read_blob_into_buf(const struct blob_descriptor *blob, void *buf); extern int -write_wim_resource(struct wim_lookup_table_entry *lte, int out_fd, - int out_ctype, struct resource_entry *out_res_entry, - int flags); +read_blob_into_alloc_buf(const struct blob_descriptor *blob, void **buf_ret); extern int -extract_wim_resource(const struct wim_lookup_table_entry *lte, - u64 size, - consume_data_callback_t extract_chunk, - void *extract_chunk_arg); +wim_reshdr_to_data(const struct wim_reshdr *reshdr, WIMStruct *wim, + void **buf_ret); extern int -extract_wim_resource_to_fd(const struct wim_lookup_table_entry *lte, - int fd, u64 size); +wim_reshdr_to_hash(const struct wim_reshdr *reshdr, WIMStruct *wim, + u8 hash[SHA1_HASH_SIZE]); extern int -sha1_resource(struct wim_lookup_table_entry *lte); +skip_wim_resource(const struct wim_resource_descriptor *rdesc); + +/* Callback functions for reading blobs */ +struct read_blob_callbacks { + + /* Called when starting to read a blob. Must return 0 on success, or a + * positive wimlib error code on failure, or in the case of + * read_blob_list(), the special value BEGIN_BLOB_STATUS_SKIP_BLOB which + * indicates that the data for this blob should not be read. */ + int (*begin_blob)(struct blob_descriptor *blob, void *ctx); +#define BEGIN_BLOB_STATUS_SKIP_BLOB (-1) + + /* Called when the next chunk of uncompressed data is available. 'size' + * is guaranteed to be nonzero. Must return 0 on success, or a positive + * wimlib error code on failure. */ + int (*consume_chunk)(const void *chunk, size_t size, void *ctx); + + /* Called when a blob has been successfully read (status=0), or when + * begin_blob() was successfully called but an error occurred before the + * blob was fully read (status != 0; in this case the implementation + * should do cleanup and then pass on the status). Must return 0 on + * success, or a positive wimlib error code on failure. */ + int (*end_blob)(struct blob_descriptor *blob, int status, void *ctx); + + /* Parameter passed to each of the callback functions. */ + void *ctx; +}; + +/* Call cbs->begin_blob() if present. */ +static inline int +call_begin_blob(struct blob_descriptor *blob, + const struct read_blob_callbacks *cbs) +{ + if (!cbs->begin_blob) + return 0; + return (*cbs->begin_blob)(blob, cbs->ctx); +} + +/* Call cbs->consume_chunk() if present. */ +static inline int +call_consume_chunk(const void *chunk, size_t size, + const struct read_blob_callbacks *cbs) +{ + if (!cbs->consume_chunk) + return 0; + return (*cbs->consume_chunk)(chunk, size, cbs->ctx); +} + +/* Call cbs->end_blob() if present. */ +static inline int +call_end_blob(struct blob_descriptor *blob, int status, + const struct read_blob_callbacks *cbs) +{ + if (!cbs->end_blob) + return status; + return (*cbs->end_blob)(blob, status, cbs->ctx); +} + +/* Flags for read_blob_list() */ +#define VERIFY_BLOB_HASHES 0x1 +#define COMPUTE_MISSING_BLOB_HASHES 0x2 +#define BLOB_LIST_ALREADY_SORTED 0x4 + +extern int +read_blob_list(struct list_head *blob_list, size_t list_head_offset, + const struct read_blob_callbacks *cbs, int flags); extern int -copy_resource(struct wim_lookup_table_entry *lte, void *w); +read_blob_with_cbs(struct blob_descriptor *blob, + const struct read_blob_callbacks *cbs); extern int -read_metadata_resource(WIMStruct *w, - struct wim_image_metadata *image_metadata); +read_blob_with_sha1(struct blob_descriptor *blob, + const struct read_blob_callbacks *cbs); extern int -write_metadata_resource(WIMStruct *w); +extract_blob_prefix_to_fd(struct blob_descriptor *blob, u64 size, + struct filedes *fd); + +extern int +extract_blob_to_fd(struct blob_descriptor *blob, struct filedes *fd); + +/* Miscellaneous blob functions. */ + +extern int +sha1_blob(struct blob_descriptor *blob); + +/* Functions to read/write metadata resources. */ + +extern int +read_metadata_resource(struct wim_image_metadata *imd); + +extern int +write_metadata_resource(WIMStruct *wim, int image, int write_resource_flags); + +/* Definitions specific to pipable WIM resources. */ + +/* Arbitrary number to begin each blob in the pipable WIM, used for sanity + * checking. */ +#define PWM_BLOB_MAGIC 0x2b9b9ba2443db9d8ULL + +/* Header that precedes each blob in a pipable WIM. */ +struct pwm_blob_hdr { + le64 magic; /* +0 */ + le64 uncompressed_size; /* +8 */ + u8 hash[SHA1_HASH_SIZE]; /* +16 */ + le32 flags; /* +36 */ + /* +40 */ +} _packed_attribute; + +/* Header that precedes each chunk of a compressed resource in a pipable WIM. + */ +struct pwm_chunk_hdr { + le32 compressed_size; +} _packed_attribute; #endif /* _WIMLIB_RESOURCE_H */