Alexandre Julliard : ntdll: Cache the DOS drives stat info for up to one second.

Alexandre Julliard julliard at winehq.org
Fri Oct 19 08:35:38 CDT 2007


Module: wine
Branch: master
Commit: 7fd1ad5ffaed038dd046dbdffdd2a66e5e6c6e67
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=7fd1ad5ffaed038dd046dbdffdd2a66e5e6c6e67

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Thu Oct 18 15:16:07 2007 +0200

ntdll: Cache the DOS drives stat info for up to one second.

---

 dlls/ntdll/directory.c  |   54 +++++++++++++++++++++++++++++++++++++++++++++++
 dlls/ntdll/ntdll_misc.h |    9 +++++++
 dlls/ntdll/path.c       |   50 +-----------------------------------------
 3 files changed, 65 insertions(+), 48 deletions(-)

diff --git a/dlls/ntdll/directory.c b/dlls/ntdll/directory.c
index 894d336..9288d31 100644
--- a/dlls/ntdll/directory.c
+++ b/dlls/ntdll/directory.c
@@ -227,6 +227,60 @@ static char *get_default_lpt_device( int num )
 
 
 /***********************************************************************
+ *           DIR_get_drives_info
+ *
+ * Retrieve device/inode number for all the drives. Helper for find_drive_root.
+ */
+unsigned int DIR_get_drives_info( struct drive_info info[MAX_DOS_DRIVES] )
+{
+    static struct drive_info cache[MAX_DOS_DRIVES];
+    static time_t last_update;
+    static unsigned int nb_drives;
+    unsigned int ret;
+    time_t now = time(NULL);
+
+    RtlEnterCriticalSection( &dir_section );
+    if (now != last_update)
+    {
+        const char *config_dir = wine_get_config_dir();
+        char *buffer, *p;
+        struct stat st;
+        unsigned int i;
+
+        if ((buffer = RtlAllocateHeap( GetProcessHeap(), 0,
+                                       strlen(config_dir) + sizeof("/dosdevices/a:") )))
+        {
+            strcpy( buffer, config_dir );
+            strcat( buffer, "/dosdevices/a:" );
+            p = buffer + strlen(buffer) - 2;
+
+            for (i = nb_drives = 0; i < MAX_DOS_DRIVES; i++)
+            {
+                *p = 'a' + i;
+                if (!stat( buffer, &st ))
+                {
+                    cache[i].dev = st.st_dev;
+                    cache[i].ino = st.st_ino;
+                    nb_drives++;
+                }
+                else
+                {
+                    cache[i].dev = 0;
+                    cache[i].ino = 0;
+                }
+            }
+            RtlFreeHeap( GetProcessHeap(), 0, buffer );
+        }
+        last_update = now;
+    }
+    memcpy( info, cache, sizeof(cache) );
+    ret = nb_drives;
+    RtlLeaveCriticalSection( &dir_section );
+    return ret;
+}
+
+
+/***********************************************************************
  *           parse_mount_entries
  *
  * Parse mount entries looking for a given device. Helper for get_default_drive_device.
diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h
index 05df507..4f64421 100644
--- a/dlls/ntdll/ntdll_misc.h
+++ b/dlls/ntdll/ntdll_misc.h
@@ -29,6 +29,14 @@
 
 #define MAX_NT_PATH_LENGTH 277
 
+#define MAX_DOS_DRIVES 26
+
+struct drive_info
+{
+    dev_t dev;
+    ino_t ino;
+};
+
 /* exceptions */
 extern void wait_suspend( CONTEXT *context );
 extern void WINAPI __regs_RtlRaiseException( PEXCEPTION_RECORD, PCONTEXT );
@@ -113,6 +121,7 @@ extern NTSTATUS FILE_GetNtStatus(void);
 extern BOOL DIR_is_hidden_file( const UNICODE_STRING *name );
 extern NTSTATUS DIR_unmount_device( HANDLE handle );
 extern NTSTATUS DIR_get_unix_cwd( char **cwd );
+extern unsigned int DIR_get_drives_info( struct drive_info info[MAX_DOS_DRIVES] );
 
 /* virtual memory */
 extern NTSTATUS VIRTUAL_HandleFault(LPCVOID addr);
diff --git a/dlls/ntdll/path.c b/dlls/ntdll/path.c
index a42682d..6f161a3 100644
--- a/dlls/ntdll/path.c
+++ b/dlls/ntdll/path.c
@@ -50,52 +50,6 @@ static const WCHAR UncPfxW[] = {'U','N','C','\\',0};
 
 #define IS_SEPARATOR(ch)  ((ch) == '\\' || (ch) == '/')
 
-#define MAX_DOS_DRIVES 26
-
-struct drive_info
-{
-    dev_t dev;
-    ino_t ino;
-};
-
-/***********************************************************************
- *           get_drives_info
- *
- * Retrieve device/inode number for all the drives. Helper for find_drive_root.
- */
-static inline int get_drives_info( struct drive_info info[MAX_DOS_DRIVES] )
-{
-    const char *config_dir = wine_get_config_dir();
-    char *buffer, *p;
-    struct stat st;
-    int i, ret;
-
-    buffer = RtlAllocateHeap( GetProcessHeap(), 0, strlen(config_dir) + sizeof("/dosdevices/a:") );
-    if (!buffer) return 0;
-    strcpy( buffer, config_dir );
-    strcat( buffer, "/dosdevices/a:" );
-    p = buffer + strlen(buffer) - 2;
-
-    for (i = ret = 0; i < MAX_DOS_DRIVES; i++)
-    {
-        *p = 'a' + i;
-        if (!stat( buffer, &st ))
-        {
-            info[i].dev = st.st_dev;
-            info[i].ino = st.st_ino;
-            ret++;
-        }
-        else
-        {
-            info[i].dev = 0;
-            info[i].ino = 0;
-        }
-    }
-    RtlFreeHeap( GetProcessHeap(), 0, buffer );
-    return ret;
-}
-
-
 /***********************************************************************
  *           remove_last_componentA
  *
@@ -149,7 +103,7 @@ static NTSTATUS find_drive_rootA( LPCSTR *ppath, unsigned int len, int *drive_re
     struct drive_info info[MAX_DOS_DRIVES];
 
     /* get device and inode of all drives */
-    if (!get_drives_info( info )) return STATUS_OBJECT_PATH_NOT_FOUND;
+    if (!DIR_get_drives_info( info )) return STATUS_OBJECT_PATH_NOT_FOUND;
 
     /* strip off trailing slashes */
     while (len > 1 && path[len - 1] == '/') len--;
@@ -240,7 +194,7 @@ static int find_drive_rootW( LPCWSTR *ppath )
     struct drive_info info[MAX_DOS_DRIVES];
 
     /* get device and inode of all drives */
-    if (!get_drives_info( info )) return -1;
+    if (!DIR_get_drives_info( info )) return -1;
 
     /* strip off trailing slashes */
     lenW = strlenW(path);




More information about the wine-cvs mailing list