Commit 51349422 authored by Alexandre Julliard's avatar Alexandre Julliard

Try to use read instead of mmap for files on removable media, so that

we don't need to keep the mapping handle open.
parent 708a846a
...@@ -104,7 +104,7 @@ static UINT page_size; ...@@ -104,7 +104,7 @@ static UINT page_size;
if (!TRACE_ON(virtual)); else VIRTUAL_DumpView(view) if (!TRACE_ON(virtual)); else VIRTUAL_DumpView(view)
static LPVOID VIRTUAL_mmap( int fd, LPVOID start, DWORD size, DWORD offset_low, static LPVOID VIRTUAL_mmap( int fd, LPVOID start, DWORD size, DWORD offset_low,
DWORD offset_high, int prot, int flags ); DWORD offset_high, int prot, int flags, BOOL *removable );
/* filter for page-fault exceptions */ /* filter for page-fault exceptions */
static WINE_EXCEPTION_FILTER(page_fault) static WINE_EXCEPTION_FILTER(page_fault)
...@@ -480,14 +480,15 @@ static void *anon_mmap_aligned( void *base, unsigned int size, int prot, int fla ...@@ -480,14 +480,15 @@ static void *anon_mmap_aligned( void *base, unsigned int size, int prot, int fla
* Map an executable (PE format) image into memory. * Map an executable (PE format) image into memory.
*/ */
static LPVOID map_image( HANDLE hmapping, int fd, char *base, DWORD total_size, static LPVOID map_image( HANDLE hmapping, int fd, char *base, DWORD total_size,
DWORD header_size, HANDLE shared_file, DWORD shared_size ) DWORD header_size, HANDLE shared_file, DWORD shared_size,
BOOL removable )
{ {
IMAGE_DOS_HEADER *dos; IMAGE_DOS_HEADER *dos;
IMAGE_NT_HEADERS *nt; IMAGE_NT_HEADERS *nt;
IMAGE_SECTION_HEADER *sec; IMAGE_SECTION_HEADER *sec;
int i, pos; int i, pos;
DWORD err = GetLastError(); DWORD err = GetLastError();
FILE_VIEW *view = NULL; FILE_VIEW *view;
char *ptr; char *ptr;
int shared_fd = -1; int shared_fd = -1;
...@@ -508,19 +509,10 @@ static LPVOID map_image( HANDLE hmapping, int fd, char *base, DWORD total_size, ...@@ -508,19 +509,10 @@ static LPVOID map_image( HANDLE hmapping, int fd, char *base, DWORD total_size,
} }
TRACE_(module)( "mapped PE file at %p-%p\n", ptr, ptr + total_size ); TRACE_(module)( "mapped PE file at %p-%p\n", ptr, ptr + total_size );
if (!(view = VIRTUAL_CreateView( ptr, total_size, 0,
VPROT_COMMITTED|VPROT_READ|VPROT_WRITE|VPROT_WRITECOPY,
hmapping )))
{
munmap( ptr, total_size );
SetLastError( ERROR_OUTOFMEMORY );
goto error;
}
/* map the header */ /* map the header */
if (VIRTUAL_mmap( fd, ptr, header_size, 0, 0, PROT_READ | PROT_WRITE, if (VIRTUAL_mmap( fd, ptr, header_size, 0, 0, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_FIXED ) == (char *)-1) goto error; MAP_PRIVATE | MAP_FIXED, &removable ) == (char *)-1) goto error;
dos = (IMAGE_DOS_HEADER *)ptr; dos = (IMAGE_DOS_HEADER *)ptr;
nt = (IMAGE_NT_HEADERS *)(ptr + dos->e_lfanew); nt = (IMAGE_NT_HEADERS *)(ptr + dos->e_lfanew);
if ((char *)(nt + 1) > ptr + header_size) goto error; if ((char *)(nt + 1) > ptr + header_size) goto error;
...@@ -582,7 +574,7 @@ static LPVOID map_image( HANDLE hmapping, int fd, char *base, DWORD total_size, ...@@ -582,7 +574,7 @@ static LPVOID map_image( HANDLE hmapping, int fd, char *base, DWORD total_size,
size, sec->Characteristics ); size, sec->Characteristics );
if (VIRTUAL_mmap( shared_fd, ptr + sec->VirtualAddress, size, if (VIRTUAL_mmap( shared_fd, ptr + sec->VirtualAddress, size,
pos, 0, PROT_READ|PROT_WRITE|PROT_EXEC, pos, 0, PROT_READ|PROT_WRITE|PROT_EXEC,
MAP_SHARED|MAP_FIXED ) == (void *)-1) MAP_SHARED|MAP_FIXED, NULL ) == (void *)-1)
{ {
ERR_(module)( "Could not map shared section %.8s\n", sec->Name ); ERR_(module)( "Could not map shared section %.8s\n", sec->Name );
goto error; goto error;
...@@ -604,7 +596,7 @@ static LPVOID map_image( HANDLE hmapping, int fd, char *base, DWORD total_size, ...@@ -604,7 +596,7 @@ static LPVOID map_image( HANDLE hmapping, int fd, char *base, DWORD total_size,
*/ */
if (VIRTUAL_mmap( fd, ptr + sec->VirtualAddress, sec->SizeOfRawData, if (VIRTUAL_mmap( fd, ptr + sec->VirtualAddress, sec->SizeOfRawData,
sec->PointerToRawData, 0, PROT_READ|PROT_WRITE|PROT_EXEC, sec->PointerToRawData, 0, PROT_READ|PROT_WRITE|PROT_EXEC,
MAP_PRIVATE | MAP_FIXED ) == (void *)-1) MAP_PRIVATE | MAP_FIXED, &removable ) == (void *)-1)
{ {
ERR_(module)( "Could not map section %.8s, file probably truncated\n", sec->Name ); ERR_(module)( "Could not map section %.8s, file probably truncated\n", sec->Name );
goto error; goto error;
...@@ -622,13 +614,22 @@ static LPVOID map_image( HANDLE hmapping, int fd, char *base, DWORD total_size, ...@@ -622,13 +614,22 @@ static LPVOID map_image( HANDLE hmapping, int fd, char *base, DWORD total_size,
} }
} }
if (removable) hmapping = 0; /* don't keep handle open on removable media */
if (!(view = VIRTUAL_CreateView( ptr, total_size, 0,
VPROT_COMMITTED|VPROT_READ|VPROT_WRITE|VPROT_WRITECOPY,
hmapping )))
{
SetLastError( ERROR_OUTOFMEMORY );
goto error;
}
SetLastError( err ); /* restore last error */ SetLastError( err ); /* restore last error */
close( fd ); close( fd );
if (shared_fd != -1) close( shared_fd ); if (shared_fd != -1) close( shared_fd );
return ptr; return ptr;
error: error:
if (view) VIRTUAL_DeleteView( view ); if (ptr != (char *)-1) munmap( ptr, total_size );
close( fd ); close( fd );
if (shared_fd != -1) close( shared_fd ); if (shared_fd != -1) close( shared_fd );
if (shared_file) CloseHandle( shared_file ); if (shared_file) CloseHandle( shared_file );
...@@ -745,14 +746,33 @@ static void *unaligned_mmap( void *addr, size_t length, unsigned int prot, ...@@ -745,14 +746,33 @@ static void *unaligned_mmap( void *addr, size_t length, unsigned int prot,
* and falls back to read if mmap of a file fails. * and falls back to read if mmap of a file fails.
*/ */
static LPVOID VIRTUAL_mmap( int fd, LPVOID start, DWORD size, static LPVOID VIRTUAL_mmap( int fd, LPVOID start, DWORD size,
DWORD offset_low, DWORD offset_high, int prot, int flags ) DWORD offset_low, DWORD offset_high,
int prot, int flags, BOOL *removable )
{ {
int pos; int pos;
LPVOID ret; LPVOID ret;
off_t offset; off_t offset;
BOOL is_shared_write = FALSE;
if (fd == -1) return wine_anon_mmap( start, size, prot, flags ); if (fd == -1) return wine_anon_mmap( start, size, prot, flags );
if (prot & PROT_WRITE)
{
#ifdef MAP_SHARED
if (flags & MAP_SHARED) is_shared_write = TRUE;
#endif
#ifdef MAP_PRIVATE
if (!(flags & MAP_PRIVATE)) is_shared_write = TRUE;
#endif
}
if (removable && *removable)
{
/* if on removable media, try using read instead of mmap */
if (!is_shared_write) goto fake_mmap;
*removable = FALSE;
}
if ((ret = unaligned_mmap( start, size, prot, flags, fd, if ((ret = unaligned_mmap( start, size, prot, flags, fd,
offset_low, offset_high )) != (LPVOID)-1) return ret; offset_low, offset_high )) != (LPVOID)-1) return ret;
...@@ -761,17 +781,9 @@ static LPVOID VIRTUAL_mmap( int fd, LPVOID start, DWORD size, ...@@ -761,17 +781,9 @@ static LPVOID VIRTUAL_mmap( int fd, LPVOID start, DWORD size,
/* does not support mmap() (ENOEXEC,ENODEV), we do it by hand. */ /* does not support mmap() (ENOEXEC,ENODEV), we do it by hand. */
if ((errno != ENOEXEC) && (errno != EINVAL) && (errno != ENODEV)) return ret; if ((errno != ENOEXEC) && (errno != EINVAL) && (errno != ENODEV)) return ret;
if (prot & PROT_WRITE) if (is_shared_write) return ret; /* we cannot fake shared write mappings */
{
/* We cannot fake shared write mappings */
#ifdef MAP_SHARED
if (flags & MAP_SHARED) return ret;
#endif
#ifdef MAP_PRIVATE
if (!(flags & MAP_PRIVATE)) return ret;
#endif
}
fake_mmap:
/* Reserve the memory with an anonymous mmap */ /* Reserve the memory with an anonymous mmap */
ret = wine_anon_mmap( start, size, PROT_READ | PROT_WRITE, flags ); ret = wine_anon_mmap( start, size, PROT_READ | PROT_WRITE, flags );
if (ret == (LPVOID)-1) return ret; if (ret == (LPVOID)-1) return ret;
...@@ -1553,6 +1565,7 @@ LPVOID WINAPI MapViewOfFileEx( ...@@ -1553,6 +1565,7 @@ LPVOID WINAPI MapViewOfFileEx(
void *base, *ptr = (void *)-1, *ret; void *base, *ptr = (void *)-1, *ret;
DWORD size_low, size_high, header_size, shared_size; DWORD size_low, size_high, header_size, shared_size;
HANDLE shared_file; HANDLE shared_file;
BOOL removable;
/* Check parameters */ /* Check parameters */
...@@ -1574,6 +1587,8 @@ LPVOID WINAPI MapViewOfFileEx( ...@@ -1574,6 +1587,8 @@ LPVOID WINAPI MapViewOfFileEx(
header_size = req->header_size; header_size = req->header_size;
shared_file = req->shared_file; shared_file = req->shared_file;
shared_size = req->shared_size; shared_size = req->shared_size;
removable = (req->drive_type == DRIVE_REMOVABLE ||
req->drive_type == DRIVE_CDROM);
} }
SERVER_END_REQ; SERVER_END_REQ;
if (res) goto error; if (res) goto error;
...@@ -1582,7 +1597,7 @@ LPVOID WINAPI MapViewOfFileEx( ...@@ -1582,7 +1597,7 @@ LPVOID WINAPI MapViewOfFileEx(
if (prot & VPROT_IMAGE) if (prot & VPROT_IMAGE)
return map_image( handle, unix_handle, base, size_low, header_size, return map_image( handle, unix_handle, base, size_low, header_size,
shared_file, shared_size ); shared_file, shared_size, removable );
if (size_high) if (size_high)
...@@ -1636,12 +1651,13 @@ LPVOID WINAPI MapViewOfFileEx( ...@@ -1636,12 +1651,13 @@ LPVOID WINAPI MapViewOfFileEx(
TRACE("handle=%x size=%x offset=%lx\n", handle, size, offset_low ); TRACE("handle=%x size=%x offset=%lx\n", handle, size, offset_low );
ret = VIRTUAL_mmap( unix_handle, ptr, size, offset_low, offset_high, ret = VIRTUAL_mmap( unix_handle, ptr, size, offset_low, offset_high,
VIRTUAL_GetUnixProt( prot ), flags | MAP_FIXED ); VIRTUAL_GetUnixProt( prot ), flags | MAP_FIXED, &removable );
if (ret != ptr) if (ret != ptr)
{ {
ERR( "VIRTUAL_mmap %p %x %lx%08lx failed\n", ptr, size, offset_high, offset_low ); ERR( "VIRTUAL_mmap %p %x %lx%08lx failed\n", ptr, size, offset_high, offset_low );
goto error; goto error;
} }
if (removable) handle = 0; /* don't keep handle open on removable media */
if (!(view = VIRTUAL_CreateView( ptr, size, 0, prot, handle ))) if (!(view = VIRTUAL_CreateView( ptr, size, 0, prot, handle )))
{ {
......
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