[PATCH v6] ntdll: Add support for EXT4 case folding per directory
Gabriel Ivăncescu
gabrielopcode at gmail.com
Thu Jun 13 10:53:59 CDT 2019
This adds support for checking the case-insensitive attribute on ext4 with
newer kernels so that Wine can rely on it for performance.
Signed-off-by: Gabriel Ivăncescu <gabrielopcode at gmail.com>
---
dlls/ntdll/directory.c | 53 ++++++++++++++++++++++++------------------
1 file changed, 31 insertions(+), 22 deletions(-)
diff --git a/dlls/ntdll/directory.c b/dlls/ntdll/directory.c
index bbdbbe9..b18f56b 100644
--- a/dlls/ntdll/directory.c
+++ b/dlls/ntdll/directory.c
@@ -115,6 +115,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(file);
/* just in case... */
#undef VFAT_IOCTL_READDIR_BOTH
+#undef EXT2_IOC_GETFLAGS
+#undef EXT4_CASEFOLD_FL
#ifdef linux
@@ -130,6 +132,12 @@ typedef struct
/* Define the VFAT ioctl to get both short and long file names */
#define VFAT_IOCTL_READDIR_BOTH _IOR('r', 1, KERNEL_DIRENT [2] )
+/* Define the ext2 ioctl for handling extra attributes */
+#define EXT2_IOC_GETFLAGS _IOR('f', 1, long)
+
+/* Case-insensitivity attribute */
+#define EXT4_CASEFOLD_FL 0x40000000
+
#ifndef O_DIRECTORY
# define O_DIRECTORY 0200000 /* must be directory */
#endif
@@ -1113,7 +1121,7 @@ static int get_dir_case_sensitivity_attr( const char *dir )
* get_dir_case_sensitivity_stat
*
* Checks if the volume containing the specified directory is case
- * sensitive or not. Uses statfs(2) or statvfs(2).
+ * sensitive or not. Uses (f)statfs(2), statvfs(2), fstatat(2), or ioctl(2).
*/
static BOOLEAN get_dir_case_sensitivity_stat( const char *dir )
{
@@ -1165,32 +1173,33 @@ static BOOLEAN get_dir_case_sensitivity_stat( const char *dir )
return FALSE;
#elif defined(__linux__)
+ BOOLEAN sens = TRUE;
struct statfs stfs;
struct stat st;
- char *cifile;
+ int fd, flags;
- /* Only assume CIOPFS is case insensitive. */
- if (statfs( dir, &stfs ) == -1) return FALSE;
- if (stfs.f_type != 0x65735546 /* FUSE_SUPER_MAGIC */)
+ if ((fd = open( dir, O_RDONLY | O_NONBLOCK | O_LARGEFILE )) == -1)
return TRUE;
- /* Normally, we'd have to parse the mtab to find out exactly what
- * kind of FUSE FS this is. But, someone on wine-devel suggested
- * a shortcut. We'll stat a special file in the directory. If it's
- * there, we'll assume it's a CIOPFS, else not.
- * This will break if somebody puts a file named ".ciopfs" in a non-
- * CIOPFS directory.
- */
- cifile = RtlAllocateHeap( GetProcessHeap(), 0, strlen( dir )+sizeof("/.ciopfs") );
- if (!cifile) return TRUE;
- strcpy( cifile, dir );
- strcat( cifile, "/.ciopfs" );
- if (stat( cifile, &st ) == 0)
+
+ if (ioctl( fd, EXT2_IOC_GETFLAGS, &flags ) != -1 && (flags & EXT4_CASEFOLD_FL))
{
- RtlFreeHeap( GetProcessHeap(), 0, cifile );
- return FALSE;
+ sens = FALSE;
}
- RtlFreeHeap( GetProcessHeap(), 0, cifile );
- return TRUE;
+ else
+ {
+ /* Assume CIOPFS is case insensitive. Normally, we'd have to parse
+ * the mtab to find out exactly what kind of FUSE FS this is. But,
+ * someone on wine-devel suggested a shortcut. We'll stat a special
+ * file in the directory. If it's there, we'll assume it's a CIOPFS,
+ * else not. This will break if somebody puts a file named ".ciopfs"
+ * in a non-CIOPFS directory.
+ */
+ if (fstatfs( fd, &stfs ) != -1 && stfs.f_type == 0x65735546 /* FUSE_SUPER_MAGIC */ &&
+ fstatat( fd, ".ciopfs", &st, AT_NO_AUTOMOUNT ) == 0)
+ sens = FALSE;
+ }
+ close( fd );
+ return sens;
#else
return TRUE;
#endif
@@ -1201,7 +1210,7 @@ static BOOLEAN get_dir_case_sensitivity_stat( const char *dir )
* get_dir_case_sensitivity
*
* Checks if the volume containing the specified directory is case
- * sensitive or not. Uses statfs(2) or statvfs(2).
+ * sensitive or not. Uses multiple methods, depending on platform.
*/
static BOOLEAN get_dir_case_sensitivity( const char *dir )
{
--
2.21.0
More information about the wine-devel
mailing list