1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
|
#if __cplusplus >= 201103L
#include <wibble/sys/mmap_v2.h>
#include <wibble/exception.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
using namespace wibble::sys;
using wibble::operator|;
int mmapProt( MMap::ProtectModeFlags flags ) {
int prot = 0;
if ( flags.has( MMap::ProtectMode::Read ) ) prot |= PROT_READ;
if ( flags.has( MMap::ProtectMode::Write ) ) prot |= PROT_WRITE;
if ( flags.has( MMap::ProtectMode::Execute ) ) prot |= PROT_EXEC;
return prot;
}
int mmapFlags( MMap::ProtectModeFlags flags ) {
int mf = 0;
if ( flags.has( MMap::ProtectMode::Shared ) ) mf |= MAP_SHARED;
if ( flags.has( MMap::ProtectMode::Private ) ) mf |= MAP_PRIVATE;
return mf;
}
int openFlags( MMap::ProtectModeFlags flags ) {
if ( flags.has( MMap::ProtectMode::Read ) &&
flags.has( MMap::ProtectMode::Write ) )
return O_RDWR;
if ( flags.has( MMap::ProtectMode::Read ) )
return O_RDONLY;
if ( flags.has( MMap::ProtectMode::Write ) )
return O_WRONLY;
}
MMap::MMap( const std::string &file, ProtectModeFlags flags ) :
_flags( flags ), _size( 0 )
{
_map( file );
}
MMap::MMap( int fd, ProtectModeFlags flags ) : _flags( flags ), _size( 0 ) {
_map( fd );
}
void MMap::map( const std::string &file, ProtectModeFlags flags ) {
_flags = flags;
_map( file );
}
void MMap::map( int fd, ProtectModeFlags flags ) {
_flags = flags;
_map( fd );
}
void MMap::unmap() {
_ptr = nullptr;
_size = 0;
}
void MMap::_map( const std::string &file ) {
int fd = ::open( file.c_str(), openFlags( _flags ) );
if ( fd < 0 )
throw wibble::exception::System( "opening file failed: " + file );
_map( fd );
}
void MMap::_map( int fd ) {
struct stat st;
if ( fstat( fd, &st ) != 0 )
throw wibble::exception::System( "stat failed while mmaping" );
size_t size = _size = st.st_size;
void *ptr = ::mmap( nullptr, _size, mmapProt( _flags ), mmapFlags( _flags ), fd, 0 );
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wold-style-cast"
if ( ptr == MAP_FAILED )
throw wibble::exception::System( "mmaping file failed" );
#pragma GCC diagnostic pop
_ptr = std::shared_ptr< void >( ptr,
[ fd, size ]( void *h ) {
::munmap( h, size );
::close( fd );
} );
}
#endif
|