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 IF NOT EXISTS tbl (ky TEXT PRIMARY KEY, dat BLOB);",
94 // fprintf(stderr, "sqlite3_open_v2: %s\n", sqlite3_errmsg(dbp));
95 return ret == SQLITE_OK ? dbp : NULL;
98 /* EXIM_DBGET - returns TRUE if successful, FALSE otherwise */
99 /* note we alloc'n'copy - the caller need not do so */
100 /* result has a NUL appended, but the length is as per the DB */
103 exim_dbget__(EXIM_DB * dbp, const uschar * s, EXIM_DATUM * res)
105 sqlite3_stmt * statement;
108 res->len = (size_t) -1;
109 /* fprintf(stderr, "exim_dbget__(%s)\n", s); */
110 if ((ret = sqlite3_prepare_v2(dbp, CCS s, -1, &statement, NULL)) != SQLITE_OK)
112 /* fprintf(stderr, "prepare fail: %s\n", sqlite3_errmsg(dbp)); */
115 if (sqlite3_step(statement) != SQLITE_ROW)
117 /* fprintf(stderr, "step fail: %s\n", sqlite3_errmsg(dbp)); */
118 sqlite3_finalize(statement);
122 res->len = sqlite3_column_bytes(statement, 0);
123 res->data = store_get(res->len + 1, GET_TAINTED);
124 memcpy(res->data, sqlite3_column_blob(statement, 0), res->len);
125 res->data[res->len] = '\0';
126 /* fprintf(stderr, "res %d bytes: '%.*s'\n", (int)res->len, (int)res->len, res->data); */
127 sqlite3_finalize(statement);
132 exim_dbget(EXIM_DB * dbp, EXIM_DATUM * key, EXIM_DATUM * res)
134 # define FMT "SELECT dat FROM tbl WHERE ky = '%.*s';"
139 # ifdef COMPILE_UTILITY
140 /* fprintf(stderr, "exim_dbget(k len %d '%.*s')\n", (int)key->len, (int)key->len, key->data); */
141 qry = malloc(i = snprintf(NULL, 0, FMT, (int) key->len, key->data));
142 snprintf(CS qry, i, FMT, (int) key->len, key->data);
143 ret = exim_dbget__(dbp, qry, res);
146 /* fprintf(stderr, "exim_dbget(k len %d '%.*s')\n", (int)key->len, (int)key->len, key->data); */
147 qry = string_sprintf(FMT, (int) key->len, key->data);
148 ret = exim_dbget__(dbp, qry, res);
156 # define EXIM_DBPUTB_OK 0
157 # define EXIM_DBPUTB_DUP (-1)
160 exim_s_dbp(EXIM_DB * dbp, EXIM_DATUM * key, EXIM_DATUM * data, const uschar * alt)
162 # define FMT "INSERT OR %s INTO tbl (ky,dat) VALUES ('%.*s', X'%.*s');"
163 uschar * hex = store_get(data->len * 2, data->data), * qry;
166 for (const uschar * s = data->data, * t = s + data->len; s < t; s++)
167 sprintf(CS hex + 2 * (s - data->data), "%02X", *s);
169 # ifdef COMPILE_UTILITY
170 res = snprintf(NULL, 0, FMT,
171 alt, (int) key->len, key->data, (int)data->len * 2, hex);
173 snprintf(CS qry, res, FMT, alt, (int) key->len, key->data, (int)data->len * 2, hex);
174 /* fprintf(stderr, "exim_s_dbp(%s)\n", qry); */
175 res = sqlite3_exec(dbp, CS qry, NULL, NULL, NULL);
178 qry = string_sprintf(FMT, alt, (int) key->len, key->data, (int)data->len * 2, hex);
179 /* fprintf(stderr, "exim_s_dbp(%s)\n", qry); */
180 res = sqlite3_exec(dbp, CS qry, NULL, NULL, NULL);
181 /* fprintf(stderr, "exim_s_dbp res %d\n", res); */
184 if (res != SQLITE_OK)
185 fprintf(stderr, "sqlite3_exec: %s\n", sqlite3_errmsg(dbp));
187 return res == SQLITE_OK ? EXIM_DBPUTB_OK : EXIM_DBPUTB_DUP;
191 /* EXIM_DBPUT - returns nothing useful, assumes replace mode */
194 exim_dbput(EXIM_DB * dbp, EXIM_DATUM * key, EXIM_DATUM * data)
196 /* fprintf(stderr, "exim_dbput()\n"); */
197 (void) exim_s_dbp(dbp, key, data, US"REPLACE");
201 /* EXIM_DBPUTB - non-overwriting for use by dbmbuild */
203 /* Returns from EXIM_DBPUTB */
206 exim_dbputb(EXIM_DB * dbp, EXIM_DATUM * key, EXIM_DATUM * data)
208 return exim_s_dbp(dbp, key, data, US"ABORT");
213 exim_dbdel(EXIM_DB * dbp, EXIM_DATUM * key)
215 # define FMT "DELETE FROM tbl WHERE ky = '%.*s';"
219 # ifdef COMPILE_UTILITY
220 res = snprintf(NULL, 0, FMT, (int) key->len, key->data);
222 snprintf(CS qry, res, FMT, (int) key->len, key->data);
223 res = sqlite3_exec(dbp, CS qry, NULL, NULL, NULL);
226 qry = string_sprintf(FMT, (int) key->len, key->data);
227 res = sqlite3_exec(dbp, CS qry, NULL, NULL, NULL);
235 /* EXIM_DBCREATE_CURSOR - initialize for scanning operation */
236 /* Cursors are inefficiently emulated by repeating searches */
238 static inline EXIM_CURSOR *
239 exim_dbcreate_cursor(EXIM_DB * dbp)
241 EXIM_CURSOR * c = store_malloc(sizeof(int));
247 /* Note that we return the (next) key, not the record value */
249 exim_dbscan(EXIM_DB * dbp, EXIM_DATUM * key, EXIM_DATUM * res, BOOL first,
250 EXIM_CURSOR * cursor)
252 # define FMT "SELECT ky FROM tbl ORDER BY ky LIMIT 1 OFFSET %d;"
257 # ifdef COMPILE_UTILITY
258 qry = malloc(i = snprintf(NULL, 0, FMT, *cursor));
259 snprintf(CS qry, i, FMT, *cursor);
260 /* fprintf(stderr, "exim_dbscan(%s)\n", qry); */
261 ret = exim_dbget__(dbp, qry, key);
263 /* fprintf(stderr, "exim_dbscan ret %c\n", ret ? 'T':'F'); */
265 qry = string_sprintf(FMT, *cursor);
266 /* fprintf(stderr, "exim_dbscan(%s)\n", qry); */
267 ret = exim_dbget__(dbp, qry, key);
268 /* fprintf(stderr, "exim_dbscan ret %c\n", ret ? 'T':'F'); */
270 if (ret) *cursor = *cursor + 1;
275 /* EXIM_DBDELETE_CURSOR - terminate scanning operation. */
277 exim_dbdelete_cursor(EXIM_CURSOR * cursor)
278 { store_free(cursor); }
283 exim_dbclose__(EXIM_DB * db)
284 { sqlite3_close(db); }
290 exim_datum_data_get(EXIM_DATUM * dp)
291 { return US dp->data; }
293 exim_datum_data_set(EXIM_DATUM * dp, void * s)
297 exim_datum_size_get(EXIM_DATUM * dp)
300 exim_datum_size_set(EXIM_DATUM * dp, unsigned n)
306 exim_datum_init(EXIM_DATUM * dp)
307 { dp->data = NULL; } /* compiler quietening */
309 /* No free needed for a datum */
312 exim_datum_free(EXIM_DATUM * dp)
317 # define EXIM_DB_RLIMIT 150
324 #elif defined(USE_TDB)
326 # if defined(USE_DB) || defined(USE_GDBM)
327 # error USE_TDB conflict with alternate definition
330 /* ************************* tdb interface ************************ */
331 /*XXX https://manpages.org/tdb/3 mentions concurrent writes.
332 Could we lose the file lock? */
337 # define EXIM_DB TDB_CONTEXT
339 /* Cursor type: tdb uses the previous "key" in _nextkey() (really it wants
340 tdb_traverse to be called) */
341 # define EXIM_CURSOR TDB_DATA
343 /* The datum type used for queries */
344 # define EXIM_DATUM TDB_DATA
346 /* Some text for messages */
347 # define EXIM_DBTYPE "tdb"
349 /* Access functions */
351 /* EXIM_DBOPEN - return pointer to an EXIM_DB, NULL if failed */
352 static inline EXIM_DB *
353 exim_dbopen__(const uschar * name, const uschar * dirname, int flags,
356 return tdb_open(CS name, 0, TDB_DEFAULT, flags, mode);
359 /* EXIM_DBGET - returns TRUE if successful, FALSE otherwise */
361 exim_dbget(EXIM_DB * dbp, EXIM_DATUM * key, EXIM_DATUM * res)
363 *res = tdb_fetch(dbp, *key); /* A struct arg and return!! */
364 return res->dptr != NULL;
367 /* EXIM_DBPUT - returns nothing useful, assumes replace mode */
369 exim_dbput(EXIM_DB * dbp, EXIM_DATUM * key, EXIM_DATUM * data)
370 { return tdb_store(dbp, *key, *data, TDB_REPLACE); }
372 /* EXIM_DBPUTB - non-overwriting for use by dbmbuild */
374 exim_dbputb(EXIM_DB * dbp, EXIM_DATUM * key, EXIM_DATUM * data)
375 { return tdb_store(dbp, *key, *data, TDB_INSERT); }
377 /* Returns from EXIM_DBPUTB */
379 # define EXIM_DBPUTB_OK 0
380 # define EXIM_DBPUTB_DUP (-1)
384 exim_dbdel(EXIM_DB * dbp, EXIM_DATUM * key)
385 { return tdb_delete(dbp, *key); }
387 /* EXIM_DBCREATE_CURSOR - initialize for scanning operation */
388 static inline EXIM_CURSOR *
389 exim_dbcreate_cursor(EXIM_DB * dbp)
391 EXIM_CURSOR * c = store_malloc(sizeof(TDB_DATA));
396 /* EXIM_DBSCAN - This is complicated because we have to free the last datum
397 free() must not die when passed NULL */
400 exim_dbscan(EXIM_DB * dbp, EXIM_DATUM * key, EXIM_DATUM * res, BOOL first,
401 EXIM_CURSOR * cursor)
403 *key = first ? tdb_firstkey(dbp) : tdb_nextkey(dbp, *cursor);
406 return key->dptr != NULL;
409 /* EXIM_DBDELETE_CURSOR - terminate scanning operation. */
411 exim_dbdelete_cursor(EXIM_CURSOR * cursor)
412 { store_free(cursor); }
416 exim_dbclose__(EXIM_DB * db)
421 static inline uschar *
422 exim_datum_data_get(EXIM_DATUM * dp)
423 { return US dp->dptr; }
425 exim_datum_data_set(EXIM_DATUM * dp, void * s)
428 static inline unsigned
429 exim_datum_size_get(EXIM_DATUM * dp)
432 exim_datum_size_set(EXIM_DATUM * dp, unsigned n)
435 /* No initialization is needed. */
438 exim_datum_init(EXIM_DATUM * d)
441 /* Free the stuff inside the datum. */
444 exim_datum_free(EXIM_DATUM * d)
452 # define EXIM_DB_RLIMIT 150
459 /********************* Berkeley db native definitions **********************/
463 # if defined(USE_TDB) || defined(USE_GDBM)
464 # error USE_DB conflict with alternate definition
469 /* 1.x did no locking
470 2.x had facilities, but exim does it's own
474 /* We can distinguish between versions 1.x and 2.x/3.x by looking for a
475 definition of DB_VERSION_STRING, which is present in versions 2.x onwards. */
477 # ifdef DB_VERSION_STRING
479 # if DB_VERSION_MAJOR >= 6
480 # error Version 6 and later BDB API is not supported
483 /* The API changed (again!) between the 2.x and 3.x versions */
485 # if DB_VERSION_MAJOR >= 3
487 /***************** Berkeley db 3.x/4.x native definitions ******************/
490 # if DB_VERSION_MAJOR > 4 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 1)
491 # define EXIM_DB DB_ENV
492 /* Cursor type, for scanning */
493 # define EXIM_CURSOR DBC
495 /* The datum type used for queries */
496 # define EXIM_DATUM DBT
498 /* Some text for messages */
499 # define EXIM_DBTYPE "db (v4.1+)"
501 /* Only more-recent versions. 5+ ? */
502 # ifndef DB_FORCESYNC
503 # define DB_FORCESYNC 0
507 /* For Berkeley DB >= 2, we can define a function to be called in case of DB
508 errors. This should help with debugging strange DB problems, e.g. getting "File
509 exists" when you try to open a db file. The API for this function was changed
510 at DB release 4.3. */
513 dbfn_bdb_error_callback(const DB_ENV * dbenv, const char * pfx, const char * msg)
516 log_write(0, LOG_MAIN, "Berkeley DB error: %s", msg);
522 /* Access functions */
524 /* EXIM_DBOPEN - return pointer to an EXIM_DB, NULL if failed */
525 /* The API changed for DB 4.1. - and we also starting using the "env" with a
526 specified working dir, to avoid the DBCONFIG file trap. */
528 # define ENV_TO_DB(env) ((DB *)(((EXIM_DB *)env)->app_private))
530 static inline EXIM_DB *
531 exim_dbopen__(const uschar * name, const uschar * dirname, int flags,
536 if ( db_env_create(&dbp, 0) != 0
537 || (dbp->set_errcall(dbp, dbfn_bdb_error_callback), 0)
538 || dbp->open(dbp, CS dirname, DB_CREATE|DB_INIT_MPOOL|DB_PRIVATE, 0) != 0
541 if (db_create(&b, dbp, 0) == 0)
543 dbp->app_private = b;
544 if (b->open(b, NULL, CS name, NULL,
545 flags == O_RDONLY ? DB_UNKNOWN : DB_HASH,
546 flags == O_RDONLY ? DB_RDONLY : DB_CREATE,
557 /* EXIM_DBGET - returns TRUE if successful, FALSE otherwise */
559 exim_dbget(EXIM_DB * dbp, EXIM_DATUM * key, EXIM_DATUM * res)
561 DB * b = ENV_TO_DB(dbp);
562 return b->get(b, NULL, key, res, 0) == 0;
565 /* EXIM_DBPUT - returns nothing useful, assumes replace mode */
567 exim_dbput(EXIM_DB * dbp, EXIM_DATUM * key, EXIM_DATUM * data)
569 DB * b = ENV_TO_DB(dbp);
570 return b->put(b, NULL, key, data, 0);
573 /* EXIM_DBPUTB - non-overwriting for use by dbmbuild */
575 exim_dbputb(EXIM_DB * dbp, EXIM_DATUM * key, EXIM_DATUM * data)
577 DB * b = ENV_TO_DB(dbp);
578 return b->put(b, NULL, key, data, DB_NOOVERWRITE);
581 /* Return values from EXIM_DBPUTB */
583 # define EXIM_DBPUTB_OK 0
584 # define EXIM_DBPUTB_DUP DB_KEYEXIST
588 exim_dbdel(EXIM_DB * dbp, EXIM_DATUM * key)
590 DB * b = ENV_TO_DB(dbp);
591 return b->del(b, NULL, key, 0);
594 /* EXIM_DBCREATE_CURSOR - initialize for scanning operation */
596 static inline EXIM_CURSOR *
597 exim_dbcreate_cursor(EXIM_DB * dbp)
599 DB * b = ENV_TO_DB(dbp);
601 b->cursor(b, NULL, &c, 0);
605 /* EXIM_DBSCAN - returns TRUE if data is returned, FALSE at end */
607 exim_dbscan(EXIM_DB * dbp, EXIM_DATUM * key, EXIM_DATUM * data, BOOL first,
608 EXIM_CURSOR * cursor)
610 return cursor->c_get(cursor, key, data, first ? DB_FIRST : DB_NEXT) == 0;
613 /* EXIM_DBDELETE_CURSOR - terminate scanning operation */
615 exim_dbdelete_cursor(EXIM_CURSOR * cursor)
616 { cursor->c_close(cursor); }
620 exim_dbclose__(EXIM_DB * dbp_o)
622 DB_ENV * dbp = dbp_o;
623 DB * b = ENV_TO_DB(dbp);
625 dbp->close(dbp, DB_FORCESYNC);
630 static inline uschar *
631 exim_datum_data_get(EXIM_DATUM * dp)
634 exim_datum_data_set(EXIM_DATUM * dp, void * s)
637 static inline unsigned
638 exim_datum_size_get(EXIM_DATUM * dp)
641 exim_datum_size_set(EXIM_DATUM * dp, unsigned n)
644 /* The whole datum structure contains other fields that must be cleared
645 before use, but we don't have to free anything after reading data. */
648 exim_datum_init(EXIM_DATUM * d)
649 { memset(d, 0, sizeof(*d)); }
652 exim_datum_free(EXIM_DATUM * d)
655 # else /* pre- 4.1 */
659 /* Cursor type, for scanning */
660 # define EXIM_CURSOR DBC
662 /* The datum type used for queries */
663 # define EXIM_DATUM DBT
665 /* Some text for messages */
666 # define EXIM_DBTYPE "db (v3/4)"
668 /* Access functions */
670 /* EXIM_DBOPEN - return pointer to an EXIM_DB, NULL if failed */
671 static inline EXIM_DB *
672 exim_dbopen__(const uschar * name, const uschar * dirname, int flags,
676 return db_create(&dbp, NULL, 0) == 0
677 && ( dbp->set_errcall(dbp, dbfn_bdb_error_callback),
678 dbp->open(dbp, CS name, NULL,
679 flags == O_RDONLY ? DB_UNKNOWN : DB_HASH,
680 flags == O_RDONLY ? DB_RDONLY : DB_CREATE,
686 /* EXIM_DBGET - returns TRUE if successful, FALSE otherwise */
688 exim_dbget(EXIM_DB * dbp, EXIM_DATUM * key, EXIM_DATUM * res)
689 { return dbp->get(dbp, NULL, key, res, 0) == 0; }
691 /* EXIM_DBPUT - returns nothing useful, assumes replace mode */
693 exim_dbput(EXIM_DB * dbp, EXIM_DATUM * key, EXIM_DATUM * data)
694 { return dbp->put(dbp, NULL, key, data, 0); }
696 /* EXIM_DBPUTB - non-overwriting for use by dbmbuild */
698 exim_dbputb(EXIM_DB * dbp, EXIM_DATUM * key, EXIM_DATUM * data)
699 { return dbp->put(dbp, NULL, key, data, DB_NOOVERWRITE); }
701 /* Return values from EXIM_DBPUTB */
703 # define EXIM_DBPUTB_OK 0
704 # define EXIM_DBPUTB_DUP DB_KEYEXIST
708 exim_dbdel(EXIM_DB * dbp, EXIM_DATUM * key)
709 { return dbp->del(dbp, NULL, key, 0); }
711 /* EXIM_DBCREATE_CURSOR - initialize for scanning operation */
713 static inline EXIM_CURSOR *
714 exim_dbcreate_cursor(EXIM_DB * dbp)
717 dbp->cursor(dbp, NULL, &c, 0);
721 /* EXIM_DBSCAN - returns TRUE if data is returned, FALSE at end */
723 exim_dbscan(EXIM_DB * dbp, EXIM_DATUM * key, EXIM_DATUM * data, BOOL first,
724 EXIM_CURSOR * cursor)
726 return cursor->c_get(cursor, key, data, first ? DB_FIRST : DB_NEXT) == 0;
729 /* EXIM_DBDELETE_CURSOR - terminate scanning operation */
731 exim_dbdelete_cursor(EXIM_CURSOR * cursor)
732 { cursor->c_close(cursor); }
736 exim_dbclose__(EXIM_DB * dbp)
737 { dbp->close(dbp, 0); }
741 static inline uschar *
742 exim_datum_data_get(EXIM_DATUM * dp)
743 { return US dp->dptr; }
745 exim_datum_data_set(EXIM_DATUM * dp, void * s)
748 static inline uschar *
749 exim_datum_size_get(EXIM_DATUM * dp)
750 { return US dp->size; }
752 exim_datum_size_set(EXIM_DATUM * dp, uschar * s)
755 /* The whole datum structure contains other fields that must be cleared
756 before use, but we don't have to free anything after reading data. */
759 exim_datum_init(EXIM_DATUM * d)
760 { memset(d, 0, sizeof(*d)); }
763 exim_datum_free(EXIM_DATUM * d)
769 # else /* DB_VERSION_MAJOR >= 3 */
770 # error Berkeley DB versions earlier than 3 are not supported */
771 # endif /* DB_VERSION_MAJOR */
773 # error Berkeley DB version 1 is no longer supported
774 # endif /* DB_VERSION_STRING */
777 /* all BDB versions */
780 # define EXIM_DB_RLIMIT 150
787 /********************* gdbm interface definitions **********************/
789 #elif defined USE_GDBM
790 /*XXX TODO: exim's locfile not needed */
792 # if defined(USE_TDB) || defined(USE_DB)
793 # error USE_GDBM conflict with alternate definition
800 GDBM_FILE gdbm; /* Database */
801 datum lkey; /* Last key, for scans */
804 /* Cursor type, not used with gdbm: just set up a dummy */
805 # define EXIM_CURSOR int
807 /* The datum type used for queries */
808 # define EXIM_DATUM datum
810 /* Some text for messages */
812 # define EXIM_DBTYPE "gdbm"
814 /* Access functions */
816 /* EXIM_DBOPEN - return pointer to an EXIM_DB, NULL if failed */
817 static inline EXIM_DB *
818 exim_dbopen__(const uschar * name, const uschar * dirname, int flags,
821 EXIM_DB * dbp = malloc(sizeof(EXIM_DB)); /*XXX why not exim mem-mgmt? */
824 dbp->lkey.dptr = NULL;
825 dbp->gdbm = gdbm_open(CS name, 0,
826 flags & O_CREAT ? GDBM_WRCREAT
827 : flags & (O_RDWR|O_WRONLY) ? GDBM_WRITER
830 if (dbp->gdbm) return dbp;
836 /* EXIM_DBGET - returns TRUE if successful, FALSE otherwise */
838 exim_dbget(EXIM_DB * dbp, EXIM_DATUM * key, EXIM_DATUM * res)
840 *res = gdbm_fetch(dbp->gdbm, *key); /* A struct arg & return! */
841 return res->dptr != NULL;
844 /* EXIM_DBPUT - returns nothing useful, assumes replace mode */
846 exim_dbput(EXIM_DB * dbp, EXIM_DATUM * key, EXIM_DATUM * data)
847 { return gdbm_store(dbp->gdbm, *key, *data, GDBM_REPLACE); }
849 /* EXIM_DBPUTB - non-overwriting for use by dbmbuild */
851 exim_dbputb(EXIM_DB * dbp, EXIM_DATUM * key, EXIM_DATUM * data)
852 { return gdbm_store(dbp->gdbm, *key, *data, GDBM_INSERT); }
854 /* Returns from EXIM_DBPUTB */
856 # define EXIM_DBPUTB_OK 0
857 # define EXIM_DBPUTB_DUP 1
861 exim_dbdel(EXIM_DB * dbp, EXIM_DATUM * key)
862 { return gdbm_delete(dbp->gdbm, *key); }
864 /* EXIM_DBCREATE_CURSOR - initialize for scanning operation (null) */
865 static inline EXIM_CURSOR *
866 exim_dbcreate_cursor(EXIM_DB * dbp)
871 exim_dbscan(EXIM_DB * dbp, EXIM_DATUM * key, EXIM_DATUM * data, BOOL first,
872 EXIM_CURSOR * cursor)
875 *key = first ? gdbm_firstkey(dbp->gdbm) : gdbm_nextkey(dbp->gdbm, dbp->lkey);
876 if ((s = dbp->lkey.dptr)) free(s);
878 return key->dptr != NULL;
881 /* EXIM_DBDELETE_CURSOR - terminate scanning operation (null). */
883 exim_dbdelete_cursor(EXIM_CURSOR * cursor)
888 exim_dbclose__(EXIM_DB * dbp)
891 gdbm_close(dbp->gdbm);
892 if ((s = dbp->lkey.dptr)) free(s);
896 /* Datum access types */
898 static inline uschar *
899 exim_datum_data_get(EXIM_DATUM * dp)
900 { return US dp->dptr; }
902 exim_datum_data_set(EXIM_DATUM * dp, void * s)
905 static inline unsigned
906 exim_datum_size_get(EXIM_DATUM * dp)
907 { return dp->dsize; }
909 exim_datum_size_set(EXIM_DATUM * dp, unsigned n)
912 /* There's no clearing required before use, but we have to free the dptr
913 after reading data. */
916 exim_datum_init(EXIM_DATUM * d)
920 exim_datum_free(EXIM_DATUM * d)
923 /* size limit. GDBM is int-max limited, but we want to be less silly */
925 # define EXIM_DB_RLIMIT 150
934 /* If none of USE_DB, USG_GDBM, or USE_TDB are set, the default is the NDBM
935 interface (which seems to be a wrapper for GDBM) */
938 /********************* ndbm interface definitions **********************/
945 /* Cursor type, not used with ndbm: just set up a dummy */
946 # define EXIM_CURSOR int
948 /* The datum type used for queries */
949 # define EXIM_DATUM datum
951 /* Some text for messages */
953 # define EXIM_DBTYPE "ndbm"
955 /* Access functions */
957 /* EXIM_DBOPEN - returns a EXIM_DB *, NULL if failed */
958 /* Check that the name given is not present. This catches
959 a directory name; otherwise we would create the name.pag and
960 name.dir files in the directory's parent. */
962 static inline EXIM_DB *
963 exim_dbopen__(const uschar * name, const uschar * dirname, int flags,
967 if (!(flags & O_CREAT) || lstat(CCS name, &st) != 0 && errno == ENOENT)
968 return dbm_open(CS name, flags, mode);
969 #ifndef COMPILE_UTILITY
970 debug_printf("%s %d errno %s\n", __FUNCTION__, __LINE__, strerror(errno));
972 errno = (st.st_mode & S_IFMT) == S_IFDIR ? EISDIR : EEXIST;
976 /* EXIM_DBGET - returns TRUE if successful, FALSE otherwise */
978 exim_dbget(EXIM_DB * dbp, EXIM_DATUM * key, EXIM_DATUM * res)
980 *res = dbm_fetch(dbp, *key); /* A struct arg & return! */
981 return res->dptr != NULL;
984 /* EXIM_DBPUT - returns nothing useful, assumes replace mode */
986 exim_dbput(EXIM_DB * dbp, EXIM_DATUM * key, EXIM_DATUM * data)
987 { return dbm_store(dbp, *key, *data, DBM_REPLACE); }
989 /* EXIM_DBPUTB - non-overwriting for use by dbmbuild */
991 exim_dbputb(EXIM_DB * dbp, EXIM_DATUM * key, EXIM_DATUM * data)
992 { return dbm_store(dbp, *key, *data, DBM_INSERT); }
994 /* Returns from EXIM_DBPUTB */
996 # define EXIM_DBPUTB_OK 0
997 # define EXIM_DBPUTB_DUP 1
1001 exim_dbdel(EXIM_DB * dbp, EXIM_DATUM * key)
1002 { return dbm_delete(dbp, *key); }
1004 /* EXIM_DBCREATE_CURSOR - initialize for scanning operation (null) */
1005 static inline EXIM_CURSOR *
1006 exim_dbcreate_cursor(EXIM_DB * dbp)
1011 exim_dbscan(EXIM_DB * dbp, EXIM_DATUM * key, EXIM_DATUM * data, BOOL first,
1012 EXIM_CURSOR * cursor)
1014 *key = first ? dbm_firstkey(dbp) : dbm_nextkey(dbp);
1015 return key->dptr != NULL;
1018 /* EXIM_DBDELETE_CURSOR - terminate scanning operation (null). */
1020 exim_dbdelete_cursor(EXIM_CURSOR * cursor)
1025 exim_dbclose__(EXIM_DB * dbp)
1028 /* Datum access types */
1030 static inline uschar *
1031 exim_datum_data_get(EXIM_DATUM * dp)
1032 { return US dp->dptr; }
1034 exim_datum_data_set(EXIM_DATUM * dp, void * s)
1037 static inline unsigned
1038 exim_datum_size_get(EXIM_DATUM * dp)
1039 { return dp->dsize; }
1041 exim_datum_size_set(EXIM_DATUM * dp, unsigned n)
1044 /* There's no clearing required before use, and we don't have to free anything
1045 after reading data. */
1048 exim_datum_init(EXIM_DATUM * d)
1052 exim_datum_free(EXIM_DATUM * d)
1057 # define EXIM_DB_RLIMIT 150
1059 #endif /* !USE_GDBM */
1065 #if defined(COMPILE_UTILITY) || defined(MACRO_PREDEF)
1067 static inline EXIM_DB *
1068 exim_dbopen(const uschar * name, const uschar * dirname, int flags,
1071 return exim_dbopen__(name, dirname, flags, mode);
1075 exim_dbclose(EXIM_DB * dbp)
1076 { exim_dbclose__(dbp); }
1078 #else /* exim mainline code */
1080 /* Wrappers for open/close with debug tracing */
1082 extern void debug_printf_indent(const char *, ...);
1083 static inline BOOL is_tainted(const void *);
1085 static inline EXIM_DB *
1086 exim_dbopen(const uschar * name, const uschar * dirname, int flags,
1090 DEBUG(D_hints_lookup)
1091 debug_printf_indent("EXIM_DBOPEN: file <%s> dir <%s> flags=%s\n",
1093 flags == O_RDONLY ? "O_RDONLY"
1094 : flags == O_RDWR ? "O_RDWR"
1095 : flags == (O_RDWR|O_CREAT) ? "O_RDWR|O_CREAT"
1097 if (is_tainted(name) || is_tainted(dirname))
1099 log_write(0, LOG_MAIN|LOG_PANIC, "Tainted name for DB file not permitted");
1103 dbp = exim_dbopen__(name, dirname, flags, mode);
1105 DEBUG(D_hints_lookup) debug_printf_indent("returned from EXIM_DBOPEN: %p\n", dbp);
1110 exim_dbclose(EXIM_DB * dbp)
1112 DEBUG(D_hints_lookup) debug_printf_indent("EXIM_DBCLOSE(%p)\n", dbp);
1113 exim_dbclose__(dbp);
1116 # endif /* defined(COMPILE_UTILITY) || defined(MACRO_PREDEF) */
1118 /********************* End of dbm library definitions **********************/
1121 #endif /* whole file */
1122 /* End of hintsdb.h */