]> wimlib.net Git - wimlib/blobdiff - include/wimlib/resource.h
New helper: wim_reshdr_to_desc_and_blob()
[wimlib] / include / wimlib / resource.h
index 8e781c2e32837a989333b04792715b67b172887c..2fea2f579048759ce3d9b5c9784603b316694ce8 100644 (file)
@@ -1,82 +1,80 @@
 #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;
 
-/* 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.  */
+/*
+ * 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;
 
-       /* Offset, in bytes, from the start of WIM file at which this resource
-        * starts.  */
+       /* 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.  */
+        * this is the compressed size, including overhead such as the chunk
+        * table.  */
        u64 size_in_wim;
 
-       /* Number of bytes of uncompressed data this resource uncompresses to.
-        */
+       /* The number of bytes of uncompressed data this resource decompresses
+        * to.  */
        u64 uncompressed_size;
 
-       /* List of streams this resource contains.  */
-       struct list_head lte_list;
+       /* The list of blobs this resource contains.  */
+       struct list_head blob_list;
 
-       /* Resource flags.  */
+       /* Flags for this resource (WIM_RESHDR_FLAG_*).  */
        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).  */
+       /* [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;
 
-       /* Compression type of this resource as one of WIMLIB_COMPRESSION_TYPE_*
-        * constants.  */
-       u32 ctype : 3;
+       /* Temporary flag.  */
+       u32 raw_copy_ok : 1;
 
-       /* Compression chunk size.  */
-       u32 cchunk_size;
-};
+       /* 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 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.  */
+/* 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];
 
-       /* WIM_RESHDR_FLAG_* flags.  */
+       /* Zero or more of the WIM_RESHDR_FLAG_* flags.  These indicate, for
+        * example, whether the resource is compressed or not.  */
        u8 flags;
 
-       /* Offset of the resource from the start of the WIM file.  */
+       /* Offset of the resource from the start of the WIM file, in bytes.  */
        le64 offset_in_wim;
 
-       /* Uncompressed size of the resource.  */
+       /* Uncompressed size of the resource, in bytes.  */
        le64 uncompressed_size;
 } _packed_attribute;
 
-/* In-memory version of wim_reshdr_disk.  */
+/* In-memory version of a WIM resource header (`struct wim_reshdr_disk').  */
 struct wim_reshdr {
        u64 size_in_wim : 56;
        u64 flags : 8;
@@ -84,31 +82,30 @@ struct wim_reshdr {
        u64 uncompressed_size;
 };
 
-/* Flags for the `flags' field of the struct resource_entry structure. */
+/* 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
 
-/* TODO  */
-#define WIM_RESHDR_FLAG_CONCAT         0x10
+/* 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
 
 static inline void
 copy_reshdr(struct wim_reshdr *dest, const struct wim_reshdr *src)
@@ -122,96 +119,180 @@ zero_reshdr(struct wim_reshdr *reshdr)
        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);
+wim_reshdr_to_desc(const struct wim_reshdr *reshdr, WIMStruct *wim,
+                  struct wim_resource_descriptor *rdesc);
 
 extern void
-wim_res_spec_to_hdr(const struct wim_resource_spec *rspec,
-                   struct wim_reshdr *reshdr);
+wim_reshdr_to_desc_and_blob(const struct wim_reshdr *reshdr, WIMStruct *wim,
+                           struct wim_resource_descriptor *rdesc,
+                           struct blob_descriptor *blob);
 
-extern int
+extern void
 get_wim_reshdr(const struct wim_reshdr_disk *disk_reshdr,
               struct wim_reshdr *reshdr);
 
-void
+extern 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
-#define WIMLIB_WRITE_RESOURCE_FLAG_PIPABLE             0x00000002
-#define WIMLIB_WRITE_RESOURCE_MASK                     0x0000ffff
+/* 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;
 
-#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
+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  */
 
-/* Functions to read a resource.  */
+extern int
+read_partial_wim_blob_into_buf(const struct blob_descriptor *blob,
+                              u64 offset, size_t size, void *buf);
 
 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_blob_into_buf(const struct blob_descriptor *blob, void *buf);
 
 extern int
-read_partial_wim_stream_into_buf(const struct wim_lookup_table_entry *lte,
-                                size_t size, u64 offset, void *buf);
+read_blob_into_alloc_buf(const struct blob_descriptor *blob, void **buf_ret);
+
 extern int
-read_full_stream_into_buf(const struct wim_lookup_table_entry *lte, void *buf);
+wim_reshdr_to_data(const struct wim_reshdr *reshdr, WIMStruct *wim,
+                  void **buf_ret);
 
 extern int
-read_full_stream_into_alloc_buf(const struct wim_lookup_table_entry *lte,
-                               void **buf_ret);
+wim_reshdr_to_hash(const struct wim_reshdr *reshdr, WIMStruct *wim,
+                  u8 hash[SHA1_HASH_SIZE]);
 
 extern int
-wim_reshdr_to_data(const struct wim_reshdr *reshdr,
-                  WIMStruct *wim, void **buf_ret);
+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
-read_stream_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);
+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_stream(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_stream_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_stream(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  */
@@ -219,16 +300,10 @@ struct pwm_stream_hdr {
                                        /* +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 */