]> wimlib.net Git - wimlib/blobdiff - src/win32.c
Win32: Do not hard link files with nNumberOfLinks = 1
[wimlib] / src / win32.c
index c36b13ae8593d106080d34915ed8b712c4b9764a..0db8c3bf72583dcbe6e9c4091996dd5eac7745ce 100644 (file)
@@ -1073,6 +1073,7 @@ win32_build_dentry_tree_recursive(struct wim_dentry **root_ret,
        DWORD err;
        u64 file_size;
        int ret = 0;
+       const wchar_t *basename;
 
        if (exclude_path(path, path_num_chars, params->config, true)) {
                if (params->add_image_flags & WIMLIB_ADD_IMAGE_FLAG_ROOT) {
@@ -1120,15 +1121,31 @@ win32_build_dentry_tree_recursive(struct wim_dentry **root_ret,
                goto out_close_handle;
        }
 
-       /* Create a WIM dentry with an associated inode, which may be shared */
-       ret = inode_table_new_dentry(params->inode_table,
-                                    path_basename_with_len(path, path_num_chars),
-                                    ((u64)file_info.nFileIndexHigh << 32) |
-                                        (u64)file_info.nFileIndexLow,
-                                    file_info.dwVolumeSerialNumber,
-                                    &root);
-       if (ret)
-               goto out_close_handle;
+       /* Create a WIM dentry with an associated inode, which may be shared.
+        *
+        * 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. */
+       basename = path_basename_with_len(path, path_num_chars);
+       if (!(file_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+           && file_info.nNumberOfLinks > 1)
+       {
+               ret = inode_table_new_dentry(params->inode_table,
+                                            basename,
+                                            ((u64)file_info.nFileIndexHigh << 32) |
+                                                (u64)file_info.nFileIndexLow,
+                                            file_info.dwVolumeSerialNumber,
+                                            &root);
+               if (ret)
+                       goto out_close_handle;
+       } else {
+               ret = new_dentry_with_inode(basename, &root);
+               if (ret)
+                       goto out_close_handle;
+               list_add_tail(&root->d_inode->i_list, &params->inode_table->extra_inodes);
+       }
+
 
        ret = win32_get_short_name(root, path);
        if (ret)