diff options
-rw-r--r-- | project/common.mk | 1 | ||||
-rw-r--r-- | project/headers.mk | 1 | ||||
-rw-r--r-- | src/internal/slibtool_mapfile_impl.c | 78 | ||||
-rw-r--r-- | src/internal/slibtool_mapfile_impl.h | 18 |
4 files changed, 98 insertions, 0 deletions
diff --git a/project/common.mk b/project/common.mk index 20a8112..9267415 100644 --- a/project/common.mk +++ b/project/common.mk @@ -22,6 +22,7 @@ INTERNAL_SRCS = \ src/internal/$(PACKAGE)_dprintf_impl.c \ src/internal/$(PACKAGE)_errinfo_impl.c \ src/internal/$(PACKAGE)_libmeta_impl.c \ + src/internal/$(PACKAGE)_mapfile_impl.c \ src/internal/$(PACKAGE)_objmeta_impl.c \ src/internal/$(PACKAGE)_symlink_impl.c \ diff --git a/project/headers.mk b/project/headers.mk index e238221..2581965 100644 --- a/project/headers.mk +++ b/project/headers.mk @@ -8,6 +8,7 @@ INTERNAL_HEADERS = \ $(PROJECT_DIR)/src/internal/$(PACKAGE)_driver_impl.h \ $(PROJECT_DIR)/src/internal/$(PACKAGE)_errinfo_impl.h \ $(PROJECT_DIR)/src/internal/$(PACKAGE)_install_impl.h \ + $(PROJECT_DIR)/src/internal/$(PACKAGE)_mapfile_impl.h \ $(PROJECT_DIR)/src/internal/$(PACKAGE)_metafile_impl.h \ $(PROJECT_DIR)/src/internal/$(PACKAGE)_mkdir_impl.h \ $(PROJECT_DIR)/src/internal/$(PACKAGE)_readlink_impl.h \ 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); +} diff --git a/src/internal/slibtool_mapfile_impl.h b/src/internal/slibtool_mapfile_impl.h new file mode 100644 index 0000000..567fc8f --- /dev/null +++ b/src/internal/slibtool_mapfile_impl.h @@ -0,0 +1,18 @@ +#ifndef SLIBTOOL_MAPFILE_IMPL_H +#define SLIBTOOL_MAPFILE_IMPL_H + +#define SLBT_MAP_INPUT 0x0001 +#define SLBT_MAP_OUTPUT 0x0002 + +struct slbt_map_info { + void * addr; + size_t size; +}; + +struct slbt_map_info * slbt_map_file( + int, const char *, + uint32_t); + +void slbt_unmap_file(struct slbt_map_info *); + +#endif |