diff options
author | midipix <writeonce@midipix.org> | 2018-06-27 20:12:56 -0400 |
---|---|---|
committer | midipix <writeonce@midipix.org> | 2018-06-29 01:37:41 -0400 |
commit | 0f9f9744d71f902054aa844bd2f136d8307a13dc (patch) | |
tree | ad7adcf27f939c8f38a78d1fcea5ba5fddbbf997 /src/internal/slibtool_mapfile_impl.c | |
parent | 089c8bfc743edc44058a665bbe695809c26c682c (diff) | |
download | slibtool-0f9f9744d71f902054aa844bd2f136d8307a13dc.tar.bz2 slibtool-0f9f9744d71f902054aa844bd2f136d8307a13dc.tar.xz |
internals: added slbt_map_file(), slbt_unmap_file().
Diffstat (limited to 'src/internal/slibtool_mapfile_impl.c')
-rw-r--r-- | src/internal/slibtool_mapfile_impl.c | 78 |
1 files changed, 78 insertions, 0 deletions
diff --git a/src/internal/slibtool_mapfile_impl.c b/src/internal/slibtool_mapfile_impl.c new file mode 100644 index 0000000..e5d40d1 --- /dev/null +++ b/src/internal/slibtool_mapfile_impl.c @@ -0,0 +1,78 @@ +#include <fcntl.h> +#include <errno.h> +#include <unistd.h> +#include <stdint.h> +#include <stdlib.h> +#include <sys/mman.h> +#include <sys/stat.h> +#include "slibtool_mapfile_impl.h" + +static void slbt_munmap(void * addr, size_t size) +{ + if (addr) { + munmap(addr,size); + } +} + +struct slbt_map_info * slbt_map_file( + int fdat, + const char * path, + uint32_t flags) +{ + int fd; + void * addr; + struct stat st; + uint32_t oflag; + uint32_t mprot; + struct slbt_map_info * mapinfo; + + if ((flags & SLBT_MAP_INPUT) && (flags & SLBT_MAP_OUTPUT)) { + oflag = O_RDWR; + mprot = PROT_READ|PROT_WRITE; + } else if (flags & SLBT_MAP_INPUT) { + oflag = O_RDONLY; + mprot = PROT_READ; + } else if (flags & SLBT_MAP_OUTPUT) { + oflag = O_WRONLY; + mprot = PROT_WRITE; + } else { + errno = EINVAL; + return 0; + } + + if ((fd = openat(fdat,path,oflag,0)) < 0) + return 0; + + if (fstat(fd,&st) < 0) { + close(fd); + return 0; + } + + addr = st.st_size + ? mmap(0,st.st_size,mprot,MAP_SHARED,fd,0) + : 0; + + if (addr == MAP_FAILED) { + close(fd); + return 0; + } + + if (!(mapinfo = malloc(sizeof(*mapinfo)))) { + close(fd); + slbt_munmap(addr,st.st_size); + return 0; + } + + close(fd); + + mapinfo->addr = addr; + mapinfo->size = st.st_size; + + return mapinfo; +} + +void slbt_unmap_file(struct slbt_map_info * mapinfo) +{ + slbt_munmap(mapinfo->addr,mapinfo->size); + free(mapinfo); +} |