1 /*************************************************
2 * Exim - an Internet mail transport agent *
3 *************************************************/
5 /* Copyright (c) The Exim Maintainers 2020 - 2024 */
6 /* Copyright (c) University of Cambridge 1995 - 2018 */
7 /* See the file NOTICE for conditions of use and distribution. */
8 /* SPDX-License-Identifier: GPL-2.0-or-later */
10 /* This header file contains macro definitions so that a variety of DBM
11 libraries can be used by Exim. Nigel Metheringham provided the original set for
12 Berkeley DB 1.x in native mode and ndbm. Subsequently, versions for Berkeley DB
13 2.x and 3.x were added. Later still, support for tdb was added, courtesy of
14 James Antill. Most recently, support for native mode gdbm was added, with code
15 from Pierre A. Humblet, so Exim could be made to work with Cygwin.
17 For convenience, the definitions of the structures used in the various hints
18 databases are also kept in this file, which is used by the maintenance
19 utilities as well as the main Exim binary.
21 A key/value store is supported (only). Keys are strings; values arbitrary
30 exim_dbputb (non-overwriting put)
33 exim_dbscan (get, and bump cursor)
41 EXIM_CURSOR datatype for cursor
42 EXIM_DATUM datatype for "value"
43 EXIM_DBTYPE text for logging & debuug
45 Selection of the shim layer implementation, and backend, is by #defines.
47 The users of this API are:
48 hintsdb interface dbfn.c
49 hintsdb utilities exim_dbutil.c and exim_dbmvuild.c
50 dbmdb lookup lookups/dbmdb,c
51 autoreply transport transports/autoreply.c
60 /* ********************* sqlite3 interface ************************ */
65 # define EXIM_DB sqlite3
67 # define EXIM_CURSOR int
69 # /* The datum type used for queries */
70 # define EXIM_DATUM blob
72 /* Some text for messages */
73 # define EXIM_DBTYPE "sqlite3"
75 # /* Access functions */
77 /* EXIM_DBOPEN - return pointer to an EXIM_DB, NULL if failed */
78 static inline EXIM_DB *
79 exim_dbopen__(const uschar * name, const uschar * dirname, int flags,
83 int ret, sflags = flags & O_RDWR ? SQLITE_OPEN_READWRITE : SQLITE_OPEN_READONLY;
84 if (flags & O_CREAT) sflags |= SQLITE_OPEN_CREATE;
85 if ((ret = sqlite3_open_v2(CCS name, &dbp, sflags, NULL)) == SQLITE_OK)
87 sqlite3_busy_timeout(dbp, 5000);
89 ret == sqlite3_exec(dbp,
90 "CREATE TABLE tbl (ky TEXT PRIMARY KEY, dat BLOB);", NULL, NULL, NULL);
93 // fprintf(stderr, "sqlite3_open_v2: %s\n", sqlite3_errmsg(dbp));
94 return ret == SQLITE_OK ? dbp : NULL;
97 /* EXIM_DBGET - returns TRUE if successful, FALSE otherwise */
98 /* note we alloc'n'copy - the caller need not do so */
99 /* result has a NUL appended, but the length is as per the DB */
102 exim_dbget__(EXIM_DB * dbp, const uschar * s, EXIM_DATUM * res)
104 sqlite3_stmt * statement;
107 res->len = (size_t) -1;
108 /* fprintf(stderr, "exim_dbget__(%s)\n", s); */
109 if ((ret = sqlite3_prepare_v2(dbp, CCS s, -1, &statement, NULL)) != SQLITE_OK)
111 /* fprintf(stderr, "prepare fail: %s\n", sqlite3_errmsg(dbp)); */
114 if (sqlite3_step(statement) != SQLITE_ROW)
116 /* fprintf(stderr, "step fail: %s\n", sqlite3_errmsg(dbp)); */
117 sqlite3_finalize(statement);
121 res->len = sqlite3_column_bytes(statement, 0);
122 res->data = store_get(res->len + 1, GET_TAINTED);
123 memcpy(res->data, sqlite3_column_blob(statement, 0), res->len);
124 res->data[res->len] = '\0';
125 /* fprintf(stderr, "res %d bytes: '%.*s'\n", (int)res->len, (int)res->len, res->data); */
126 sqlite3_finalize(statement);
131 exim_dbget(EXIM_DB * dbp, EXIM_DATUM * key, EXIM_DATUM * res)
133 # define FMT "SELECT dat FROM tbl WHERE ky = '%.*s';"
138 # ifdef COMPILE_UTILITY
139 /* fprintf(stderr, "exim_dbget(k len %d '%.*s')\n", (int)key->len, (int)key->len, key->data); */
140 qry = malloc(i = snprintf(NULL, 0, FMT, (int) key->len, key->data));
141 snprintf(CS qry, i, FMT, (int) key->len, key->data);
142 ret = exim_dbget__(dbp, qry, res);
145 /* fprintf(stderr, "exim_dbget(k len %d '%.*s')\n", (int)key->len, (int)key->len, key->data); */
146 qry = string_sprintf(FMT, (int) key->len, key->data);
147 ret = exim_dbget__(dbp, qry, res);
155 # define EXIM_DBPUTB_OK 0
156 # define EXIM_DBPUTB_DUP (-1)
159 exim_s_dbp(EXIM_DB * dbp, EXIM_DATUM * key, EXIM_DATUM * data, const uschar * alt)
161 # define FMT "INSERT OR %s INTO tbl (ky,dat) VALUES ('%.*s', X'%.*s');"
162 uschar * hex = store_get(data->len * 2, data->data), * qry;
165 for (const uschar * s = data->data, * t = s + data->len; s < t; s++)
166 sprintf(CS hex + 2 * (s - data->data), "%02X", *s);
168 # ifdef COMPILE_UTILITY
169 res = snprintf(NULL, 0, FMT,
170 alt, (int) key->len, key->data, (int)data->len * 2, hex);
172 snprintf(CS qry, res, FMT, alt, (int) key->len, key->data, (int)data->len * 2, hex);
173 /* fprintf(stderr, "exim_s_dbp(%s)\n", qry); */
174 res = sqlite3_exec(dbp, CS qry, NULL, NULL, NULL);
177 qry = string_sprintf(FMT, alt, (int) key->len, key->data, (int)data->len * 2, hex);
178 /* fprintf(stderr, "exim_s_dbp(%s)\n", qry); */
179 res = sqlite3_exec(dbp, CS qry, NULL, NULL, NULL);
180 /* fprintf(stderr, "exim_s_dbp res %d\n", res); */
183 if (res != SQLITE_OK)
184 fprintf(stderr, "sqlite3_exec: %s\n", sqlite3_errmsg(dbp));
186 return res == SQLITE_OK ? EXIM_DBPUTB_OK : EXIM_DBPUTB_DUP;
190 /* EXIM_DBPUT - returns nothing useful, assumes replace mode */
193 exim_dbput(EXIM_DB * dbp, EXIM_DATUM * key, EXIM_DATUM * data)
195 /* fprintf(stderr, "exim_dbput()\n"); */
196 (void) exim_s_dbp(dbp, key, data, US"REPLACE");
200 /* EXIM_DBPUTB - non-overwriting for use by dbmbuild */
202 /* Returns from EXIM_DBPUTB */
205 exim_dbputb(EXIM_DB * dbp, EXIM_DATUM * key, EXIM_DATUM * data)
207 return exim_s_dbp(dbp, key, data, US"ABORT");
212 exim_dbdel(EXIM_DB * dbp, EXIM_DATUM * key)
214 # define FMT "DELETE FROM tbl WHERE ky = '%.*s';"
218 # ifdef COMPILE_UTILITY
219 res = snprintf(NULL, 0, FMT, (int) key->len, key->data);
221 snprintf(CS qry, res, FMT, (int) key->len, key->data);
222 res = sqlite3_exec(dbp, CS qry, NULL, NULL, NULL);
225 qry = string_sprintf(FMT, (int) key->len, key->data);
226 res = sqlite3_exec(dbp, CS qry, NULL, NULL, NULL);
234 /* EXIM_DBCREATE_CURSOR - initialize for scanning operation */
235 /* Cursors are inefficiently emulated by repeating searches */
237 static inline EXIM_CURSOR *
238 exim_dbcreate_cursor(EXIM_DB * dbp)
240 EXIM_CURSOR * c = store_malloc(sizeof(int));
246 /* Note that we return the (next) key, not the record value */
248 exim_dbscan(EXIM_DB * dbp, EXIM_DATUM * key, EXIM_DATUM * res, BOOL first,
249 EXIM_CURSOR * cursor)
251 # define FMT "SELECT ky FROM tbl ORDER BY ky LIMIT 1 OFFSET %d;"
256 # ifdef COMPILE_UTILITY
257 qry = malloc(i = snprintf(NULL, 0, FMT, *cursor));
258 snprintf(CS qry, i, FMT, *cursor);
259 /* fprintf(stderr, "exim_dbscan(%s)\n", qry); */
260 ret = exim_dbget__(dbp, qry, key);
262 /* fprintf(stderr, "exim_dbscan ret %c\n", ret ? 'T':'F'); */
264 qry = string_sprintf(FMT, *cursor);
265 /* fprintf(stderr, "exim_dbscan(%s)\n", qry); */
266 ret = exim_dbget__(dbp, qry, key);
267 /* fprintf(stderr, "exim_dbscan ret %c\n", ret ? 'T':'F'); */
269 if (ret) *cursor = *cursor + 1;
274 /* EXIM_DBDELETE_CURSOR - terminate scanning operation. */
276 exim_dbdelete_cursor(EXIM_CURSOR * cursor)
277 { store_free(cursor); }
282 exim_dbclose__(EXIM_DB * db)
283 { sqlite3_close(db); }
289 exim_datum_data_get(EXIM_DATUM * dp)
290 { return US dp->data; }
292 exim_datum_data_set(EXIM_DATUM * dp, void * s)
296 exim_datum_size_get(EXIM_DATUM * dp)
299 exim_datum_size_set(EXIM_DATUM * dp, unsigned n)
305 exim_datum_init(EXIM_DATUM * dp)
306 { dp->data = NULL; } /* compiler quietening */
308 /* No free needed for a datum */
311 exim_datum_free(EXIM_DATUM * dp)
316 # define EXIM_DB_RLIMIT 150
323 #elif defined(USE_TDB)
325 # if defined(USE_DB) || defined(USE_GDBM)
326 # error USE_TDB conflict with alternate definition
329 /* ************************* tdb interface ************************ */
330 /*XXX https://manpages.org/tdb/3 mentions concurrent writes.
331 Could we lose the file lock? */
336 # define EXIM_DB TDB_CONTEXT
338 /* Cursor type: tdb uses the previous "key" in _nextkey() (really it wants
339 tdb_traverse to be called) */
340 # define EXIM_CURSOR TDB_DATA
342 /* The datum type used for queries */
343 # define EXIM_DATUM TDB_DATA
345 /* Some text for messages */
346 # define EXIM_DBTYPE "tdb"
348 /* Access functions */
350 /* EXIM_DBOPEN - return pointer to an EXIM_DB, NULL if failed */
351 static inline EXIM_DB *
352 exim_dbopen__(const uschar * name, const uschar * dirname, int flags,
355 return tdb_open(CS name, 0, TDB_DEFAULT, flags, mode);
358 /* EXIM_DBGET - returns TRUE if successful, FALSE otherwise */
360 exim_dbget(EXIM_DB * dbp, EXIM_DATUM * key, EXIM_DATUM * res)
362 *res = tdb_fetch(dbp, *key); /* A struct arg and return!! */
363 return res->dptr != NULL;
366 /* EXIM_DBPUT - returns nothing useful, assumes replace mode */
368 exim_dbput(EXIM_DB * dbp, EXIM_DATUM * key, EXIM_DATUM * data)
369 { return tdb_store(dbp, *key, *data, TDB_REPLACE); }
371 /* EXIM_DBPUTB - non-overwriting for use by dbmbuild */
373 exim_dbputb(EXIM_DB * dbp, EXIM_DATUM * key, EXIM_DATUM * data)
374 { return tdb_store(dbp, *key, *data, TDB_INSERT); }
376 /* Returns from EXIM_DBPUTB */
378 # define EXIM_DBPUTB_OK 0
379 # define EXIM_DBPUTB_DUP (-1)
383 exim_dbdel(EXIM_DB * dbp, EXIM_DATUM * key)
384 { return tdb_delete(dbp, *key); }
386 /* EXIM_DBCREATE_CURSOR - initialize for scanning operation */
387 static inline EXIM_CURSOR *
388 exim_dbcreate_cursor(EXIM_DB * dbp)
390 EXIM_CURSOR * c = store_malloc(sizeof(TDB_DATA));
395 /* EXIM_DBSCAN - This is complicated because we have to free the last datum
396 free() must not die when passed NULL */
399 exim_dbscan(EXIM_DB * dbp, EXIM_DATUM * key, EXIM_DATUM * res, BOOL first,
400 EXIM_CURSOR * cursor)
402 *key = first ? tdb_firstkey(dbp) : tdb_nextkey(dbp, *cursor);
405 return key->dptr != NULL;
408 /* EXIM_DBDELETE_CURSOR - terminate scanning operation. */
410 exim_dbdelete_cursor(EXIM_CURSOR * cursor)
411 { store_free(cursor); }
415 exim_dbclose__(EXIM_DB * db)
420 static inline uschar *
421 exim_datum_data_get(EXIM_DATUM * dp)
422 { return US dp->dptr; }
424 exim_datum_data_set(EXIM_DATUM * dp, void * s)
427 static inline unsigned
428 exim_datum_size_get(EXIM_DATUM * dp)
431 exim_datum_size_set(EXIM_DATUM * dp, unsigned n)
434 /* No initialization is needed. */
437 exim_datum_init(EXIM_DATUM * d)
440 /* Free the stuff inside the datum. */
443 exim_datum_free(EXIM_DATUM * d)
451 # define EXIM_DB_RLIMIT 150
458 /********************* Berkeley db native definitions **********************/
462 # if defined(USE_TDB) || defined(USE_GDBM)
463 # error USE_DB conflict with alternate definition
468 /* 1.x did no locking
469 2.x had facilities, but exim does it's own
473 /* We can distinguish between versions 1.x and 2.x/3.x by looking for a
474 definition of DB_VERSION_STRING, which is present in versions 2.x onwards. */
476 # ifdef DB_VERSION_STRING
478 # if DB_VERSION_MAJOR >= 6
479 # error Version 6 and later BDB API is not supported
482 /* The API changed (again!) between the 2.x and 3.x versions */
484 # if DB_VERSION_MAJOR >= 3
486 /***************** Berkeley db 3.x/4.x native definitions ******************/
489 # if DB_VERSION_MAJOR > 4 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 1)
490 # define EXIM_DB DB_ENV
491 /* Cursor type, for scanning */
492 # define EXIM_CURSOR DBC
494 /* The datum type used for queries */
495 # define EXIM_DATUM DBT
497 /* Some text for messages */
498 # define EXIM_DBTYPE "db (v4.1+)"
500 /* Only more-recent versions. 5+ ? */
501 # ifndef DB_FORCESYNC
502 # define DB_FORCESYNC 0
506 /* For Berkeley DB >= 2, we can define a function to be called in case of DB
507 errors. This should help with debugging strange DB problems, e.g. getting "File
508 exists" when you try to open a db file. The API for this function was changed
509 at DB release 4.3. */
512 dbfn_bdb_error_callback(const DB_ENV * dbenv, const char * pfx, const char * msg)
515 log_write(0, LOG_MAIN, "Berkeley DB error: %s", msg);
521 /* Access functions */
523 /* EXIM_DBOPEN - return pointer to an EXIM_DB, NULL if failed */
524 /* The API changed for DB 4.1. - and we also starting using the "env" with a
525 specified working dir, to avoid the DBCONFIG file trap. */
527 # define ENV_TO_DB(env) ((DB *)(((EXIM_DB *)env)->app_private))
529 static inline EXIM_DB *
530 exim_dbopen__(const uschar * name, const uschar * dirname, int flags,
535 if ( db_env_create(&dbp, 0) != 0
536 || (dbp->set_errcall(dbp, dbfn_bdb_error_callback), 0)
537 || dbp->open(dbp, CS dirname, DB_CREATE|DB_INIT_MPOOL|DB_PRIVATE, 0) != 0
540 if (db_create(&b, dbp, 0) == 0)
542 dbp->app_private = b;
543 if (b->open(b, NULL, CS name, NULL,
544 flags == O_RDONLY ? DB_UNKNOWN : DB_HASH,
545 flags == O_RDONLY ? DB_RDONLY : DB_CREATE,
556 /* EXIM_DBGET - returns TRUE if successful, FALSE otherwise */
558 exim_dbget(EXIM_DB * dbp, EXIM_DATUM * key, EXIM_DATUM * res)
560 DB * b = ENV_TO_DB(dbp);
561 return b->get(b, NULL, key, res, 0) == 0;
564 /* EXIM_DBPUT - returns nothing useful, assumes replace mode */
566 exim_dbput(EXIM_DB * dbp, EXIM_DATUM * key, EXIM_DATUM * data)
568 DB * b = ENV_TO_DB(dbp);
569 return b->put(b, NULL, key, data, 0);
572 /* EXIM_DBPUTB - non-overwriting for use by dbmbuild */
574 exim_dbputb(EXIM_DB * dbp, EXIM_DATUM * key, EXIM_DATUM * data)
576 DB * b = ENV_TO_DB(dbp);
577 return b->put(b, NULL, key, data, DB_NOOVERWRITE);
580 /* Return values from EXIM_DBPUTB */
582 # define EXIM_DBPUTB_OK 0
583 # define EXIM_DBPUTB_DUP DB_KEYEXIST
587 exim_dbdel(EXIM_DB * dbp, EXIM_DATUM * key)
589 DB * b = ENV_TO_DB(dbp);
590 return b->del(b, NULL, key, 0);
593 /* EXIM_DBCREATE_CURSOR - initialize for scanning operation */
595 static inline EXIM_CURSOR *
596 exim_dbcreate_cursor(EXIM_DB * dbp)
598 DB * b = ENV_TO_DB(dbp);
600 b->cursor(b, NULL, &c, 0);
604 /* EXIM_DBSCAN - returns TRUE if data is returned, FALSE at end */
606 exim_dbscan(EXIM_DB * dbp, EXIM_DATUM * key, EXIM_DATUM * data, BOOL first,
607 EXIM_CURSOR * cursor)
609 return cursor->c_get(cursor, key, data, first ? DB_FIRST : DB_NEXT) == 0;
612 /* EXIM_DBDELETE_CURSOR - terminate scanning operation */
614 exim_dbdelete_cursor(EXIM_CURSOR * cursor)
615 { cursor->c_close(cursor); }
619 exim_dbclose__(EXIM_DB * dbp_o)
621 DB_ENV * dbp = dbp_o;
622 DB * b = ENV_TO_DB(dbp);
624 dbp->close(dbp, DB_FORCESYNC);
629 static inline uschar *
630 exim_datum_data_get(EXIM_DATUM * dp)
633 exim_datum_data_set(EXIM_DATUM * dp, void * s)
636 static inline unsigned
637 exim_datum_size_get(EXIM_DATUM * dp)
640 exim_datum_size_set(EXIM_DATUM * dp, unsigned n)
643 /* The whole datum structure contains other fields that must be cleared
644 before use, but we don't have to free anything after reading data. */
647 exim_datum_init(EXIM_DATUM * d)
648 { memset(d, 0, sizeof(*d)); }
651 exim_datum_free(EXIM_DATUM * d)
654 # else /* pre- 4.1 */
658 /* Cursor type, for scanning */
659 # define EXIM_CURSOR DBC
661 /* The datum type used for queries */
662 # define EXIM_DATUM DBT
664 /* Some text for messages */
665 # define EXIM_DBTYPE "db (v3/4)"
667 /* Access functions */
669 /* EXIM_DBOPEN - return pointer to an EXIM_DB, NULL if failed */
670 static inline EXIM_DB *
671 exim_dbopen__(const uschar * name, const uschar * dirname, int flags,
675 return db_create(&dbp, NULL, 0) == 0
676 && ( dbp->set_errcall(dbp, dbfn_bdb_error_callback),
677 dbp->open(dbp, CS name, NULL,
678 flags == O_RDONLY ? DB_UNKNOWN : DB_HASH,
679 flags == O_RDONLY ? DB_RDONLY : DB_CREATE,
685 /* EXIM_DBGET - returns TRUE if successful, FALSE otherwise */
687 exim_dbget(EXIM_DB * dbp, EXIM_DATUM * key, EXIM_DATUM * res)
688 { return dbp->get(dbp, NULL, key, res, 0) == 0; }
690 /* EXIM_DBPUT - returns nothing useful, assumes replace mode */
692 exim_dbput(EXIM_DB * dbp, EXIM_DATUM * key, EXIM_DATUM * data)
693 { return dbp->put(dbp, NULL, key, data, 0); }
695 /* EXIM_DBPUTB - non-overwriting for use by dbmbuild */
697 exim_dbputb(EXIM_DB * dbp, EXIM_DATUM * key, EXIM_DATUM * data)
698 { return dbp->put(dbp, NULL, key, data, DB_NOOVERWRITE); }
700 /* Return values from EXIM_DBPUTB */
702 # define EXIM_DBPUTB_OK 0
703 # define EXIM_DBPUTB_DUP DB_KEYEXIST
707 exim_dbdel(EXIM_DB * dbp, EXIM_DATUM * key)
708 { return dbp->del(dbp, NULL, key, 0); }
710 /* EXIM_DBCREATE_CURSOR - initialize for scanning operation */
712 static inline EXIM_CURSOR *
713 exim_dbcreate_cursor(EXIM_DB * dbp)
716 dbp->cursor(dbp, NULL, &c, 0);
720 /* EXIM_DBSCAN - returns TRUE if data is returned, FALSE at end */
722 exim_dbscan(EXIM_DB * dbp, EXIM_DATUM * key, EXIM_DATUM * data, BOOL first,
723 EXIM_CURSOR * cursor)
725 return cursor->c_get(cursor, key, data, first ? DB_FIRST : DB_NEXT) == 0;
728 /* EXIM_DBDELETE_CURSOR - terminate scanning operation */
730 exim_dbdelete_cursor(EXIM_CURSOR * cursor)
731 { cursor->c_close(cursor); }
735 exim_dbclose__(EXIM_DB * dbp)
736 { dbp->close(dbp, 0); }
740 static inline uschar *
741 exim_datum_data_get(EXIM_DATUM * dp)
742 { return US dp->dptr; }
744 exim_datum_data_set(EXIM_DATUM * dp, void * s)
747 static inline uschar *
748 exim_datum_size_get(EXIM_DATUM * dp)
749 { return US dp->size; }
751 exim_datum_size_set(EXIM_DATUM * dp, uschar * s)
754 /* The whole datum structure contains other fields that must be cleared
755 before use, but we don't have to free anything after reading data. */
758 exim_datum_init(EXIM_DATUM * d)
759 { memset(d, 0, sizeof(*d)); }
762 exim_datum_free(EXIM_DATUM * d)
768 # else /* DB_VERSION_MAJOR >= 3 */
769 # error Berkeley DB versions earlier than 3 are not supported */
770 # endif /* DB_VERSION_MAJOR */
772 # error Berkeley DB version 1 is no longer supported
773 # endif /* DB_VERSION_STRING */
776 /* all BDB versions */
779 # define EXIM_DB_RLIMIT 150
786 /********************* gdbm interface definitions **********************/
788 #elif defined USE_GDBM
789 /*XXX TODO: exim's locfile not needed */
791 # if defined(USE_TDB) || defined(USE_DB)
792 # error USE_GDBM conflict with alternate definition
799 GDBM_FILE gdbm; /* Database */
800 datum lkey; /* Last key, for scans */
803 /* Cursor type, not used with gdbm: just set up a dummy */
804 # define EXIM_CURSOR int
806 /* The datum type used for queries */
807 # define EXIM_DATUM datum
809 /* Some text for messages */
811 # define EXIM_DBTYPE "gdbm"
813 /* Access functions */
815 /* EXIM_DBOPEN - return pointer to an EXIM_DB, NULL if failed */
816 static inline EXIM_DB *
817 exim_dbopen__(const uschar * name, const uschar * dirname, int flags,
820 EXIM_DB * dbp = malloc(sizeof(EXIM_DB)); /*XXX why not exim mem-mgmt? */
823 dbp->lkey.dptr = NULL;
824 dbp->gdbm = gdbm_open(CS name, 0,
825 flags & O_CREAT ? GDBM_WRCREAT
826 : flags & (O_RDWR|O_WRONLY) ? GDBM_WRITER
829 if (dbp->gdbm) return dbp;
835 /* EXIM_DBGET - returns TRUE if successful, FALSE otherwise */
837 exim_dbget(EXIM_DB * dbp, EXIM_DATUM * key, EXIM_DATUM * res)
839 *res = gdbm_fetch(dbp->gdbm, *key); /* A struct arg & return! */
840 return res->dptr != NULL;
843 /* EXIM_DBPUT - returns nothing useful, assumes replace mode */
845 exim_dbput(EXIM_DB * dbp, EXIM_DATUM * key, EXIM_DATUM * data)
846 { return gdbm_store(dbp->gdbm, *key, *data, GDBM_REPLACE); }
848 /* EXIM_DBPUTB - non-overwriting for use by dbmbuild */
850 exim_dbputb(EXIM_DB * dbp, EXIM_DATUM * key, EXIM_DATUM * data)
851 { return gdbm_store(dbp->gdbm, *key, *data, GDBM_INSERT); }
853 /* Returns from EXIM_DBPUTB */
855 # define EXIM_DBPUTB_OK 0
856 # define EXIM_DBPUTB_DUP 1
860 exim_dbdel(EXIM_DB * dbp, EXIM_DATUM * key)
861 { return gdbm_delete(dbp->gdbm, *key); }
863 /* EXIM_DBCREATE_CURSOR - initialize for scanning operation (null) */
864 static inline EXIM_CURSOR *
865 exim_dbcreate_cursor(EXIM_DB * dbp)
870 exim_dbscan(EXIM_DB * dbp, EXIM_DATUM * key, EXIM_DATUM * data, BOOL first,
871 EXIM_CURSOR * cursor)
874 *key = first ? gdbm_firstkey(dbp->gdbm) : gdbm_nextkey(dbp->gdbm, dbp->lkey);
875 if ((s = dbp->lkey.dptr)) free(s);
877 return key->dptr != NULL;
880 /* EXIM_DBDELETE_CURSOR - terminate scanning operation (null). */
882 exim_dbdelete_cursor(EXIM_CURSOR * cursor)
887 exim_dbclose__(EXIM_DB * dbp)
890 gdbm_close(dbp->gdbm);
891 if ((s = dbp->lkey.dptr)) free(s);
895 /* Datum access types */
897 static inline uschar *
898 exim_datum_data_get(EXIM_DATUM * dp)
899 { return US dp->dptr; }
901 exim_datum_data_set(EXIM_DATUM * dp, void * s)
904 static inline unsigned
905 exim_datum_size_get(EXIM_DATUM * dp)
906 { return dp->dsize; }
908 exim_datum_size_set(EXIM_DATUM * dp, unsigned n)
911 /* There's no clearing required before use, but we have to free the dptr
912 after reading data. */
915 exim_datum_init(EXIM_DATUM * d)
919 exim_datum_free(EXIM_DATUM * d)
922 /* size limit. GDBM is int-max limited, but we want to be less silly */
924 # define EXIM_DB_RLIMIT 150
933 /* If none of USE_DB, USG_GDBM, or USE_TDB are set, the default is the NDBM
934 interface (which seems to be a wrapper for GDBM) */
937 /********************* ndbm interface definitions **********************/
944 /* Cursor type, not used with ndbm: just set up a dummy */
945 # define EXIM_CURSOR int
947 /* The datum type used for queries */
948 # define EXIM_DATUM datum
950 /* Some text for messages */
952 # define EXIM_DBTYPE "ndbm"
954 /* Access functions */
956 /* EXIM_DBOPEN - returns a EXIM_DB *, NULL if failed */
957 /* Check that the name given is not present. This catches
958 a directory name; otherwise we would create the name.pag and
959 name.dir files in the directory's parent. */
961 static inline EXIM_DB *
962 exim_dbopen__(const uschar * name, const uschar * dirname, int flags,
966 if (!(flags & O_CREAT) || lstat(CCS name, &st) != 0 && errno == ENOENT)
967 return dbm_open(CS name, flags, mode);
968 #ifndef COMPILE_UTILITY
969 debug_printf("%s %d errno %s\n", __FUNCTION__, __LINE__, strerror(errno));
971 errno = (st.st_mode & S_IFMT) == S_IFDIR ? EISDIR : EEXIST;
975 /* EXIM_DBGET - returns TRUE if successful, FALSE otherwise */
977 exim_dbget(EXIM_DB * dbp, EXIM_DATUM * key, EXIM_DATUM * res)
979 *res = dbm_fetch(dbp, *key); /* A struct arg & return! */
980 return res->dptr != NULL;
983 /* EXIM_DBPUT - returns nothing useful, assumes replace mode */
985 exim_dbput(EXIM_DB * dbp, EXIM_DATUM * key, EXIM_DATUM * data)
986 { return dbm_store(dbp, *key, *data, DBM_REPLACE); }
988 /* EXIM_DBPUTB - non-overwriting for use by dbmbuild */
990 exim_dbputb(EXIM_DB * dbp, EXIM_DATUM * key, EXIM_DATUM * data)
991 { return dbm_store(dbp, *key, *data, DBM_INSERT); }
993 /* Returns from EXIM_DBPUTB */
995 # define EXIM_DBPUTB_OK 0
996 # define EXIM_DBPUTB_DUP 1
1000 exim_dbdel(EXIM_DB * dbp, EXIM_DATUM * key)
1001 { return dbm_delete(dbp, *key); }
1003 /* EXIM_DBCREATE_CURSOR - initialize for scanning operation (null) */
1004 static inline EXIM_CURSOR *
1005 exim_dbcreate_cursor(EXIM_DB * dbp)
1010 exim_dbscan(EXIM_DB * dbp, EXIM_DATUM * key, EXIM_DATUM * data, BOOL first,
1011 EXIM_CURSOR * cursor)
1013 *key = first ? dbm_firstkey(dbp) : dbm_nextkey(dbp);
1014 return key->dptr != NULL;
1017 /* EXIM_DBDELETE_CURSOR - terminate scanning operation (null). */
1019 exim_dbdelete_cursor(EXIM_CURSOR * cursor)
1024 exim_dbclose__(EXIM_DB * dbp)
1027 /* Datum access types */
1029 static inline uschar *
1030 exim_datum_data_get(EXIM_DATUM * dp)
1031 { return US dp->dptr; }
1033 exim_datum_data_set(EXIM_DATUM * dp, void * s)
1036 static inline unsigned
1037 exim_datum_size_get(EXIM_DATUM * dp)
1038 { return dp->dsize; }
1040 exim_datum_size_set(EXIM_DATUM * dp, unsigned n)
1043 /* There's no clearing required before use, and we don't have to free anything
1044 after reading data. */
1047 exim_datum_init(EXIM_DATUM * d)
1051 exim_datum_free(EXIM_DATUM * d)
1056 # define EXIM_DB_RLIMIT 150
1058 #endif /* !USE_GDBM */
1064 #if defined(COMPILE_UTILITY) || defined(MACRO_PREDEF)
1066 static inline EXIM_DB *
1067 exim_dbopen(const uschar * name, const uschar * dirname, int flags,
1070 return exim_dbopen__(name, dirname, flags, mode);
1074 exim_dbclose(EXIM_DB * dbp)
1075 { exim_dbclose__(dbp); }
1077 #else /* exim mainline code */
1079 /* Wrappers for open/close with debug tracing */
1081 extern void debug_printf_indent(const char *, ...);
1082 static inline BOOL is_tainted(const void *);
1084 static inline EXIM_DB *
1085 exim_dbopen(const uschar * name, const uschar * dirname, int flags,
1089 DEBUG(D_hints_lookup)
1090 debug_printf_indent("EXIM_DBOPEN: file <%s> dir <%s> flags=%s\n",
1092 flags == O_RDONLY ? "O_RDONLY"
1093 : flags == O_RDWR ? "O_RDWR"
1094 : flags == (O_RDWR|O_CREAT) ? "O_RDWR|O_CREAT"
1096 if (is_tainted(name) || is_tainted(dirname))
1098 log_write(0, LOG_MAIN|LOG_PANIC, "Tainted name for DB file not permitted");
1102 dbp = exim_dbopen__(name, dirname, flags, mode);
1104 DEBUG(D_hints_lookup) debug_printf_indent("returned from EXIM_DBOPEN: %p\n", dbp);
1109 exim_dbclose(EXIM_DB * dbp)
1111 DEBUG(D_hints_lookup) debug_printf_indent("EXIM_DBCLOSE(%p)\n", dbp);
1112 exim_dbclose__(dbp);
1115 # endif /* defined(COMPILE_UTILITY) || defined(MACRO_PREDEF) */
1117 /********************* End of dbm library definitions **********************/
1120 #endif /* whole file */
1121 /* End of hintsdb.h */