unsigned long invalid_sequence;
unsigned long partial_security_descriptors;
unsigned long no_security_descriptors;
+ struct wim_lookup_table_entry *cur_stream;
struct filedes tmpfile_fd;
tchar *tmpfile_name;
u64 num_streams_remaining;
* @lte:
* Stream that is about to be read.
*
- * @is_partial_res:
- * Set to true if the stream is just one of several being read from a
- * single pack and therefore would be extra expensive to read
- * independently.
+ * @flags:
+ * Bitwise OR of BEGIN_STREAM_FLAG_PARTIAL_RESOURCE and/or
+ * BEGIN_STREAM_FLAG_WHOLE_STREAM.
*
* @ctx:
* User-provided context.
* (without calling @consume_chunk or @end_stream).
*/
typedef int (*read_stream_list_begin_stream_t)(struct wim_lookup_table_entry *lte,
- bool is_partial_res,
+ u32 flags,
void *ctx);
+/* Set to true if the stream is just one of several being read from a single
+ * pack and therefore would be extra expensive to read independently. */
+#define BEGIN_STREAM_FLAG_PARTIAL_RESOURCE 0x00000001
+
+/* This is purely advisory and indicates that the entire stream data will be
+ * provided in one call to consume_chunk(). */
+#define BEGIN_STREAM_FLAG_WHOLE_STREAM 0x00000002
+
#define BEGIN_STREAM_STATUS_SKIP_STREAM -1
/*
}
static int
-begin_extract_stream_to_tmpfile(struct wim_lookup_table_entry *lte,
- bool is_partial_res,
- void *_ctx)
+begin_extract_stream(struct wim_lookup_table_entry *lte,
+ u32 flags, void *_ctx)
{
struct apply_ctx *ctx = _ctx;
int ret;
- if (!need_tmpfile_to_extract(lte, is_partial_res)) {
+ if (flags & BEGIN_STREAM_FLAG_WHOLE_STREAM) {
+ DEBUG("Whole stream (size=%"PRIu64") will be read into memory",
+ lte->size);
+ ctx->cur_stream = lte;
+ filedes_invalidate(&ctx->tmpfile_fd);
+ return 0;
+ }
+
+ if (!need_tmpfile_to_extract(lte,
+ (flags & BEGIN_STREAM_FLAG_PARTIAL_RESOURCE)))
+ {
DEBUG("Temporary file not needed "
"for stream (size=%"PRIu64")", lte->size);
ret = extract_stream_instances(lte, lte, ctx);
}
static int
-end_extract_stream_to_tmpfile(struct wim_lookup_table_entry *lte,
- int status, void *_ctx)
+extract_chunk(const void *chunk, size_t size, void *_ctx)
+{
+ struct apply_ctx *ctx = _ctx;
+ int ret;
+
+ if (filedes_valid(&ctx->tmpfile_fd)) {
+ ret = full_write(&ctx->tmpfile_fd, chunk, size);
+ if (ret)
+ ERROR_WITH_ERRNO("Error writing to file descriptor");
+ } else {
+ struct wim_lookup_table_entry lte_override;
+
+ memcpy(<e_override, ctx->cur_stream,
+ sizeof(struct wim_lookup_table_entry));
+
+ lte_override.resource_location = RESOURCE_IN_ATTACHED_BUFFER;
+ lte_override.size = size;
+ lte_override.attached_buffer = (void *)chunk;
+
+ ret = extract_stream_instances(ctx->cur_stream, <e_override, ctx);
+ }
+ return ret;
+}
+
+static int
+end_extract_stream(struct wim_lookup_table_entry *lte,
+ int status, void *_ctx)
{
struct apply_ctx *ctx = _ctx;
struct wim_lookup_table_entry lte_override;
int ret;
int errno_save = errno;
+ if (!filedes_valid(&ctx->tmpfile_fd))
+ return status;
+
ret = filedes_close(&ctx->tmpfile_fd);
if (status) {
extract_stream_list(struct apply_ctx *ctx)
{
struct read_stream_list_callbacks cbs = {
- .begin_stream = begin_extract_stream_to_tmpfile,
+ .begin_stream = begin_extract_stream,
.begin_stream_ctx = ctx,
- .consume_chunk = extract_chunk_to_fd,
- .consume_chunk_ctx = &ctx->tmpfile_fd,
- .end_stream = end_extract_stream_to_tmpfile,
+ .consume_chunk = extract_chunk,
+ .consume_chunk_ctx = ctx,
+ .end_stream = end_extract_stream,
.end_stream_ctx = ctx,
};
return read_stream_list(&ctx->stream_list,
wimlib_assert(size <= ctx->cur_stream->size - ctx->cur_stream_offset);
if (ctx->cur_stream_offset == 0) {
+ u32 flags;
+
/* Starting a new stream. */
DEBUG("Begin new stream (size=%"PRIu64").",
ctx->cur_stream->size);
- ret = (*ctx->cbs.begin_stream)(ctx->cur_stream, true,
+
+ flags = BEGIN_STREAM_FLAG_PARTIAL_RESOURCE;
+ if (size == ctx->cur_stream->size)
+ flags |= BEGIN_STREAM_FLAG_WHOLE_STREAM;
+ ret = (*ctx->cbs.begin_stream)(ctx->cur_stream,
+ flags,
ctx->cbs.begin_stream_ctx);
if (ret)
return ret;
/* Callback for starting to read a stream while calculating its SHA1 message
* digest. */
static int
-hasher_begin_stream(struct wim_lookup_table_entry *lte, bool is_partial_res,
+hasher_begin_stream(struct wim_lookup_table_entry *lte, u32 flags,
void *_ctx)
{
struct hasher_context *ctx = _ctx;
if (ctx->cbs.begin_stream == NULL)
return 0;
else
- return (*ctx->cbs.begin_stream)(lte, is_partial_res,
+ return (*ctx->cbs.begin_stream)(lte, flags,
ctx->cbs.begin_stream_ctx);
}
{
int ret;
- ret = (*cbs->begin_stream)(lte, false, cbs->begin_stream_ctx);
+ ret = (*cbs->begin_stream)(lte, 0, cbs->begin_stream_ctx);
if (ret)
return ret;
.consume_chunk_ctx = &hasher_ctx,
.end_stream = hasher_end_stream,
.end_stream_ctx = &hasher_ctx,
-
};
return read_full_stream_with_cbs(lte, &hasher_cbs);
}
/* Begin processing a stream for writing. */
static int
write_stream_begin_read(struct wim_lookup_table_entry *lte,
- bool is_partial_res, void *_ctx)
+ u32 flags, void *_ctx)
{
struct write_streams_ctx *ctx = _ctx;
int ret;
ctx->stream_was_duplicate = false;
if (ctx->lookup_table != NULL && lte->unhashed && !lte->unique_size) {
- wimlib_assert(!is_partial_res);
+ wimlib_assert(!(flags & BEGIN_STREAM_FLAG_PARTIAL_RESOURCE));
struct wim_lookup_table_entry *lte_new;