Alexandre Julliard : ntdll: Remove VFAT_IOCTL_READDIR_BOTH kernel bugs workarounds.

Alexandre Julliard julliard at winehq.org
Tue Apr 28 16:32:21 CDT 2020


Module: wine
Branch: master
Commit: 69f068bfb1046391fd8cd323543dd7bc63e0ec6b
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=69f068bfb1046391fd8cd323543dd7bc63e0ec6b

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Tue Apr 28 12:20:26 2020 +0200

ntdll: Remove VFAT_IOCTL_READDIR_BOTH kernel bugs workarounds.

Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/ntdll/directory.c | 103 +++++++++++++------------------------------------
 1 file changed, 27 insertions(+), 76 deletions(-)

diff --git a/dlls/ntdll/directory.c b/dlls/ntdll/directory.c
index 1adc0c9b0d..d18df38f62 100644
--- a/dlls/ntdll/directory.c
+++ b/dlls/ntdll/directory.c
@@ -1592,46 +1592,6 @@ static NTSTATUS get_dir_data_entry( struct dir_data *dir_data, void *info_ptr, I
 
 #ifdef VFAT_IOCTL_READDIR_BOTH
 
-/***********************************************************************
- *           start_vfat_ioctl
- *
- * Wrapper for the VFAT ioctl to work around various kernel bugs.
- * dir_section must be held by caller.
- */
-static KERNEL_DIRENT *start_vfat_ioctl( int fd )
-{
-    static KERNEL_DIRENT *de;
-    int res;
-
-    if (!de)
-    {
-        SIZE_T size = 2 * sizeof(*de) + page_size;
-        void *addr = NULL;
-
-        if (virtual_alloc_aligned( &addr, 0, &size, MEM_RESERVE, PAGE_READWRITE, 1 ))
-            return NULL;
-        /* commit only the size needed for the dir entries */
-        /* this leaves an extra unaccessible page, which should make the kernel */
-        /* fail with -EFAULT before it stomps all over our memory */
-        de = addr;
-        size = 2 * sizeof(*de);
-        virtual_alloc_aligned( &addr, 0, &size, MEM_COMMIT, PAGE_READWRITE, 1 );
-    }
-
-    /* set d_reclen to 65535 to work around an AFS kernel bug */
-    de[0].d_reclen = 65535;
-    res = ioctl( fd, VFAT_IOCTL_READDIR_BOTH, (long)de );
-    if (res == -1)
-    {
-        if (errno != ENOENT) return NULL;  /* VFAT ioctl probably not supported */
-        de[0].d_reclen = 0;  /* eof */
-    }
-    else if (!res && de[0].d_reclen == 65535) return NULL;  /* AFS bug */
-
-    return de;
-}
-
-
 /***********************************************************************
  *           read_directory_vfat
  *
@@ -1640,40 +1600,42 @@ static KERNEL_DIRENT *start_vfat_ioctl( int fd )
 static NTSTATUS read_directory_data_vfat( struct dir_data *data, int fd, const UNICODE_STRING *mask )
 {
     char *short_name, *long_name;
-    size_t len;
-    KERNEL_DIRENT *de;
+    KERNEL_DIRENT de[2];
     NTSTATUS status = STATUS_NO_MEMORY;
     off_t old_pos = lseek( fd, 0, SEEK_CUR );
 
-    if (!(de = start_vfat_ioctl( fd ))) return STATUS_NOT_SUPPORTED;
-
     lseek( fd, 0, SEEK_SET );
 
+    if (ioctl( fd, VFAT_IOCTL_READDIR_BOTH, (long)de ) == -1)
+    {
+        if (errno != ENOENT)
+        {
+            status = STATUS_NOT_SUPPORTED;
+            goto done;
+        }
+        de[0].d_reclen = 0;
+    }
+
     if (!append_entry( data, ".", NULL, mask )) goto done;
     if (!append_entry( data, "..", NULL, mask )) goto done;
 
-    while (ioctl( fd, VFAT_IOCTL_READDIR_BOTH, (long)de ) != -1)
+    while (de[0].d_reclen)
     {
-        if (!de[0].d_reclen) break;  /* eof */
-
-        /* make sure names are null-terminated to work around an x86-64 kernel bug */
-        len = min( de[0].d_reclen, sizeof(de[0].d_name) - 1 );
-        de[0].d_name[len] = 0;
-        len = min( de[1].d_reclen, sizeof(de[1].d_name) - 1 );
-        de[1].d_name[len] = 0;
-
-        if (!strcmp( de[0].d_name, "." ) || !strcmp( de[0].d_name, ".." )) continue;
-        if (de[1].d_name[0])
-        {
-            short_name = de[0].d_name;
-            long_name = de[1].d_name;
-        }
-        else
+        if (strcmp( de[0].d_name, "." ) && strcmp( de[0].d_name, ".." ))
         {
-            long_name = de[0].d_name;
-            short_name = NULL;
+            if (de[1].d_name[0])
+            {
+                short_name = de[0].d_name;
+                long_name = de[1].d_name;
+            }
+            else
+            {
+                long_name = de[0].d_name;
+                short_name = NULL;
+            }
+            if (!append_entry( data, long_name, short_name, mask )) goto done;
         }
-        if (!append_entry( data, long_name, short_name, mask )) goto done;
+        if (ioctl( fd, VFAT_IOCTL_READDIR_BOTH, (long)de ) == -1) break;
     }
     status = STATUS_SUCCESS;
 done:
@@ -2083,20 +2045,13 @@ static NTSTATUS find_file_in_dir( char *unix_name, int pos, const WCHAR *name, i
         int fd = open( unix_name, O_RDONLY | O_DIRECTORY );
         if (fd != -1)
         {
-            KERNEL_DIRENT *kde;
+            KERNEL_DIRENT kde[2];
 
-            RtlEnterCriticalSection( &dir_section );
-            if ((kde = start_vfat_ioctl( fd )))
+            if (ioctl( fd, VFAT_IOCTL_READDIR_BOTH, (long)kde ) != -1)
             {
                 unix_name[pos - 1] = '/';
                 while (kde[0].d_reclen)
                 {
-                    /* make sure names are null-terminated to work around an x86-64 kernel bug */
-                    size_t len = min(kde[0].d_reclen, sizeof(kde[0].d_name) - 1 );
-                    kde[0].d_name[len] = 0;
-                    len = min(kde[1].d_reclen, sizeof(kde[1].d_name) - 1 );
-                    kde[1].d_name[len] = 0;
-
                     if (kde[1].d_name[0])
                     {
                         ret = ntdll_umbstowcs( kde[1].d_name, strlen(kde[1].d_name),
@@ -2104,7 +2059,6 @@ static NTSTATUS find_file_in_dir( char *unix_name, int pos, const WCHAR *name, i
                         if (ret == length && !RtlCompareUnicodeStrings( buffer, ret, name, ret, TRUE ))
                         {
                             strcpy( unix_name + pos, kde[1].d_name );
-                            RtlLeaveCriticalSection( &dir_section );
                             close( fd );
                             goto success;
                         }
@@ -2115,19 +2069,16 @@ static NTSTATUS find_file_in_dir( char *unix_name, int pos, const WCHAR *name, i
                     {
                         strcpy( unix_name + pos,
                                 kde[1].d_name[0] ? kde[1].d_name : kde[0].d_name );
-                        RtlLeaveCriticalSection( &dir_section );
                         close( fd );
                         goto success;
                     }
                     if (ioctl( fd, VFAT_IOCTL_READDIR_BOTH, (long)kde ) == -1)
                     {
-                        RtlLeaveCriticalSection( &dir_section );
                         close( fd );
                         goto not_found;
                     }
                 }
             }
-            RtlLeaveCriticalSection( &dir_section );
             close( fd );
         }
         /* fall through to normal handling */




More information about the wine-cvs mailing list