diff options
-rw-r--r-- | configure.ac | 199 | ||||
-rw-r--r-- | lib/Makefile.am | 4 | ||||
-rw-r--r-- | lib/cache.c | 106 | ||||
-rw-r--r-- | lib/db.c | 294 | ||||
-rw-r--r-- | lib/dbcfg.c | 15 | ||||
-rw-r--r-- | lib/greylist.c | 12 | ||||
-rw-r--r-- | lib/libmf.h | 1 | ||||
-rw-r--r-- | lib/mf-dbm.c | 658 | ||||
-rw-r--r-- | lib/mf-dbm.h | 75 | ||||
-rw-r--r-- | lib/mfdb.h | 9 | ||||
-rw-r--r-- | lib/rate.c | 67 | ||||
-rw-r--r-- | lib/tbf_rate.c | 60 | ||||
-rw-r--r-- | lib/utils.c | 9 | ||||
-rw-r--r-- | po/POTFILES.in | 1 | ||||
-rw-r--r-- | src/Makefile.am | 3 | ||||
-rw-r--r-- | src/builtin/db.bi | 410 | ||||
-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 |
21 files changed, 670 insertions, 1403 deletions
diff --git a/configure.ac b/configure.ac index 0e975fc6..136e037b 100644 --- a/configure.ac +++ b/configure.ac @@ -105,13 +105,13 @@ gl_INIT AH_BOTTOM([ /* program_name is used by lib/error.c */ #define program_name program_invocation_name ]) # Check for GNU Mailutils -AM_GNU_MAILUTILS([2.99.94], [all auth sieve cfg argp], [:]) +AM_GNU_MAILUTILS([2.99.94], [all auth dbm sieve cfg argp], [:]) AC_CHECK_TYPES([struct mu_argp_node_list],,,[#include <mailutils/libargp.h>]) ### Check for Emacs site-lisp directory AM_PATH_LISPDIR if test "$EMACS" != "no"; then @@ -142,200 +142,47 @@ if test $syslog_async = "yes"; then AC_DEFINE_UNQUOTED([DEFAULT_SYSLOG_ASYNC],$DEFAULT_SYSLOG_ASYNC, [Define to 1 to use syslog_async by default]) AC_SUBST([BUILD_SYSLOG_ASYNC], '$(SYSLOG_ASYNC_O)') AC_DEFINE([USE_SYSLOG_ASYNC], [1], [Define if syslog-async is being used]) fi -# Check for DBM flavor -AH_TEMPLATE(BDB2_CURSOR_LASTARG, - [Last argument to the cursor member of Berkeley 2 DB structure]) - -dnl The cursor member of DB structure used to take three arguments in older -dnl implementations of Berkeley DB. Newer versions (>= 4.0) declare -dnl it as taking four arguments. -dnl This macro checks which of the variants we have. -AC_DEFUN([MU_DB2_CURSOR], - [AC_CACHE_CHECK([whether db->cursor takes 4 arguments], - [mu_cv_bdb2_cursor_four_args], - [AC_TRY_COMPILE([#include <db.h>], - [ -DB *db; -db->cursor(NULL, NULL, NULL, 0) - ], - [mu_cv_bdb2_cursor_four_args=yes], - [mu_cv_bdb2_cursor_four_args=no])]) - if test $mu_cv_bdb2_cursor_four_args = yes; then - AC_DEFINE(BDB2_CURSOR_LASTARG,[,0]) - else - AC_DEFINE(BDB2_CURSOR_LASTARG,[]) - fi]) - -AH_TEMPLATE([WITH_BDB], - [Define to the major version of Berkeley DB library to use]) - -use_dbm=no -status_dbm=no - +AC_ARG_VAR([DEFAULT_DB_TYPE],[Set default database type]) + AC_ARG_WITH([gdbm], - AC_HELP_STRING([--with-gdbm], - [use GNU DBM]), + AC_HELP_STRING([--with-gdbm], + [use GNU DBM by default]), [ case "${withval}" in - yes) use_dbm=GDBM ;; - no) use_dbm=no ;; + yes) DEFAULT_DB_TYPE=gdbm;; + no) ;; *) AC_MSG_ERROR(bad value ${withval} for --with-gdbm) ;; esac]) -## Support --with-db2 for backward compatibility -if test "${with_db2+set}" = set; then - case "${with_db2}" in - yes) use_dbm=BDB2 ;; - no) use_dbm=no ;; - *) AC_MSG_ERROR(bad value ${with_db2} for --with-db2) ;; - esac -fi - AC_ARG_WITH([berkeley-db], - AC_HELP_STRING([--with-berkeley-db@<:@=version@:>@], - [use Berkeley DB]), + AC_HELP_STRING([--with-berkeley-db], + [use Berkeley DB by default]), [ case "${withval}" in - yes) use_dbm=BDB ;; - no) use_dbm=no ;; - *) use_dbm=BDB="${withval}";; + no) ;; + *) DEFAULT_DB_TYPE=bdb;; esac]) -## Set the variable status_dbm to $1 if: -## -## 1. Function $3 is defined in the library $2 -## 2. Header file db.h is available -## -## Then check if the major version, minor version and patchlevel of the -## library matches those from the header. If so, define WITH_BDB -## to the version (i.e. $1 with all dots removed). Otherwise, report -## an error and stop. -## -check_bdb() { - ver=`echo $1 | tr -d '.'` - major=`expr $ver : '\(.\).*'` - AC_CHECK_LIB($2, $3, - [AC_CHECK_HEADERS(db.h) - if test $ac_cv_header_db_h = yes; then - LIBS="$LIBS -l$2" - MU_DB2_CURSOR - status_dbm=$1 - fi]) - if test $status_dbm = no; then - : - else - AC_RUN_IFELSE( - [AC_LANG_PROGRAM([#include "db.h"], - [int v_major, v_minor, v_patch; - db_version(&v_major, &v_minor, &v_patch); - return !(DB_VERSION_MAJOR == $major - && v_major == DB_VERSION_MAJOR - && v_minor == DB_VERSION_MINOR - && v_patch == DB_VERSION_PATCH); - ])], - [AC_DEFINE_UNQUOTED(WITH_BDB,$ver)], - [status_dbm=no]) - fi -} - -AC_SUBST(MU_COMMON_INCLUDES) - -## Check for the Berkeley DB library version $1, assuming Slackware-like -## installation layout (header files in /usr/incude/db$vn and library named -## libdb-$version.so, where $version is the library version and $vn is -## $version with all dots removed. -## -check_slackware_bdb() { - dir=db`echo $1|tr -d '.'` - save_CPPFLAGS=$CPPFLAGS - while test -n "$dir" - do - if test -d /usr/include/$dir; then - CPPFLAGS="$CPPFLAGS -I/usr/include/$dir" - break - elif test -d /usr/local/include/$dir; then - CPPFLAGS="$CPPFLAGS -I/usr/local/include/$dir" - break - fi - dir=`expr "$dir" : '\(.*\)[[0-9]]$'` - done - check_bdb $1 db-$1 db_create - CPPFLAGS=$save_CPPFLAGS - if test $status_dbm = "$1"; then - MU_COMMON_INCLUDES="$MU_COMMON_INCLUDES -I/usr/include/$dir" - fi -} - -try_dbm() { - case "$1" in - GDBM) - AC_CHECK_LIB(gdbm, gdbm_open, - [AC_CHECK_HEADERS(gdbm.h, - AC_DEFINE(WITH_GDBM,1, - [Enable use of GNU DBM library])) - LIBS="$LIBS -lgdbm" - POPAUTH='popauth$(EXEEXT)' - status_dbm=GDBM]);; - - BDB2) check_bdb 2 db db_open - test "$status_dbm" != "no" && status_dbm="Berkeley DB v. $status_dbm";; - - BDB) for version in 4 3 2 - do - case $version in - 4|3) func=db_create;; - 2) func=db_open;; - esac - check_bdb $version db $func - if test "$status_dbm" != no; then - status_dbm="Berkeley DB v. $status_dbm" - break; - fi - done;; - - BDB=*) - name=`expr $1 : 'BDB=\(.*\)'` - case $name in - [[0-9]]*) check_slackware_bdb $name;; - *) for version in 4 3 2 - do - case $version in - 4|3) func=db_create;; - 2) func=db_open;; - esac - check_bdb $version $name $func - if test "$status_dbm" != no; then - break; - fi - done - ;; - esac - test "$status_dbm" != "no" && status_dbm="Berkeley DB v. $status_dbm" - ;; - esac -} - -if test $use_dbm = no; then - # Try all possible DBM values - for use_dbm in BDB GDBM - do - try_dbm $use_dbm - if test "$status_dbm" != no; then - break - fi - done +AH_TEMPLATE([DEFAULT_DB_TYPE], [Define default database type]) +if test -n "$DEFAULT_DB_TYPE"; then + if mu info $DEFAULT_DB_TYPE >/dev/null; then + AC_MSG_ERROR([requested DBM type $DEFAULT_DB_TYPE not supported by Mailutils]) + fi else - try_dbm $use_dbm + # Traditionally Mailfromd preferred Berkeley DB over GDBM + DEFAULT_DB_TYPE=`mu info bdb gdbm | head -n 1 | sed 's/WITH_//' | tr A-Z a-z` fi - -if test "$status_dbm" = "no"; then - AC_MSG_ERROR([Cannot find DBM library to link with.]) +if test -n "$DEFAULT_DB_TYPE"; then + AC_DEFINE_UNQUOTED([DEFAULT_DB_TYPE], "$DEFAULT_DB_TYPE") + status_dbm=$DEFAULT_DB_TYPE +else + AC_DEFINE_UNQUOTED([DEFAULT_DB_TYPE], NULL) fi ## Preprocessor AC_ARG_WITH([preprocessor], AC_HELP_STRING([--without-preprocessor], [do not use external preprocessor]), diff --git a/lib/Makefile.am b/lib/Makefile.am index d3854538..42025942 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -12,13 +12,13 @@ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. -noinst_LIBRARIES=libmf.a libdbm.a libmfdb.a +noinst_LIBRARIES=libmf.a libmfdb.a noinst_HEADERS = \ libmf.h\ syslog_async.h\ mudefs.h\ dns.h\ @@ -52,14 +52,12 @@ libmf_a_SOURCES=\ vercmp.c\ version.c libmf_a_LIBADD=$(LIBOBJS) $(BUILD_SYSLOG_ASYNC) libmf_a_DEPENDENCIES=$(BUILD_SYSLOG_ASYNC) -libdbm_a_SOURCES = mf-dbm.c mf-dbm.h - libmfdb_a_SOURCES = \ db.c\ dbcfg.c\ cache.c\ greylist.c\ rate.c\ diff --git a/lib/cache.c b/lib/cache.c index 0abd7141..b15cbf9a 100644 --- a/lib/cache.c +++ b/lib/cache.c @@ -19,21 +19,20 @@ # include <config.h> #endif #include <mailutils/mailutils.h> #include "libmf.h" #include "mfdb.h" -#include "mf-dbm.h" #include "filenames.h" time_t negative_expire_interval;//FIXME time_t tempfail_expire_interval = 37*60;/* FIXME: Equals to the sum of the ``hard'' timeouts */ -static void cache_print_item(const char *email, size_t size, - const void *content, size_t contsize); +static void cache_print_item(struct mu_dbm_datum const *key, + struct mu_dbm_datum const *val); static int cache_expire_item(const void *content); static struct db_format cache_format_struct = { "cache", DEFAULT_DATABASE, 1, @@ -66,42 +65,39 @@ format_timestr(time_t timestamp, char *timebuf, size_t bufsize) } mf_status cache_get(const char *email) { mf_status 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; + int result; int readonly = 0; - int res; - + if (!cache_format->enabled) return mf_failure; - + mu_debug(cache_format->debug_handle, MU_DEBUG_TRACE5, ("getting cache info for %s", email)); - if (mf_dbm_open(cache_format->dbname, &db, MU_STREAM_RDWR, 0600, - &readonly)) { - mu_error(_("mf_dbm_open(%s) failed: %s"), cache_format->dbname, - mf_dbm_strerror()); - return mf_failure; + db = mf_dbm_open(cache_format->dbname, MU_STREAM_RDWR, 0600); + if (!db) { + db = mf_dbm_open(cache_format->dbname, MU_STREAM_READ, 0600); + if (!db) + return mf_failure; + readonly = 1; } - if (readonly) - mu_debug(cache_format->debug_handle, MU_DEBUG_TRACE0, - ("cannot lock %s: switching to read-only mode", - cache_format->dbname)); memset (&key, 0, sizeof key); memset (&contents, 0, sizeof contents); - MF_DATUM_PTR (key) = (void*) email; - MF_DATUM_SIZE (key) = strlen (email) + 1; - if ((res = mf_dbm_fetch(&db, key, &contents)) == 0) { + key.mu_dptr = (void*) email; + key.mu_dsize = strlen (email) + 1; + if ((result = mu_dbm_fetch(db, &key, &contents)) == 0) { char timebuf[80]; struct cache_result *res = (struct cache_result *) - MF_DATUM_PTR(contents); + contents.mu_dptr; time_t t = time(NULL); mu_debug(cache_format->debug_handle, MU_DEBUG_TRACE5, ("found status: %s (%d), time: %s", mf_status_str(res->status), res->status, format_timestr(res->timestamp, timebuf, sizeof timebuf))); @@ -109,78 +105,84 @@ cache_get(const char *email) if (t - res->timestamp > EXPIRE_INTERVAL(res->status)) { if (!readonly) { mu_debug(cache_format->debug_handle, MU_DEBUG_TRACE5, ("removing expired entry for %s", email)); - if (mf_dbm_delete(&db, key)) + result = mu_dbm_delete(db, &key); + if (result) mu_error(_("cannot remove record `%s' from `%s': %s"), - email, db.name, - mf_dbm_strerror()); + email, cache_format->dbname, + result == MU_ERR_FAILURE ? + mu_dbm_strerror(db) : + mu_strerror(result)); + } rc = mf_failure; } else { rc = res->status; } } else { - if (res != MU_ERR_NOENT) + if (result == MU_ERR_FAILURE) mu_error(_("cannot fetch record `%s' from `%s': %s"), - email, db.name, mf_dbm_strerror()); + email, cache_format->dbname, + mu_dbm_strerror(db)); rc = mf_failure; } - mf_dbm_datum_free(&contents); - mf_dbm_close(&db); + mu_dbm_datum_free(&contents); + mu_dbm_destroy(&db); return rc; } void cache_insert(const char *email, mf_status 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; struct cache_result res; char timebuf[80]; + int result; if (!cache_format->enabled) return; time(&res.timestamp); res.status = rc; mu_debug(cache_format->debug_handle, MU_DEBUG_TRACE5, ("inserting cache info for %s. status=%s (%d), time=%s", email, mf_status_str(rc), rc, format_timestr(res.timestamp, timebuf, sizeof timebuf))); - if (mf_dbm_open(cache_format->dbname, &db, MU_STREAM_RDWR, - 0600, NULL)) { - mu_error(_("mf_dbm_open(%s) failed: %s"), cache_format->dbname, - mf_dbm_strerror()); + db = mf_dbm_open(cache_format->dbname, MU_STREAM_RDWR, 0600); + if (!db) return; - } - + memset(&key, 0, sizeof key); memset(&contents, 0, sizeof contents); - MF_DATUM_PTR(key) = (void*) email; - MF_DATUM_SIZE(key) = strlen (email) + 1; - MF_DATUM_PTR(contents) = (void*)&res; - MF_DATUM_SIZE(contents) = sizeof(res); - if (mf_dbm_insert(&db, key, contents, 1)) - mu_error(_("cannot insert datum `%s' into `%s': %s"), - email, db.name, mf_dbm_strerror()); + key.mu_dptr = (void*) email; + key.mu_dsize = strlen (email) + 1; + contents.mu_dptr = (void*)&res; + contents.mu_dsize = sizeof(res); + result = mu_dbm_store(db, &key, &contents, 1); + if (result) + mu_error(_("cannot store datum `%s' into `%s': %s"), + email, cache_format->dbname, + result == MU_ERR_FAILURE ? + mu_dbm_strerror(db) : mu_strerror(result)); - mf_dbm_close(&db); + mu_dbm_destroy(&db); } static void -cache_print_item(const char *email, size_t size, const void *content, - size_t contsize) +cache_print_item(struct mu_dbm_datum const *key, + struct mu_dbm_datum const *val) { - const struct cache_result *res = content; - - size--; /* Size includes the trailing nul */ - printf("%*.*s", size, size, email); + const struct cache_result *res = (const struct cache_result *) + val->mu_dptr; + int size = key->mu_dsize - 1; /* Size includes the trailing nul */ + printf("%*.*s", size, size, key->mu_dptr); printf(" %10.10s ", mf_status_str(res->status)); format_time_str(stdout, res->timestamp); putchar('\n'); } static int @@ -25,13 +25,12 @@ #define obstack_chunk_alloc malloc #define obstack_chunk_free free #include "obstack.h" #include "libmf.h" #include "mfdb.h" -#include "mf-dbm.h" int ignore_failed_reads_option;//FIXME; struct db_fmt_list { struct db_fmt_list *next; struct db_format fmt; @@ -85,149 +84,191 @@ db_format_setup() cache_format = db_format_install(cache_format); rate_format = db_format_install(rate_format); tbf_rate_format = db_format_install(tbf_rate_format); greylist_format = db_format_install(greylist_format); } +int +mf_file_mode_to_safety_criteria(int mode) +{ + int fl = 0; + + if (!(mode & 0002)) + fl |= MU_FILE_SAFETY_WORLD_WRITABLE; + if (!(mode & 0004)) + fl |= MU_FILE_SAFETY_WORLD_READABLE; + if (!(mode & 0020)) + fl |= MU_FILE_SAFETY_GROUP_WRITABLE; + if (!(mode & 0040)) + fl |= MU_FILE_SAFETY_GROUP_READABLE; + return fl; +} + +mu_dbm_file_t +mf_dbm_open(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) { + mu_error(_("unable to create database %s: %s"), + dbname, mu_strerror (rc)); + return NULL; + } + + 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 NULL; + } + + rc = mu_dbm_open(db, access, mode); + if (rc) { + mu_error(_("mu_dbm_open(%s) failed: %s (%s)"), dbname, + mu_strerror (rc), mu_strerror (errno)); + return NULL; + } + return db; +} int db_list_item(char *dbname, char *email, db_item_printer_t fun) { - MF_DBM_FILE db; - MF_DBM_DATUM key, contents; + mu_dbm_file_t db; + struct mu_dbm_datum key, contents; int rc = 1; - int res; - - if (mf_dbm_open(dbname, &db, MU_STREAM_READ, 0600, NULL)) { - mu_error(_("mf_dbm_open(%s) failed: %s"), dbname, - mf_dbm_strerror()); + + db = mf_dbm_open(dbname, MU_STREAM_READ, 0600); + if (!db) return 1; - } - memset (&contents, 0, sizeof contents); + memset(&contents, 0, sizeof contents); memset(&key, 0, sizeof key); - MF_DATUM_PTR(key) = email; - MF_DATUM_SIZE(key) = strlen (email) + 1; - if ((res = mf_dbm_fetch(&db, key, &contents)) == 0) { - fun(MF_DATUM_PTR(key), - MF_DATUM_SIZE(key), - MF_DATUM_PTR(contents), - MF_DATUM_SIZE(contents)); - rc = 0; - } else if (res != MU_ERR_NOENT) + key.mu_dptr = email; + key.mu_dsize = strlen (email) + 1; + rc = mu_dbm_fetch(db, &key, &contents); + if (rc == 0) { + fun(&key, &contents); + } else if (rc != MU_ERR_NOENT) { mu_error(_("cannot fetch record `%s' from `%s': %s"), - email, db.name, mf_dbm_strerror()); - - mf_dbm_close(&db); + email, dbname, mu_dbm_strerror(db)); + rc = 0; + } + mu_dbm_destroy(&db); return rc; } -typedef int (*db_enum_func)(MF_DBM_DATUM key, MF_DBM_DATUM cnt, void *data); +typedef int (*db_enum_func)(struct mu_dbm_datum *key, + struct mu_dbm_datum *cnt, void *data); int -db_enumerate(MF_DBM_FILE *db, db_enum_func fun, void *data) +db_enumerate(mu_dbm_file_t db, db_enum_func fun, void *data) { int rc = 0; - int res; - MF_DBM_DATUM key, prev, contents; - - for (res = mf_dbm_firstkey (db, &key); res == 0; - prev = key, - res = mf_dbm_nextkey (db, prev, &key), - mf_dbm_datum_free(&prev)) { - memset (&contents, 0, sizeof contents); - if (mf_dbm_fetch (db, key, &contents) == 0) { - int fr = fun(key, contents, data); - mf_dbm_datum_free(&contents); - if (fr) { - mf_dbm_datum_free(&key); + int ret = 0; + struct mu_dbm_datum key, contents; + const char *name = ""; + + mu_dbm_get_name(db, &name); + + memset(&key, 0, sizeof key); + memset(&contents, 0, sizeof contents); + for (rc = mu_dbm_firstkey(db, &key); rc == 0; + rc = mu_dbm_nextkey(db, &key)) { + int res = mu_dbm_fetch(db, &key, &contents); + if (res == 0) { + res = fun(&key, &contents, data); + if (res) { + mu_dbm_datum_free(&key); break; } + mu_dbm_datum_free(&contents); } else { mu_error(_("cannot fetch data `%*.*s' from `%s': %s"), - MF_DATUM_SIZE(key), MF_DATUM_SIZE(key), - (char*) MF_DATUM_PTR(key), - db->name, - mf_dbm_strerror()); - rc = 1; + key.mu_dsize, key.mu_dsize, key.mu_dptr, + name, + mu_dbm_strerror(db)); + ret = 1; } } - if (res != MU_ERR_NOENT) { + if (rc != MU_ERR_NOENT) { mu_error(_("unexpected error scanning database %s: %s"), - db->name, mf_dbm_strerror()); - rc = 1; + name, mu_dbm_strerror(db)); + ret = 1; } - return rc; + return ret; } static int -db_list_func(MF_DBM_DATUM key, MF_DBM_DATUM contents, void *data) +db_list_func(struct mu_dbm_datum *key, struct mu_dbm_datum *contents, + void *data) { db_item_printer_t fun = data; - fun(MF_DATUM_PTR(key), MF_DATUM_SIZE(key), - MF_DATUM_PTR(contents), MF_DATUM_SIZE(contents)); + fun(key, contents); return 0; } int db_list(char *dbname, db_item_printer_t fun) { - MF_DBM_FILE db; - - if (mf_dbm_open(dbname, &db, MU_STREAM_READ, 0600, NULL)) { - mu_error(_("mf_dbm_open(%s) failed: %s"), dbname, - mf_dbm_strerror()); + mu_dbm_file_t db = mf_dbm_open(dbname, MU_STREAM_READ, 0600); + if (!db) return 1; - } - db_enumerate(&db, db_list_func, fun); - mf_dbm_close(&db); + db_enumerate(db, db_list_func, fun); + mu_dbm_destroy(&db); return 1; } struct expire_data { db_expire_t fun; struct obstack stk; size_t key_count; }; static int -db_expire_func(MF_DBM_DATUM key, MF_DBM_DATUM contents, void *data) +db_expire_func(struct mu_dbm_datum *key, struct mu_dbm_datum *contents, + void *data) { struct expire_data *dp = data; - if (dp->fun(MF_DATUM_PTR(contents))) { - size_t size = MF_DATUM_SIZE(key); - obstack_grow(&dp->stk, &size, sizeof size); - obstack_grow(&dp->stk, MF_DATUM_PTR(key), size); + if (dp->fun(contents)) { + obstack_grow(&dp->stk, &contents->mu_dsize, + sizeof contents->mu_dsize); + obstack_grow(&dp->stk, key->mu_dptr, key->mu_dsize); dp->key_count++; } return 0; } int db_expire(char *dbname, db_expire_t fun) { - MF_DBM_FILE db; - MF_DBM_DATUM key; + mu_dbm_file_t db; + struct mu_dbm_datum key; struct expire_data ed; size_t size; char *base, *p; size_t i; int rc = 0; - - if (mf_dbm_open(dbname, &db, MU_STREAM_RDWR, 0600, NULL)) { - mu_error(_("mf_dbm_open(%s) failed: %s"), dbname, - mf_dbm_strerror()); + + db = mf_dbm_open(dbname, MU_STREAM_RDWR, 0600); + if (!db) return 1; - } ed.fun = fun; obstack_init(&ed.stk); ed.key_count = 0; mu_debug(debug_handle, MU_DEBUG_TRACE0, ("Expiring %s: mark phase", dbname)); - if (db_enumerate(&db, db_expire_func, &ed)) + if (db_enumerate(db, db_expire_func, &ed)) rc = !ignore_failed_reads_option; size = 0; obstack_grow(&ed.stk, &size, sizeof size); mu_debug(debug_handle, MU_DEBUG_TRACE0, @@ -236,57 +277,56 @@ db_expire(char *dbname, db_expire_t fun) (unsigned) obstack_memory_used(&ed.stk))); mu_debug(debug_handle, MU_DEBUG_TRACE0, ("Expiring %s: sweep phase", dbname)); base = obstack_finish(&ed.stk); + memset(&key, 0, sizeof key); for (i = 0, p = base; i < ed.key_count; i++) { size = *(size_t*)p; p += sizeof(size_t); mu_debug(debug_handle, MU_DEBUG_TRACE5, ("Remove: %*.*s", size, size, p)); - MF_DATUM_PTR(key) = p; - MF_DATUM_SIZE(key) = size; - if (mf_dbm_delete(&db, key)) { + key.mu_dptr = p; + key.mu_dsize = size; + rc = mu_dbm_delete(db, &key); + if (rc && rc != MU_ERR_NOENT) { mu_error (_("cannot remove record `%*.*s' from `%s': %s"), - size, size, p, db.name, mf_dbm_strerror()); + size, size, p, dbname, mu_dbm_strerror(db)); rc = 1; } p += size; } mu_debug(debug_handle, MU_DEBUG_TRACE0, ("Finished expiring %s", dbname)); obstack_free(&ed.stk, NULL); - mf_dbm_close(&db); + mu_dbm_destroy(&db); return rc; } int db_delete(char *dbname, char *id) { - MF_DBM_FILE db; - MF_DBM_DATUM key; + mu_dbm_file_t db; + struct mu_dbm_datum key; int rc; - if (mf_dbm_open(dbname, &db, MU_STREAM_RDWR, 0600, NULL)) { - mu_error(_("mf_dbm_open(%s) failed: %s"), dbname, - mf_dbm_strerror()); + db = mf_dbm_open(dbname, MU_STREAM_RDWR, 0600); + if (!db) return 1; - } memset(&key, 0, sizeof key); - MF_DATUM_PTR(key) = id; - MF_DATUM_SIZE(key) = strlen (id) + 1; - if (mf_dbm_delete(&db, key)) { + key.mu_dptr = id; + key.mu_dsize = strlen (id) + 1; + rc = mu_dbm_delete(db, &key); + if (rc) { mu_error(_("cannot remove record `%s' from `%s': %s"), id, - dbname, mf_dbm_strerror()); - rc = 1; - } else - rc = 0; - mf_dbm_close(&db); + dbname, mu_dbm_strerror(db)); + } + mu_dbm_destroy(&db); return rc; } static char * make_tmp_name(char *dbname) { @@ -310,88 +350,90 @@ make_tmp_name(char *dbname) return newname; } struct compact_data { int rc; db_expire_t fun; - MF_DBM_FILE ndb; + mu_dbm_file_t ndb; }; static int -db_compact_func(MF_DBM_DATUM key, MF_DBM_DATUM contents, void *data) +db_compact_func(struct mu_dbm_datum *key, struct mu_dbm_datum *contents, + void *data) { struct compact_data *dp = data; - - if (!dp->fun || dp->fun(MF_DATUM_PTR(contents)) == 0) { - if (((char*)MF_DATUM_PTR(key))[MF_DATUM_SIZE(key) - 1]) { + int rc; + const char *name; + + mu_dbm_get_name(dp->ndb, &name); + + if (!dp->fun || dp->fun(contents) == 0) { + if (((char*)key->mu_dptr)[key->mu_dsize - 1]) { /* Old database format. Convert. */ - size_t size; char *p; - MF_DBM_DATUM newkey; - - size = MF_DATUM_SIZE(key); - p = malloc(size+1); - if (!MF_DATUM_PTR(newkey)) { + struct mu_dbm_datum newkey; + + p = malloc(key->mu_dsize + 1); + if (!p) { mu_error(_("not enough memory")); return 1; } - memcpy(p, MF_DATUM_PTR(key), size); - p[size] = 0; - + memcpy(p, key->mu_dptr, key->mu_dsize); + p[key->mu_dsize] = 0; + memset(&newkey, 0, sizeof newkey); - MF_DATUM_SIZE(newkey) = size+1; - MF_DATUM_PTR(newkey) = p; - if (mf_dbm_insert(&dp->ndb, newkey, contents, 1)) { + newkey.mu_dptr = p; + newkey.mu_dsize = key->mu_dsize + 1; + rc = mu_dbm_store(dp->ndb, &newkey, contents, 1); + if (rc) { mu_error(_("cannot insert datum `%s' into `%s': %s"), - p, dp->ndb.name, - mf_dbm_strerror()); + p, name, + rc == MU_ERR_FAILURE ? + mu_dbm_strerror(dp->ndb) : + mu_strerror(rc)); dp->rc = 1; } free(p); - } else if (mf_dbm_insert(&dp->ndb, key, contents, 1)) { + } else if ((rc = mu_dbm_store(dp->ndb, key, contents, 1))) { mu_error(_("cannot insert datum `%*.*s' into `%s': %s"), - MF_DATUM_SIZE(key), MF_DATUM_SIZE(key), - (char*) MF_DATUM_PTR(key), - dp->ndb.name, - mf_dbm_strerror()); + key->mu_dsize, key->mu_dsize, + (char*) key->mu_dsize, + name, + rc == MU_ERR_FAILURE ? + mu_dbm_strerror(dp->ndb) : + mu_strerror(rc)); dp->rc = 1; } } return 0; } int db_compact(char *dbname, db_expire_t fun) { - MF_DBM_FILE odb; + mu_dbm_file_t odb; char *tmpname; struct compact_data dat; mu_debug(debug_handle, MU_DEBUG_TRACE0, ("Compacting database `%s'", dbname)); tmpname = make_tmp_name(dbname); - if (mf_dbm_open(dbname, &odb, MU_STREAM_READ, 0600, NULL)) { - mu_error(_("mf_dbm_open(%s) failed: %s"), dbname, - mf_dbm_strerror()); - return 1; - } + odb = mf_dbm_open(dbname, MU_STREAM_READ, 0600); dat.rc = 0; dat.fun = fun; - if (mf_dbm_open(tmpname, &dat.ndb, MU_STREAM_CREAT, 0600, NULL)) { - mu_error(_("mf_dbm_open(%s) failed: %s"), tmpname, - mf_dbm_strerror()); + dat.ndb = mf_dbm_open(tmpname, MU_STREAM_CREAT, 0600); + if (!dat.ndb) return 1; - } - db_enumerate(&odb, db_compact_func, &dat); + db_enumerate(odb, db_compact_func, &dat); - mf_dbm_close(&dat.ndb); - mf_dbm_close(&odb); + mu_dbm_destroy(&dat.ndb); + mu_dbm_destroy(&odb); if (dat.rc == 0) { if (unlink(dbname)) { mu_error(_("cannot unlink %s: %s"), dbname, mu_strerror(errno)); dat.rc = 1; diff --git a/lib/dbcfg.c b/lib/dbcfg.c index 96700e6b..39daee56 100644 --- a/lib/dbcfg.c +++ b/lib/dbcfg.c @@ -58,19 +58,19 @@ cb_db_positive_expire_interval(void *data, mu_config_value_t *arg) static int cb_db_negative_expire_interval(void *data, mu_config_value_t *arg) { struct db_format *fmt = data; struct timeval tv; - int rc = config_cb_timeout (&tv, arg); + int rc = config_cb_timeout(&tv, arg); if (fmt == cache_format) negative_expire_interval = tv.tv_sec; else - mu_error (_("negative-expire-interval is valid only " - "for cache database")); + mu_error(_("negative-expire-interval is valid only " + "for cache database")); return rc; } int cb_database_file(void *data, mu_config_value_t *arg) { @@ -106,27 +106,26 @@ database_section_parser (enum mu_cfg_section_stage stage, const mu_cfg_node_t *node, const char *section_label, void **section_data, void *call_data, mu_cfg_tree_t *tree) { switch (stage) { - case mu_cfg_section_start: - { + case mu_cfg_section_start: { struct db_format *fmt; if (mu_cfg_assert_value_type(node->label, MU_CFG_STRING)) return 0; fmt = db_format_lookup(node->label->v.string); |