]> wimlib.net Git - wimlib/blobdiff - src/win32_capture.c
win32_capture.c: Exclude files pending deletion
[wimlib] / src / win32_capture.c
index 7a836a5bc663be85b886dbc66b6709257299fe09..4bccfa1412f6c4902f8551f4cc0e5f806db754fa 100644 (file)
@@ -1110,11 +1110,19 @@ winnt_build_dentry_tree_recursive(struct wim_dentry **root_ret,
                                        SYNCHRONIZE,
                              &h);
        if (unlikely(!NT_SUCCESS(status))) {
-               set_errno_from_nt_status(status);
-               ERROR_WITH_ERRNO("\"%ls\": Can't open file "
-                                "(status=0x%08"PRIx32")",
-                                printable_path(full_path), (u32)status);
-               ret = WIMLIB_ERR_OPEN;
+               if (status == STATUS_DELETE_PENDING) {
+                       WARNING("\"%ls\": Deletion pending; skipping file",
+                               printable_path(full_path));
+                       ret = 0;
+               } else {
+                       set_errno_from_nt_status(status);
+                       ERROR_WITH_ERRNO("\"%ls\": Can't open file "
+                                        "(status=0x%08"PRIx32")",
+                                        printable_path(full_path), (u32)status);
+                       ret = WIMLIB_ERR_OPEN;
+               }
+               /* XXX: Provide option to exclude files that fail with
+                * STATUS_SHARING_VIOLATION?  */
                goto out;
        }
 
@@ -1385,9 +1393,8 @@ win32_build_dentry_tree(struct wim_dentry **root_ret,
                        struct add_image_params *params)
 {
        wchar_t *path;
-       DWORD dret;
-       size_t path_nchars;
        int ret;
+       UNICODE_STRING ntpath;
        struct winnt_scan_stats stats;
 
        /* WARNING: There is no check for overflow later when this buffer is
@@ -1397,33 +1404,31 @@ win32_build_dentry_tree(struct wim_dentry **root_ret,
        if (!path)
                return WIMLIB_ERR_NOMEM;
 
-       /* Translate into full path.  */
-       dret = GetFullPathName(root_disk_path, WINDOWS_NT_MAX_PATH - 3,
-                              &path[4], NULL);
+       ret = win32_path_to_nt_path(root_disk_path, &ntpath);
+       if (ret)
+               goto out_free_path;
 
-       if (unlikely(dret == 0 || dret >= WINDOWS_NT_MAX_PATH - 3)) {
-               ERROR("Can't get full path name for \"%ls\"", root_disk_path);
-               return WIMLIB_ERR_UNSUPPORTED;
+       if (ntpath.Length < 4 * sizeof(wchar_t) ||
+           ntpath.Length > WINDOWS_NT_MAX_PATH * sizeof(wchar_t) ||
+           wmemcmp(ntpath.Buffer, L"\\??\\", 4))
+       {
+               ERROR("\"%ls\": unrecognized path format", root_disk_path);
+               ret = WIMLIB_ERR_INVALID_PARAM;
+               goto out_free_path;
        }
 
-       /* Add \??\ prefix to form the NT namespace path.  */
-       wmemcpy(path, L"\\??\\", 4);
-       path_nchars = dret + 4;
-
-       /* Strip trailing slashes.  If we don't do this, we may create a path
-       * with multiple consecutive backslashes, which for some reason causes
-       * Windows to report that the file cannot be found.  */
-       while (unlikely(path[path_nchars - 1] == L'\\' &&
-                       path[path_nchars - 2] != L':'))
-               path[--path_nchars] = L'\0';
+       params->capture_root_nchars = ntpath.Length / sizeof(wchar_t);
+       wmemcpy(path, ntpath.Buffer, params->capture_root_nchars);
+       path[params->capture_root_nchars] = L'\0';
 
-       params->capture_root_nchars = path_nchars;
+       HeapFree(GetProcessHeap(), 0, ntpath.Buffer);
 
        memset(&stats, 0, sizeof(stats));
 
        ret = winnt_build_dentry_tree_recursive(root_ret, NULL,
-                                               path, path_nchars, L"", 0,
-                                               params, &stats, 0);
+                                               path, params->capture_root_nchars,
+                                               L"", 0, params, &stats, 0);
+out_free_path:
        FREE(path);
        if (ret == 0)
                winnt_do_scan_warnings(root_disk_path, &stats);