API:
exim_lockfile_needed facilities predicate
+ dbfn_open_path full pathname; no lock taken, readonly
dbfn_open takes lockfile or opens transaction
dbfn_open_multi only if transactions supported;
no lock or transaction taken
dbfn_close_multi
dbfn_transaction_start only if transactions supported
dbfn_transaction_commit
+ dbfn_read_klen explicit key length; embedded NUL ok
dbfn_read_with_length
dbfn_read_enforce_length
dbfn_write
TLS session resumption
peer capability cache
callout & quota cache
+ DBM lookup type
*/
* Open and lock a database file *
*************************************************/
+/* Used by DBM lookups:
+full pathname for DB file rather than hintsdb name, readonly, no locking. */
+
+open_db *
+dbfn_open_path(const uschar * path, open_db * dbblock)
+{
+uschar * dirname = string_copy(path);
+
+dbblock->readonly = TRUE;
+dbblock->lockfd = -1;
+dbblock->dbptr = !exim_lockfile_needed()
+ ? exim_dbopen_multi(path, dirname, O_RDONLY, 0)
+ : exim_dbopen(path, dirname, O_RDONLY, 0);
+return dbblock->dbptr ? dbblock : NULL;;
+}
+
/* Ensure the directory for the DB is present */
static inline void
Arguments:
dbblock a pointer to an open database block
key the key of the record to be read
+ klen length of key including a terminating NUL (if present)
length a pointer to an int into which to return the length, if not NULL
Returns: a pointer to the retrieved record, or
*/
void *
-dbfn_read_with_length(open_db * dbblock, const uschar * key, int * length)
+dbfn_read_klen(open_db * dbblock, const uschar * key, int klen, int * length)
{
void * yield;
EXIM_DATUM key_datum, result_datum;
-int klen = Ustrlen(key) + 1;
uschar * key_copy = store_get(klen, key);
unsigned dlen;
memcpy(key_copy, key, klen);
-DEBUG(D_hints_lookup) debug_printf_indent("dbfn_read: key=%s\n", key);
+DEBUG(D_hints_lookup) debug_printf_indent("dbfn_read: key=%.*s\n", klen, key);
exim_datum_init(&key_datum); /* Some DBM libraries require the datum */
exim_datum_init(&result_datum); /* to be cleared before use. */
}
+/*
+Arguments:
+ dbblock a pointer to an open database block
+ key the key of the record to be read (NUL-terminated)
+ lenp a pointer to an int into which to return the data length,
+ if not NULL
+
+Returns: a pointer to the retrieved record, or
+ NULL if the record is not found
+*/
+
+void *
+dbfn_read_with_length(open_db * dbblock, const uschar * key, int * lenp)
+{
+return dbfn_read_klen(dbblock, key, Ustrlen(key)+1, lenp);
+}
+
+
+
/* Read a record. If the length is not as expected then delete it, write
an error log line, delete the record and return NULL.
Use this for fixed-size records (so not retry or wait records).
return NULL;
}
-
/*************************************************
* Write to database file *
*************************************************/
void dbfn_close_multi(open_db *);
int dbfn_delete(open_db *, const uschar *);
open_db *dbfn_open(const uschar *, int, open_db *, BOOL, BOOL);
+open_db * dbfn_open_path(const uschar *, open_db *);
open_db *dbfn_open_multi(const uschar *, int, open_db *);
+void *dbfn_read_klen(open_db *, const uschar *, int, int *);
void *dbfn_read_with_length(open_db *, const uschar *, int *);
void *dbfn_read_enforce_length(open_db *, const uschar *, size_t);
uschar *dbfn_scan(open_db *, BOOL, EXIM_CURSOR **);
libraries can be used by Exim. Nigel Metheringham provided the original set for
Berkeley DB 1.x in native mode and ndbm. Subsequently, versions for Berkeley DB
2.x and 3.x were added. Later still, support for tdb was added, courtesy of
-James Antill. Most recently, support for native mode gdbm was added, with code
+James Antill. More recently, support for native mode gdbm was added, with code
from Pierre A. Humblet, so Exim could be made to work with Cygwin.
+Most recently, sqlite3 was added.
For convenience, the definitions of the structures used in the various hints
databases are also kept in this file, which is used by the maintenance
The users of this API are:
hintsdb interface dbfn.c
hintsdb utilities exim_dbutil.c and exim_dbmvuild.c
- dbmdb lookup lookups/dbmdb,c
autoreply transport transports/autoreply.c
-Note that the dbmdb lookup use, bypassing the dbfn.c layer,
-means that no file-locking is done.
-XXX This feels like a layering violation; I don't see it commented on
-anywhere.
-
Future: consider re-architecting to support caching of the open-handle
for hintsdb uses (the dbmdb use gets that already). This would need APIs
for transaction locks. Perhaps merge the implementation with the lookups
/* See the file NOTICE for conditions of use and distribution. */
/* SPDX-License-Identifier: GPL-2.0-or-later */
+/* The "dbm" lookup uses whichever provider that is
+compiled in for supporting hintsdbs. */
+
#include "../exim.h"
#include "lf_functions.h"
static void *
dbmdb_open(const uschar * filename, uschar ** errmsg)
{
-uschar * dirname = string_copy(filename);
-uschar * s;
-EXIM_DB * yield = NULL;
+open_db * yield = store_get(sizeof(open_db), GET_UNTAINTED);
-if ((s = Ustrrchr(dirname, '/'))) *s = '\0';
-if (!(yield = exim_dbopen(filename, dirname, O_RDONLY, 0)))
+if (!(yield = dbfn_open_path(filename, yield)))
*errmsg = string_open_failed("%s as a %s file", filename, EXIM_DBTYPE);
return yield;
}
int length, uschar ** result, uschar ** errmsg, uint * do_cache,
const uschar * opts)
{
-EXIM_DB *d = (EXIM_DB *)handle;
-EXIM_DATUM key, data;
-
-exim_datum_init(&key); /* Some DBM libraries require datums to */
-exim_datum_init(&data); /* be cleared before use. */
-length++;
-exim_datum_data_set(&key,
- memcpy(store_get(length, keystring), keystring, length)); /* key can have embedded NUL */
-exim_datum_size_set(&key, length);
-
-if (exim_dbget(d, &key, &data))
- {
- unsigned len = exim_datum_size_get(&data);
- *result = len > 0 ? string_copyn(exim_datum_data_get(&data), len) : US"";
- exim_datum_free(&data); /* Some DBM libraries need a free() call */
- return OK;
- }
-return FAIL;
+open_db * d = (open_db *)handle;
+return (*result = dbfn_read_klen(d, keystring, length+1, NULL)) ? OK : FAIL;
}
void
static dbmdb_close(void *handle)
{
-exim_dbclose((EXIM_DB *)handle);
+dbfn_close((open_db *)handle);
}