]> wimlib.net Git - wimlib/blobdiff - src/win32_capture.c
Warn rather than abort if SHA-1 is same but size is different
[wimlib] / src / win32_capture.c
index d62f7d07ef20c08c9bec93f261131033e39b159b..8c9d726d3417a4fb02cdaa79dd405ec5b7301931 100644 (file)
@@ -5,7 +5,7 @@
  */
 
 /*
- * 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
@@ -488,7 +488,8 @@ read_win32_encrypted_file_prefix(const wchar_t *path, bool is_dir, u64 size,
  * 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;
 
@@ -803,12 +804,13 @@ out:
 }
 
 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,
@@ -850,13 +852,14 @@ 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);
 
@@ -1515,7 +1518,7 @@ try_to_use_wimboot_hash(HANDLE h, struct wim_inode *inode,
        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;
@@ -1533,8 +1536,8 @@ try_to_use_wimboot_hash(HANDLE h, struct wim_inode *inode,
                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  */
 
@@ -1542,8 +1545,8 @@ try_to_use_wimboot_hash(HANDLE h, struct wim_inode *inode,
                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;
 
@@ -1577,13 +1580,13 @@ try_to_use_wimboot_hash(HANDLE h, struct wim_inode *inode,
                }
 
                /* 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
@@ -1601,7 +1604,8 @@ try_to_use_wimboot_hash(HANDLE h, struct wim_inode *inode,
                        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);
        }
 
@@ -1701,12 +1705,13 @@ get_volume_information(HANDLE h, struct winnt_scan_ctx *ctx)
 }
 
 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;
@@ -1883,7 +1888,7 @@ winnt_build_dentry_tree_recursive(struct wim_dentry **root_ret,
 
        set_sort_key(inode, sort_key);
 
-       if (inode_is_directory(inode)) {
+       if (inode_is_directory(inode) && recursive) {
 
                /* Directory: recurse to children.  */
 
@@ -1907,10 +1912,16 @@ winnt_build_dentry_tree_recursive(struct wim_dentry **root_ret,
        }
 
 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);
@@ -2710,10 +2721,10 @@ security_map_destroy(struct security_map *map)
  *     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,
@@ -2732,7 +2743,7 @@ 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.  */
@@ -2740,13 +2751,16 @@ generate_wim_structures_recursive(struct wim_dentry **root_ret,
                              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.  */
@@ -2866,6 +2880,7 @@ generate_wim_structures_recursive(struct wim_dentry **root_ret,
        /* 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;
 
@@ -3027,10 +3042,8 @@ win32_build_dentry_tree(struct wim_dentry **root_ret,
                }
        }
 #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)