Hello!
Is there anybody interested in CDB support for auth dicts?
I've implemented simple patch for it.
diff --git a/configure.in b/configure.in
index a4e5b5a..89e076e 100644
--- a/configure.in
+++ b/configure.in
@@ -121,6 +121,11 @@ AS_HELP_STRING([--with-vpopmail], [Build with vpopmail support (auto)]),
# want_db=no)
want_db=no
+AC_ARG_WITH(cdb,
+AS_HELP_STRING([--with-cdb], [Build with CDB support]),
+ TEST_WITH(cdb, $withval),
+ want_cdb=no)
+
dnl The --with-sql is useful only if Dovecot is being built with all the SQL
dnl drivers as modules. If any SQL driver is built-in, this option is ignored.
AC_ARG_WITH(sql,
@@ -2110,6 +2115,27 @@ if test $want_db != no; then
fi
fi
+if test $want_cdb != no; then
+ AC_CHECK_LIB(cdb, cdb_init, [
+ AC_CHECK_HEADER(cdb.h, [
+ CDB_LIBS="$CDB_LIBS -lcdb"
+ AC_DEFINE(BUILD_CDB,, Build with CDB support)
+ ], [
+ if test $want_cdb = yes; then
+ AC_ERROR([Can't build with CDB support: cdb.h not found])
+ fi
+ ])
+ ], [
+ if test $want_cdb = yes; then
+ AC_ERROR([Can't build with CDB support: libcdb not found])
+ fi
+ ])
+echo "CDB_LIBS: $CDB_LIBS"
+ if test "$CDB_LIBS" != ""; then
+ LIBS="$LIBS $CDB_LIBS"
+ fi
+fi
+
if test $want_pgsql != no; then
AC_CHECK_PROG(PG_CONFIG, pg_config, pg_config, NO)
if test $PG_CONFIG = NO; then
@@ -2394,6 +2420,7 @@ AC_SUBST(SQLITE_CFLAGS)
AC_SUBST(SQLITE_LIBS)
AC_SUBST(DICT_LIBS)
+AC_SUBST(CDB_LIBS)
AC_SUBST(dict_drivers)
dnl **
diff --git a/src/lib-dict/Makefile.am b/src/lib-dict/Makefile.am
index 31d3522..a447a90 100644
--- a/src/lib-dict/Makefile.am
+++ b/src/lib-dict/Makefile.am
@@ -14,6 +14,7 @@ base_sources = \
dict.c \
dict-client.c \
dict-file.c \
+ dict-cdb.c \
dict-memcached.c \
dict-redis.c
diff --git a/src/lib-dict/dict-cdb.c b/src/lib-dict/dict-cdb.c
new file mode 100644
index 0000000..49e5ac0
--- /dev/null
+++ b/src/lib-dict/dict-cdb.c
@@ -0,0 +1,137 @@
+/* Copyright (c) 2006-2012 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+
+#ifdef BUILD_CDB
+#include "dict-private.h"
+#include "safe-memset.h"
+
+#include <string.h>
+#include <cdb.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#define CDB_WITH_NULL 1
+#define CDB_WITHOUT_NULL 2
+
+struct cdb_dict {
+ struct dict dict;
+ struct cdb cdb;
+ char *path;
+ int fd, flag;
+};
+
+static void cdb_dict_deinit(struct dict *_dict);
+
+static struct dict *
+cdb_dict_init(struct dict *driver, const char *uri,
+ enum dict_data_type value_type ATTR_UNUSED,
+ const char *username ATTR_UNUSED, const char *base_dir ATTR_UNUSED)
+{
+ struct cdb_dict *dict;
+
+ dict = i_new(struct cdb_dict, 1);
+
+ dict->dict = *driver;
+ dict->path = i_strdup(uri);
+ dict->flag = CDB_WITH_NULL | CDB_WITHOUT_NULL;
+
+ /* initialize cdb to 0 (unallocated) */
+ safe_memset(&dict->cdb, 0, sizeof(struct cdb));
+
+ dict->fd = open(dict->path, O_RDONLY);
+ if (dict->fd == -1) {
+ i_error("open(%s) failed: %m", dict->path);
+ cdb_dict_deinit(&dict->dict);
+ return NULL;
+ }
+
+#ifdef TINYCDB_VERSION
+ if (cdb_init(&dict->cdb, dict->fd) < 0) {
+ i_error("cdb_init(%s) failed: %m", dict->path);
+ cdb_dict_deinit(&dict->dict);
+ return NULL;
+ }
+#else
+ cdb_init(&dict->cdb, dict->fd);
+#endif
+
+ return &dict->dict;
+}
+static void cdb_dict_deinit(struct dict *_dict)
+{
+ struct cdb_dict *dict = (struct cdb_dict *)_dict;
+
+ /* we can safely deinit unallocated cdb */
+ cdb_free(&dict->cdb);
+
+ if (dict->fd != -1) {
+ if (close(dict->fd) < 0)
+ i_error("close(%s) failed: %m", dict->path);
+ }
+
+ i_free(dict->path);
+ i_free(dict);
+}
+
+static int cdb_dict_lookup(struct dict *_dict, pool_t pool,
+ const char *key, const char **value_r)
+{
+ struct cdb_dict *dict = (struct cdb_dict *)_dict;
+ unsigned datalen;
+ int ret = 0;
+ char *data;
+
+ /* keys and values may be null terminated... */
+ if (dict->flag & CDB_WITH_NULL) {
+ ret = cdb_find(&dict->cdb, key, (unsigned)strlen(key)+1);
+ if (ret > 0)
+ dict->flag &= ~CDB_WITHOUT_NULL;
+ }
+
+ /* ...or not */
+ if ((0 == ret) && (dict->flag & CDB_WITHOUT_NULL)) {
+ ret = cdb_find(&dict->cdb, key, (unsigned)strlen(key));
+ if (ret > 0)
+ dict->flag &= ~CDB_WITH_NULL;
+ }
+
+ if (ret <= 0) {
+ *value_r = NULL;
+ /* something bad with db */
+ if (ret < 0) {
+ /*i_error("cdb_lookup(%s) on %s failed: %m",
+ key, dict->path);*/
+ return -1;
+ }
+ /* found nothing */
+ return 0;
+ }
+
+ datalen = cdb_datalen(&dict->cdb);
+ data = p_new(pool, char, datalen + 1);
+ cdb_read(&dict->cdb, data, datalen, cdb_datapos(&dict->cdb));
+ *value_r = data;
+ return 1;
+}
+
+
+struct dict dict_driver_cdb = {
+ .name = "cdb",
+ {
+ cdb_dict_init,
+ cdb_dict_deinit,
+ NULL,
+ cdb_dict_lookup,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ }
+};
+#endif
diff --git a/src/lib-dict/dict-private.h b/src/lib-dict/dict-private.h
index ae41dc8..9200c8f 100644
--- a/src/lib-dict/dict-private.h
+++ b/src/lib-dict/dict-private.h
@@ -55,5 +55,8 @@ extern struct dict dict_driver_client;
extern struct dict dict_driver_file;
extern struct dict dict_driver_memcached;
extern struct dict dict_driver_redis;
+#ifdef HAVE_CDB
+extern struct dict dict_driver_cdb;
+#endif
#endif
diff --git a/src/lib-dict/dict.c b/src/lib-dict/dict.c
index 99d1580..a67eacc 100644
--- a/src/lib-dict/dict.c
+++ b/src/lib-dict/dict.c
@@ -58,6 +58,9 @@ void dict_drivers_register_builtin(void)
dict_driver_register(&dict_driver_file);
dict_driver_register(&dict_driver_memcached);
dict_driver_register(&dict_driver_redis);
+#ifdef HAVE_CDB
+ dict_driver_register(&dict_driver_cdb);
+#endif
}
void dict_drivers_unregister_builtin(void)
@@ -66,6 +69,10 @@ void dict_drivers_unregister_builtin(void)
dict_driver_unregister(&dict_driver_file);
dict_driver_unregister(&dict_driver_memcached);
dict_driver_unregister(&dict_driver_redis);
+#ifdef HAVE_CDB
+ dict_driver_unregister(&dict_driver_cdb);
+#endif
+
}
struct dict *dict_init(const char *uri, enum dict_data_type value_type,
diff --git a/src/lib-dict/test-dict.c b/src/lib-dict/test-dict.c
index 88164e0..0aa8e9b 100644
--- a/src/lib-dict/test-dict.c
+++ b/src/lib-dict/test-dict.c
@@ -8,6 +8,7 @@ struct dict dict_driver_client;
struct dict dict_driver_file;
struct dict dict_driver_memcached;
struct dict dict_driver_redis;
+struct dict dict_driver_cdb;
static void test_dict_escape(void)
{