#include "wimlib/apply.h"
#include "wimlib/assert.h"
+#include "wimlib/blob_table.h"
#include "wimlib/capture.h" /* for mangle_pat() and match_pattern_list() */
#include "wimlib/dentry.h"
+#include "wimlib/encoding.h"
#include "wimlib/error.h"
-#include "wimlib/lookup_table.h"
#include "wimlib/metadata.h"
#include "wimlib/paths.h"
#include "wimlib/reparse.h"
/* WIMBoot information, only filled in if WIMLIB_EXTRACT_FLAG_WIMBOOT
* was provided */
struct {
- u64 data_source_id;
+ /* This array contains the WIM files registered with WOF on the
+ * target volume for this extraction operation. All WIMStructs
+ * in this array are distinct and have ->filename != NULL. */
+ struct wimboot_wim {
+ WIMStruct *wim;
+ u64 data_source_id;
+ u8 blob_table_hash[SHA1_HASH_SIZE];
+ } *wims;
+ size_t num_wims;
struct string_set *prepopulate_pats;
void *mem_prepopulate_pats;
- u8 wim_lookup_table_hash[SHA1_HASH_SIZE];
bool wof_running;
bool tried_to_load_prepopulate_list;
} wimboot;
* target-relative NT paths */
wchar_t *print_buffer;
- /* Allocated buffer for reading stream data when it cannot be extracted
+ /* Allocated buffer for reading blob data when it cannot be extracted
* directly */
u8 *data_buffer;
/* Array of open handles to filesystem streams currently being written
*/
- HANDLE open_handles[MAX_OPEN_STREAMS];
+ HANDLE open_handles[MAX_OPEN_FILES];
/* Number of handles in @open_handles currently open (filled in from the
* beginning of the array) */
unsigned num_open_handles;
/* List of dentries, joined by @tmp_list, that need to have reparse data
- * extracted as soon as the whole stream has been read into
- * @data_buffer. */
+ * extracted as soon as the whole blob has been read into @data_buffer.
+ * */
struct list_head reparse_dentries;
/* List of dentries, joined by @tmp_list, that need to have raw
- * encrypted data extracted as soon as the whole stream has been read
- * into @data_buffer. */
+ * encrypted data extracted as soon as the whole blob has been read into
+ * @data_buffer. */
struct list_head encrypted_dentries;
/* Number of files for which we didn't have permission to set the full
{
const wchar_t *path = L"\\Windows\\System32\\WimBootCompress.ini";
struct wim_dentry *dentry;
- struct wim_lookup_table_entry *lte;
+ struct blob_descriptor *blob;
int ret;
void *buf;
struct string_set *s;
(dentry->d_inode->i_attributes & (FILE_ATTRIBUTE_DIRECTORY |
FILE_ATTRIBUTE_REPARSE_POINT |
FILE_ATTRIBUTE_ENCRYPTED)) ||
- !(lte = inode_unnamed_lte(dentry->d_inode, ctx->common.wim->lookup_table)))
+ !(blob = inode_get_blob_for_unnamed_data_stream(dentry->d_inode,
+ ctx->common.wim->blob_table)))
{
WARNING("%ls does not exist in WIM image!", path);
return WIMLIB_ERR_PATH_DOES_NOT_EXIST;
}
- ret = read_full_stream_into_alloc_buf(lte, &buf);
+ ret = read_full_blob_into_alloc_buf(blob, &buf);
if (ret)
return ret;
sec.name = T("PrepopulateList");
sec.strings = s;
- ret = do_load_text_file(path, buf, lte->size, &mem, &sec, 1,
+ ret = do_load_text_file(path, buf, blob->size, &mem, &sec, 1,
LOAD_TEXT_FILE_REMOVE_QUOTES |
LOAD_TEXT_FILE_NO_WARNINGS,
mangle_pat);
return true;
}
+static bool
+is_resource_valid_for_external_backing(const struct wim_resource_descriptor *rdesc)
+{
+ /* Must be the original WIM file format. This check excludes pipable
+ * resources and solid resources. It also excludes other resources
+ * contained in such files even if they would be otherwise compatible.
+ */
+ if (rdesc->wim->hdr.magic != WIM_MAGIC ||
+ rdesc->wim->hdr.wim_version != WIM_VERSION_DEFAULT)
+ return false;
+
+ /*
+ * Whitelist of compression types and chunk sizes supported by
+ * Microsoft's WOF driver.
+ *
+ * Notes:
+ * - Uncompressed WIMs result in BSOD. However, this only applies to
+ * the WIM file itself, not to uncompressed resources in a WIM file
+ * that is otherwise compressed.
+ * - XPRESS 64K sometimes appears to work, but sometimes it causes
+ * reads to fail with STATUS_UNSUCCESSFUL.
+ */
+ switch (rdesc->compression_type) {
+ case WIMLIB_COMPRESSION_TYPE_NONE:
+ if (rdesc->wim->compression_type == WIMLIB_COMPRESSION_TYPE_NONE)
+ return false;
+ break;
+ case WIMLIB_COMPRESSION_TYPE_XPRESS:
+ switch (rdesc->chunk_size) {
+ case 4096:
+ case 8192:
+ case 16384:
+ case 32768:
+ break;
+ default:
+ return false;
+ }
+ break;
+ case WIMLIB_COMPRESSION_TYPE_LZX:
+ switch (rdesc->chunk_size) {
+ case 32768:
+ break;
+ default:
+ return false;
+ }
+ break;
+ default:
+ return false;
+ }
+
+ /* Microsoft's WoF driver errors out if it tries to satisfy a read with
+ * ending offset >= 4 GiB from an externally backed file. */
+ if (rdesc->uncompressed_size > 4200000000)
+ return false;
+
+ return true;
+}
+
#define WIM_BACKING_NOT_ENABLED -1
#define WIM_BACKING_NOT_POSSIBLE -2
#define WIM_BACKING_EXCLUDED -3
{
struct list_head *next;
struct wim_dentry *dentry;
- struct wim_lookup_table_entry *stream;
+ struct blob_descriptor *blob;
int ret;
if (inode->i_can_externally_back)
FILE_ATTRIBUTE_ENCRYPTED))
return WIM_BACKING_NOT_POSSIBLE;
- stream = inode_unnamed_lte_resolved(inode);
+ blob = inode_get_blob_for_unnamed_data_stream_resolved(inode);
- if (!stream ||
- stream->resource_location != RESOURCE_IN_WIM ||
- stream->rspec->wim != ctx->common.wim ||
- stream->size != stream->rspec->uncompressed_size)
+ if (!blob || blob->blob_location != BLOB_IN_WIM ||
+ !is_resource_valid_for_external_backing(blob->rdesc, ctx))
return WIM_BACKING_NOT_POSSIBLE;
/*
return will_externally_back_inode(dentry->d_inode, ctx, NULL);
}
+/* Find the WOF registration information for the specified WIM file. */
+static struct wimboot_wim *
+find_wimboot_wim(WIMStruct *wim_to_find, struct win32_apply_ctx *ctx)
+{
+ for (size_t i = 0; i < ctx->wimboot.num_wims; i++)
+ if (wim_to_find == ctx->wimboot.wims[i].wim)
+ return &ctx->wimboot.wims[i];
+
+ wimlib_assert(0);
+ return NULL;
+}
+
static int
set_external_backing(HANDLE h, struct wim_inode *inode, struct win32_apply_ctx *ctx)
{
int ret;
const struct wim_dentry *excluded_dentry;
+ const struct blob_descriptor *blob;
+ const struct wimboot_wim *wimboot_wim;
ret = will_externally_back_inode(inode, ctx, &excluded_dentry);
if (ret > 0) /* Error. */
return call_progress(ctx->common.progfunc,
WIMLIB_PROGRESS_MSG_WIMBOOT_EXCLUDE,
&info, ctx->common.progctx);
- } else {
- /* Externally backing. */
- if (unlikely(!wimboot_set_pointer(h,
- inode_unnamed_lte_resolved(inode),
- ctx->wimboot.data_source_id,
- ctx->wimboot.wim_lookup_table_hash,
- ctx->wimboot.wof_running)))
- {
- const DWORD err = GetLastError();
+ }
- build_extraction_path(inode_first_extraction_dentry(inode), ctx);
- win32_error(err, L"\"%ls\": Couldn't set WIMBoot pointer data",
- current_path(ctx));
- return WIMLIB_ERR_WIMBOOT;
- }
- return 0;
+ /* Externally backing. */
+
+ blob = inode_get_blob_for_unnamed_data_stream_resolved(inode);
+ wimboot_wim = find_wimboot_wim(blob->rdesc->wim, ctx);
+
+ if (unlikely(!wimboot_set_pointer(h,
+ blob,
+ wimboot_wim->data_source_id,
+ wimboot_wim->blob_table_hash,
+ ctx->wimboot.wof_running)))
+ {
+ const DWORD err = GetLastError();
+
+ build_extraction_path(inode_first_extraction_dentry(inode), ctx);
+ win32_error(err, L"\"%ls\": Couldn't set WIMBoot pointer data",
+ current_path(ctx));
+ return WIMLIB_ERR_WIMBOOT;
}
+ return 0;
}
-/* Calculates the SHA-1 message digest of the WIM's lookup table. */
+/* Calculates the SHA-1 message digest of the WIM's blob table. */
static int
-hash_lookup_table(WIMStruct *wim, u8 hash[SHA1_HASH_SIZE])
+hash_blob_table(WIMStruct *wim, u8 hash[SHA1_HASH_SIZE])
{
- return wim_reshdr_to_hash(&wim->hdr.lookup_table_reshdr, wim, hash);
+ return wim_reshdr_to_hash(&wim->hdr.blob_table_reshdr, wim, hash);
+}
+
+static int
+register_wim_with_wof(WIMStruct *wim, struct win32_apply_ctx *ctx)
+{
+ struct wimboot_wim *p;
+ int ret;
+
+ /* Check if already registered */
+ for (size_t i = 0; i < ctx->wimboot.num_wims; i++)
+ if (wim == ctx->wimboot.wims[i].wim)
+ return 0;
+
+ /* Not yet registered */
+
+ p = REALLOC(ctx->wimboot.wims,
+ (ctx->wimboot.num_wims + 1) * sizeof(ctx->wimboot.wims[0]));
+ if (!p)
+ return WIMLIB_ERR_NOMEM;
+ ctx->wimboot.wims = p;
+
+ ctx->wimboot.wims[ctx->wimboot.num_wims].wim = wim;
+
+ ret = hash_blob_table(wim, ctx->wimboot.wims[ctx->wimboot.num_wims].blob_table_hash);
+ if (ret)
+ return ret;
+
+ ret = wimboot_alloc_data_source_id(wim->filename,
+ wim->hdr.guid,
+ ctx->common.wim->current_image,
+ ctx->common.target,
+ &ctx->wimboot.wims[ctx->wimboot.num_wims].data_source_id,
+ &ctx->wimboot.wof_running);
+ if (ret)
+ return ret;
+
+ ctx->wimboot.num_wims++;
+ return 0;
}
/* Prepare for doing a "WIMBoot" extraction by loading patterns from
- * [PrepopulateList] of WimBootCompress.ini and allocating a WOF data source ID
- * on the target volume. */
+ * [PrepopulateList] of WimBootCompress.ini and registering each source WIM file
+ * with WOF on the target volume. */
static int
-start_wimboot_extraction(struct win32_apply_ctx *ctx)
+start_wimboot_extraction(struct list_head *dentry_list, struct win32_apply_ctx *ctx)
{
int ret;
- WIMStruct *wim = ctx->common.wim;
+ struct wim_dentry *dentry;
if (!ctx->wimboot.tried_to_load_prepopulate_list)
if (load_prepopulate_pats(ctx) == WIMLIB_ERR_NOMEM)
return WIMLIB_ERR_NOMEM;
- if (!wim_info_get_wimboot(wim->wim_info, wim->current_image))
+ if (!wim_info_get_wimboot(ctx->common.wim->wim_info,
+ ctx->common.wim->current_image))
WARNING("Image is not marked as WIMBoot compatible!");
- ret = hash_lookup_table(ctx->common.wim,
- ctx->wimboot.wim_lookup_table_hash);
- if (ret)
- return ret;
+ list_for_each_entry(dentry, dentry_list, d_extraction_list_node) {
+ struct blob_descriptor *blob;
- return wimboot_alloc_data_source_id(wim->filename,
- wim->hdr.guid,
- wim->current_image,
- ctx->common.target,
- &ctx->wimboot.data_source_id,
- &ctx->wimboot.wof_running);
+ ret = win32_will_externally_back(dentry, &ctx->common);
+ if (ret > 0) /* Error */
+ return ret;
+ if (ret < 0) /* Won't externally back */
+ continue;
+
+ blob = inode_get_blob_for_unnamed_data_stream_resolved(dentry->d_inode);
+ ret = register_wim_with_wof(blob->rdesc->wim, ctx);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
}
static void
inode_longest_named_data_stream_spec(const struct wim_inode *inode)
{
size_t max = 0;
- for (u16 i = 0; i < inode->i_num_ads; i++) {
- size_t len = inode->i_ads_entries[i].stream_name_nbytes;
+ for (unsigned i = 0; i < inode->i_num_streams; i++) {
+ const struct wim_inode_stream *strm = &inode->i_streams[i];
+ if (!stream_is_named_data_stream(strm))
+ continue;
+ size_t len = utf16le_len_chars(strm->stream_name);
if (len > max)
max = len;
}
if (max)
- max = 1 + (max / sizeof(wchar_t));
+ max += 1;
return max;
}
return WIMLIB_ERR_OPEN;
}
-/* Create empty named data streams.
+/*
+ * Create empty named data streams for the specified file, if there are any.
*
- * Since these won't have 'struct wim_lookup_table_entry's, they won't show up
- * in the call to extract_stream_list(). Hence the need for the special case.
+ * Since these won't have blob descriptors, they won't show up in the call to
+ * extract_blob_list(). Hence the need for the special case.
*/
static int
-create_any_empty_ads(const struct wim_dentry *dentry,
- struct win32_apply_ctx *ctx)
+create_empty_named_data_streams(const struct wim_dentry *dentry,
+ struct win32_apply_ctx *ctx)
{
const struct wim_inode *inode = dentry->d_inode;
bool path_modified = false;
if (!ctx->common.supported_features.named_data_streams)
return 0;
- for (u16 i = 0; i < inode->i_num_ads; i++) {
- const struct wim_ads_entry *entry;
+ for (unsigned i = 0; i < inode->i_num_streams; i++) {
+ const struct wim_inode_stream *strm = &inode->i_streams[i];
HANDLE h;
- entry = &inode->i_ads_entries[i];
-
- /* Not named? */
- if (!entry->stream_name_nbytes)
- continue;
-
- /* Not empty? */
- if (entry->lte)
+ if (!stream_is_named_data_stream(strm) ||
+ stream_blob_resolved(strm) != NULL)
continue;
build_extraction_path_with_ads(dentry, ctx,
- entry->stream_name,
- entry->stream_name_nbytes /
- sizeof(wchar_t));
+ strm->stream_name,
+ utf16le_len_chars(strm->stream_name));
path_modified = true;
ret = supersede_file_or_stream(ctx, &h);
if (ret)
ret = create_directory(dentry, ctx);
if (!ret)
- ret = create_any_empty_ads(dentry, ctx);
+ ret = create_empty_named_data_streams(dentry, ctx);
ret = check_apply_error(dentry, ctx, ret);
if (ret)
if (ret)
goto out_close;
- ret = create_any_empty_ads(dentry, ctx);
+ ret = create_empty_named_data_streams(dentry, ctx);
if (ret)
goto out_close;
(*func_NtClose)(ctx->open_handles[i]);
}
-/* Prepare to read the next stream, which has size @stream_size, into an
- * in-memory buffer. */
+/* Prepare to read the next blob, which has size @blob_size, into an in-memory
+ * buffer. */
static bool
-prepare_data_buffer(struct win32_apply_ctx *ctx, u64 stream_size)
+prepare_data_buffer(struct win32_apply_ctx *ctx, u64 blob_size)
{
- if (stream_size > ctx->data_buffer_size) {
+ if (blob_size > ctx->data_buffer_size) {
/* Larger buffer needed. */
void *new_buffer;
- if ((size_t)stream_size != stream_size)
+ if ((size_t)blob_size != blob_size)
return false;
- new_buffer = REALLOC(ctx->data_buffer, stream_size);
+ new_buffer = REALLOC(ctx->data_buffer, blob_size);
if (!new_buffer)
return false;
ctx->data_buffer = new_buffer;
- ctx->data_buffer_size = stream_size;
+ ctx->data_buffer_size = blob_size;
}
/* On the first call this changes data_buffer_ptr from NULL, which tells
* extract_chunk() that the data buffer needs to be filled while reading
}
static int
-begin_extract_stream_instance(const struct wim_lookup_table_entry *stream,
- struct wim_dentry *dentry,
- const wchar_t *stream_name,
- struct win32_apply_ctx *ctx)
+begin_extract_blob_instance(const struct blob_descriptor *blob,
+ struct wim_dentry *dentry,
+ const struct wim_inode_stream *strm,
+ struct win32_apply_ctx *ctx)
{
- const struct wim_inode *inode = dentry->d_inode;
- size_t stream_name_nchars = 0;
FILE_ALLOCATION_INFORMATION alloc_info;
HANDLE h;
NTSTATUS status;
- if (unlikely(stream_name))
- stream_name_nchars = wcslen(stream_name);
-
- if (unlikely(stream_name_nchars)) {
- build_extraction_path_with_ads(dentry, ctx,
- stream_name, stream_name_nchars);
- } else {
- build_extraction_path(dentry, ctx);
+ if (unlikely(strm->stream_type == STREAM_TYPE_REPARSE_POINT)) {
+ /* We can't write the reparse point stream directly; we must set
+ * it with FSCTL_SET_REPARSE_POINT, which requires that all the
+ * data be available. So, stage the data in a buffer. */
+ if (!prepare_data_buffer(ctx, blob->size))
+ return WIMLIB_ERR_NOMEM;
+ list_add_tail(&dentry->tmp_list, &ctx->reparse_dentries);
+ return 0;
}
-
- /* Encrypted file? */
- if (unlikely(inode->i_attributes & FILE_ATTRIBUTE_ENCRYPTED)
- && (stream_name_nchars == 0))
- {
- if (!ctx->common.supported_features.encrypted_files)
- return 0;
-
- /* We can't write encrypted file streams directly; we must use
+ if (unlikely(strm->stream_type == STREAM_TYPE_EFSRPC_RAW_DATA)) {
+ /* We can't write encrypted files directly; we must use
* WriteEncryptedFileRaw(), which requires providing the data
* through a callback function. This can't easily be combined
* with our own callback-based approach.
*
- * The current workaround is to simply read the stream into
- * memory and write the encrypted file from that.
+ * The current workaround is to simply read the blob into memory
+ * and write the encrypted file from that.
*
* TODO: This isn't sufficient for extremely large encrypted
* files. Perhaps we should create an extra thread to write
* such files... */
- if (!prepare_data_buffer(ctx, stream->size))
+ if (!prepare_data_buffer(ctx, blob->size))
return WIMLIB_ERR_NOMEM;
list_add_tail(&dentry->tmp_list, &ctx->encrypted_dentries);
return 0;
}
- /* Reparse point?
- *
- * Note: FILE_ATTRIBUTE_REPARSE_POINT is tested *after*
- * FILE_ATTRIBUTE_ENCRYPTED since the WIM format does not store both EFS
- * data and reparse data for the same file, and the EFS data takes
- * precedence. */
- if (unlikely(inode->i_attributes & FILE_ATTRIBUTE_REPARSE_POINT)
- && (stream_name_nchars == 0))
- {
- if (!ctx->common.supported_features.reparse_points)
- return 0;
-
- /* We can't write the reparse stream directly; we must set it
- * with FSCTL_SET_REPARSE_POINT, which requires that all the
- * data be available. So, stage the data in a buffer. */
+ /* It's a data stream (may be unnamed or named). */
+ wimlib_assert(strm->stream_type == STREAM_TYPE_DATA);
- if (!prepare_data_buffer(ctx, stream->size))
- return WIMLIB_ERR_NOMEM;
- list_add_tail(&dentry->tmp_list, &ctx->reparse_dentries);
- return 0;
- }
-
- if (ctx->num_open_handles == MAX_OPEN_STREAMS) {
+ if (ctx->num_open_handles == MAX_OPEN_FILES) {
/* XXX: Fix this. But because of the checks in
- * extract_stream_list(), this can now only happen on a
- * filesystem that does not support hard links. */
+ * extract_blob_list(), this can now only happen on a filesystem
+ * that does not support hard links. */
ERROR("Can't extract data: too many open files!");
return WIMLIB_ERR_UNSUPPORTED;
}
+
+ if (unlikely(stream_is_named(strm))) {
+ build_extraction_path_with_ads(dentry, ctx,
+ strm->stream_name,
+ utf16le_len_chars(strm->stream_name));
+ } else {
+ build_extraction_path(dentry, ctx);
+ }
+
+
/* Open a new handle */
status = do_create_file(&h,
FILE_WRITE_DATA | SYNCHRONIZE,
ctx->open_handles[ctx->num_open_handles++] = h;
/* Allocate space for the data. */
- alloc_info.AllocationSize.QuadPart = stream->size;
+ alloc_info.AllocationSize.QuadPart = blob->size;
(*func_NtSetInformationFile)(h, &ctx->iosb,
&alloc_info, sizeof(alloc_info),
FileAllocationInformation);
return 0;
}
-/* Called when starting to read a stream for extraction on Windows */
+/* Called when starting to read a blob for extraction on Windows */
static int
-begin_extract_stream(struct wim_lookup_table_entry *stream, void *_ctx)
+begin_extract_blob(struct blob_descriptor *blob, void *_ctx)
{
struct win32_apply_ctx *ctx = _ctx;
- const struct stream_owner *owners = stream_owners(stream);
+ const struct blob_extraction_target *targets = blob_extraction_targets(blob);
int ret;
ctx->num_open_handles = 0;
INIT_LIST_HEAD(&ctx->reparse_dentries);
INIT_LIST_HEAD(&ctx->encrypted_dentries);
- for (u32 i = 0; i < stream->out_refcnt; i++) {
- const struct wim_inode *inode = owners[i].inode;
- const wchar_t *stream_name = owners[i].stream_name;
+ for (u32 i = 0; i < blob->out_refcnt; i++) {
+ const struct wim_inode *inode = targets[i].inode;
+ const struct wim_inode_stream *strm = targets[i].stream;
struct wim_dentry *dentry;
- /* A copy of the stream needs to be extracted to @inode. */
+ /* A copy of the blob needs to be extracted to @inode. */
if (ctx->common.supported_features.hard_links) {
dentry = inode_first_extraction_dentry(inode);
- ret = begin_extract_stream_instance(stream, dentry,
- stream_name, ctx);
+ ret = begin_extract_blob_instance(blob, dentry, strm, ctx);
ret = check_apply_error(dentry, ctx, ret);
if (ret)
goto fail;
} else {
- /* Hard links not supported. Extract the stream
+ /* Hard links not supported. Extract the blob
* separately to each alias of the inode. */
struct list_head *next;
do {
dentry = list_entry(next, struct wim_dentry,
d_extraction_alias_node);
- ret = begin_extract_stream_instance(stream,
- dentry,
- stream_name,
- ctx);
+ ret = begin_extract_blob_instance(blob, dentry, strm, ctx);
ret = check_apply_error(dentry, ctx, ret);
if (ret)
goto fail;
return ret;
}
-/* Called when the next chunk of a stream has been read for extraction on
- * Windows */
+/* Called when the next chunk of a blob has been read for extraction on Windows
+ */
static int
extract_chunk(const void *chunk, size_t size, void *_ctx)
{
return 0;
}
-/* Called when a stream has been fully read for extraction on Windows */
+/* Called when a blob has been fully read for extraction on Windows */
static int
-end_extract_stream(struct wim_lookup_table_entry *stream, int status, void *_ctx)
+end_extract_blob(struct blob_descriptor *blob, int status, void *_ctx)
{
struct win32_apply_ctx *ctx = _ctx;
int ret;
return 0;
if (!list_empty(&ctx->reparse_dentries)) {
- if (stream->size > REPARSE_DATA_MAX_SIZE) {
+ if (blob->size > REPARSE_DATA_MAX_SIZE) {
dentry = list_first_entry(&ctx->reparse_dentries,
struct wim_dentry, tmp_list);
build_extraction_path(dentry, ctx);
ERROR("Reparse data of \"%ls\" has size "
"%"PRIu64" bytes (exceeds %u bytes)",
- current_path(ctx), stream->size,
+ current_path(ctx), blob->size,
REPARSE_DATA_MAX_SIZE);
ret = WIMLIB_ERR_INVALID_REPARSE_DATA;
return check_apply_error(dentry, ctx, ret);
}
- /* In the WIM format, reparse streams are just the reparse data
- * and omit the header. But we can reconstruct the header. */
- memcpy(ctx->rpbuf.rpdata, ctx->data_buffer, stream->size);
- ctx->rpbuf.rpdatalen = stream->size;
+ /* In the WIM format, reparse point streams are just the reparse
+ * data and omit the header. But we can reconstruct the header.
+ */
+ memcpy(ctx->rpbuf.rpdata, ctx->data_buffer, blob->size);
+ ctx->rpbuf.rpdatalen = blob->size;
ctx->rpbuf.rpreserved = 0;
list_for_each_entry(dentry, &ctx->reparse_dentries, tmp_list) {
ctx->rpbuf.rptag = dentry->d_inode->i_reparse_tag;
ret = set_reparse_data(dentry, &ctx->rpbuf,
- stream->size + REPARSE_DATA_OFFSET,
+ blob->size + REPARSE_DATA_OFFSET,
ctx);
ret = check_apply_error(dentry, ctx, ret);
if (ret)
}
if (!list_empty(&ctx->encrypted_dentries)) {
- ctx->encrypted_size = stream->size;
+ ctx->encrypted_size = blob->size;
list_for_each_entry(dentry, &ctx->encrypted_dentries, tmp_list) {
ret = extract_encrypted_file(dentry, ctx);
ret = check_apply_error(dentry, ctx, ret);
}
}
-static uint64_t
+static u64
count_dentries(const struct list_head *dentry_list)
{
const struct list_head *cur;
- uint64_t count = 0;
+ u64 count = 0;
list_for_each(cur, dentry_list)
count++;
{
int ret;
struct win32_apply_ctx *ctx = (struct win32_apply_ctx *)_ctx;
- uint64_t dentry_count;
+ u64 dentry_count;
ret = prepare_target(dentry_list, ctx);
if (ret)
goto out;
if (unlikely(ctx->common.extract_flags & WIMLIB_EXTRACT_FLAG_WIMBOOT)) {
- ret = start_wimboot_extraction(ctx);
+ ret = start_wimboot_extraction(dentry_list, ctx);
if (ret)
goto out;
}
if (ret)
goto out;
- struct read_stream_list_callbacks cbs = {
- .begin_stream = begin_extract_stream,
- .begin_stream_ctx = ctx,
+ struct read_blob_list_callbacks cbs = {
+ .begin_blob = begin_extract_blob,
+ .begin_blob_ctx = ctx,
.consume_chunk = extract_chunk,
.consume_chunk_ctx = ctx,
- .end_stream = end_extract_stream,
- .end_stream_ctx = ctx,
+ .end_blob = end_extract_blob,
+ .end_blob_ctx = ctx,
};
- ret = extract_stream_list(&ctx->common, &cbs);
+ ret = extract_blob_list(&ctx->common, &cbs);
if (ret)
goto out;
HeapFree(GetProcessHeap(), 0, ctx->target_ntpath.Buffer);
FREE(ctx->pathbuf.Buffer);
FREE(ctx->print_buffer);
+ FREE(ctx->wimboot.wims);
if (ctx->wimboot.prepopulate_pats) {
FREE(ctx->wimboot.prepopulate_pats->strings);
FREE(ctx->wimboot.prepopulate_pats);