*/
/*
- * Copyright (C) 2013-2018 Eric Biggers
+ * Copyright (C) 2013-2021 Eric Biggers
*
* This file is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* described by @blob. */
int
read_windows_file_prefix(const struct blob_descriptor *blob, u64 size,
- const struct consume_chunk_callback *cb)
+ const struct consume_chunk_callback *cb,
+ bool recover_data)
{
const struct windows_file *file = blob->windows_file;
if (status == STATUS_OBJECTID_NOT_FOUND) /* No object ID */
return 0;
- if (status == STATUS_INVALID_DEVICE_REQUEST) {
+ if (status == STATUS_INVALID_DEVICE_REQUEST ||
+ status == STATUS_NOT_SUPPORTED /* Samba volume, WinXP */) {
/* The filesystem claimed to support object IDs, but we can't
* actually read them. This happens with Samba. */
ctx->vol_flags &= ~FILE_SUPPORTS_OBJECT_IDS;
}
static int
-winnt_build_dentry_tree_recursive(struct wim_dentry **root_ret,
- HANDLE cur_dir,
- const wchar_t *relative_path,
- size_t relative_path_nchars,
- const wchar_t *filename,
- struct winnt_scan_ctx *ctx);
+winnt_build_dentry_tree(struct wim_dentry **root_ret,
+ HANDLE cur_dir,
+ const wchar_t *relative_path,
+ size_t relative_path_nchars,
+ const wchar_t *filename,
+ struct winnt_scan_ctx *ctx,
+ bool recursive);
static int
winnt_recurse_directory(HANDLE h,
if (!filename)
goto out_free_buf;
- ret = winnt_build_dentry_tree_recursive(
+ ret = winnt_build_dentry_tree(
&child,
h,
filename,
info->FileNameLength / 2,
filename,
- ctx);
+ ctx,
+ true);
pathbuf_truncate(ctx->params, orig_path_nchars);
if (inode->i_attributes & FILE_ATTRIBUTE_REPARSE_POINT) {
struct reparse_buffer_disk rpbuf;
struct {
- struct wof_external_info wof_info;
+ WOF_EXTERNAL_INFO wof_info;
struct wim_provider_rpdata wim_info;
} *rpdata = (void *)rpbuf.rpdata;
struct blob_descriptor *reparse_blob;
if (ret)
return ret;
- if (rpdata->wof_info.version != WOF_CURRENT_VERSION ||
- rpdata->wof_info.provider != WOF_PROVIDER_WIM ||
+ if (rpdata->wof_info.Version != WOF_CURRENT_VERSION ||
+ rpdata->wof_info.Provider != WOF_PROVIDER_WIM ||
rpdata->wim_info.version != 2)
return 0; /* Not a WIM-backed file */
copy_hash(hash, rpdata->wim_info.unnamed_data_stream_hash);
} else {
struct {
- struct wof_external_info wof_info;
- struct wim_provider_external_info wim_info;
+ WOF_EXTERNAL_INFO wof_info;
+ WIM_PROVIDER_EXTERNAL_INFO wim_info;
} out;
NTSTATUS status;
}
/* Is this file backed by a WIM? */
- if (out.wof_info.version != WOF_CURRENT_VERSION ||
- out.wof_info.provider != WOF_PROVIDER_WIM ||
- out.wim_info.version != WIM_PROVIDER_CURRENT_VERSION)
+ if (out.wof_info.Version != WOF_CURRENT_VERSION ||
+ out.wof_info.Provider != WOF_PROVIDER_WIM ||
+ out.wim_info.Version != WIM_PROVIDER_CURRENT_VERSION)
return 0;
/* Okay, this is a WIM backed file. Get its SHA-1 hash. */
- copy_hash(hash, out.wim_info.unnamed_data_stream_hash);
+ copy_hash(hash, out.wim_info.ResourceHash);
}
/* If the file's unnamed data stream is nonempty, then fill in its hash
return 0;
back_ptr = retrieve_pointer_to_unhashed_blob(blob);
copy_hash(blob->hash, hash);
- if (after_blob_hashed(blob, back_ptr, blob_table) != blob)
+ if (after_blob_hashed(blob, back_ptr, blob_table,
+ inode) != blob)
free_blob_descriptor(blob);
}
}
static int
-winnt_build_dentry_tree_recursive(struct wim_dentry **root_ret,
- HANDLE cur_dir,
- const wchar_t *relative_path,
- size_t relative_path_nchars,
- const wchar_t *filename,
- struct winnt_scan_ctx *ctx)
+winnt_build_dentry_tree(struct wim_dentry **root_ret,
+ HANDLE cur_dir,
+ const wchar_t *relative_path,
+ size_t relative_path_nchars,
+ const wchar_t *filename,
+ struct winnt_scan_ctx *ctx,
+ bool recursive)
{
struct wim_dentry *root = NULL;
struct wim_inode *inode = NULL;
set_sort_key(inode, sort_key);
- if (inode_is_directory(inode)) {
+ if (inode_is_directory(inode) && recursive) {
/* Directory: recurse to children. */
}
out_progress:
- if (likely(root))
- ret = do_scan_progress(ctx->params, WIMLIB_SCAN_DENTRY_OK, inode);
- else
- ret = do_scan_progress(ctx->params, WIMLIB_SCAN_DENTRY_EXCLUDED, NULL);
+ ret = 0;
+ if (recursive) { /* if !recursive, caller handles progress */
+ if (likely(root))
+ ret = do_scan_progress(ctx->params,
+ WIMLIB_SCAN_DENTRY_OK, inode);
+ else
+ ret = do_scan_progress(ctx->params,
+ WIMLIB_SCAN_DENTRY_EXCLUDED,
+ NULL);
+ }
out:
if (likely(h))
NtClose(h);
* all files have been enumerated. */
if (status != STATUS_END_OF_FILE) {
if (status == STATUS_INVALID_DEVICE_REQUEST /* old OS */ ||
- status == STATUS_INVALID_PARAMETER /* not root directory */ ) {
+ status == STATUS_NOT_SUPPORTED /* Samba volume, WinXP */ ||
+ status == STATUS_INVALID_PARAMETER /* not root directory */ )
+ {
/* Silently try standard recursive scan instead */
ret = -1;
} else {
* ntfs_stream => wim_inode_stream
*
* This also handles things such as exclusions and issuing progress messages.
- * It's similar to winnt_build_dentry_tree_recursive(), but this is much faster
- * because almost all information we need is already loaded in memory in the
- * ntfs_* structures. However, in some cases we still fall back to
- * winnt_build_dentry_tree_recursive() and/or opening the file.
+ * It's similar to winnt_build_dentry_tree(), but this is much faster because
+ * almost all information we need is already loaded in memory in the ntfs_*
+ * structures. However, in some cases we still fall back to
+ * winnt_build_dentry_tree() and/or opening the file.
*/
static int
generate_wim_structures_recursive(struct wim_dentry **root_ret,
if (NTFS_IS_SPECIAL_FILE(ni->ino))
goto out;
- /* Fall back to a recursive scan for unhandled cases. Reparse points,
+ /* Fall back to the standard scan for unhandled cases. Reparse points,
* in particular, can't be properly handled here because a commonly used
* filter driver (WOF) hides reparse points from regular filesystem APIs
* but not from FSCTL_QUERY_FILE_LAYOUT. */
FILE_ATTRIBUTE_ENCRYPTED) ||
ni->special_streams != 0)
{
- ret = winnt_build_dentry_tree_recursive(&root,
- NULL,
- ctx->params->cur_path,
- ctx->params->cur_path_nchars,
- filename,
- ctx);
- goto out;
+ ret = winnt_build_dentry_tree(&root, NULL,
+ ctx->params->cur_path,
+ ctx->params->cur_path_nchars,
+ filename, ctx, false);
+ if (ret) /* Error? */
+ goto out;
+ if (!root) /* Excluded? */
+ goto out_progress;
+ inode = root->d_inode;
+ goto process_children;
}
/* Test for exclusion based on path. */
/* If processing a directory, then recurse to its children. In this
* version there is no need to go to disk, as we already have the list
* of children cached from the MFT. */
+process_children:
if (inode_is_directory(inode)) {
const struct ntfs_dentry *nd = ni->first_child;
}
}
#endif
- ret = winnt_build_dentry_tree_recursive(root_ret, NULL,
- params->cur_path,
- params->cur_path_nchars,
- L"", &ctx);
+ ret = winnt_build_dentry_tree(root_ret, NULL, params->cur_path,
+ params->cur_path_nchars, L"", &ctx, true);
out:
vss_put_snapshot(ctx.snapshot);
if (ret == 0)