From: Eric Biggers Date: Thu, 25 Apr 2013 05:17:06 +0000 (-0500) Subject: win32: Do not hard link directories, even if file IDs say so X-Git-Tag: v1.3.3~33 X-Git-Url: https://wimlib.net/git/?p=wimlib;a=commitdiff_plain;h=c6aa9e6bfdeee0e08407d0efe02270f2ba4b62c6 win32: Do not hard link directories, even if file IDs say so --- diff --git a/src/hardlink.c b/src/hardlink.c index 3022cadf..e2f6ca0c 100644 --- a/src/hardlink.c +++ b/src/hardlink.c @@ -551,5 +551,6 @@ inode_table_prepare_inode_list(struct wim_inode_table *table, } INIT_HLIST_HEAD(&table->array[i]); } + list_splice_tail(&table->extra_inodes, head); table->num_entries = 0; } diff --git a/src/win32.c b/src/win32.c index c36b13ae..932d2933 100644 --- a/src/win32.c +++ b/src/win32.c @@ -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,28 @@ 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 refuse to + * hard link them. This is because Windows has a bug where it can + * return duplicate File IDs for directories on the FAT filesystem. */ + basename = path_basename_with_len(path, path_num_chars); + if (!(file_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { + 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, ¶ms->inode_table->extra_inodes); + } + ret = win32_get_short_name(root, path); if (ret)