-/* $Cambridge: exim/src/src/lookups/cdb.c,v 1.2 2005/06/07 15:20:56 ph10 Exp $ */
-
/*************************************************
* Exim - an Internet mail transport agent *
*************************************************/
* Changed over to using unsigned chars
* Makes use of lf_check_file() for file checking
* --------------------------------------------------------------
+ * Modified by The Exim Maintainers 2015:
+ * const propagation
+ * --------------------------------------------------------------
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* cdb.[ch] it does *not* link against an external cdb library.
*
*
- * There are 2 varients included within this code. One uses MMAP and
+ * There are 2 variants included within this code. One uses MMAP and
* should give better performance especially for multiple lookups on a
* modern machine. The other is the default implementation which is
* used in the case where the MMAP fails or if MMAP was not compiled
#include "../exim.h"
#include "lf_functions.h"
-#include "cdb.h"
#ifdef HAVE_MMAP
# include <sys/mman.h>
* Internal function to make hash value */
static uint32
-cdb_hash(uschar *buf, unsigned int len)
+cdb_hash(const uschar *buf, unsigned int len)
{
uint32 h;
/*
* cdb_bread()
- * Internal function to parse 4 byte number (endian independant) */
+ * Internal function to parse 4 byte number (endian independent) */
static uint32
cdb_unpack(uschar *buf)
return num;
}
-void *
+static void cdb_close(void *handle);
+
+static void *
cdb_open(uschar *filename,
uschar **errmsg)
{
}
/* Having got a file open we need the structure to put things in */
- cdbp = store_get(sizeof(struct cdb_state));
+ cdbp = store_get(sizeof(struct cdb_state), FALSE);
/* store_get() does not return if memory was not available... */
/* preload the structure.... */
cdbp->fileno = fileno;
/* Now return the state struct */
return(cdbp);
- } else {
+ } else
/* If we got here the map failed. Basically we can ignore
* this since we fall back to slower methods....
* However lets debug log it...
*/
- DEBUG(D_lookup) debug_printf("cdb mmap failed - %d\n", errno);
- }
+ DEBUG(D_lookup) debug_printf_indent("cdb mmap failed - %d\n", errno);
#endif /* HAVE_MMAP */
/* In this case we have either not got MMAP allowed, or it failed */
/* get a buffer to stash the basic offsets in - this should speed
* things up a lot - especially on multiple lookups */
- cdbp->cdb_offsets = store_get(CDB_HASH_TABLE);
+ cdbp->cdb_offsets = store_get(CDB_HASH_TABLE, FALSE);
/* now fill the buffer up... */
if (cdb_bread(fileno, cdbp->cdb_offsets, CDB_HASH_TABLE) == -1) {
* Check entry point *
*************************************************/
-BOOL
+static BOOL
cdb_check(void *handle,
uschar *filename,
int modemask,
* Find entry point *
*************************************************/
-int
+static int
cdb_find(void *handle,
uschar *filename,
- uschar *keystring,
+ const uschar *keystring,
int key_len,
uschar **result,
uschar **errmsg,
- BOOL *do_cache)
+ uint *do_cache)
{
- struct cdb_state * cdbp = handle;
- uint32 item_key_len,
- item_dat_len,
- key_hash,
- item_hash,
- item_posn,
- cur_offset,
- end_offset,
- hash_offset_entry,
- hash_offset,
- hash_offlen,
- hash_slotnm;
- int loop;
-
- /* Keep picky compilers happy */
- do_cache = do_cache;
-
- key_hash = cdb_hash((uschar *)keystring, key_len);
-
- hash_offset_entry = CDB_HASH_ENTRY * (key_hash & CDB_HASH_MASK);
- hash_offset = cdb_unpack(cdbp->cdb_offsets + hash_offset_entry);
- hash_offlen = cdb_unpack(cdbp->cdb_offsets + hash_offset_entry + 4);
-
- /* If the offset length is zero this key cannot be in the file */
- if (hash_offlen == 0) {
- return FAIL;
- }
- hash_slotnm = (key_hash >> 8) % hash_offlen;
-
- /* check to ensure that the file is not corrupt
- * if the hash_offset + (hash_offlen * CDB_HASH_ENTRY) is longer
- * than the file, then we have problems.... */
- if ((hash_offset + (hash_offlen * CDB_HASH_ENTRY)) > cdbp->filelen) {
- *errmsg = string_sprintf("cdb: corrupt cdb file %s (too short)",
- filename);
- DEBUG(D_lookup) debug_printf("%s\n", *errmsg);
- return DEFER;
+struct cdb_state * cdbp = handle;
+uint32 item_key_len,
+item_dat_len,
+key_hash,
+item_hash,
+item_posn,
+cur_offset,
+end_offset,
+hash_offset_entry,
+hash_offset,
+hash_offlen,
+hash_slotnm;
+
+/* Keep picky compilers happy */
+do_cache = do_cache;
+
+key_hash = cdb_hash(keystring, key_len);
+
+hash_offset_entry = CDB_HASH_ENTRY * (key_hash & CDB_HASH_MASK);
+hash_offset = cdb_unpack(cdbp->cdb_offsets + hash_offset_entry);
+hash_offlen = cdb_unpack(cdbp->cdb_offsets + hash_offset_entry + 4);
+
+/* If the offset length is zero this key cannot be in the file */
+
+if (hash_offlen == 0)
+ return FAIL;
+
+hash_slotnm = (key_hash >> 8) % hash_offlen;
+
+/* check to ensure that the file is not corrupt
+ * if the hash_offset + (hash_offlen * CDB_HASH_ENTRY) is longer
+ * than the file, then we have problems.... */
+
+if ((hash_offset + (hash_offlen * CDB_HASH_ENTRY)) > cdbp->filelen)
+ {
+ *errmsg = string_sprintf("cdb: corrupt cdb file %s (too short)",
+ filename);
+ DEBUG(D_lookup) debug_printf_indent("%s\n", *errmsg);
+ return DEFER;
}
- cur_offset = hash_offset + (hash_slotnm * CDB_HASH_ENTRY);
- end_offset = hash_offset + (hash_offlen * CDB_HASH_ENTRY);
- /* if we are allowed to we use mmap here.... */
+cur_offset = hash_offset + (hash_slotnm * CDB_HASH_ENTRY);
+end_offset = hash_offset + (hash_offlen * CDB_HASH_ENTRY);
+
+/* if we are allowed to we use mmap here.... */
+
#ifdef HAVE_MMAP
- /* make sure the mmap was OK */
- if (cdbp->cdb_map != NULL) {
- uschar * cur_pos = cur_offset + cdbp->cdb_map;
- uschar * end_pos = end_offset + cdbp->cdb_map;
- for (loop = 0; (loop < hash_offlen); ++loop) {
- item_hash = cdb_unpack(cur_pos);
- cur_pos += 4;
- item_posn = cdb_unpack(cur_pos);
- cur_pos += 4;
- /* if the position is zero then we have a definite miss */
- if (item_posn == 0)
- return FAIL;
-
- if (item_hash == key_hash) {
- /* matching hash value */
- uschar * item_ptr = cdbp->cdb_map + item_posn;
- item_key_len = cdb_unpack(item_ptr);
- item_ptr += 4;
- item_dat_len = cdb_unpack(item_ptr);
- item_ptr += 4;
- /* check key length matches */
- if (item_key_len == key_len) {
- /* finally check if key matches */
- if (Ustrncmp(keystring, item_ptr, key_len) == 0) {
- /* we have a match....
- * make item_ptr point to data */
- item_ptr += item_key_len;
- /* ... and the returned result */
- *result = store_get(item_dat_len + 1);
- memcpy(*result, item_ptr, item_dat_len);
- (*result)[item_dat_len] = 0;
- return OK;
- }
- }
- }
- /* handle warp round of table */
- if (cur_pos == end_pos)
- cur_pos = cdbp->cdb_map + hash_offset;
- }
- /* looks like we failed... */
- return FAIL;
- }
-#endif /* HAVE_MMAP */
- for (loop = 0; (loop < hash_offlen); ++loop) {
- uschar packbuf[8];
- if (lseek(cdbp->fileno, (off_t) cur_offset,SEEK_SET) == -1) return DEFER;
- if (cdb_bread(cdbp->fileno, packbuf,8) == -1) return DEFER;
- item_hash = cdb_unpack(packbuf);
- item_posn = cdb_unpack(packbuf + 4);
+/* make sure the mmap was OK */
+if (cdbp->cdb_map != NULL)
+ {
+ uschar * cur_pos = cur_offset + cdbp->cdb_map;
+ uschar * end_pos = end_offset + cdbp->cdb_map;
+
+ for (int loop = 0; (loop < hash_offlen); ++loop)
+ {
+ item_hash = cdb_unpack(cur_pos);
+ cur_pos += 4;
+ item_posn = cdb_unpack(cur_pos);
+ cur_pos += 4;
+
/* if the position is zero then we have a definite miss */
+
if (item_posn == 0)
return FAIL;
- if (item_hash == key_hash) {
- /* matching hash value */
- if (lseek(cdbp->fileno, (off_t) item_posn, SEEK_SET) == -1) return DEFER;
- if (cdb_bread(cdbp->fileno, packbuf, 8) == -1) return DEFER;
- item_key_len = cdb_unpack(packbuf);
+ if (item_hash == key_hash)
+ { /* matching hash value */
+ uschar * item_ptr = cdbp->cdb_map + item_posn;
+
+ item_key_len = cdb_unpack(item_ptr);
+ item_ptr += 4;
+ item_dat_len = cdb_unpack(item_ptr);
+ item_ptr += 4;
+
/* check key length matches */
- if (item_key_len == key_len) {
- /* finally check if key matches */
- uschar * item_key = store_get(key_len);
- if (cdb_bread(cdbp->fileno, item_key, key_len) == -1) return DEFER;
- if (Ustrncmp(keystring, item_key, key_len) == 0) {
- /* Reclaim some store */
- store_reset(item_key);
- /* matches - get data length */
- item_dat_len = cdb_unpack(packbuf + 4);
- /* then we build a new result string */
- *result = store_get(item_dat_len + 1);
- if (cdb_bread(cdbp->fileno, *result, item_dat_len) == -1)
- return DEFER;
- (*result)[item_dat_len] = 0;
- return OK;
- }
- /* Reclaim some store */
- store_reset(item_key);
+
+ if (item_key_len == key_len)
+ {
+ /* finally check if key matches */
+ if (Ustrncmp(keystring, item_ptr, key_len) == 0)
+ {
+ /* we have a match.... * make item_ptr point to data */
+
+ item_ptr += item_key_len;
+
+ /* ... and the returned result. Assume it is not
+ tainted, lacking any way of telling. */
+
+ *result = store_get(item_dat_len + 1, FALSE);
+ memcpy(*result, item_ptr, item_dat_len);
+ (*result)[item_dat_len] = 0;
+ return OK;
+ }
+ }
}
+ /* handle warp round of table */
+ if (cur_pos == end_pos)
+ cur_pos = cdbp->cdb_map + hash_offset;
}
- cur_offset += 8;
+ /* looks like we failed... */
+ return FAIL;
+ }
- /* handle warp round of table */
- if (cur_offset == end_offset)
- cur_offset = hash_offset;
+#endif /* HAVE_MMAP */
+
+for (int loop = 0; (loop < hash_offlen); ++loop)
+ {
+ uschar packbuf[8];
+
+ if (lseek(cdbp->fileno, (off_t) cur_offset, SEEK_SET) == -1) return DEFER;
+ if (cdb_bread(cdbp->fileno, packbuf, 8) == -1) return DEFER;
+
+ item_hash = cdb_unpack(packbuf);
+ item_posn = cdb_unpack(packbuf + 4);
+
+ /* if the position is zero then we have a definite miss */
+
+ if (item_posn == 0)
+ return FAIL;
+
+ if (item_hash == key_hash)
+ { /* matching hash value */
+ if (lseek(cdbp->fileno, (off_t) item_posn, SEEK_SET) == -1) return DEFER;
+ if (cdb_bread(cdbp->fileno, packbuf, 8) == -1) return DEFER;
+
+ item_key_len = cdb_unpack(packbuf);
+
+ /* check key length matches */
+
+ if (item_key_len == key_len)
+ { /* finally check if key matches */
+ rmark reset_point = store_mark();
+ uschar * item_key = store_get(key_len, TRUE); /* keys liable to be tainted */
+
+ if (cdb_bread(cdbp->fileno, item_key, key_len) == -1) return DEFER;
+ if (Ustrncmp(keystring, item_key, key_len) == 0)
+ {
+ /* Reclaim some store */
+ store_reset(reset_point);
+
+ /* matches - get data length */
+ item_dat_len = cdb_unpack(packbuf + 4);
+
+ /* then we build a new result string. We know we have enough
+ memory so disable Coverity errors about the tainted item_dat_ken */
+
+ *result = store_get(item_dat_len + 1, FALSE);
+ /* coverity[tainted_data] */
+ if (cdb_bread(cdbp->fileno, *result, item_dat_len) == -1)
+ return DEFER;
+
+ /* coverity[tainted_data] */
+ (*result)[item_dat_len] = 0;
+ return OK;
+ }
+ /* Reclaim some store */
+ store_reset(reset_point);
+ }
+ }
+ cur_offset += 8;
+
+ /* handle warp round of table */
+ if (cur_offset == end_offset)
+ cur_offset = hash_offset;
}
- return FAIL;
+return FAIL;
}
/* See local README for interface description */
-void
+static void
cdb_close(void *handle)
{
struct cdb_state * cdbp = handle;
#ifdef HAVE_MMAP
- if (cdbp->cdb_map) {
- munmap(CS cdbp->cdb_map, cdbp->filelen);
- if (cdbp->cdb_map == cdbp->cdb_offsets)
+if (cdbp->cdb_map)
+ {
+ munmap(CS cdbp->cdb_map, cdbp->filelen);
+ if (cdbp->cdb_map == cdbp->cdb_offsets)
cdbp->cdb_offsets = NULL;
- }
+ }
#endif /* HAVE_MMAP */
- close(cdbp->fileno);
+(void)close(cdbp->fileno);
+}
+
+
+
+/*************************************************
+* Version reporting entry point *
+*************************************************/
+
+/* See local README for interface description. */
+
+#include "../version.h"
+
+void
+cdb_version_report(FILE *f)
+{
+#ifdef DYNLOOKUP
+fprintf(f, "Library version: CDB: Exim version %s\n", EXIM_VERSION_STR);
+#endif
}
+
+lookup_info cdb_lookup_info = {
+ US"cdb", /* lookup name */
+ lookup_absfile, /* uses absolute file name */
+ cdb_open, /* open function */
+ cdb_check, /* check function */
+ cdb_find, /* find function */
+ cdb_close, /* close function */
+ NULL, /* no tidy function */
+ NULL, /* no quoting function */
+ cdb_version_report /* version reporting */
+};
+
+#ifdef DYNLOOKUP
+#define cdb_lookup_module_info _lookup_module_info
+#endif
+
+static lookup_info *_lookup_list[] = { &cdb_lookup_info };
+lookup_module_info cdb_lookup_module_info = { LOOKUP_MODULE_INFO_MAGIC, _lookup_list, 1 };
+
/* End of lookups/cdb.c */