Commit 7fd1ad5f authored by Alexandre Julliard's avatar Alexandre Julliard

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

parent d7892ccf
......@@ -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.
......
......@@ -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);
......
......@@ -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);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment