aboutsummaryrefslogtreecommitdiffstats
path: root/src/libstrongswan/utils/chunk.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstrongswan/utils/chunk.c')
-rw-r--r--src/libstrongswan/utils/chunk.c80
1 files changed, 80 insertions, 0 deletions
diff --git a/src/libstrongswan/utils/chunk.c b/src/libstrongswan/utils/chunk.c
index 644b8060f..5c00c5b32 100644
--- a/src/libstrongswan/utils/chunk.c
+++ b/src/libstrongswan/utils/chunk.c
@@ -18,6 +18,7 @@
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
+#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
@@ -275,6 +276,85 @@ chunk_t chunk_from_fd(int fd)
return chunk_clone(chunk_create(buf, total));
}
+/**
+ * Implementation for mmap()ed chunks
+ */
+typedef struct {
+ /* public chunk interface */
+ chunk_t public;
+ /* FD of open file */
+ int fd;
+ /* mmap() address */
+ void *map;
+ /* size of map */
+ size_t len;
+} mmaped_chunk_t;
+
+/**
+ * See header.
+ */
+chunk_t *chunk_map(char *path, bool wr)
+{
+ mmaped_chunk_t *chunk;
+ struct stat sb;
+ int tmp;
+
+ INIT(chunk,
+ .fd = open(path, wr ? O_RDWR : O_RDONLY),
+ );
+
+ if (chunk->fd == -1)
+ {
+ free(chunk);
+ return NULL;
+ }
+ if (fstat(chunk->fd, &sb) == -1)
+ {
+ tmp = errno;
+ chunk_unmap(&chunk->public);
+ errno = tmp;
+ return NULL;
+ }
+ chunk->len = sb.st_size;
+ /* map non-empty files only, as mmap() complains otherwise */
+ if (chunk->len)
+ {
+ /* in read-only mode, we allow writes, but don't sync to disk */
+ chunk->map = mmap(NULL, chunk->len, PROT_READ | PROT_WRITE,
+ wr ? MAP_SHARED : MAP_PRIVATE, chunk->fd, 0);
+ if (chunk->map == MAP_FAILED)
+ {
+ tmp = errno;
+ chunk_unmap(&chunk->public);
+ errno = tmp;
+ return NULL;
+ }
+ }
+ chunk->public = chunk_create(chunk->map, chunk->len);
+ return &chunk->public;
+}
+
+/**
+ * See header.
+ */
+bool chunk_unmap(chunk_t *public)
+{
+ mmaped_chunk_t *chunk;
+ bool ret = FALSE;
+ int tmp = 0;
+
+ chunk = (mmaped_chunk_t*)public;
+ if (chunk->map && chunk->map != MAP_FAILED)
+ {
+ ret = munmap(chunk->map, chunk->len) == 0;
+ tmp = errno;
+ }
+ close(chunk->fd);
+ free(chunk);
+ errno = tmp;
+
+ return ret;
+}
/** hex conversion digits */
static char hexdig_upper[] = "0123456789ABCDEF";