#ifndef _WIMLIB_RESOURCE_H
#define _WIMLIB_RESOURCE_H
-#include "wimlib/types.h"
-#include "wimlib/endianness.h"
-#include "wimlib/callback.h"
-#include "wimlib/file_io.h"
+#include "wimlib/list.h"
#include "wimlib/sha1.h"
+#include "wimlib/types.h"
-struct wim_lookup_table_entry;
+struct blob_descriptor;
+struct filedes;
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;
+/*
+ * 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;
- /* Offset, in bytes, of the resource from the start of the WIM file. */
- u64 offset;
+ /* The list of blobs this resource contains. */
+ struct list_head blob_list;
- /* Uncompressed size, in bytes, of the resource (stream). */
- u64 original_size;
+ /* Flags for this resource (WIM_RESHDR_FLAG_*). */
+ u32 flags : 8;
+
+ /* [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;
+
+ /* 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;
};
-/* On-disk version of `struct resource_entry'. See `struct resource_entry' for
- * description of fields. */
-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, wimlib doesn'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. This flag
- * is also set in the resource entry for the lookup table in the WIM header. */
+/* 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 (using the WIM's set compression
- * type). */
+/* 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, wimlib doesn't actually use this flag for anything. */
+/* Unknown meaning; currently ignored by wimlib. */
#define WIM_RESHDR_FLAG_SPANNED 0x08
-/* Functions that operate directly on `struct resource_entry's. */
+/* 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
-static inline int
-resource_is_compressed(const struct resource_entry *entry)
-{
- return (entry->flags & WIM_RESHDR_FLAG_COMPRESSED);
-}
+/* 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
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
-get_resource_entry(const struct resource_entry_disk *disk_entry,
- struct resource_entry *entry);
+wim_reshdr_to_desc(const struct wim_reshdr *reshdr, WIMStruct *wim,
+ struct wim_resource_descriptor *rdesc);
extern void
-put_resource_entry(const struct resource_entry *entry,
- struct resource_entry_disk *disk_entry);
+wim_reshdr_to_desc_and_blob(const struct wim_reshdr *reshdr, WIMStruct *wim,
+ struct wim_resource_descriptor *rdesc,
+ struct blob_descriptor *blob);
-/* wimlib internal flags used when reading or writing resources. */
-#define WIMLIB_WRITE_RESOURCE_FLAG_RECOMPRESS 0x00000001
-#define WIMLIB_WRITE_RESOURCE_FLAG_PIPABLE 0x00000002
-#define WIMLIB_WRITE_RESOURCE_MASK 0x0000ffff
+extern void
+get_wim_reshdr(const struct wim_reshdr_disk *disk_reshdr,
+ struct wim_reshdr *reshdr);
-#define WIMLIB_READ_RESOURCE_FLAG_RAW_FULL 0x80000000
-#define WIMLIB_READ_RESOURCE_FLAG_RAW_CHUNKS 0x40000000
-#define WIMLIB_READ_RESOURCE_FLAG_RAW (WIMLIB_READ_RESOURCE_FLAG_RAW_FULL | \
- WIMLIB_READ_RESOURCE_FLAG_RAW_CHUNKS)
-#define WIMLIB_READ_RESOURCE_MASK 0xffff0000
+extern void
+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;
-/* Functions to read a resource. */
+ /* 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(const struct wim_lookup_table_entry *lte,
- u64 size, consume_data_callback_t cb,
- u32 in_chunk_size, void *ctx_or_buf,
- int flags, u64 offset);
+read_partial_wim_blob_into_buf(const struct blob_descriptor *blob,
+ u64 offset, size_t size, void *buf);
extern int
-read_partial_wim_resource_into_buf(const struct wim_lookup_table_entry *lte,
- size_t size, u64 offset, void *buf);
+read_blob_into_buf(const struct blob_descriptor *blob, void *buf);
+
extern int
-read_full_resource_into_buf(const struct wim_lookup_table_entry *lte, void *buf);
+read_blob_into_alloc_buf(const struct blob_descriptor *blob, void **buf_ret);
extern int
-read_full_resource_into_alloc_buf(const struct wim_lookup_table_entry *lte,
- void **buf_ret);
+wim_reshdr_to_data(const struct wim_reshdr *reshdr, WIMStruct *wim,
+ void **buf_ret);
extern int
-res_entry_to_data(const struct resource_entry *res_entry,
- WIMStruct *wim, void **buf_ret);
+wim_reshdr_to_hash(const struct wim_reshdr *reshdr, WIMStruct *wim,
+ u8 hash[SHA1_HASH_SIZE]);
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);
+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
-/* Functions to write a resource. */
+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
-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);
+read_blob_with_cbs(struct blob_descriptor *blob,
+ const struct read_blob_callbacks *cbs);
-/* Functions to extract a resource. */
+extern int
+read_blob_with_sha1(struct blob_descriptor *blob,
+ const struct read_blob_callbacks *cbs);
extern int
-extract_wim_resource(const struct wim_lookup_table_entry *lte,
- u64 size,
- consume_data_callback_t extract_chunk,
- void *extract_chunk_arg);
+extract_blob_prefix_to_fd(struct blob_descriptor *blob, u64 size,
+ struct filedes *fd);
extern int
-extract_wim_resource_to_fd(const struct wim_lookup_table_entry *lte,
- struct filedes *fd, u64 size);
+extract_blob_to_fd(struct blob_descriptor *blob, struct filedes *fd);
-/* Miscellaneous resource functions. */
+/* Miscellaneous blob functions. */
extern int
-sha1_resource(struct wim_lookup_table_entry *lte);
+sha1_blob(struct blob_descriptor *blob);
/* Functions to read/write metadata resources. */
extern int
-read_metadata_resource(WIMStruct *wim,
- struct wim_image_metadata *image_metadata);
+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 stream in the pipable WIM, used for sanity
+/* Arbitrary number to begin each blob in the pipable WIM, used for sanity
* checking. */
-#define PWM_STREAM_MAGIC 0x2b9b9ba2443db9d8ULL
+#define PWM_BLOB_MAGIC 0x2b9b9ba2443db9d8ULL
-/* Header that precedes each resource in a pipable WIM. */
-struct pwm_stream_hdr {
+/* 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 */
/* +40 */
} _packed_attribute;
-/* Extra flag for the @flags field in `struct pipable_wim_stream_hdr': Indicates
- * that the SHA1 message digest of the stream has not been calculated.
- * Currently only used for the XML data. */
-#define PWM_RESHDR_FLAG_UNHASHED 0x100
-
/* 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 */