[exim-cvs] DBM lookups: use dbfn layer interface

Αρχική Σελίδα
Delete this message
Reply to this message
Συντάκτης: Exim Git Commits Mailing List
Ημερομηνία:  
Προς: exim-cvs
Αντικείμενο: [exim-cvs] DBM lookups: use dbfn layer interface
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/