///////////////////////////////////////////////////////////////////////////// // Rev 06/12/2003 // // // CFILEMAP.CPP // ------------ // // // Sylvain MARECHAL - sylvain.marechal1@libertysurf.fr ///////////////////////////////////////////////////////////////////////////// // // Map one file into memory // ///////////////////////////////////////////////////////////////////////////// #ifdef _WIN32 #include #else #include #include #include #include #include #endif #include #include #include #include #include "cfilemap.h" ///////////////////////////////////////////////////////////////////////////// // // FILEMAP_CREATE ///////////////////////////////////////////////////////////////////////////// // // DESCRIPTION // --filemap_create-- // // C Interface // // ARGUMENTS // RETOUR/RESULTAT // FILEMAP // REMARQUE // Rev 06/12/2003 ////////////////////////////////////////////////////////////////////////////// FILEMAP filemap_create() { return (FILEMAP)(new CFileMap); } ///////////////////////////////////////////////////////////////////////////// // // FILEMAP_OPEN ///////////////////////////////////////////////////////////////////////////// // // DESCRIPTION // --filemap_open-- // // C Interface // // ARGUMENTS // Argument1: FILEMAP filemap // Argument2: const char * pszFile // Argument3: int flag // Argument4: unsigned int nSize // RETOUR/RESULTAT // int // REMARQUE // Rev 06/12/2003 ////////////////////////////////////////////////////////////////////////////// int filemap_open( FILEMAP filemap, const char * pszFile, int flag, unsigned int nSize ) { CFileMap * pFileMap = (CFileMap *)filemap; if( ! pFileMap ) return -1; return pFileMap->Open( pszFile, flag, nSize ); } ///////////////////////////////////////////////////////////////////////////// // // FILEMAP_GETBASEADDRESS ///////////////////////////////////////////////////////////////////////////// // // DESCRIPTION // --filemap_getbaseaddress-- // // C Interface // // ARGUMENTS // Argument1: FILEMAP filemap // RETOUR/RESULTAT // void * // REMARQUE // Rev 06/12/2003 ////////////////////////////////////////////////////////////////////////////// void * filemap_getbaseaddress( FILEMAP filemap ) { CFileMap * pFileMap = (CFileMap *)filemap; if( ! pFileMap ) return NULL; return pFileMap->GetBaseAddr(); } ///////////////////////////////////////////////////////////////////////////// // // FILEMAP_MAP ///////////////////////////////////////////////////////////////////////////// // // DESCRIPTION // --filemap_map-- // // C Interface // // ARGUMENTS // Argument1: FILEMAP filemap // Argument2: unsigned int Offset // Argument3: unsigned int size // Argument4: int flag // Argument5: unsigned int * pRelativeOffset // RETOUR/RESULTAT // void * // REMARQUE // Rev 06/12/2003 ////////////////////////////////////////////////////////////////////////////// void * filemap_map( FILEMAP filemap, unsigned int Offset, unsigned int size, int flag, unsigned int * pRelativeOffset ) { CFileMap * pFileMap = (CFileMap *)filemap; if( ! pFileMap ) return NULL; return pFileMap->Map( Offset, size, flag, pRelativeOffset ); } ///////////////////////////////////////////////////////////////////////////// // // FILEMAP_UNMAP ///////////////////////////////////////////////////////////////////////////// // // DESCRIPTION // --filemap_unmap-- // // C Interface // // ARGUMENTS // Argument1: FILEMAP filemap // Argument2: void * pAddr // Argument3: unsigned int size // Argument4: unsigned int RelativeOffset // RETOUR/RESULTAT // int // REMARQUE // Rev 06/12/2003 ////////////////////////////////////////////////////////////////////////////// int filemap_unmap( FILEMAP filemap, void * pAddr, unsigned int size, unsigned int RelativeOffset ) { CFileMap * pFileMap = (CFileMap *)filemap; if( ! pFileMap ) return -1; return pFileMap->UnMap( pAddr, size, RelativeOffset ); } ///////////////////////////////////////////////////////////////////////////// // // FILEMAP_CLOSE ///////////////////////////////////////////////////////////////////////////// // // DESCRIPTION // --filemap_close-- // // C Interface // // ARGUMENTS // Argument1: FILEMAP filemap // RETOUR/RESULTAT // int // REMARQUE // Rev 06/12/2003 ////////////////////////////////////////////////////////////////////////////// int filemap_close( FILEMAP filemap ) { CFileMap * pFileMap = (CFileMap *)filemap; if( ! pFileMap ) return -1; return pFileMap->Close(); } ///////////////////////////////////////////////////////////////////////////// // // FILEMAP_DESTROY ///////////////////////////////////////////////////////////////////////////// // // DESCRIPTION // --filemap_destroy-- // // C Interface // // ARGUMENTS // Argument1: FILEMAP filemap // RETOUR/RESULTAT // int // REMARQUE // Rev 06/12/2003 ////////////////////////////////////////////////////////////////////////////// int filemap_destroy( FILEMAP filemap ) { CFileMap * pFileMap = (CFileMap *)filemap; if( ! pFileMap ) return -1; delete pFileMap; return 0; } ///////////////////////////////////////////////////////////////////////////// // // FILEMAP_DELETE ///////////////////////////////////////////////////////////////////////////// // // DESCRIPTION // --filemap_delete-- // // C Interface // // ARGUMENTS // Argument1: const char * pszFile // RETOUR/RESULTAT // int // REMARQUE // Rev 06/12/2003 ////////////////////////////////////////////////////////////////////////////// int filemap_delete( const char * pszFile ) { return unlink( pszFile ); } ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// // // CFILEMAP::CFILEMAP ///////////////////////////////////////////////////////////////////////////// // // DESCRIPTION // --CFileMap::CFileMap-- // ARGUMENTS // Argument1: 0) // Argument2: (0) // Argument3: // RETOUR/RESULTAT // // REMARQUE // Rev 06/12/2003 ////////////////////////////////////////////////////////////////////////////// CFileMap::CFileMap() : m_pAddr (0), m_nSize (0), #ifdef _WIN32 m_hFile (INVALID_HANDLE_VALUE), m_hMap (NULL) #else m_hFile (-1) #endif { } ///////////////////////////////////////////////////////////////////////////// // // CFILEMAP::~CFILEMAP ///////////////////////////////////////////////////////////////////////////// // // DESCRIPTION // --CFileMap::~CFileMap-- // ARGUMENTS // RETOUR/RESULTAT // // REMARQUE // Rev 06/12/2003 ////////////////////////////////////////////////////////////////////////////// CFileMap::~CFileMap() { Close(); } ///////////////////////////////////////////////////////////////////////////// // // CFILEMAP::OPEN ///////////////////////////////////////////////////////////////////////////// // // DESCRIPTION // --CFileMap::Open-- // ARGUMENTS // Argument1: const char * pszFile // Argument2: int flag // Argument3: unsigned int nSize // RETOUR/RESULTAT // int // REMARQUE // Rev 06/12/2003 ////////////////////////////////////////////////////////////////////////////// int CFileMap::Open( const char * pszFile, int flag, unsigned int nSize ) { unsigned int RelativeOffsetAlwaysZero; // Coherence if( (flag & MAP_RDONLY && flag & MAP_RDWR) || (flag & MAP_RDONLY && flag & MAP_CREAT) ) { return -1; } // Find the size m_nSize = nSize; if( m_nSize == 0 ) // if( flag ^ MAP_CREAT ) { struct stat st; if( stat( pszFile, & st ) ) return -1; m_nSize = st.st_size; } #ifdef _WIN32 // CreateFile 's arguments DWORD dwAccess = GENERIC_READ | GENERIC_WRITE; DWORD dwShare = FILE_SHARE_READ | FILE_SHARE_WRITE; DWORD dwCreate = OPEN_EXISTING; // Map file 's arguments DWORD flProtect = PAGE_READWRITE; DWORD dwMapDesiredAccess = FILE_MAP_WRITE; // Read only if( flag & MAP_RDONLY ) { // File dwAccess = GENERIC_READ; // Map flProtect = PAGE_READONLY; dwMapDesiredAccess = FILE_MAP_READ; } // Creation if( flag & MAP_CREAT ) { dwCreate = CREATE_ALWAYS; } // Open the file m_hFile = CreateFile( pszFile, dwAccess, dwShare, NULL, dwCreate, FILE_ATTRIBUTE_NORMAL, NULL); if( m_hFile == INVALID_HANDLE_VALUE ) return -1; // If Creation, set the size if( flag & MAP_CREAT ) { SetFilePointer(m_hFile, m_nSize, 0, FILE_BEGIN); if( SetEndOfFile(m_hFile) == 0 ) { CloseHandle( m_hFile ); m_hFile = INVALID_HANDLE_VALUE; return -1; } } // Create a memory file mapping m_hMap = CreateFileMapping( m_hFile, NULL, flProtect, 0, 0, NULL ); if( m_hMap == NULL ) { DWORD dwError = GetLastError(); CloseHandle( m_hFile ); m_hFile = INVALID_HANDLE_VALUE; return -1; } if( (flag & MAP_DONTMAP) == 0 ) { // Map all file into memory m_pAddr = Map( 0, m_nSize, flag, &RelativeOffsetAlwaysZero ); if( m_pAddr == NULL ) { CloseHandle(m_hMap); CloseHandle( m_hFile ); m_hFile = INVALID_HANDLE_VALUE; m_hMap = NULL; return -1; } } #else int oFlag = 0; int pMode = 0644; // Read only if( flag & MAP_RDONLY ) { oFlag |= O_RDONLY; } if( flag & MAP_RDWR ) { oFlag |= O_RDWR; } // Creation if( flag & MAP_CREAT ) { oFlag |= O_CREAT; } // Create/ open the file m_hFile = open( pszFile, oFlag, pMode ); if( m_hFile == -1 ) return -1; // If Creation, set the size if( flag & MAP_CREAT ) { if( (ftruncate(m_hFile, m_nSize)) == -1) { close( m_hFile ); m_hFile = -1; return -1; } } /* Map one page */ if( (flag & MAP_DONTMAP) == 0 ) { m_pAddr = Map( 0, m_nSize, flag, &RelativeOffsetAlwaysZero ); if( m_pAddr == NULL ) { close( m_hFile ); m_hFile = -1; return -1; } } #endif if( flag & MAP_CREAT && m_nSize) { memset( m_pAddr, m_nSize, 0 ); } return 0; } ///////////////////////////////////////////////////////////////////////////// // // GETPAGESIZE ///////////////////////////////////////////////////////////////////////////// // // DESCRIPTION // --GetPageSize-- // ARGUMENTS // RETOUR/RESULTAT // static int // REMARQUE // Rev 06/12/2003 ////////////////////////////////////////////////////////////////////////////// static int GetPageSize() { int PageSize; #ifdef _WIN32 SYSTEM_INFO SystemInfo; GetSystemInfo( &SystemInfo ); PageSize = SystemInfo.dwAllocationGranularity; #else //int PageSize = sysconf(_SC_PAGE_SIZE); PageSize = getpagesize(); PageSize = ( PageSize == 0 ? 4096 : PageSize); #endif return PageSize; } #ifndef _WIN32 ///////////////////////////////////////////////////////////////////////////// // // GETMAPPINGSIZE ///////////////////////////////////////////////////////////////////////////// // // DESCRIPTION // --GetMappingSize-- // // Round size to a multiple of page size // // ARGUMENTS // Argument1: int size // RETOUR/RESULTAT // static int // REMARQUE // Rev 06/12/2003 ////////////////////////////////////////////////////////////////////////////// static int GetMappingSize( int size) { // m_nSize multiple of PageSize int PageSize = GetPageSize(); int nbPages = (size / PageSize); if( size % PageSize != 0 ) { nbPages ++; } size = nbPages * PageSize; return size; } #endif ///////////////////////////////////////////////////////////////////////////// // // CFILEMAP::MAP ///////////////////////////////////////////////////////////////////////////// // // DESCRIPTION // --CFileMap::Map-- // // Mapping should be aligned // pRelativeOffset is != from 0 if size isn't multiple of pagesize // // ARGUMENTS // Argument1: unsigned int Offset // Argument2: unsigned int size // Argument3: int flag // Argument4: unsigned int * pRelativeOffset // RETOUR/RESULTAT // void * // REMARQUE // Rev 06/12/2003 ////////////////////////////////////////////////////////////////////////////// void * CFileMap::Map( unsigned int Offset, unsigned int size, int flag, unsigned int * pRelativeOffset ) { unsigned int PageSize = GetPageSize(); if( ! pRelativeOffset ) return NULL; *pRelativeOffset = Offset % PageSize; #ifdef _WIN32 DWORD dwMapDesiredAccess = FILE_MAP_WRITE; // Read only if( flag & MAP_RDONLY ) { dwMapDesiredAccess = FILE_MAP_READ; } // Map all file into memory void * ret = MapViewOfFile( m_hMap, dwMapDesiredAccess, 0, Offset - *pRelativeOffset, size + *pRelativeOffset ); int n = GetLastError(); return ret; #else int mProt = 0; // Read only if( flag & MAP_RDONLY ) { mProt = PROT_READ; } if( flag & MAP_RDWR ) { mProt = PROT_READ | PROT_WRITE; } size = GetMappingSize( size + *pRelativeOffset ); return mmap( 0, size, mProt, MAP_SHARED, m_hFile, Offset - *pRelativeOffset ); #endif } ///////////////////////////////////////////////////////////////////////////// // // CFILEMAP::UNMAP ///////////////////////////////////////////////////////////////////////////// // // DESCRIPTION // --CFileMap::UnMap-- // ARGUMENTS // Argument1: void * pAddr // Argument2: unsigned int size // Argument3: unsigned int RelativeOffset // RETOUR/RESULTAT // int 0 OK, -1 KO // REMARQUE // Rev 06/12/2003 ////////////////////////////////////////////////////////////////////////////// int CFileMap::UnMap( void * pAddr, unsigned int size, unsigned int RelativeOffset ) { #ifdef _WIN32 if( UnmapViewOfFile( pAddr ) ) { return 0; } return -1; #else size = GetMappingSize( size + RelativeOffset ); return munmap( (caddr_t)pAddr, size ); #endif } ///////////////////////////////////////////////////////////////////////////// // // CFILEMAP::CLOSE ///////////////////////////////////////////////////////////////////////////// // // DESCRIPTION // --CFileMap::Close-- // ARGUMENTS // RETOUR/RESULTAT // int 0 OK, -1 KO // REMARQUE // Rev 06/12/2003 ////////////////////////////////////////////////////////////////////////////// int CFileMap::Close() { if( m_pAddr ) { UnMap( m_pAddr, m_nSize, 0 ); m_pAddr = NULL; } #ifdef _WIN32 if( m_hMap ) { CloseHandle(m_hMap); m_hMap = NULL; } if( m_hFile != INVALID_HANDLE_VALUE ) { CloseHandle( m_hFile ); m_hFile = INVALID_HANDLE_VALUE; } #else if( m_hFile != -1 ) { close(m_hFile); /* Close file */ m_hFile = -1; } #endif return 0; }