From 7fd1ad5ffaed038dd046dbdffdd2a66e5e6c6e67 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Thu, 18 Oct 2007 15:16:07 +0200 Subject: [PATCH] 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 894d3365cdf..9288d31f629 100644 --- a/dlls/ntdll/directory.c +++ b/dlls/ntdll/directory.c @@ -226,6 +226,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 * diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h index 05df50796e8..4f64421d642 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 a42682dbf4b..6f161a3ed3d 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);