diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2011-11-10 00:21:13 +0200 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2011-11-10 00:52:54 +0200 |
commit | 4926ea635ee23341615c351db3e4949553ca4dfb (patch) | |
tree | a1a8c4aede69cf55b5e27fa1dc1630aeeda70329 /src | |
parent | 7e4d54bd39368b36e8451d52975052c00e745f7a (diff) | |
download | mailfromd-4926ea635ee23341615c351db3e4949553ca4dfb.tar.gz mailfromd-4926ea635ee23341615c351db3e4949553ca4dfb.tar.bz2 |
Switch to libmu_dbm for DBM support.
* configure.ac (DEFAULT_DB_TYPE): New variable.
Use mu info to determine which DBM is supported.
* lib/Makefile.am (noinst_LIBRARIES): Remove libdbm.a
* lib/mf-dbm.c: remove.
* lib/mf-dbm.h: remove.
* lib/cache.c: Use libmu_dbm functions.
* lib/db.c: Likewise.
* lib/dbcfg.c: Likewise.
* lib/greylist.c: Likewise.
* lib/rate.c: Likewise.
* lib/tbf_rate.c: Likewise.
* src/builtin/db.bi: Likewise.
* src/savsrv.c: Likewise.
* src/srvcfg.c (srv_cfg_param) <database-type>: New statement.
* lib/libmf.h (config_cb_ignore): New proto.
* lib/mfdb.h (db_item_printer_t): Change signature.
* lib/utils.c (config_cb_ignore): New function.
* po/POTFILES.in: Update.
* src/Makefile.am (mailfromd_LDADD)
(calloutd_LDADD): Remove libdbm.a.
* src/calloutd.c: Update.
* src/main.c (mf_cfg_param): lock-retry-count and
lock-retry-timeout are no-op now.
* src/mfdbtool.c: Likewise.
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 3 | ||||
-rw-r--r-- | src/builtin/db.bi | 384 | ||||
-rw-r--r-- | src/calloutd.c | 2 | ||||
-rw-r--r-- | src/main.c | 52 | ||||
-rw-r--r-- | src/mfdbtool.c | 76 | ||||
-rw-r--r-- | src/savsrv.c | 1 | ||||
-rw-r--r-- | src/srvcfg.c | 19 |
7 files changed, 315 insertions, 222 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 4400f8d4..af404ca5 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -48,7 +48,6 @@ mailfromd_LDADD = \ builtin/libbuiltin.a\ ../lib/libmfdb.a\ ../lib/libmf.a\ - ../lib/libdbm.a\ ../gnu/libgnu.a\ $(MAILUTILS_LIBS)\ $(MILTER)\ @@ -71,7 +70,6 @@ calloutd_LDADD = \ ./libcallout.a\ ../lib/libmfdb.a\ ../lib/libmf.a\ - ../lib/libdbm.a\ ../gnu/libgnu.a\ $(MAILUTILS_LIBS)\ $(MILTER) @@ -82,7 +80,6 @@ mfdbtool_SOURCES = \ mfdbtool_LDADD = \ ../lib/libmfdb.a\ ../lib/libmf.a\ - ../lib/libdbm.a\ ../gnu/libgnu.a\ $(MAILUTILS_LIBS) diff --git a/src/builtin/db.bi b/src/builtin/db.bi index a734dc10..90d926eb 100644 --- a/src/builtin/db.bi +++ b/src/builtin/db.bi @@ -16,7 +16,6 @@ #define DEFAULT_DB_MODE 0640 #include <fnmatch.h> -#include "mf-dbm.h" struct db_prop { /* Database properties */ char *pat; /* Database name pattern */ @@ -144,6 +143,35 @@ db_prop_lookup(const char *name) return found; } +int +_mf_dbm_open(mu_dbm_file_t *pdb, char *dbname, int access, int mode) +{ + mu_dbm_file_t db; + int rc; + int sflg = MU_FILE_SAFETY_LINKED_WRDIR | + MU_FILE_SAFETY_DIR_IWOTH; + + rc = mu_dbm_create(dbname, &db); + if (rc) + return rc; + + mu_dbm_safety_set_flags(db, + sflg | mf_file_mode_to_safety_criteria(mode)); + rc = mu_dbm_safety_check(db); + if (rc && rc != ENOENT) { + mu_error(_("%s fails safety check: %s"), + dbname, mu_strerror(rc)); + mu_dbm_destroy(&db); + return rc; + } + /* FIXME: Safety checking */ + rc = mu_dbm_open(db, access, mode); + if (rc) + return rc; + *pdb = db; + return rc; +} + #define LOOKUP_NULL_BYTE 0x1 #define LOOKUP_TEST_ONLY 0x2 @@ -154,27 +182,34 @@ dbmap_lookup(eval_environ_t env, char *dbname, const char *keystr, const char *defval, int flags) { int rc; - MF_DBM_FILE db; - MF_DBM_DATUM key; - MF_DBM_DATUM contents; + mu_dbm_file_t db; + struct mu_dbm_datum key; + struct mu_dbm_datum contents; if (!defval) defval = ""; - if (mf_dbm_open(dbname, &db, MU_STREAM_READ, 0, NULL)) + rc = _mf_dbm_open(&db, dbname, MU_STREAM_READ, 0); + if (rc) MF_THROW(mfe_dbfailure, _("mf_dbm_open(%s) failed: %s"), dbname, - mf_dbm_strerror()); + mu_strerror(rc)); memset(&key, 0, sizeof key); memset(&contents, 0, sizeof contents); - MF_DATUM_PTR(key) = (void*) keystr; - MF_DATUM_SIZE(key) = strlen(keystr); + key.mu_dptr = (void*) keystr; + key.mu_dsize = strlen(keystr); if (flags & LOOKUP_NULL_BYTE) - MF_DATUM_SIZE(key)++; - rc = mf_dbm_fetch(&db, key, &contents) == 0; + key.mu_dsize++; + rc = mu_dbm_fetch(db, &key, &contents); + if (rc && rc != MU_ERR_NOENT) { + mu_dbm_destroy(&db); + MF_THROW(mfe_dbfailure, + _("cannot fetch data: %s"), + mu_dbm_strerror(db)); + } MF_DEBUG(MU_DEBUG_TRACE5, - ("Looking up %s: %s", keystr, rc ? "true" : "false")); + ("Looking up %s: %s", keystr, rc ? "false" : "true")); if (flags & LOOKUP_TEST_ONLY) push(env, (STKVAL)rc); else { @@ -183,18 +218,18 @@ dbmap_lookup(eval_environ_t env, char *dbname, const char *keystr, pushs(env, (STKVAL)defval); else push(env, 0); - } else if (((char*)MF_DATUM_PTR(contents))[MF_DATUM_SIZE(contents)-1]) { + } else if (((char*)contents.mu_dptr)[contents.mu_dsize-1]) { size_t off; - size_t len = MF_DATUM_SIZE(contents); + size_t len = contents.mu_dsize; char *s = MF_ALLOC_HEAP(off, len + 1); - memcpy(s, MF_DATUM_PTR(contents), len); + memcpy(s, contents.mu_dptr, len); s[len] = 0; push(env, (STKVAL) off); } else - pushs(env, MF_DATUM_PTR(contents)); + pushs(env, contents.mu_dptr); } - mf_dbm_datum_free(&contents); - mf_dbm_close(&db); + mu_dbm_datum_free(&contents); + mu_dbm_destroy(&db); return rc; } >]) @@ -225,37 +260,41 @@ MF_DEFUN(dbput, VOID, STRING dbname, STRING keystr, STRING value, OPTIONAL, NUMBER null, NUMBER mode) { int rc; - MF_DBM_FILE db; - MF_DBM_DATUM key; - MF_DBM_DATUM contents; + mu_dbm_file_t db; + struct mu_dbm_datum key; + struct mu_dbm_datum contents; const struct db_prop *prop = db_prop_lookup(dbname); - if (mf_dbm_open(dbname, &db, MU_STREAM_RDWR, - MF_OPTVAL(mode, (prop ? prop->mode : DEFAULT_DB_MODE)), - NULL)) + rc = _mf_dbm_open(&db, dbname, MU_STREAM_RDWR, + MF_OPTVAL(mode, + (prop ? prop->mode : DEFAULT_DB_MODE))); + if (rc) MF_THROW(mfe_dbfailure, _("mf_dbm_open(%s) failed: %s"), dbname, - mf_dbm_strerror()); + mu_strerror(rc)); memset(&key, 0, sizeof key); - MF_DATUM_PTR(key) = keystr; - MF_DATUM_SIZE(key) = strlen(keystr); + key.mu_dptr = keystr; + key.mu_dsize = strlen(keystr); if (MF_OPTVAL(null, prop && prop->null)) - MF_DATUM_SIZE(key)++; + key.mu_dsize++; memset(&contents, 0, sizeof contents); - MF_DATUM_PTR(contents) = value; - MF_DATUM_SIZE(contents) = strlen(value) + 1; + contents.mu_dptr = value; + contents.mu_dsize = strlen(value) + 1; - rc = mf_dbm_insert(&db, key, contents, 1); - mf_dbm_close(&db); - MF_ASSERT(rc == 0, - mfe_dbfailure, + rc = mu_dbm_store(db, &key, &contents, 1); + if (rc) { + const char *errstr = mu_dbm_strerror(db); + mu_dbm_destroy(&db); + MF_THROW(mfe_dbfailure, _("failed to insert data to %s: %s %s: %s"), dbname, keystr, value, - mf_dbm_strerror()); + errstr); + } + mu_dbm_destroy(&db); } END @@ -263,30 +302,34 @@ MF_DEFUN(dbinsert, VOID, STRING dbname, STRING keystr, STRING value, OPTIONAL, NUMBER replace, NUMBER null, NUMBER mode) { int rc; - MF_DBM_FILE db; - MF_DBM_DATUM key; - MF_DBM_DATUM contents; + mu_dbm_file_t db; + struct mu_dbm_datum key; + struct mu_dbm_datum contents; const struct db_prop *prop = db_prop_lookup(dbname); + const char *errstr; - if (mf_dbm_open(dbname, &db, MU_STREAM_RDWR, - MF_OPTVAL(mode, (prop ? prop->mode : DEFAULT_DB_MODE)), - NULL)) + rc = _mf_dbm_open(&db, dbname, MU_STREAM_RDWR, + MF_OPTVAL(mode, + (prop ? prop->mode : DEFAULT_DB_MODE))); + if (rc) MF_THROW(mfe_dbfailure, _("mf_dbm_open(%s) failed: %s"), dbname, - mf_dbm_strerror()); + mu_strerror(rc)); memset(&key, 0, sizeof key); - MF_DATUM_PTR(key) = keystr; - MF_DATUM_SIZE(key) = strlen(keystr); + key.mu_dptr = keystr; + key.mu_dsize = strlen(keystr); if (MF_OPTVAL(null, prop && prop->null)) - MF_DATUM_SIZE(key)++; + key.mu_dsize++; memset(&contents, 0, sizeof contents); - MF_DATUM_PTR(contents) = value; - MF_DATUM_SIZE(contents) = strlen(value) + 1; + contents.mu_dptr = value; + contents.mu_dsize = strlen(value) + 1; - rc = mf_dbm_insert(&db, key, contents, MF_OPTVAL(replace)); - mf_dbm_close(&db); + rc = mu_dbm_store(db, &key, &contents, MF_OPTVAL(replace)); + if (rc && rc != MU_ERR_EXISTS) + errstr = mu_dbm_strerror(db); + mu_dbm_destroy(&db); if (rc == MU_ERR_EXISTS) MF_THROW(mfe_exists, _("record already exists")); @@ -296,38 +339,42 @@ MF_DEFUN(dbinsert, VOID, STRING dbname, STRING keystr, STRING value, dbname, keystr, value, - mf_dbm_strerror()); + errstr); } END MF_DEFUN(dbdel, VOID, STRING dbname, STRING keystr, OPTIONAL, NUMBER null, NUMBER mode) { - MF_DBM_FILE db; - MF_DBM_DATUM key; + mu_dbm_file_t db; + struct mu_dbm_datum key; int rc; const struct db_prop *prop = db_prop_lookup(dbname); - if (mf_dbm_open(dbname, &db, MU_STREAM_RDWR, - MF_OPTVAL(mode, (prop ? prop->mode : DEFAULT_DB_MODE)), - NULL)) - MF_THROW(mfe_dbfailure, + rc = _mf_dbm_open(&db, dbname, MU_STREAM_RDWR, + MF_OPTVAL(mode, + (prop ? prop->mode : DEFAULT_DB_MODE))); + MF_ASSERT(rc == 0, + mfe_dbfailure, _("mf_dbm_open(%s) failed: %s"), dbname, - mf_dbm_strerror()); + mu_strerror(rc)); memset(&key, 0, sizeof key); - MF_DATUM_PTR(key) = keystr; - MF_DATUM_SIZE(key) = strlen(keystr); + key.mu_dptr = keystr; + key.mu_dsize = strlen(keystr); if (MF_OPTVAL(null, prop && prop->null)) - MF_DATUM_SIZE(key)++; - rc = mf_dbm_delete(&db, key); - mf_dbm_close(&db); + key.mu_dsize++; + rc = mu_dbm_delete(db, &key); + if (rc && rc != MU_ERR_FAILURE) + mu_error(_("error deleting %s from %s: %s"), + keystr, dbname, mu_dbm_strerror(db)); + mu_dbm_destroy(&db); MF_ASSERT(rc == 0, mfe_dbfailure, _("failed to delete data `%s' from `%s': %s"), keystr, dbname, - mf_dbm_strerror()); + mu_strerror(rc)); } END @@ -336,8 +383,8 @@ END struct db_tab { int used; - MF_DBM_FILE db; - MF_DBM_DATUM key; + mu_dbm_file_t db; + struct mu_dbm_datum key; }; static void * @@ -350,8 +397,8 @@ static void close_db_tab(struct db_tab *dbt) { if (dbt->used) { - mf_dbm_datum_free(&dbt->key); - mf_dbm_close(&dbt->db); + mu_dbm_datum_free(&dbt->key); + mu_dbm_destroy(&dbt->db); dbt->used = 0; } } @@ -387,18 +434,28 @@ MF_DEFUN(dbfirst, NUMBER, STRING dbname) int rc; int n; struct db_tab *dbt = MF_GET_DATA; - MF_DBM_FILE db; - MF_DBM_DATUM key; + mu_dbm_file_t db; + struct mu_dbm_datum key; - if (mf_dbm_open(dbname, &db, MU_STREAM_READ, 0, NULL)) - MF_THROW(mfe_dbfailure, + rc = _mf_dbm_open(&db, dbname, MU_STREAM_READ, 0); + MF_ASSERT(rc == 0, + mfe_dbfailure, _("mf_dbm_open(%s) failed: %s"), dbname, - mf_dbm_strerror()); - rc = mf_dbm_firstkey(&db, &key); - MF_ASSERT(rc == 0, mfe_dbfailure, + mu_strerror(rc)); + memset(&key, 0, sizeof key); + rc = mu_dbm_firstkey(db, &key); + if (rc) { + if (rc == MU_ERR_NOENT) { + mu_dbm_destroy(&db); + MF_RETURN(0); + } else if (rc) { + mu_dbm_destroy(&db); + MF_THROW(mfe_dbfailure, _("mf_dbm_firstkey failed: %s"), - mf_dbm_strerror()); + mu_strerror(rc)); + } + } n = new_db_tab(dbt); MF_ASSERT(n >= 0, mfe_failure, @@ -413,19 +470,22 @@ END MF_DEFUN(dbnext, NUMBER, NUMBER dn) { struct db_tab *dbt = MF_GET_DATA + dn; - MF_DBM_DATUM nextkey; + struct mu_dbm_datum nextkey; int rc; MF_ASSERT(dn >= 0 && dn < NUMDB && dbt->used, mfe_range, _("invalid database descriptor")); - rc = mf_dbm_nextkey(&dbt->db, dbt->key, &nextkey); + rc = mu_dbm_nextkey(dbt->db, &nextkey); if (rc) { + if (rc == MU_ERR_FAILURE) + mu_error(_("mu_dbm_nextkey: %s"), + mu_dbm_strerror(dbt->db)); close_db_tab(dbt); MF_RETURN(0); } - mf_dbm_datum_free(&dbt->key); + mu_dbm_datum_free(&nextkey); dbt->key = nextkey; MF_RETURN(1); } @@ -441,9 +501,9 @@ MF_DEFUN(dbkey, STRING, NUMBER dn) mfe_range, _("invalid database descriptor")); - len = MF_DATUM_SIZE(dbt->key); + len = dbt->key.mu_dsize; s = MF_ALLOC_HEAP(off, len + 1); - memcpy(s, MF_DATUM_PTR(dbt->key), len); + memcpy(s, dbt->key.mu_dptr, len); s[len] = 0; MF_RETURN(off); } @@ -455,24 +515,25 @@ MF_DEFUN(dbvalue, STRING, NUMBER dn) size_t off, len; char *s; struct db_tab *dbt = MF_GET_DATA + dn; - MF_DBM_DATUM contents; + struct mu_dbm_datum contents; MF_ASSERT(dn >= 0 && dn < NUMDB && dbt->used, mfe_range, _("invalid database descriptor")); memset(&contents, 0, sizeof contents); - rc = mf_dbm_fetch(&dbt->db, dbt->key, &contents); + rc = mu_dbm_fetch(dbt->db, &dbt->key, &contents); MF_ASSERT(rc == 0, mfe_dbfailure, - _("key not found: %s"), - mf_dbm_strerror()); + _("cannot fetch key: %s"), + rc == MU_ERR_FAILURE ? + mu_dbm_strerror(dbt->db) : mu_strerror (rc)); - len = MF_DATUM_SIZE(contents); + len = contents.mu_dsize; s = MF_ALLOC_HEAP(off, len + 1); - memcpy(s, MF_DATUM_PTR(contents), len); + memcpy(s, contents.mu_dptr, len); s[len] = 0; - mf_dbm_datum_free(&contents); + mu_dbm_datum_free(&contents); MF_RETURN(off); } END @@ -522,32 +583,37 @@ static int do_greylist_traditional(eval_environ_t env, char *email, long interval) { int rc; - MF_DBM_FILE db; - MF_DBM_DATUM key; - MF_DBM_DATUM contents; - int readonly; + mu_dbm_file_t db; + struct mu_dbm_datum key; + struct mu_dbm_datum contents; + int readonly = 0; time_t now; - rc = mf_dbm_open(greylist_format->dbname, &db, MU_STREAM_RDWR, 0600, - &readonly); + rc = _mf_dbm_open(&db, greylist_format->dbname, MU_STREAM_RDWR, 0600); + if (rc) { + rc = _mf_dbm_open(&db, greylist_format->dbname, + MU_STREAM_READ, 0); + readonly = 1; + } MF_ASSERT(rc == 0, mfe_dbfailure, _("mf_dbm_open(%s) failed: %s"), - greylist_format->dbname, mf_dbm_strerror()); + greylist_format->dbname, mu_strerror(rc)); memset(&key, 0, sizeof key); memset(&contents, 0, sizeof contents); - MF_DATUM_PTR(key) = email; - MF_DATUM_SIZE(key) = strlen(email)+1; + key.mu_dptr = email; + key.mu_dsize = strlen(email)+1; time(&now); - if (mf_dbm_fetch(&db, key, &contents) == 0) { + rc = mu_dbm_fetch(db, &key, &contents); + if (rc == 0) { time_t timestamp, diff; - MF_ASSERT(MF_DATUM_SIZE(contents) == sizeof timestamp, + MF_ASSERT(contents.mu_dsize == sizeof timestamp, mfe_dbfailure, _("greylist database %s has wrong data size"), greylist_format->dbname); - timestamp = *(time_t*) MF_DATUM_PTR(contents); + timestamp = *(time_t*) contents.mu_dptr; diff = now - timestamp; if (mu_debug_level_p(debug_handle, MU_DEBUG_TRACE5)) { @@ -575,15 +641,17 @@ do_greylist_traditional(eval_environ_t env, char *email, long interval) ("greylist record for %s expired", email)); MF_VAR_REF(greylist_seconds_left, interval); if (!readonly) { - memcpy(MF_DATUM_PTR(contents), - &now, sizeof now); - if (mf_dbm_insert(&db, key, contents, 1)) + memcpy(contents.mu_dptr, &now, sizeof now); + rc = mu_dbm_store(db, &key, &contents, 1); + if (rc) mu_error(_("cannot insert datum `%-.*s' in " "greylist database %s: %s"), - MF_DATUM_SIZE(key), - (char*)MF_DATUM_PTR(key), + key.mu_dsize, + (char*)key.mu_dptr, greylist_format->dbname, - mf_dbm_strerror()); + rc == MU_ERR_FAILURE ? + mu_dbm_strerror(db) : + mu_strerror(rc)); } else MF_DEBUG(MU_DEBUG_TRACE6, ("database opened in readonly mode: " @@ -594,23 +662,25 @@ do_greylist_traditional(eval_environ_t env, char *email, long interval) ("%s finished greylisting period", email)); rc = 0; } - mf_dbm_datum_free(&contents); + mu_dbm_datum_free(&contents); } else if (!readonly) { MF_DEBUG(MU_DEBUG_TRACE6, ("greylisting %s", email)); MF_VAR_REF(greylist_seconds_left, interval); - MF_DATUM_PTR(contents) = (void*)&now; - MF_DATUM_SIZE(contents) = sizeof now; - if (mf_dbm_insert(&db, key, contents, 1)) + contents.mu_dptr = (void*)&now; + contents.mu_dsize = sizeof now; + rc = mu_dbm_store(db, &key, &contents, 1); + if (rc) mu_error(_("Cannot insert datum `%-.*s' in greylist " "database %s: %s"), - MF_DATUM_SIZE(key), (char*)MF_DATUM_PTR(key), + key.mu_dsize, (char*)key.mu_dptr, greylist_format->dbname, - mf_dbm_strerror()); + rc == MU_ERR_FAILURE ? + mu_dbm_strerror(db) : mu_strerror(rc)); rc = 1; } else rc = 0; - mf_dbm_close(&db); + mu_dbm_destroy(&db); return rc; } @@ -638,32 +708,37 @@ static int do_greylist_ct(eval_environ_t env, char *email, long interval) { int rc; - MF_DBM_FILE db; - MF_DBM_DATUM key; - MF_DBM_DATUM contents; - int readonly; + mu_dbm_file_t db; + struct mu_dbm_datum key; + struct mu_dbm_datum contents; + int readonly = 0; time_t now; - rc = mf_dbm_open(greylist_format->dbname, &db, MU_STREAM_RDWR, 0600, - &readonly); + rc = _mf_dbm_open(&db, greylist_format->dbname, MU_STREAM_RDWR, 0600); + if (rc) { + rc = _mf_dbm_open(&db, greylist_format->dbname, + MU_STREAM_READ, 0); + readonly = 1; + } MF_ASSERT(rc == 0, mfe_dbfailure, _("mf_dbm_open(%s) failed: %s"), - greylist_format->dbname, mf_dbm_strerror()); + greylist_format->dbname, mu_strerror(rc)); memset(&key, 0, sizeof key); memset(&contents, 0, sizeof contents); - MF_DATUM_PTR(key) = email; - MF_DATUM_SIZE(key) = strlen(email)+1; + key.mu_dptr = email; + key.mu_dsize = strlen(email) + 1; time(&now); - if (mf_dbm_fetch(&db, key, &contents) == 0) { + rc = mu_dbm_fetch(db, &key, &contents); + if (rc == 0) { time_t timestamp; - MF_ASSERT(MF_DATUM_SIZE(contents) == sizeof timestamp, + MF_ASSERT(contents.mu_dsize == sizeof timestamp, mfe_dbfailure, _("greylist database %s has wrong data size"), greylist_format->dbname); - timestamp = *(time_t*) MF_DATUM_PTR(contents); + timestamp = *(time_t*) contents.mu_dptr; if (now < timestamp) { time_t diff = timestamp - now; @@ -681,16 +756,18 @@ do_greylist_ct(eval_environ_t env, char *email, long interval) MF_VAR_REF(greylist_seconds_left, interval); if (!readonly) { now += interval; - memcpy(MF_DATUM_PTR(contents), - &now, sizeof now); - if (mf_dbm_insert(&db, key, contents, 1)) + memcpy(contents.mu_dptr, &now, sizeof now); + rc = mu_dbm_store(db, &key, &contents, 1); + if (rc) mu_error(_("Cannot insert datum " "`%-.*s' in greylist " "database %s: %s"), - MF_DATUM_SIZE(key), - (char*)MF_DATUM_PTR(key), + key.mu_dsize, + (char*)key.mu_dptr, greylist_format->dbname, - mf_dbm_strerror()); + rc == MU_ERR_FAILURE ? + mu_dbm_strerror(db) : + mu_strerror(rc)); } else MF_DEBUG(MU_DEBUG_TRACE6, ("database opened in readonly mode: " @@ -701,24 +778,26 @@ do_greylist_ct(eval_environ_t env, char *email, long interval) ("%s finished greylisting period", email)); rc = 0; } - mf_dbm_datum_free(&contents); + mu_dbm_datum_free(&contents); } else if (!readonly) { MF_DEBUG(MU_DEBUG_TRACE6, ("greylisting %s", email)); MF_VAR_REF(greylist_seconds_left, interval); now += interval; - MF_DATUM_PTR(contents) = (void*)&now; - MF_DATUM_SIZE(contents) = sizeof now; - if (mf_dbm_insert(&db, key, contents, 1)) + contents.mu_dptr = (void*)&now; + contents.mu_dsize = sizeof now; + rc = mu_dbm_store(db, &key, &contents, 1); + if (rc) mu_error(_("Cannot insert datum `%-.*s' in greylist " "database %s: %s"), - MF_DATUM_SIZE(key), (char*)MF_DATUM_PTR(key), + key.mu_dsize, (char*)key.mu_dptr, greylist_format->dbname, - mf_dbm_strerror()); + rc == MU_ERR_FAILURE ? + mu_dbm_strerror(db) : mu_strerror(rc)); rc = 1; } else rc = 0; - mf_dbm_close(&db); + mu_dbm_destroy(&db); return rc; } @@ -728,42 +807,47 @@ static int is_greylisted_ct(eval_environ_t env, char *email) { int rc; - MF_DBM_FILE db; - MF_DBM_DATUM key; - MF_DBM_DATUM contents; - int readonly; + mu_dbm_file_t db; + struct mu_dbm_datum key; + struct mu_dbm_datum contents; + int readonly = 0; time_t now; - rc = mf_dbm_open(greylist_format->dbname, &db, MU_STREAM_RDWR, 0600, - &readonly); + rc = _mf_dbm_open(&db, greylist_format->dbname, MU_STREAM_RDWR, 0600); + if (rc) { + rc = _mf_dbm_open(&db, greylist_format->dbname, + MU_STREAM_READ, 0); + readonly = 1; + } MF_ASSERT(rc == 0, mfe_dbfailure, _("mf_dbm_open(%s) failed: %s"), - greylist_format->dbname, mf_dbm_strerror()); + greylist_format->dbname, mu_strerror(rc)); memset(&key, 0, sizeof key); memset(&contents, 0, sizeof contents); - MF_DATUM_PTR(key) = email; - MF_DATUM_SIZE(key) = strlen(email) + 1; + key.mu_dptr = email; + key.mu_dsize = strlen(email) + 1; time(&now); - if (mf_dbm_fetch(&db, key, &contents) == 0) { + rc = mu_dbm_fetch(db, &key, &contents); + if (rc == 0) { time_t timestamp; - MF_ASSERT(MF_DATUM_SIZE(contents) == sizeof timestamp, + MF_ASSERT(contents.mu_dsize == sizeof timestamp, mfe_dbfailure, _("greylist database %s has wrong data size"), greylist_format->dbname); - timestamp = *(time_t*) MF_DATUM_PTR(contents); + timestamp = *(time_t*) contents.mu_dptr; rc = timestamp > now; if (rc) MF_VAR_REF(greylist_seconds_left, timestamp - now); - mf_dbm_datum_free(&contents); + mu_dbm_datum_free(&contents); } else rc = 0; - mf_dbm_close(&db); + mu_dbm_destroy(&db); return rc; } diff --git a/src/calloutd.c b/src/calloutd.c index cd054125..c3753593 100644 --- a/src/calloutd.c +++ b/src/calloutd.c @@ -39,7 +39,6 @@ #include "srvman.h" #include "srvcfg.h" #include "mfdb.h" -#include "mf-dbm.h" void xalloc_die() @@ -125,7 +124,6 @@ main(int argc, char **argv) mf_srvcfg_log_setup(stderr_closed_p() ? "syslog" : "stderr"); libcallout_init(); - libdbm_init(); db_format_setup(); mf_server_save_cmdline(argc, argv); @@ -37,6 +37,7 @@ #include <mailutils/server.h> #include <mailutils/syslog.h> #include <mailutils/libargp.h> +#include <mailutils/dbm.h> #include "mailfromd.h" #include "callout.h" @@ -44,7 +45,6 @@ #include "inttostr.h" #include "srvcfg.h" #include "filenames.h" -#include "mf-dbm.h" #include "builtin.h" #include "prog.h" @@ -918,11 +918,10 @@ struct mu_cfg_param mf_cfg_param[] = { { "database", mu_cfg_section, NULL }, - { "lock-retry-count", mu_cfg_size, &lock_retry_count_option, 0, NULL, - N_("Retry acquiring DBM file lock this number of times.") }, - { "lock-retry-timeout", mu_cfg_callback, &lock_retry_timeout_option, 0, - config_cb_time_t, - N_("Set the time span between the two DBM locking attempts."), + { "lock-retry-count", mu_cfg_callback, 0, 0, config_cb_ignore, + N_("Ignored for backward compatibility.") }, + { "lock-retry-timeout", mu_cfg_callback, 0,0, config_cb_ignore, + N_("Ignored for backward compatibility."), N_("time") }, { "max-match-mx", mu_cfg_size, &max_match_mx, 0, NULL, @@ -1003,6 +1002,37 @@ db_format_enumerator(struct db_format *fmt, void *data) return 0; } +static void +list_db_formats(const char *pfx) +{ + mu_iterator_t itr; + int rc; + const char *defdb = DEFAULT_DB_TYPE; + printf("%s", pfx); + + rc = mu_dbm_impl_iterator(&itr); + if (rc) { + printf("%s\n", _("unknown")); + mu_error("%s", mu_strerror(rc)); + } else { + int i; + for (mu_iterator_first(itr), i = 0; !mu_iterator_is_done(itr); + mu_iterator_next(itr), i++) { + struct mu_dbm_impl *impl; + + mu_iterator_current(itr, (void**)&impl); + if (i) + printf(", "); + else if (!defdb) + defdb = impl->_dbm_name; + printf("%s", impl->_dbm_name); + } + putchar('\n'); + mu_iterator_destroy(&itr); + } + printf("default database type: %s\n", defdb); +} + void mailfromd_show_defaults() { @@ -1020,14 +1050,7 @@ mailfromd_show_defaults() printf("default syslog: blocking\n"); #endif #endif - printf("database format: "); -#if defined WITH_GDBM - printf("GDBM"); -#elif defined WITH_BDB - printf("Berkeley DB %d.x", WITH_BDB); -#endif - printf("\n"); - + list_db_formats("supported databases: "); printf("Optional features: "); #if defined WITH_GEOIP printf(" GeoIP"); @@ -1193,7 +1216,6 @@ main(int argc, char **argv) init_symbols(); builtin_setup(); mf_runtime_param_finish(); - libdbm_init(); db_format_setup(); include_path_setup(); pragma_setup(); diff --git a/src/mfdbtool.c b/src/mfdbtool.c index 991bbdfc..98e87acc 100644 --- a/src/mfdbtool.c +++ b/src/mfdbtool.c @@ -31,7 +31,6 @@ #include "libmf.h" #include "mfdb.h" -#include "mf-dbm.h" char *state_dir = DEFAULT_STATE_DIR; char *file_option; /* File name for DB management commands */ @@ -41,8 +40,9 @@ time_t expire_interval = 0; /* When set, overrides the expire interval int all_option; /* Process all databases */ int predict_next_option; double predict_rate; /* Prediction rate for --list --format=rates*/ -void (*run)(int argc, char **argv) = NULL; +char *db_type_str = DEFAULT_DB_TYPE; +void (*run)(int argc, char **argv) = NULL; void assert_db_format() @@ -184,8 +184,6 @@ enum { OPTION_COMPACT, OPTION_IGNORE_FAILED_READS, OPTION_PREDICT_NEXT, - OPTION_LOCK_RETRY_COUNT, - OPTION_LOCK_RETRY_TIMEOUT, OPTION_ALL, OPTION_TIME_FORMAT }; @@ -228,10 +226,6 @@ static struct argp_option options[] = { #define GRP 30 { NULL, 0, NULL, 0, N_("Configuration modifiers"), GRP }, - { "lock-retry-count", OPTION_LOCK_RETRY_COUNT, N_("NUMBER"), 0, - N_("set maximum number of attempts to acquire the lock"), GRP+1 }, - { "lock-retry-timeout", OPTION_LOCK_RETRY_TIMEOUT, N_("TIME"), 0, - N_("set timeout for acquiring the lockfile"), GRP+1 }, { "state-directory", OPTION_STATE_DIRECTORY, N_("DIR"), 0, N_("set new program state directory"), GRP+1 }, { "expire-interval", 'e', N_("NUMBER"), 0, @@ -254,20 +248,6 @@ parse_opt(int key, char *arg, struct argp_state *state) case OPTION_STATE_DIRECTORY: mf_optcache_set_option("state-directory", arg); break; - case OPTION_LOCK_RETRY_COUNT: - mf_optcache_set_option("lock-retry-count", arg); - break; - case OPTION_LOCK_RETRY_TIMEOUT: { - const char *endp; - time_t t; - - if (parse_time_interval(arg, &t, &endp)) - argp_error(state, - _("unrecognized time format (near `%s')"), - endp); - mf_optcache_set_option("lock-retry-timeout", (void*)&t); - break; - } case 'd': mf_optcache_set_option("debug", arg); @@ -351,6 +331,9 @@ cb_debug(void *data, mu_config_value_t *arg) struct mu_cfg_param mfdbtool_cfg_param[] = { + { "database-type", mu_cfg_string, &db_type_str, 0, NULL, + N_("Default database type"), + N_("type") }, { "database", mu_cfg_section, NULL, 0, NULL, NULL }, { "state-directory", mu_cfg_string, &state_dir, 0, NULL, N_("Set program state directory."), @@ -363,12 +346,13 @@ struct mu_cfg_param mfdbtool_cfg_param[] = { "where <module> is the name of a Mailfromd module, and <level> " "is the desired verbosity level for that module."), N_("spec: list") }, - { "lock-retry-count", mu_cfg_size, &lock_retry_count_option, 0, NULL, - N_("Retry acquiring DBM file lock this number of times.") }, - { "lock-retry-timeout", mu_cfg_callback, &lock_retry_timeout_option, 0, - config_cb_time_t, - N_("Set the time span between the two DBM locking attempts."), + + { "lock-retry-count", mu_cfg_callback, 0, 0, config_cb_ignore, + N_("Ignored for backward compatibility.") }, + { "lock-retry-timeout", mu_cfg_callback, 0,0, config_cb_ignore, + N_("Ignored for backward compatibility."), N_("time") }, + { NULL } }; @@ -384,32 +368,10 @@ set_debug(void *value) mu_debug_parse_spec(value); } -static void -set_lock_retry_count(void *value) -{ - char *p; - - lock_retry_count_option = strtoul(value, &p, 10); - if (*p) { - mu_error(_("invalid value for lock-retry-count: %s"), - (char*)value); - exit(EX_USAGE); - } - free(value); -} - -static void -set_lock_retry_timeout(void *value) -{ - lock_retry_timeout_option = *(time_t*) value; - free(value); -} - static struct mf_option_cache option_cache[] = { { "state-directory", NULL, mf_option_string, set_state_directory }, { "debug", NULL, mf_option_string, set_debug }, - { "lock-retry-count", NULL, mf_option_string, set_lock_retry_count }, - { "lock-retry-timeout", NULL, mf_option_time_t, set_lock_retry_timeout }, + { NULL } }; @@ -452,7 +414,6 @@ main(int argc, char **argv) program_invocation_short_name = argv[0]; argp_program_version_hook = version; - libdbm_init(); db_format_setup(); database_cfg_init(); @@ -466,6 +427,19 @@ main(int argc, char **argv) if (rc) exit(EX_CONFIG); + if (db_type_str) { + mu_url_t dbhint; + + if ((rc = mu_url_create_null(&dbhint)) || + (rc = mu_url_set_scheme(dbhint, db_type_str))) { + mu_error(_("cannot initialize DBM hint: %s"), + mu_strerror(rc)); + exit(EX_SOFTWARE); + } + mu_url_destroy(&mu_dbm_hint); + mu_dbm_hint = dbhint; + } + if (!run) { mu_error(_("you must specify one of --list, --delete," " --expire or --compat")); diff --git a/src/savsrv.c b/src/savsrv.c index be1aa758..a987a465 100644 --- a/src/savsrv.c +++ b/src/savsrv.c @@ -38,7 +38,6 @@ #include "srvcfg.h" #include "callout.h" #include "mfdb.h" -#include "mf-dbm.h" #include "callout-dbgmod.h" char *ehlo_domain; diff --git a/src/srvcfg.c b/src/srvcfg.c index 0afb7f6a..4030a4e6 100644 --- a/src/srvcfg.c +++ b/src/srvcfg.c @@ -21,6 +21,7 @@ #include <mailutils/mailutils.h> #include <mailutils/libargp.h> +#include <mailutils/dbm.h> #include <argp.h> #include <sysexits.h> #include "xalloc.h" @@ -41,6 +42,7 @@ int smtp_transcript; static int transcript_option; struct mu_sockaddr *source_address; /* Source address for TCP connections */ int mtasim_option; /* mtasim compatibility mode */ +char *db_type_str = DEFAULT_DB_TYPE; size_t max_callout_mx = MAXMXCOUNT; @@ -614,6 +616,9 @@ static struct mu_cfg_param srv_cfg_param[] = { { "state-directory", mu_cfg_callback, NULL, 0, cb_state_directory, N_("Set program state directory."), N_("dir") }, + { "database-type", mu_cfg_string, &db_type_str, 0, NULL, + N_("Default database type"), + N_("type") }, { "database", mu_cfg_section, NULL, 0, NULL, NULL }, { "ehlo-domain", mu_cfg_string, &ehlo_domain, 0, NULL, N_("Set the domain name for EHLO command.") }, @@ -861,6 +866,20 @@ mf_srvcfg_flu |