static int
read_winnt_stream_prefix(const struct windows_file *file,
- u64 size, const struct read_blob_callbacks *cbs)
+ u64 size, const struct consume_chunk_callback *cb)
{
IO_STATUS_BLOCK iosb;
UNICODE_STRING name = {
bytes_read = iosb.Information;
bytes_remaining -= bytes_read;
- ret = call_consume_chunk(buf, bytes_read, cbs);
+ ret = consume_chunk(cb, buf, bytes_read);
if (ret)
break;
}
}
struct win32_encrypted_read_ctx {
- const struct read_blob_callbacks *cbs;
+ const struct consume_chunk_callback *cb;
int wimlib_err_code;
u64 bytes_remaining;
};
if (bytes_to_consume == 0)
return ERROR_SUCCESS;
- ret = call_consume_chunk(data, bytes_to_consume, ctx->cbs);
+ ret = consume_chunk(ctx->cb, data, bytes_to_consume);
if (ret) {
ctx->wimlib_err_code = ret;
/* It doesn't matter what error code is returned here, as long
static int
read_win32_encrypted_file_prefix(const wchar_t *path, bool is_dir, u64 size,
- const struct read_blob_callbacks *cbs)
+ const struct consume_chunk_callback *cb)
{
struct win32_encrypted_read_ctx export_ctx;
DWORD err;
if (is_dir)
flags |= CREATE_FOR_DIR;
- export_ctx.cbs = cbs;
+ export_ctx.cb = cb;
export_ctx.wimlib_err_code = 0;
export_ctx.bytes_remaining = size;
* described by @blob. */
int
read_windows_file_prefix(const struct blob_descriptor *blob, u64 size,
- const struct read_blob_callbacks *cbs)
+ const struct consume_chunk_callback *cb)
{
const struct windows_file *file = blob->windows_file;
if (unlikely(file->is_encrypted)) {
bool is_dir = (blob->file_inode->i_attributes & FILE_ATTRIBUTE_DIRECTORY);
- return read_win32_encrypted_file_prefix(file->path, is_dir, size, cbs);
+ return read_win32_encrypted_file_prefix(file->path, is_dir, size, cb);
}
- return read_winnt_stream_prefix(file, size, cbs);
+ return read_winnt_stream_prefix(file, size, cb);
}
/*
return WIMLIB_ERR_INVALID_REPARSE_DATA;
}
+ if (le32_to_cpu(rpbuf.rptag) == WIM_IO_REPARSE_TAG_DEDUP) {
+ /*
+ * Windows treats Data Deduplication reparse points specially.
+ * Reads from the unnamed data stream actually return the
+ * redirected file contents, even with FILE_OPEN_REPARSE_POINT.
+ * Deduplicated files also cannot be properly restored without
+ * also restoring the "System Volume Information" directory,
+ * which wimlib excludes by default. Therefore, the logical
+ * behavior for us seems to be to ignore the reparse point and
+ * treat the file as a normal file.
+ */
+ inode->i_attributes &= ~FILE_ATTRIBUTE_REPARSE_POINT;
+ return 0;
+ }
+
if (params->add_flags & WIMLIB_ADD_FLAG_RPFIX) {
ret = winnt_try_rpfix(&rpbuf, &rpbuflen, full_path, params);
if (ret == RP_FIXED)
QUERY_FILE_LAYOUT_INCLUDE_STREAMS_WITH_NO_CLUSTERS_ALLOCATED,
.FilterType = QUERY_FILE_LAYOUT_FILTER_TYPE_NONE,
};
- const size_t outsize = 32768;
+ size_t outsize = 32768;
QUERY_FILE_LAYOUT_OUTPUT *out = NULL;
int ret;
NTSTATUS status;
goto out;
}
- out = MALLOC(outsize);
- if (!out) {
- ret = WIMLIB_ERR_NOMEM;
- goto out;
- }
+ for (;;) {
+ /* Allocate a buffer for the output of the ioctl. */
+ out = MALLOC(outsize);
+ if (!out) {
+ ret = WIMLIB_ERR_NOMEM;
+ goto out;
+ }
- while (NT_SUCCESS(status = winnt_fsctl(h, FSCTL_QUERY_FILE_LAYOUT,
- &in, sizeof(in),
- out, outsize, NULL)))
- {
- const FILE_LAYOUT_ENTRY *file =
- (const void *)out + out->FirstFileOffset;
- for (;;) {
- ret = load_one_file(file, inode_map);
- if (ret)
- goto out;
- if (file->NextFileOffset == 0)
- break;
- file = (const void *)file + file->NextFileOffset;
+ /* Execute FSCTL_QUERY_FILE_LAYOUT until it fails. */
+ while (NT_SUCCESS(status = winnt_fsctl(h,
+ FSCTL_QUERY_FILE_LAYOUT,
+ &in, sizeof(in),
+ out, outsize, NULL)))
+ {
+ const FILE_LAYOUT_ENTRY *file =
+ (const void *)out + out->FirstFileOffset;
+ for (;;) {
+ ret = load_one_file(file, inode_map);
+ if (ret)
+ goto out;
+ if (file->NextFileOffset == 0)
+ break;
+ file = (const void *)file + file->NextFileOffset;
+ }
+ in.Flags &= ~QUERY_FILE_LAYOUT_RESTART;
}
- in.Flags &= ~QUERY_FILE_LAYOUT_RESTART;
+
+ /* Enlarge the buffer if needed. */
+ if (status != STATUS_BUFFER_TOO_SMALL)
+ break;
+ FREE(out);
+ outsize *= 2;
}
/* Normally, FSCTL_QUERY_FILE_LAYOUT fails with STATUS_END_OF_FILE after