From: Florent Bruneau Date: Fri, 12 Sep 2008 14:12:19 +0000 (+0200) Subject: Factorize code to map a file into memory. X-Git-Url: http://git.madism.org/?p=apps%2Fpfixtools.git;a=commitdiff_plain;h=193694fdba386a89b4b2a83ce803764302995e89 Factorize code to map a file into memory. Signed-off-by: Florent Bruneau --- diff --git a/common/Makefile b/common/Makefile index 0f09ebf..3720069 100644 --- a/common/Makefile +++ b/common/Makefile @@ -32,7 +32,7 @@ LIBS = lib TESTS = tst-trie -lib_SOURCES = str.c buffer.c common.c epoll.c server.c trie.c +lib_SOURCES = str.c buffer.c common.c epoll.c server.c trie.c file.c tst-trie_SOURCES = tst-trie.c lib.a include ../mk/common.mk diff --git a/common/file.c b/common/file.c new file mode 100644 index 0000000..dd6fc91 --- /dev/null +++ b/common/file.c @@ -0,0 +1,102 @@ +/******************************************************************************/ +/* pfixtools: a collection of postfix related tools */ +/* ~~~~~~~~~ */ +/* ________________________________________________________________________ */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions */ +/* are met: */ +/* */ +/* 1. Redistributions of source code must retain the above copyright */ +/* notice, this list of conditions and the following disclaimer. */ +/* 2. Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* 3. The names of its contributors may not be used to endorse or promote */ +/* products derived from this software without specific prior written */ +/* permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND */ +/* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE */ +/* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR */ +/* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS */ +/* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR */ +/* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF */ +/* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS */ +/* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN */ +/* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) */ +/* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF */ +/* THE POSSIBILITY OF SUCH DAMAGE. */ +/******************************************************************************/ + +/* + * Copyright © 2008 Florent Bruneau + */ + +#include +#include + +#include "file.h" + +file_map_t *file_map_new(const char *file, bool memlock) +{ + file_map_t *map = p_new(file_map_t, 1); + if (!file_map_open(map, file, memlock)) { + p_delete(&map); + return NULL; + } + return map; +} + +void file_map_delete(file_map_t **map) +{ + if (*map) { + file_map_close(*map); + p_delete(map); + } +} + +bool file_map_open(file_map_t *map, const char *file, bool memlock) +{ + struct stat st; + int fd; + + fd = open(file, O_RDONLY, 0000); + if (fd < 0) { + UNIXERR("open"); + return false; + } + + if (fstat(fd, &st) < 0) { + UNIXERR("fstat"); + close(fd); + return false; + } + + map->map = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + if (map->map == MAP_FAILED) { + UNIXERR("mmap"); + close(fd); + map->map = NULL; + return false; + } + close(fd); + + map->end = map->map + st.st_size; + map->locked = memlock && mlock(map->map, st.st_size) == 0; + return true; +} + +void file_map_close(file_map_t *map) +{ + if (!map->map) { + return; + } + if (map->locked) { + munlock(map->map, map->end - map->map); + } + munmap((void*)map->map, map->end - map->map); + map->map = NULL; + map->end = NULL; + map->locked = false; +} diff --git a/common/file.h b/common/file.h new file mode 100644 index 0000000..ead058c --- /dev/null +++ b/common/file.h @@ -0,0 +1,62 @@ +/******************************************************************************/ +/* pfixtools: a collection of postfix related tools */ +/* ~~~~~~~~~ */ +/* ________________________________________________________________________ */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions */ +/* are met: */ +/* */ +/* 1. Redistributions of source code must retain the above copyright */ +/* notice, this list of conditions and the following disclaimer. */ +/* 2. Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* 3. The names of its contributors may not be used to endorse or promote */ +/* products derived from this software without specific prior written */ +/* permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND */ +/* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE */ +/* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR */ +/* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS */ +/* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR */ +/* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF */ +/* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS */ +/* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN */ +/* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) */ +/* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF */ +/* THE POSSIBILITY OF SUCH DAMAGE. */ +/******************************************************************************/ + +/* + * Copyright © 2008 Florent Bruneau + */ + +#ifndef PFIXTOOLS_FILE_H +#define PFIXTOOLS_FILE_H + +#include "common.h" + +/* Read-only mapping of a file into memory. + */ + +typedef struct file_map_t { + const char *map; + const char *end; + + bool locked; +} file_map_t; + +__attribute__((nonnull(1))) +file_map_t *file_map_new(const char *file, bool memlock); + +void file_map_delete(file_map_t **map); + +__attribute__((nonnull(1,2))) +bool file_map_open(file_map_t *map, const char *file, bool memlock); + +__attribute__((nonnull(1))) +void file_map_close(file_map_t *map); + +#endif diff --git a/common/tst-trie.c b/common/tst-trie.c index 25f31c5..990b151 100644 --- a/common/tst-trie.c +++ b/common/tst-trie.c @@ -33,49 +33,27 @@ * Copyright © 2008 Florent Bruneau */ -#include -#include -#include -#include -#include - #include "common.h" #include "str.h" #include "trie.h" +#include "file.h" static trie_t *create_trie_from_file(const char *file) { trie_t *db; - const char *map, *p, *end; - struct stat st; - int fd; + file_map_t map; + const char *p, *end; char line[BUFSIZ]; - fd = open(file, O_RDONLY, 0000); - if (fd < 0) { - UNIXERR("open"); - return NULL; - } - - if (fstat(fd, &st) < 0) { - UNIXERR("fstat"); - close(fd); + if (!file_map_open(&map, file, false)) { return NULL; } - - p = map = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); - if (map == MAP_FAILED) { - UNIXERR("mmap"); - close(fd); - return NULL; - } - close(fd); - - end = map + st.st_size; - while (end > map && end[-1] != '\n') { + p = map.map; + end = map.end; + while (end > p && end[-1] != '\n') { --end; } - if (end != map + st.st_size) { + if (end != map.end) { syslog(LOG_WARNING, "file %s miss a final \\n, ignoring last line", file); } @@ -102,7 +80,7 @@ static trie_t *create_trie_from_file(const char *file) trie_insert(db, line); p = eol + 1; } - munmap((void*)map, st.st_size); + file_map_close(&map); trie_compile(db, false); return db; } diff --git a/postlicyd/rbl.c b/postlicyd/rbl.c index cf1d734..bb0dda0 100644 --- a/postlicyd/rbl.c +++ b/postlicyd/rbl.c @@ -35,14 +35,13 @@ */ #include -#include #include #include -#include #include "common.h" #include "rbl.h" #include "str.h" +#include "file.h" #define IPv4_BITS 5 #define IPv4_PREFIX(ip) ((uint32_t)(ip) >> IPv4_BITS) @@ -119,35 +118,19 @@ static int parse_ipv4(const char *s, const char **out, uint32_t *ip) rbldb_t *rbldb_create(const char *file, bool lock) { rbldb_t *db; - const char *map, *p, *end; - struct stat st; - int fd; + file_map_t map; + const char *p, *end; - fd = open(file, O_RDONLY, 0000); - if (fd < 0) { - UNIXERR("open"); + if (!file_map_open(&map, file, false)) { return NULL; } - if (fstat(fd, &st) < 0) { - UNIXERR("fstat"); - close(fd); - return NULL; - } - - p = map = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); - if (map == MAP_FAILED) { - UNIXERR("mmap"); - close(fd); - return NULL; - } - close(fd); - - end = map + st.st_size; - while (end > map && end[-1] != '\n') { + p = map.map; + end = map.end; + while (end > p && end[-1] != '\n') { --end; } - if (end != map + st.st_size) { + if (end != map.end) { syslog(LOG_WARNING, "file %s miss a final \\n, ignoring last line", file); } @@ -169,7 +152,7 @@ rbldb_t *rbldb_create(const char *file, bool lock) db->ips[db->len++] = ip; } } - munmap((void*)map, st.st_size); + file_map_close(&map); /* Lookup may perform serveral I/O, so avoid swap. */