@ -4,6 +4,7 @@
# include <string.h>
# include <fcntl.h>
# include <sys/mman.h>
# include <sys/stat.h>
# include <macros.h>
# include <map.h>
@ -12,17 +13,21 @@
static inline void _map_init ( map_t * pOUT map )
{
memset ( map , 0xff , sizeof ( map_t ) ) ;
TRACE ( " blanked %p->%lu to 0xff " , map , sizeof ( map_t ) ) ;
}
static inline bool _map_is_file ( const map_t * map )
{
TRACE ( " fd element of union is %x (%d) " , map - > file . fd , map - > file . fd ) ;
return map - > file . fd > 0 ;
}
map_result_t map_fd ( int fd , bool write , usize size , off_t offset , map_t * pOUT map )
{
TRACE ( " mapping %lu bytes of fd %d (%s) from offset %lu to %p " , size , fd , write ? " rw " : " ro " , offset , map ) ;
void * ptr = mmap ( NULL , size , PROT_READ | ( write ? PROT_WRITE : 0 ) , MAP_SHARED , fd , offset ) ;
if ( ptr = = MAP_FAILED ) return MAP_ERR_MMAP ;
TRACE ( " mapped %p->%lu " , ptr , size ) ;
map - > file = ( struct mm_file ) {
. origin = ptr ,
. len = size ,
@ -34,16 +39,31 @@ map_result_t map_fd(int fd, bool write, usize size, off_t offset, map_t *pOUT ma
map_result_t map_file ( const char * file , bool write , usize size , off_t offset , map_t * pOUT map )
{
TRACE ( " mapping %lu bytes of file `%s' (%s) from %lu to %p " , size , file , write ? " rw " : " ro " , offset , map ) ;
int fd = open ( file , write ? O_RDWR : O_RDONLY ) ;
if ( fd < 0 ) return MAP_ERR_OPEN ;
TRACE ( " opened file %d " , fd ) ;
if ( ! size ) {
TRACE ( " user asked for max-size map (size: 0), stating %d to find size... " , fd ) ;
struct stat st ;
// Find size of file
if ( fstat ( fd , & st ) ! = 0 ) return ( close ( fd ) , MAP_ERR_STAT ) ;
TRACE ( " fstat() reports size is %lu " , st . st_size ) ;
size = st . st_size ;
}
TRACE ( " passing fd %d, size %lu to `map_fd()` " , fd , size ) ;
return map_fd ( fd , write , size , offset , map ) ;
}
map_result_t map_anon ( void * ptr , usize len , map_t * pOUT map )
{
TRACE ( " mapping anon at %p (%s) of size %lu (map %p) " , ptr , ptr ? " fixed " : " dynamic " , len , map ) ;
ptr = mmap ( ptr , len , PROT_READ | PROT_WRITE , MAP_PRIVATE | MAP_ANONYMOUS | ( ptr ? MAP_FIXED : 0 ) , - 1 , 0 ) ;
if ( ptr = = MAP_FAILED ) return MAP_ERR_MMAP ;
TRACE ( " mapped ptr %p->%lu " , ptr , len ) ;
// Make sure .file.fd is -1, so we can tell this is anon in `map_free()`.
_map_init ( map ) ;
map - > anon = ( struct mm_anon ) {
@ -55,9 +75,30 @@ map_result_t map_anon(void* ptr, usize len, map_t *pOUT map)
map_result_t map_free ( map_t map )
{
TRACE ( " unmapping %p->%lu " , map . origin , map . len ) ;
if ( munmap ( map . anon . origin , map . anon . len ) ! = 0 ) return MAP_ERR_UNMAP ;
if ( _map_is_file ( & map ) ) {
TRACE ( " map is file, closing fd %d " , map . file . fd ) ;
if ( close ( map . file . fd ) ! = 0 ) return MAP_ERR_CLOSE ;
}
return MAP_SUCCESS ;
}
const char * map_error_str ( map_result_t res )
{
switch ( res )
{
# define CASE(err, str) case err: return str
CASE ( MAP_ERR_MMAP , " mmap() failed (creating a map) " ) ;
CASE ( MAP_ERR_UNMAP , " munmap() failed (freeing a map) " ) ;
CASE ( MAP_ERR_OPEN , " open() failed (mapping a filepath) " ) ;
CASE ( MAP_ERR_CLOSE , " close() failed (freeing a file-map) " ) ;
CASE ( MAP_ERR_STAT , " fstat() failed: (mapping a full filepath) " ) ;
CASE ( MAP_SUCCESS , " success " ) ;
# undef CASE
default :
ERROR ( " unkown or invalid error code %d " , ( int ) res ) ;
return " unknown error " ;
}
}