summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--project/common.mk1
-rw-r--r--project/headers.mk1
-rw-r--r--src/internal/slibtool_mapfile_impl.c78
-rw-r--r--src/internal/slibtool_mapfile_impl.h18
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