Created
June 29, 2015 20:56
-
-
Save smx-smx/222101ebfd4e813f3e79 to your computer and use it in GitHub Desktop.
A wrapper to open files via mmap
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
A mmap file wrapper | |
Copyright 2015 Smx | |
*/ | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <stdbool.h> | |
#include <string.h> | |
#include <sys/mman.h> | |
#include <sys/stat.h> | |
#include <fcntl.h> | |
#include <unistd.h> | |
#include <errno.h> | |
#include "mfile.h" | |
/* | |
* Creates a new mfile structure | |
*/ | |
MFILE *mfile_new(){ | |
MFILE *mem = calloc(1, sizeof(MFILE)); | |
return mem; | |
} | |
/* | |
* Updates size and path to a file | |
*/ | |
int _mfile_update_info(MFILE *file, const char *path){ | |
if(path){ | |
if(file->path) | |
free(file->path); | |
file->path = strdup(path); | |
} | |
if(stat(file->path, &(file->statBuf)) < 0) | |
return -1; | |
return 0; | |
} | |
/* | |
* Wrapper to mmap | |
*/ | |
void *mfile_map(MFILE *file, size_t size){ | |
size_t mapSize; | |
if(size == 0){ | |
mapSize = msize(file); | |
} else { | |
mapSize = size; | |
} | |
if(msize(file) < size){ | |
lseek(file->fd, size-1, SEEK_SET); | |
uint8_t buf = 0x00; | |
write(file->fd, &buf, 1); | |
lseek(file->fd, 0, SEEK_SET); | |
_mfile_update_info(file, NULL); | |
} | |
if(file->pMem){ | |
} | |
file->pMem = mmap(0, mapSize, file->prot, MAP_SHARED, file->fd, 0); | |
if(file->pMem == MAP_FAILED){ | |
//err_exit("mmap failed: %s\n", strerror(errno)); | |
return NULL; | |
} | |
return file->pMem; | |
} | |
/* | |
* Opens and maps a file with open | |
*/ | |
MFILE *mopen(const char *path, int oflags){ | |
MFILE *file = mfile_new(); | |
file->fd = open(path, oflags); | |
if(file->fd < 0){ | |
goto e0_ret; | |
} | |
if(_mfile_update_info(file, path) < 0) | |
goto e1_ret; | |
if((oflags & O_ACCMODE) == O_RDONLY) { | |
file->prot = PROT_READ; | |
} else if((oflags & O_ACCMODE) == O_WRONLY) { | |
file->prot = PROT_WRITE; | |
} else if((oflags & O_ACCMODE) == O_RDWR) { | |
file->prot = PROT_READ | PROT_WRITE; | |
} | |
if(msize(file) > 0){ | |
if(mfile_map(file, 0) == MAP_FAILED){ | |
goto e1_ret; | |
} | |
} | |
return file; | |
e1_ret: | |
close(file->fd); | |
e0_ret: | |
if(file->path) | |
free(file->path); | |
free(file); | |
return NULL; | |
} | |
/* | |
* Closes an opened file and frees the structure | |
*/ | |
int mclose(MFILE *mfile){ | |
if(!mfile || mfile->fd < 0 || !mfile->pMem || mfile->size <= 0) | |
return -1; | |
if(munmap(mfile->pMem, mfile->size) < 0) | |
return -2; | |
free(mfile->path); | |
close(mfile->fd); | |
free(mfile); | |
mfile = NULL; | |
return 0; | |
} | |
/* | |
* Opens and maps a file with fopen | |
*/ | |
MFILE *mfopen(const char *path, const char *mode){ | |
MFILE *file = mfile_new(); | |
file->fh = fopen(path, mode); | |
if(file->fh == NULL){ | |
goto e0_ret; | |
} | |
file->fd = fileno(file->fh); | |
if(_mfile_update_info(file, path) < 0) | |
goto e1_ret; | |
if(strstr(mode, "r") != NULL){ | |
file->prot |= PROT_READ; | |
} | |
if(strstr(mode, "w") != NULL){ | |
file->prot |= PROT_WRITE; | |
} | |
if(msize(file) > 0){ | |
if(mfile_map(file, 0) == MAP_FAILED){ | |
goto e1_ret; | |
} | |
} | |
return file; | |
e1_ret: | |
fclose(file->fh); | |
e0_ret: | |
free(file); | |
return NULL; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
A mmap file wrapper | |
Copyright 2015 Smx | |
*/ | |
#ifndef __MFILE_H | |
#define __MFILE_H | |
#include <fcntl.h> | |
#include <stdint.h> | |
#include <sys/stat.h> | |
#include <sys/mman.h> | |
/* Gets the size of the memory mapped file */ | |
#define msize(mfile) mfile->statBuf.st_size | |
/* Gets the data, casted to the type specified in the second argument */ | |
#define mdata(mfile, type) (type *)(mfile->pMem) | |
/* Gets the file handler (for mfopen) */ | |
#define mfh(mfile) mfile->fh | |
typedef struct { | |
int fd; | |
FILE *fh; | |
char *path; | |
size_t size; | |
int prot; | |
struct stat statBuf; | |
void *pMem; | |
} MFILE; | |
MFILE *mfile_new(); | |
void *mfile_map(MFILE *file, size_t size); | |
MFILE *mopen(const char *path, int oflags); | |
int mclose(MFILE *mfile); | |
MFILE *mfopen(const char *path, const char *mode); | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment