Gitweb:
https://git.exim.org/exim.git/commitdiff/c66a6edf7ba81ab9615cf3e31af1eb8cc48066eb
Commit: c66a6edf7ba81ab9615cf3e31af1eb8cc48066eb
Parent: bfba2a3018912e44d89b52e6649fc11f37a42ecb
Author: Jeremy Harris <jgh146exb@???>
AuthorDate: Sun Jul 21 11:01:56 2024 +0100
Committer: Jeremy Harris <jgh146exb@???>
CommitDate: Sun Jul 21 11:01:56 2024 +0100
DBM lookups: use dbfn layer interface
---
src/src/dbfn.c | 45 +++++++++++++++++++++++++++++++++++++++++----
src/src/dbfunctions.h | 2 ++
src/src/hintsdb.h | 9 ++-------
src/src/lookups/dbmdb.c | 32 ++++++++------------------------
4 files changed, 53 insertions(+), 35 deletions(-)
diff --git a/src/src/dbfn.c b/src/src/dbfn.c
index 27bd9e56c..16b300180 100644
--- a/src/src/dbfn.c
+++ b/src/src/dbfn.c
@@ -39,6 +39,7 @@ arrange to hold the locks for the bare minimum of time.
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
@@ -46,6 +47,7 @@ API:
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
@@ -59,6 +61,7 @@ Users:
TLS session resumption
peer capability cache
callout & quota cache
+ DBM lookup type
*/
@@ -67,6 +70,22 @@ Users:
* 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
@@ -368,6 +387,7 @@ has two arguments; it calls this function adding NULL as the third.
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
@@ -375,17 +395,16 @@ 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. */
@@ -412,6 +431,25 @@ return yield;
}
+/*
+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).
@@ -440,7 +478,6 @@ if (yield)
return NULL;
}
-
/*************************************************
* Write to database file *
*************************************************/
diff --git a/src/src/dbfunctions.h b/src/src/dbfunctions.h
index 08f8c2311..9d0e75623 100644
--- a/src/src/dbfunctions.h
+++ b/src/src/dbfunctions.h
@@ -16,7 +16,9 @@ void dbfn_close(open_db *);
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 **);
diff --git a/src/src/hintsdb.h b/src/src/hintsdb.h
index a35791409..abf5f0123 100644
--- a/src/src/hintsdb.h
+++ b/src/src/hintsdb.h
@@ -11,8 +11,9 @@
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
@@ -52,14 +53,8 @@ Selection of the shim layer implementation, and backend, is by #defines.
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
diff --git a/src/src/lookups/dbmdb.c b/src/src/lookups/dbmdb.c
index d68110b12..8c7b576f2 100644
--- a/src/src/lookups/dbmdb.c
+++ b/src/src/lookups/dbmdb.c
@@ -7,6 +7,9 @@
/* 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"
@@ -20,12 +23,9 @@
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;
}
@@ -90,24 +90,8 @@ dbmdb_find(void * handle, const uschar * filename, const uschar * keystring,
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;
}
@@ -217,7 +201,7 @@ return dbmdb_find(handle, filename, key_buffer, key_item_len - 1,
void
static dbmdb_close(void *handle)
{
-exim_dbclose((EXIM_DB *)handle);
+dbfn_close((open_db *)handle);
}
--
## subscription configuration (requires account):
##
https://lists.exim.org/mailman3/postorius/lists/exim-cvs.lists.exim.org/
## unsubscribe (doesn't require an account):
## exim-cvs-unsubscribe@???
## Exim details at
http://www.exim.org/
## Please use the Wiki with this list -
http://wiki.exim.org/