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

we don't need to keep the mapping handle open.
This commit is contained in:
Alexandre Julliard 2001-10-24 00:30:23 +00:00
parent 708a846a88
commit 51349422b9
1 changed files with 45 additions and 29 deletions

View File

@ -104,7 +104,7 @@ static UINT page_size;
if (!TRACE_ON(virtual)); else VIRTUAL_DumpView(view)
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 */
static WINE_EXCEPTION_FILTER(page_fault)
@ -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.
*/
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_NT_HEADERS *nt;
IMAGE_SECTION_HEADER *sec;
int i, pos;
DWORD err = GetLastError();
FILE_VIEW *view = NULL;
FILE_VIEW *view;
char *ptr;
int shared_fd = -1;
@ -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 );
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 */
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;
nt = (IMAGE_NT_HEADERS *)(ptr + dos->e_lfanew);
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,
size, sec->Characteristics );
if (VIRTUAL_mmap( shared_fd, ptr + sec->VirtualAddress, size,
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 );
goto error;
@ -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,
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 );
goto error;
@ -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 */
close( fd );
if (shared_fd != -1) close( shared_fd );
return ptr;
error:
if (view) VIRTUAL_DeleteView( view );
if (ptr != (char *)-1) munmap( ptr, total_size );
close( fd );
if (shared_fd != -1) close( shared_fd );
if (shared_file) CloseHandle( shared_file );
@ -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.
*/
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;
LPVOID ret;
off_t offset;
BOOL is_shared_write = FALSE;
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,
offset_low, offset_high )) != (LPVOID)-1) return ret;
@ -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. */
if ((errno != ENOEXEC) && (errno != EINVAL) && (errno != ENODEV)) return ret;
if (prot & PROT_WRITE)
{
/* 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
}
if (is_shared_write) return ret; /* we cannot fake shared write mappings */
fake_mmap:
/* Reserve the memory with an anonymous mmap */
ret = wine_anon_mmap( start, size, PROT_READ | PROT_WRITE, flags );
if (ret == (LPVOID)-1) return ret;
@ -1553,6 +1565,7 @@ LPVOID WINAPI MapViewOfFileEx(
void *base, *ptr = (void *)-1, *ret;
DWORD size_low, size_high, header_size, shared_size;
HANDLE shared_file;
BOOL removable;
/* Check parameters */
@ -1574,6 +1587,8 @@ LPVOID WINAPI MapViewOfFileEx(
header_size = req->header_size;
shared_file = req->shared_file;
shared_size = req->shared_size;
removable = (req->drive_type == DRIVE_REMOVABLE ||
req->drive_type == DRIVE_CDROM);
}
SERVER_END_REQ;
if (res) goto error;
@ -1582,7 +1597,7 @@ LPVOID WINAPI MapViewOfFileEx(
if (prot & VPROT_IMAGE)
return map_image( handle, unix_handle, base, size_low, header_size,
shared_file, shared_size );
shared_file, shared_size, removable );
if (size_high)
@ -1636,12 +1651,13 @@ LPVOID WINAPI MapViewOfFileEx(
TRACE("handle=%x size=%x offset=%lx\n", handle, size, offset_low );
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)
{
ERR( "VIRTUAL_mmap %p %x %lx%08lx failed\n", ptr, size, offset_high, offset_low );
goto error;
}
if (removable) handle = 0; /* don't keep handle open on removable media */
if (!(view = VIRTUAL_CreateView( ptr, size, 0, prot, handle )))
{