On 11/5/10 8:17 AM, Charles Davis wrote:
Changes since try 5: o All case-sensitivity logic has been absorbed into find_file_in_dir(). o Eliminated one more stat(2) that I missed last time. o Eliminated a statfs(2) call on Linux.
This is a far as I think I can take it without gutting it completely. If any of you have better ideas, I'd like to hear them.
dlls/ntdll/directory.c | 233 +++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 229 insertions(+), 4 deletions(-)
diff --git a/dlls/ntdll/directory.c b/dlls/ntdll/directory.c index 865c2fa..2891792 100644 --- a/dlls/ntdll/directory.c +++ b/dlls/ntdll/directory.c @@ -41,6 +41,9 @@ #ifdef HAVE_SYS_STAT_H # include<sys/stat.h> #endif +#ifdef HAVE_SYS_ATTR_H +#include<sys/attr.h> +#endif #ifdef HAVE_SYS_IOCTL_H #include<sys/ioctl.h> #endif @@ -56,6 +59,9 @@ #ifdef HAVE_SYS_MOUNT_H #include<sys/mount.h> #endif +#ifdef HAVE_SYS_STATFS_H +#include<sys/statfs.h> +#endif #include<time.h> #ifdef HAVE_UNISTD_H # include<unistd.h> @@ -130,6 +136,35 @@ static inline int getdents64( int fd, char *de, unsigned int size )
#endif /* linux */
+#if defined(HAVE_GETATTRLIST)
+struct get_fsid +{
- ULONG size;
- dev_t dev;
- fsid_t fsid;
+};
+struct fs_cache +{
- dev_t dev;
- fsid_t fsid;
- BOOLEAN case_sensitive;
+} fs_cache[64];
+#if defined(ATTR_VOL_CAPABILITIES)&& defined(VOL_CAPABILITIES_FORMAT)&& \
- defined(VOL_CAP_FMT_CASE_SENSITIVE)
+struct vol_caps +{
- ULONG size;
- vol_capabilities_attr_t caps;
+};
+#endif /* ATTR_VOL_CAPABILITIES */
+#endif /* HAVE_GETATTRLIST */
- #define IS_OPTION_TRUE(ch) ((ch) == 'y' || (ch) == 'Y' || (ch) == 't' || (ch) == 'T' || (ch) == '1') #define IS_SEPARATOR(ch) ((ch) == '\' || (ch) == '/')
@@ -783,6 +818,192 @@ static char *get_device_mount_point( dev_t dev ) }
+#ifdef HAVE_GETATTRLIST +/***********************************************************************
look_up_fs_cache
- Checks if the specified file system is in the cache.
- */
+static struct fs_cache *look_up_fs_cache( dev_t dev ) +{
- int i;
- for (i = 0; i< sizeof(fs_cache)/sizeof(fs_cache[0]); i++)
if (fs_cache[i].dev == dev)
return fs_cache+i;
- return NULL;
+}
+/***********************************************************************
add_fs_cache
- Adds the specified file system to the cache.
- */
+static void add_fs_cache( dev_t dev, fsid_t fsid, BOOLEAN case_sensitive ) +{
- int i;
- struct fs_cache *entry = look_up_fs_cache( dev );
- static int once = 0;
- if (entry)
- {
/* Update the cache */
entry->fsid = fsid;
entry->case_sensitive = case_sensitive;
return;
- }
- /* Add a new entry */
- for (i = 0; i< sizeof(fs_cache)/sizeof(fs_cache[0]); i++)
if (fs_cache[i].dev == 0)
{
/* This entry is empty, use it */
fs_cache[i].dev = dev;
fs_cache[i].fsid = fsid;
fs_cache[i].case_sensitive = case_sensitive;
return;
}
- /* Cache is out of space, warn */
- if (once++)
WARN( "FS cache is out of space, expect performance problems\n" );
+} +#endif
+/***********************************************************************
get_dir_case_sensitivity
- Checks if the volume containing the specified directory is case
- sensitive or not.
- */
+static BOOLEAN get_dir_case_sensitivity( const char *dir ) +{ +#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
- struct statfs stfs;
+#elif defined(__NetBSD__)
- struct statvfs stfs;
+#elif defined(__linux__)
- struct stat st;
- char *cifile;
+#endif
+#if defined(HAVE_GETATTRLIST)&& defined(ATTR_VOL_CAPABILITIES)&& \
- defined(VOL_CAPABILITIES_FORMAT)&& defined(VOL_CAP_FMT_CASE_SENSITIVE)
- char *mntpoint = NULL;
- struct attrlist attr;
- struct vol_caps caps;
- struct get_fsid get_fsid;
- struct fs_cache *entry;
- /* First get the FS ID of the volume */
- attr.bitmapcount = ATTR_BIT_MAP_COUNT;
- attr.reserved = 0;
- attr.commonattr = ATTR_CMN_DEVID|ATTR_CMN_FSID;
- attr.volattr = attr.dirattr = attr.fileattr = attr.forkattr = 0;
- get_fsid.size = 0;
- if (getattrlist( dir,&attr,&get_fsid, sizeof(get_fsid), 0 ) != 0 ||
get_fsid.size != sizeof(get_fsid))
return TRUE;
- /* Try to look it up in the cache */
- entry = look_up_fs_cache( get_fsid.dev );
- if (entry&& !memcmp(&entry->fsid,&get_fsid.fsid, sizeof(fsid_t) ))
/* Cache lookup succeeded */
return entry->case_sensitive;
- /* Cache is stale at this point, we have to update it */
- mntpoint = get_device_mount_point( get_fsid.dev );
- /* Now look up the case-sensitivity */
- attr.commonattr = 0;
- attr.volattr = ATTR_VOL_INFO|ATTR_VOL_CAPABILITIES;
- if (getattrlist( mntpoint,&attr,&caps, sizeof(caps), 0 ) == 0)
- {
if (caps.size == sizeof(caps)&&
(caps.caps.valid[VOL_CAPABILITIES_FORMAT]&
(VOL_CAP_FMT_CASE_SENSITIVE | VOL_CAP_FMT_CASE_PRESERVING)) ==
(VOL_CAP_FMT_CASE_SENSITIVE | VOL_CAP_FMT_CASE_PRESERVING))
{
BOOLEAN ret;
RtlFreeHeap( GetProcessHeap(), 0, mntpoint );
if ((caps.caps.capabilities[VOL_CAPABILITIES_FORMAT]&
VOL_CAP_FMT_CASE_SENSITIVE) != VOL_CAP_FMT_CASE_SENSITIVE)
ret = FALSE;
ret = TRUE;
/* Update the cache */
add_fs_cache( get_fsid.dev, get_fsid.fsid, ret );
return ret;
}
- }
- RtlFreeHeap( GetProcessHeap(), 0, mntpoint );
- /* Fall through */
+#endif +#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
- statfs( dir,&stfs );
- /* Assume these file systems are always case insensitive on Mac OS.
Don't do this. Quake2 and quake2 turn out to be different (and I tried to move to a directory called Quake2 using cd $HOME/wine.../drive_c/quake2 and received an error this morning [Yes, I'm playing Quake2 on my Mac, I really, really need the stress relief, it is really hard to explain.})
* For FreeBSD, only assume CIOPFS is case insensitive (AFAIK, Mac OS
* is the only UNIX that supports case-insensitive lookup).
*/
On 11/14/10 3:01 PM, James McKenzie wrote:
On 11/5/10 8:17 AM, Charles Davis wrote:
Changes since try 5: o All case-sensitivity logic has been absorbed into find_file_in_dir(). o Eliminated one more stat(2) that I missed last time. o Eliminated a statfs(2) call on Linux.
This is a far as I think I can take it without gutting it completely. If any of you have better ideas, I'd like to hear them.
dlls/ntdll/directory.c | 233 +++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 229 insertions(+), 4 deletions(-)
diff --git a/dlls/ntdll/directory.c b/dlls/ntdll/directory.c index 865c2fa..2891792 100644 --- a/dlls/ntdll/directory.c +++ b/dlls/ntdll/directory.c @@ -41,6 +41,9 @@ #ifdef HAVE_SYS_STAT_H # include<sys/stat.h> #endif +#ifdef HAVE_SYS_ATTR_H +#include<sys/attr.h> +#endif #ifdef HAVE_SYS_IOCTL_H #include<sys/ioctl.h> #endif @@ -56,6 +59,9 @@ #ifdef HAVE_SYS_MOUNT_H #include<sys/mount.h> #endif +#ifdef HAVE_SYS_STATFS_H +#include<sys/statfs.h> +#endif #include<time.h> #ifdef HAVE_UNISTD_H # include<unistd.h> @@ -130,6 +136,35 @@ static inline int getdents64( int fd, char *de, unsigned int size )
#endif /* linux */
+#if defined(HAVE_GETATTRLIST)
+struct get_fsid +{
- ULONG size;
- dev_t dev;
- fsid_t fsid;
+};
+struct fs_cache +{
- dev_t dev;
- fsid_t fsid;
- BOOLEAN case_sensitive;
+} fs_cache[64];
+#if defined(ATTR_VOL_CAPABILITIES)&& defined(VOL_CAPABILITIES_FORMAT)&& \
- defined(VOL_CAP_FMT_CASE_SENSITIVE)
+struct vol_caps +{
- ULONG size;
- vol_capabilities_attr_t caps;
+};
+#endif /* ATTR_VOL_CAPABILITIES */
+#endif /* HAVE_GETATTRLIST */
- #define IS_OPTION_TRUE(ch) ((ch) == 'y' || (ch) == 'Y' || (ch) ==
't' || (ch) == 'T' || (ch) == '1') #define IS_SEPARATOR(ch) ((ch) == '\' || (ch) == '/')
@@ -783,6 +818,192 @@ static char *get_device_mount_point( dev_t dev ) }
+#ifdef HAVE_GETATTRLIST +/***********************************************************************
look_up_fs_cache
- Checks if the specified file system is in the cache.
- */
+static struct fs_cache *look_up_fs_cache( dev_t dev ) +{
- int i;
- for (i = 0; i< sizeof(fs_cache)/sizeof(fs_cache[0]); i++)
if (fs_cache[i].dev == dev)
return fs_cache+i;
- return NULL;
+}
+/***********************************************************************
add_fs_cache
- Adds the specified file system to the cache.
- */
+static void add_fs_cache( dev_t dev, fsid_t fsid, BOOLEAN case_sensitive ) +{
- int i;
- struct fs_cache *entry = look_up_fs_cache( dev );
- static int once = 0;
- if (entry)
- {
/* Update the cache */
entry->fsid = fsid;
entry->case_sensitive = case_sensitive;
return;
- }
- /* Add a new entry */
- for (i = 0; i< sizeof(fs_cache)/sizeof(fs_cache[0]); i++)
if (fs_cache[i].dev == 0)
{
/* This entry is empty, use it */
fs_cache[i].dev = dev;
fs_cache[i].fsid = fsid;
fs_cache[i].case_sensitive = case_sensitive;
return;
}
- /* Cache is out of space, warn */
- if (once++)
WARN( "FS cache is out of space, expect performance
problems\n" ); +} +#endif
+/***********************************************************************
get_dir_case_sensitivity
- Checks if the volume containing the specified directory is case
- sensitive or not.
- */
+static BOOLEAN get_dir_case_sensitivity( const char *dir ) +{ +#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
- struct statfs stfs;
+#elif defined(__NetBSD__)
- struct statvfs stfs;
+#elif defined(__linux__)
- struct stat st;
- char *cifile;
+#endif
+#if defined(HAVE_GETATTRLIST)&& defined(ATTR_VOL_CAPABILITIES)&& \
- defined(VOL_CAPABILITIES_FORMAT)&&
defined(VOL_CAP_FMT_CASE_SENSITIVE)
- char *mntpoint = NULL;
- struct attrlist attr;
- struct vol_caps caps;
- struct get_fsid get_fsid;
- struct fs_cache *entry;
- /* First get the FS ID of the volume */
- attr.bitmapcount = ATTR_BIT_MAP_COUNT;
- attr.reserved = 0;
- attr.commonattr = ATTR_CMN_DEVID|ATTR_CMN_FSID;
- attr.volattr = attr.dirattr = attr.fileattr = attr.forkattr = 0;
- get_fsid.size = 0;
- if (getattrlist( dir,&attr,&get_fsid, sizeof(get_fsid), 0 ) != 0 ||
get_fsid.size != sizeof(get_fsid))
return TRUE;
- /* Try to look it up in the cache */
- entry = look_up_fs_cache( get_fsid.dev );
- if (entry&& !memcmp(&entry->fsid,&get_fsid.fsid, sizeof(fsid_t) ))
/* Cache lookup succeeded */
return entry->case_sensitive;
- /* Cache is stale at this point, we have to update it */
- mntpoint = get_device_mount_point( get_fsid.dev );
- /* Now look up the case-sensitivity */
- attr.commonattr = 0;
- attr.volattr = ATTR_VOL_INFO|ATTR_VOL_CAPABILITIES;
- if (getattrlist( mntpoint,&attr,&caps, sizeof(caps), 0 ) == 0)
- {
if (caps.size == sizeof(caps)&&
(caps.caps.valid[VOL_CAPABILITIES_FORMAT]&
(VOL_CAP_FMT_CASE_SENSITIVE |
VOL_CAP_FMT_CASE_PRESERVING)) ==
(VOL_CAP_FMT_CASE_SENSITIVE | VOL_CAP_FMT_CASE_PRESERVING))
{
BOOLEAN ret;
RtlFreeHeap( GetProcessHeap(), 0, mntpoint );
if ((caps.caps.capabilities[VOL_CAPABILITIES_FORMAT]&
VOL_CAP_FMT_CASE_SENSITIVE) !=
VOL_CAP_FMT_CASE_SENSITIVE)
ret = FALSE;
ret = TRUE;
/* Update the cache */
add_fs_cache( get_fsid.dev, get_fsid.fsid, ret );
return ret;
}
- }
- RtlFreeHeap( GetProcessHeap(), 0, mntpoint );
- /* Fall through */
+#endif +#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
- statfs( dir,&stfs );
- /* Assume these file systems are always case insensitive on Mac OS.
Don't do this. Quake2 and quake2 turn out to be different (and I tried to move to a directory called Quake2 using cd $HOME/wine.../drive_c/quake2 and received an error this morning [Yes, I'm playing Quake2 on my Mac, I really, really need the stress relief, it is really hard to explain.})
Your FS must be a case-sensitive one. That's why I check for specific subtypes of HFS. The ones I check for are the ones that are case insensitive. Subtypes 0 (HFS+), 1 (HFS+ with journaling), and 128 (the original HFS) don't check case. Subtypes 2 (HFSX) and 3 (HFSX with journaling) do.
Last I checked, FAT, CDFS, UDF, and NTFS (but not the NTFS-3g FUSE driver) were all case-insensitive. SMB/CIFS are also case-insensitive, except for certain subtypes (which I don't know yet, and I need to read the source for the SMB driver to find out).
Chip