]> wimlib.net Git - wimlib/blobdiff - src/win32_capture.c
win32_capture.c: Use volume ID as device number
[wimlib] / src / win32_capture.c
index 08a0654f812ac18573a3b22b049962998bd3c41a..2df80f34a0d9059e9b988544fce5df2fbd7b0aa6 100644 (file)
@@ -888,6 +888,9 @@ winnt_scan_stream(const wchar_t *path, size_t path_nchars,
                                                        sizeof(wchar_t));
                if (!ads_entry)
                        return WIMLIB_ERR_NOMEM;
+       } else if (inode->i_attributes & FILE_ATTRIBUTE_REPARSE_POINT) {
+               /* Ignore unnamed data stream of reparse point  */
+               return 0;
        } else {
                ads_entry = NULL;
        }
@@ -1094,10 +1097,11 @@ winnt_build_dentry_tree_recursive(struct wim_dentry **root_ret,
        u16 rpbuflen;
        u16 not_rpfixed;
 
-       if (should_exclude_path(full_path + params->capture_root_nchars,
-                               full_path_nchars - params->capture_root_nchars,
-                               params->config))
+       ret = try_exclude(full_path, full_path_nchars, params);
+       if (ret < 0) /* Excluded? */
                goto out_progress;
+       if (ret > 0) /* Error? */
+               goto out;
 
        /* Open the file.  */
        status = winnt_openat(cur_dir,
@@ -1119,7 +1123,10 @@ winnt_build_dentry_tree_recursive(struct wim_dentry **root_ret,
                        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_FVE_LOCKED_VOLUME)
+                               ret = WIMLIB_ERR_FVE_LOCKED_VOLUME;
+                       else
+                               ret = WIMLIB_ERR_OPEN;
                }
                /* XXX: Provide option to exclude files that fail with
                 * STATUS_SHARING_VIOLATION?  */
@@ -1230,13 +1237,17 @@ winnt_build_dentry_tree_recursive(struct wim_dentry **root_ret,
         * However, we need to explicitly check for directories and files with
         * only 1 link and refuse to hard link them.  This is because Windows
         * has a bug where it can return duplicate File IDs for files and
-        * directories on the FAT filesystem. */
+        * directories on the FAT filesystem.
+        *
+        * Since we don't follow mount points on Windows, we don't need to query
+        * the volume ID per-file.  Just once, for the root, is enough.  But we
+        * can't simply pass 0, because then there could be inode collisions
+        * among multiple calls to win32_build_dentry_tree() that are scanning
+        * files on different volumes.  */
        ret = inode_table_new_dentry(params->inode_table,
                                     filename,
                                     file_info.InternalInformation.IndexNumber.QuadPart,
-                                    0, /* We don't follow mount points, so we
-                                          currently don't need to get the
-                                          volume ID / device number.  */
+                                    params->capture_root_dev,
                                     (file_info.StandardInformation.NumberOfLinks <= 1 ||
                                        (file_info.BasicInformation.FileAttributes &
                                         FILE_ATTRIBUTE_DIRECTORY)),
@@ -1415,18 +1426,19 @@ win32_build_dentry_tree(struct wim_dentry **root_ret,
        {
                ERROR("\"%ls\": unrecognized path format", root_disk_path);
                ret = WIMLIB_ERR_INVALID_PARAM;
-               goto out_free_path;
-       }
-
-       ntpath_nchars = ntpath.Length / sizeof(wchar_t);
-       wmemcpy(path, ntpath.Buffer, ntpath_nchars);
-       path[ntpath_nchars] = L'\0';
-
-       params->capture_root_nchars = ntpath_nchars;
-       if (path[ntpath_nchars - 1] == L'\\')
-               params->capture_root_nchars--;
+       } else {
+               ntpath_nchars = ntpath.Length / sizeof(wchar_t);
+               wmemcpy(path, ntpath.Buffer, ntpath_nchars);
+               path[ntpath_nchars] = L'\0';
 
+               params->capture_root_nchars = ntpath_nchars;
+               if (path[ntpath_nchars - 1] == L'\\')
+                       params->capture_root_nchars--;
+               ret = 0;
+       }
        HeapFree(GetProcessHeap(), 0, ntpath.Buffer);
+       if (ret)
+               goto out_free_path;
 
        memset(&stats, 0, sizeof(stats));