+/* 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 (*continue_blob)(const struct blob_descriptor *blob, u64 offset,
+ 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->continue_blob() if present. */
+static inline int
+call_continue_blob(const struct blob_descriptor *blob, u64 offset,
+ const void *chunk, size_t size,
+ const struct read_blob_callbacks *cbs)
+{
+ if (!cbs->continue_blob)
+ return 0;
+ return (*cbs->continue_blob)(blob, offset, 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