exiv2/msvc/src/mmap.cpp

197 lines
5.4 KiB
C++

/*
This file is part of the KDE libraries
Copyright (c) 2006 Christian Ehrlicher <ch.ehrlicher@gmx.de>
These sources are based on ftp://g.oswego.edu/pub/misc/malloc.c
file by Doug Lea, released to the public domain.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License version 2 as published by the Free Software Foundation.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include <winposix_export.h>
#include <windows.h>
#include <assert.h>
#include <stdlib.h>
#include <errno.h>
#include <io.h>
#include <sys/mman.h>
#include <sys/socket.h>
#ifndef SECTION_MAP_EXECUTE_EXPLICIT
//not defined in the February 2003 version of the Platform SDK
#define SECTION_MAP_EXECUTE_EXPLICIT 0x0020
#endif
#ifndef FILE_MAP_EXECUTE
//not defined in the February 2003 version of the Platform SDK
#define FILE_MAP_EXECUTE SECTION_MAP_EXECUTE_EXPLICIT
#endif
#define MUNMAP_FAILURE (-1)
#define USE_MALLOC_LOCK 1
struct mmapInfos {
HANDLE hFile; // the duplicated fd
HANDLE hMap; // handle returned by CreateFileMapping
void* start; // ptr returned by MapViewOfFile
};
CRITICAL_SECTION cs;
// rmills - only change is to add long to the following 2 lines
static long g_curMMapInfos = 0;
static long g_maxMMapInfos = -1;
static struct mmapInfos *g_mmapInfos = NULL;
#define NEW_MMAP_STRUCT_CNT 10
static int mapProtFlags(int flags, DWORD *dwAccess)
{
if ( ( flags & PROT_READ ) == PROT_READ ) {
if ( ( flags & PROT_WRITE ) == PROT_WRITE ) {
*dwAccess = FILE_MAP_WRITE;
if ( ( flags & PROT_EXEC ) == PROT_EXEC ) {
return PAGE_EXECUTE_READWRITE;
}
return PAGE_READWRITE;
}
if ( ( flags & PROT_EXEC ) == PROT_EXEC ) {
*dwAccess = FILE_MAP_EXECUTE;
return PAGE_EXECUTE_READ;
}
*dwAccess = FILE_MAP_READ;
return PAGE_READONLY;
}
if ( ( flags & PROT_WRITE ) == PROT_WRITE ) {
*dwAccess = FILE_MAP_COPY;
return PAGE_WRITECOPY;
}
if ( ( flags & PROT_EXEC ) == PROT_EXEC ) {
*dwAccess = FILE_MAP_EXECUTE;
return PAGE_EXECUTE_READ;
}
*dwAccess = 0;
return 0;
}
void *mmap(void *start, size_t length, int prot , int flags, int fd, off_t offset)
{
struct mmapInfos mmi;
DWORD dwAccess;
DWORD flProtect;
HANDLE hfd;
if ( g_maxMMapInfos == -1 ) {
g_maxMMapInfos = 0;
InitializeCriticalSection( &cs );
}
flProtect = mapProtFlags( flags, &dwAccess );
if ( flProtect == 0 ) {
_set_errno( EINVAL );
return MAP_FAILED;
}
// we don't support this atm
if ( prot == MAP_FIXED ) {
_set_errno( ENOTSUP );
return MAP_FAILED;
}
if ( fd == -1 ) {
_set_errno( EBADF );
return MAP_FAILED;
}
hfd = (HANDLE)_get_osfhandle( fd );
if ( hfd == INVALID_HANDLE_VALUE )
return MAP_FAILED;
if ( !DuplicateHandle( GetCurrentProcess(), hfd, GetCurrentProcess(),
&mmi.hFile, 0, FALSE, DUPLICATE_SAME_ACCESS ) ) {
#ifdef _DEBUG
DWORD dwLastErr = GetLastError();
#endif
return MAP_FAILED;
}
mmi.hMap = CreateFileMapping( mmi.hFile, NULL, flProtect,
0, length, NULL );
if ( mmi.hMap == 0 ) {
_set_errno( EACCES );
return MAP_FAILED;
}
mmi.start = MapViewOfFile( mmi.hMap, dwAccess, 0, offset, 0 );
if ( mmi.start == 0 ) {
DWORD dwLastErr = GetLastError();
if ( dwLastErr == ERROR_MAPPED_ALIGNMENT )
_set_errno( EINVAL );
else
_set_errno( EACCES );
return MAP_FAILED;
}
EnterCriticalSection( &cs );
if ( g_mmapInfos == NULL ) {
g_maxMMapInfos = NEW_MMAP_STRUCT_CNT;
g_mmapInfos = ( struct mmapInfos* )calloc( g_maxMMapInfos,
sizeof( struct mmapInfos ) );
}
if( g_curMMapInfos == g_maxMMapInfos) {
g_maxMMapInfos += NEW_MMAP_STRUCT_CNT;
g_mmapInfos = ( struct mmapInfos* )realloc( g_mmapInfos,
g_maxMMapInfos * sizeof( struct mmapInfos ) );
}
memcpy( &g_mmapInfos[g_curMMapInfos], &mmi, sizeof( struct mmapInfos) );
g_curMMapInfos++;
LeaveCriticalSection( &cs );
return mmi.start;
}
int munmap(void *start, size_t length)
{
int i, j;
for( i = 0; i < g_curMMapInfos; i++ ) {
if( g_mmapInfos[i].start == start )
break;
}
if( i == g_curMMapInfos ) {
_set_errno( EINVAL );
return -1;
}
UnmapViewOfFile( g_mmapInfos[i].start );
CloseHandle( g_mmapInfos[i].hMap );
CloseHandle( g_mmapInfos[i].hFile );
EnterCriticalSection( &cs );
for( j = i + 1; j < g_curMMapInfos; j++ ) {
memcpy( &g_mmapInfos[ j - 1 ], &g_mmapInfos[ j ],
sizeof( struct mmapInfos ) );
}
g_curMMapInfos--;
if( g_curMMapInfos == 0 ) {
free( g_mmapInfos );
g_mmapInfos = NULL;
g_maxMMapInfos = 0;
}
LeaveCriticalSection( &cs );
return 0;
}