]> the.earth.li Git - onak.git/commitdiff
Add dynamic loading of backends.
authorJonathan McDowell <noodles@earth.li>
Thu, 14 Jul 2005 16:15:57 +0000 (16:15 +0000)
committerJonathan McDowell <noodles@earth.li>
Thu, 14 Jul 2005 16:15:57 +0000 (16:15 +0000)
This adds support for the dynamic loading of backends. By default we
now try to build all the backends we can and then dynamically load the
one the user wants.

Makefile.in
configure.ac
keydb_dynamic.c [new file with mode: 0644]
keydb_dynamic.h [new file with mode: 0644]
onak-conf.c
onak-conf.h

index dec603d999874e6056c02f390b44f24ce0682560..6a15a7fc90f004d80fadff803da4bb063a76b367 100644 (file)
@@ -3,13 +3,14 @@
 #
 
 CC = @CC@
-CFLAGS += @CFLAGS@ -Wall -pedantic
+CFLAGS += @CFLAGS@ -Wall -pedantic -fPIC
 # Uncomment to enable profiling.
 LDFLAGS += @LDFLAGS@
 # Can be "pg" for Postgresql, "file" for flat files or "db2" for pksd db2 style.
 DBTYPE = @DBTYPE@
 #
 LIBS = @LIBS@
+DB4LIBS = @DB4LIBS@
 #MAKEDEPEND = makedepend -f- -- 
 MAKEDEPEND = $(CC) -MM
 prefix ?= @prefix@
@@ -22,7 +23,8 @@ CORE_OBJS = armor.o charfuncs.o decodekey.o getcgi.o hash.o \
 SRCS = armor.c parsekey.c merge.c keyid.c md5.c sha1.c main.c getcgi.c mem.c \
        keyindex.c stats.c lookup.c add.c keydb_$(DBTYPE).c ll.c hash.c \
        gpgwww.c onak-conf.c charfuncs.c sendsync.c log.c photoid.c \
-       wordlist.c cleankey.c cleanup.c keyarray.c
+       wordlist.c cleankey.c cleanup.c keyarray.c \
+       $(foreach be,@BACKENDS@,keydb_$(be).c)
 
 ifeq (x@KEYD@, xyes)
 PROGS += keyd
@@ -32,13 +34,33 @@ else
 KEYDB_OBJ = keydb_$(DBTYPE).o
 endif
 
+ifeq (x@DBTYPE@, xdynamic)
+LIBS += -ldl
+BACKENDS = $(foreach be,@BACKENDS@,libkeydb_$(be).so)
+PROGS += keyd
+SRCS += keyd.c
+endif
+
 OBJS = stats.o cleankey.o $(CORE_OBJS) $(KEYDB_OBJ)
 
-all: .depend $(PROGS) testparse maxpath sixdegrees splitkeys onak.conf
+all: .depend $(PROGS) testparse maxpath sixdegrees splitkeys onak.conf \
+       $(BACKENDS)
 
 keyd: keyd.o $(CORE_OBJS) keydb_$(DBTYPE).o
        $(CC) $(LDFLAGS) -o keyd keyd.o $(CORE_OBJS) keydb_$(DBTYPE).o $(LIBS)
 
+libkeydb_db4.so: keydb_db4.o
+       $(CC) -shared $(DB4LIBS) -o libkeydb_db4.so keydb_db4.o $(CORE_OBJS)
+
+libkeydb_pg.so: keydb_pg.o
+       $(CC) -shared $(PQLIBS) -o libkeydb_pg.so keydb_pg.o $(CORE_OBJS)
+
+libkeydb_%.so: keydb_%.o
+       $(CC) -shared -o $@ $< $(CORE_OBJS)
+
+keydb_%.o: keydb_%.c
+       $(CC) -c -fPIC $(LDFLAGS) -o $@ $<
+
 splitkeys: splitkeys.o $(CORE_OBJS) $(KEYDB_OBJ)
        $(CC) $(LDFLAGS) -o splitkeys splitkeys.o $(CORE_OBJS) $(KEYDB_OBJ) \
                $(LIBS)
@@ -85,7 +107,8 @@ onak.conf: onak.conf.in
 clean:
        $(RM) $(PROGS) $(OBJS) Makefile.bak testparse maxpath *.core core \
                gpgwww.o add.o lookup.o main.o maxpath.o onak.o sixdegrees \
-               sixdegrees.o splitkeys.o stripkey.o onak.conf
+               sixdegrees.o splitkeys.o stripkey.o onak.conf keyd.o \
+               $(foreach be,@BACKENDS@,keydb_$(be).o) *.so
 ifeq (x@KEYD@, xyes)
        $(RM) keyd.o keydb_$(DBTYPE).o
 endif
index d9712fa92d5d0067afc0f81784e4649e7fac3de8..bc93f4bbcafb42cf92a64f266d9149579f9ab292 100644 (file)
@@ -7,48 +7,70 @@ AC_PROG_CC
 
 AC_C_BIGENDIAN
 
-AC_ARG_ENABLE(backend,AC_HELP_STRING([--enable-backend=<backend>],[Choose the backend database to use. Defaults to db4.]), [], [enable_backend="db4"])
+dnl We should always have these backends available.
+backends="file fs keyd"
 
-AC_ARG_ENABLE(keyd,AC_HELP_STRING([--enable-keyd],[Use keyd as the DB backend.]), [], [])
-
-AC_MSG_CHECKING([which key database backend to use])
-AC_MSG_RESULT([$enable_backend])
-AC_CHECK_FILE([$srcdir/keydb_$enable_backend.c], ,AC_MSG_ERROR([non existent key database backend $enable_backend]))
+AC_CHECK_LIB(pq, PQsetdbLogin,[have_libpq="yes" backends="$backends pg"],have_libpq="no")
 
-if test "x$enable_backend" = "xdb4"
-then
-       AC_CHECK_HEADER(db.h, have_db_h="yes", have_db_h="no")
-       AC_MSG_CHECKING(for libdb version in db.h)
-       printf "#include <db.h>\nDB_VERSION_MAJOR DB_VERSION_MINOR\n" >conftest.c
-       set `eval $ac_cpp conftest.c | egrep '^ *[[0-9]] *'`; v="$1"; vv="$2"
-       AC_MSG_RESULT($v.$vv)
-       if test "$v" -ne 4; then
-               AC_MSG_ERROR([   * onak requires libdb version 4])
-       fi
+AC_CHECK_HEADER(db.h, have_db_h="yes", have_db_h="no")
+AC_MSG_CHECKING(for libdb version in db.h)
+printf "#include <db.h>\nDB_VERSION_MAJOR DB_VERSION_MINOR\n" >conftest.c
+set `eval $ac_cpp conftest.c | egrep '^ *[[0-9]] *'`; v="$1"; vv="$2"
+AC_MSG_RESULT($v.$vv)
+if test "$v" -eq 4; then
        for db in "db-$v.$vv" "db$v.$vv" "db-$v" "db$v" "db"; do
                AC_MSG_CHECKING(for db_create in lib$db)
                oldLIBS="$LIBS"
                LIBS="$LIBS -l$db"
+               db4libs="-l$db"
                AC_TRY_LINK([#include <db.h>], db_create(0, 0, 0),
                        have_libdb="yes", have_libdb="no")
                AC_MSG_RESULT($have_libdb)
-               if test "$have_libdb" != "no"; then break; fi
                LIBS="$oldLIBS"
+               if test "$have_libdb" != "no"; then break; fi
        done
+fi
+if test "$have_libdb" = "yes" -a "$have_db_h" = "yes"; then
+       AC_DEFINE(HAVE_LIBDB4, 1, [libdb found])
+       backends="$backends db4"
+fi
+
+AC_MSG_CHECKING(available backends)
+AC_MSG_RESULT($backends)
+
+AC_ARG_ENABLE(backend,AC_HELP_STRING([--enable-backend=<backend>],[Choose the backend database to use. Defaults to dynamic.]), [], [enable_backend="dynamic"])
+
+AC_ARG_ENABLE(keyd,AC_HELP_STRING([--enable-keyd],[Use keyd as the DB backend.]), [], [])
+
+AC_MSG_CHECKING([which key database backend to use])
+AC_MSG_RESULT([$enable_backend])
+AC_CHECK_FILE([$srcdir/keydb_$enable_backend.c], ,AC_MSG_ERROR([non existent key database backend $enable_backend]))
+
+if test "x$enable_backend" = "xdb4"
+then
        if test "$have_libdb" = "no" -o "$have_db_h" = "no"; then
                AC_MSG_ERROR(libdb not found.)
        fi
-       AC_DEFINE(HAVE_LIBDB, 1, [libdb found])
+       LIBS="$LIBS $db4libs"
 else if test "x$enable_backend" = "xpg"
 then
-       AC_CHECK_LIB(pq, PQsetdbLogin,,
-               AC_MSG_ERROR([cannot compile PostgreSQL backend without libpq]))
+       if test "$have_libpq" = "no"; then
+               AC_MSG_ERROR(libpq not found.)
+       fi
+       LIBS="$LIBS -lpq"
 fi
 fi
 
-AC_SUBST(DBTYPE, $enable_backend)
+dnl If we are explicitly told which backend to use, only build that one.
+if test "x$enable_backend" = "xdb4"
+then
+       backend="$enable_backend"
+fi
 
+AC_SUBST(DBTYPE, $enable_backend)
+AC_SUBST(DB4LIBS, $db4libs)
 AC_SUBST(KEYD, $enable_keyd)
+AC_SUBST(BACKENDS, $backends)
 
 AC_CONFIG_FILES(Makefile)
 
diff --git a/keydb_dynamic.c b/keydb_dynamic.c
new file mode 100644 (file)
index 0000000..ca489ae
--- /dev/null
@@ -0,0 +1,531 @@
+/*
+ * keydb_dynamic.c - backend that can load the other backends
+ *
+ * Brett Parker <iDunno@sommitrealweird.co.uk>
+ *
+ * Copyright 2005 Project Purple
+ */
+
+#include <stdio.h>
+
+#include "decodekey.h"
+#include "hash.h"
+#include "keydb.h"
+#include "keyid.h"
+#include "keystructs.h"
+#include "mem.h"
+#include "merge.h"
+#include "parsekey.h"
+#include "sendsync.h"
+#include "keydb_dynamic.h"
+
+struct dynamic_backend *get_backend(void)
+{
+       return &__dynamicdb_backend__;
+}
+
+bool backend_loaded(void)
+{
+       return __dynamicdb_backend__.loaded;
+}
+
+bool load_backend(void)
+{
+       char *soname = NULL;
+       void *handle;
+       struct dynamic_backend *backend = get_backend();
+
+       if (backend->loaded) {
+               close_backend();
+       }
+
+       if (config.backends_dir == NULL) {
+               soname = malloc(strlen(config.db_backend)
+                       + strlen("/libkeydb_")
+                       + strlen(".so")
+                       + 1);
+
+               sprintf(soname, "libkeydb_%s.so", config.db_backend);
+       } else {
+               soname = malloc(strlen(config.db_backend)
+                       + strlen("/libkeydb_")
+                       + strlen(".so")
+                       + strlen(config.backends_dir)
+                       + 1);
+
+               sprintf(soname, "%s/libkeydb_%s.so", config.backends_dir,
+                       config.db_backend);
+       }
+               
+       logthing(LOGTHING_INFO, "Loading dynamic backend: %s", soname);
+
+       handle = dlopen(soname, RTLD_LAZY);
+       if (handle == NULL) {
+               logthing(LOGTHING_ERROR,
+                               "Failed to open handle to library '%s': %s",
+                               soname, dlerror());
+               free(soname);
+               soname = NULL;
+               return false;
+       }
+       free(soname);
+       soname = NULL;
+
+       backend->initdb = (initdbfunc_t) dlsym(handle, "initdb");
+       backend->cleanupdb = (cleanupdbfunc_t) dlsym(handle, "cleanupdb");
+       backend->starttrans = (starttransfunc_t) dlsym(handle, "starttrans");
+       backend->endtrans = (endtransfunc_t) dlsym(handle, "endtrans");
+       backend->fetch_key = (fetch_keyfunc_t) dlsym(handle, "fetch_key");
+       backend->store_key = (store_keyfunc_t) dlsym(handle, "store_key");
+       backend->delete_key = (delete_keyfunc_t) dlsym(handle, "delete_key");
+       backend->fetch_key_text = (fetch_key_textfunc_t)
+                                 dlsym (handle, "fetch_key_text");
+       backend->update_keys = (update_keysfunc_t)
+                              dlsym(handle, "update_keys");
+       backend->keyid2uid = (keyid2uidfunc_t) dlsym(handle, "keyid2uid");
+       backend->cached_getkeysigs = (cached_getkeysigsfunc_t)
+                                    dlsym(handle, "cached_getkeysigs");
+       backend->getfullkeyid = (getfullkeyidfunc_t)
+                               dlsym(handle, "getfullkeyid");
+       backend->iterate_keys = (iterate_keysfunc_t)
+                               dlsym(handle, "iterate_keys");
+
+       backend->handle = handle;
+       backend->loaded = true;
+
+       return true;
+}
+
+bool close_backend(void)
+{
+       struct dynamic_backend *backend;
+       backend = get_backend();
+       
+       backend->initdb = NULL;
+       backend->cleanupdb = NULL;
+       backend->starttrans = NULL;
+       backend->endtrans = NULL;
+       backend->fetch_key = NULL;
+       backend->store_key = NULL;
+       backend->delete_key = NULL;
+       backend->fetch_key_text = NULL;
+       backend->update_keys = NULL;
+       backend->keyid2uid = NULL;
+       backend->cached_getkeysigs = NULL;
+       backend->getfullkeyid = NULL;
+       backend->iterate_keys = NULL;
+       backend->loaded = false;
+       dlclose(backend->handle);
+       backend->handle = NULL;
+
+       return true;
+}
+
+/**
+ *     keyid2uid - Takes a keyid and returns the primary UID for it.
+ *     @keyid: The keyid to lookup.
+ */
+char *keyid2uid(uint64_t keyid)
+{
+       struct openpgp_publickey *publickey = NULL;
+       struct openpgp_signedpacket_list *curuid = NULL;
+       char buf[1024];
+
+       struct dynamic_backend *backend;
+       if (!backend_loaded()) {
+               load_backend();
+       }
+       
+       if (backend_loaded()) {
+               backend = get_backend();
+               if (backend->keyid2uid != NULL) {
+                       return backend->keyid2uid(keyid);
+               }
+       }
+       
+       buf[0]=0;
+       if (fetch_key(keyid, &publickey, false) && publickey != NULL) {
+               curuid = publickey->uids;
+               while (curuid != NULL && buf[0] == 0) {
+                       if (curuid->packet->tag == 13) {
+                               snprintf(buf, 1023, "%.*s",
+                                               (int) curuid->packet->length,
+                                               curuid->packet->data);
+                       }
+                       curuid = curuid -> next;
+               }
+               free_publickey(publickey);
+       }
+
+       if (buf[0] == 0) {
+               return NULL;
+       } else {
+               return strdup(buf);
+       }
+}
+
+/**
+ *     getkeysigs - Gets a linked list of the signatures on a key.
+ *     @keyid: The keyid to get the sigs for.
+ *     @revoked: Is the key revoked?
+ *
+ *     This function gets the list of signatures on a key. Used for key 
+ *     indexing and doing stats bits. If revoked is non-NULL then if the key
+ *     is revoked it's set to true.
+ */
+struct ll *getkeysigs(uint64_t keyid, bool *revoked)
+{
+       struct ll *sigs = NULL;
+       struct openpgp_signedpacket_list *uids = NULL;
+       struct openpgp_publickey *publickey = NULL;
+       
+       struct dynamic_backend *backend;
+       if ( !backend_loaded() ) {
+               load_backend();
+       }
+       
+       if (backend_loaded()) {
+               backend = get_backend();
+               if (backend->getkeysigs != NULL) {
+                       return backend->getkeysigs(keyid,revoked);
+               }
+       }
+
+       fetch_key(keyid, &publickey, false);
+       
+       if (publickey != NULL) {
+               for (uids = publickey->uids; uids != NULL; uids = uids->next) {
+                       sigs = keysigs(sigs, uids->sigs);
+               }
+               if (revoked != NULL) {
+                       *revoked = (publickey->revocations != NULL);
+               }
+               free_publickey(publickey);
+       }
+
+       return sigs;
+}
+
+/**
+ *     cached_getkeysigs - Gets the signatures on a key.
+ *     @keyid: The key we want the signatures for.
+ *     
+ *     This function gets the signatures on a key. It's the same as the
+ *     getkeysigs function above except we use the hash module to cache the
+ *     data so if we need it again it's already loaded.
+ */
+struct ll *cached_getkeysigs(uint64_t keyid)
+{
+       struct stats_key *key = NULL;
+       struct stats_key *signedkey = NULL;
+       struct ll        *cursig = NULL;
+       bool              revoked = false;
+       
+       struct dynamic_backend *backend;
+
+       if (keyid == 0)  {
+               return NULL;
+       }
+       
+       if (!backend_loaded()) {
+               load_backend();
+       }
+       
+       if (backend_loaded()) {
+               backend = get_backend();
+               if (backend->cached_getkeysigs != NULL) {
+                       return backend->cached_getkeysigs(keyid);
+               }
+       }
+
+       key = createandaddtohash(keyid);
+
+       if (key->gotsigs == false) {
+               key->sigs = getkeysigs(key->keyid, &revoked);
+               key->revoked = revoked;
+               for (cursig = key->sigs; cursig != NULL;
+                               cursig = cursig->next) {
+                       signedkey = (struct stats_key *) cursig->object;
+                       signedkey->signs = lladd(signedkey->signs, key);
+               }
+               key->gotsigs = true;
+       }
+
+       return key->sigs;
+}
+
+/**
+ *     getfullkeyid - Maps a 32bit key id to a 64bit one.
+ *     @keyid: The 32bit keyid.
+ *
+ *     This function maps a 32bit key id to the full 64bit one. It returns the
+ *     full keyid. If the key isn't found a keyid of 0 is returned.
+ */
+uint64_t getfullkeyid(uint64_t keyid)
+{
+       struct openpgp_publickey *publickey = NULL;
+       struct dynamic_backend *backend;
+       
+       if (!backend_loaded()) {
+               load_backend();
+       }
+       
+       if (backend_loaded()) {
+               backend = get_backend();
+               if (backend->getfullkeyid != NULL) {
+                       return backend->getfullkeyid(keyid);
+               }
+       }
+
+       if (keyid < 0x100000000LL) {
+               fetch_key(keyid, &publickey, false);
+               if (publickey != NULL) {
+                       keyid = get_keyid(publickey);
+                       free_publickey(publickey);
+                       publickey = NULL;
+               } else {
+                       keyid = 0;
+               }
+       }
+       
+       return keyid;
+}
+
+/**
+ *     update_keys - Takes a list of public keys and updates them in the DB.
+ *     @keys: The keys to update in the DB.
+ *     @sendsync: Should we send a sync mail to our peers.
+ *
+ *     Takes a list of keys and adds them to the database, merging them with
+ *     the key in the database if it's already present there. The key list is
+ *     update to contain the minimum set of updates required to get from what
+ *     we had before to what we have now (ie the set of data that was added to
+ *     the DB). Returns the number of entirely new keys added.
+ */
+int update_keys(struct openpgp_publickey **keys, bool sendsync)
+{
+       struct openpgp_publickey *curkey = NULL;
+       struct openpgp_publickey *oldkey = NULL;
+       struct openpgp_publickey *prev = NULL;
+       struct dynamic_backend *backend;
+       int newkeys = 0;
+       bool intrans;
+       
+       if (!backend_loaded()) {
+               load_backend();
+       }
+       
+       if (backend_loaded()) {
+               backend = get_backend();
+               if (backend->update_keys != NULL) {
+                       return backend->update_keys(keys, sendsync);
+               }
+       }
+
+       for (curkey = *keys; curkey != NULL; curkey = curkey->next) {
+               intrans = starttrans();
+               logthing(LOGTHING_INFO,
+                       "Fetching key 0x%llX, result: %d",
+                       get_keyid(curkey),
+                       fetch_key(get_keyid(curkey), &oldkey, intrans));
+
+               /*
+                * If we already have the key stored in the DB then merge it
+                * with the new one that's been supplied. Otherwise the key
+                * we've just got is the one that goes in the DB and also the
+                * one that we send out.
+                */
+               if (oldkey != NULL) {
+                       merge_keys(oldkey, curkey);
+                       if (curkey->revocations == NULL &&
+                                       curkey->uids == NULL &&
+                                       curkey->subkeys == NULL) {
+                               if (prev == NULL) {
+                                       *keys = curkey->next;
+                               } else {
+                                       prev->next = curkey->next;
+                                       curkey->next = NULL;
+                                       free_publickey(curkey);
+                                       curkey = prev;
+                               }
+                       } else {
+                               prev = curkey;
+                               logthing(LOGTHING_INFO,
+                                       "Merged key; storing updated key.");
+                               store_key(oldkey, intrans, true);
+                       }
+                       free_publickey(oldkey);
+                       oldkey = NULL;
+               
+               } else {
+                       logthing(LOGTHING_INFO,
+                               "Storing completely new key.");
+                       store_key(curkey, intrans, false);
+                       newkeys++;
+               }
+               endtrans();
+               intrans = false;
+       }
+
+       if (sendsync && keys != NULL) {
+               sendkeysync(*keys);
+       }
+
+       return newkeys;
+}
+
+void initdb(bool readonly)
+{
+       struct dynamic_backend *backend;
+       backend = get_backend();
+       
+       if (!backend_loaded()) {
+               load_backend();
+       }
+
+       if (backend->loaded) {
+               if (backend->initdb != NULL) {
+                       backend->initdb(readonly);
+               }
+       }
+}
+
+void cleanupdb(void)
+{
+       struct dynamic_backend *backend;
+       backend = get_backend();
+
+       if (backend->loaded) {
+               if (backend->cleanupdb != NULL) {
+                       backend->cleanupdb();
+               }
+       }
+
+       close_backend();
+}
+
+bool starttrans()
+{
+       struct dynamic_backend *backend;
+       backend = get_backend();
+
+       if (!backend_loaded()) {
+               load_backend();
+       }
+       
+       if (backend->loaded) {
+               if (backend->starttrans != NULL) {
+                       return backend->starttrans();
+               }
+       }
+
+       return false;
+}
+
+void endtrans()
+{
+       struct dynamic_backend *backend;
+       backend = get_backend();
+
+       if (!backend_loaded()) {
+               load_backend();
+       }
+       
+       if (backend->loaded) {
+               if (backend->endtrans != NULL) {
+                       backend->endtrans();
+               }
+       }
+}
+
+int fetch_key(uint64_t keyid, struct openpgp_publickey **publickey,
+               bool intrans)
+{
+       struct dynamic_backend *backend;
+       backend = get_backend();
+
+       if (!backend_loaded()) {
+               load_backend();
+       }
+       
+       if (backend->loaded) {
+               if (backend->fetch_key != NULL) {
+                       return backend->fetch_key(keyid,publickey,intrans);
+               }
+       }
+
+       return -1;
+}
+
+int store_key(struct openpgp_publickey *publickey, bool intrans, bool update)
+{
+       struct dynamic_backend *backend;
+       backend = get_backend();
+
+       if (!backend_loaded()) {
+               load_backend();
+       }
+       
+       if (backend->loaded) {
+               if (backend->store_key != NULL) {
+                       return backend->store_key(publickey,intrans,update);
+               }
+       }
+
+       return -1;
+}
+
+int delete_key(uint64_t keyid, bool intrans)
+{
+       struct dynamic_backend *backend;
+       backend = get_backend();
+
+       if (!backend_loaded()) {
+               load_backend();
+       }
+       
+       if (backend->loaded) {
+               if (backend->delete_key != NULL) {
+                       return backend->delete_key(keyid, intrans);
+               }
+       }
+
+       return -1;
+}
+
+int fetch_key_text(const char *search, struct openpgp_publickey **publickey)
+{
+       struct dynamic_backend *backend;
+       backend = get_backend();
+
+       if (!backend_loaded()) {
+               load_backend();
+       }
+       
+       if (backend->loaded) {
+               if (backend->fetch_key_text != NULL) {
+                       return backend->fetch_key_text(search, publickey);
+               }
+       }
+
+       return -1;
+}
+
+int iterate_keys(void (*iterfunc)(void *ctx, struct openpgp_publickey *key),
+               void *ctx)
+{
+       struct dynamic_backend *backend;
+       backend = get_backend();
+
+       if (!backend_loaded()) {
+               load_backend();
+       }
+       
+       if (backend->loaded) {
+               if (backend->iterate_keys != NULL) {
+                       return backend->iterate_keys(iterfunc, ctx);
+               }
+       }
+
+       return -1;
+}
diff --git a/keydb_dynamic.h b/keydb_dynamic.h
new file mode 100644 (file)
index 0000000..a739db1
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * keydb_dynamic.h - declarations for the dynamic backend
+ *
+ * Brett Parker <iDunno@sommitrealweird.co.uk>
+ *
+ * Copyright 2005 Project Purple
+ */
+#include <stdlib.h>
+#include <dlfcn.h>
+#include <string.h>
+#include <inttypes.h>
+
+#include "charfuncs.h"
+#include "onak-conf.h"
+#include "keystructs.h"
+#include "ll.h"
+#include "log.h"
+
+#ifndef __KEYDB_DYNAMIC_H__
+#define __KEYDB_DYNAMIC_H__
+
+/*
+ * Hide the ugly function definitions in typedefs that we use elsewhere
+ */
+typedef void (*initdbfunc_t)(bool);
+typedef void (*cleanupdbfunc_t)(void);
+typedef bool (*starttransfunc_t)(void);
+typedef bool (*endtransfunc_t)(void);
+typedef int (*fetch_keyfunc_t)(uint64_t keyid,
+               struct openpgp_publickey **publickey, bool intrans);
+typedef int (*store_keyfunc_t)(struct openpgp_publickey *publickey,
+               bool intrans, bool update);
+typedef int (*delete_keyfunc_t)(uint64_t keyid, bool intrans);
+typedef int (*fetch_key_textfunc_t)(const char *search,
+               struct openpgp_publickey **publickey);
+typedef int (*update_keysfunc_t)(struct openpgp_publickey **keys,
+               bool sendsync);
+typedef char *(*keyid2uidfunc_t)(uint64_t keyid);
+typedef struct ll *(*getkeysigsfunc_t)(uint64_t keyid, bool *revoked);
+typedef struct ll *(*cached_getkeysigsfunc_t)(uint64_t keyid);
+typedef uint64_t (*getfullkeyidfunc_t)(uint64_t keyid);
+typedef int (*iterate_keysfunc_t)(
+               void (*iterfunc) (void *ctx, struct openpgp_publickey *key),
+               void *ctx);
+
+
+/*
+ * Define a nice struct to hold pointers to the functions, once the backend
+ * is loaded
+ */
+struct dynamic_backend {
+       initdbfunc_t initdb;
+       cleanupdbfunc_t cleanupdb;
+       starttransfunc_t starttrans;
+       endtransfunc_t endtrans;
+       fetch_keyfunc_t fetch_key;
+       store_keyfunc_t store_key;
+       delete_keyfunc_t delete_key;
+       fetch_key_textfunc_t fetch_key_text;
+       update_keysfunc_t update_keys;
+       keyid2uidfunc_t keyid2uid;
+       getkeysigsfunc_t getkeysigs;
+       cached_getkeysigsfunc_t cached_getkeysigs;
+       getfullkeyidfunc_t getfullkeyid;
+       iterate_keysfunc_t iterate_keys;
+       char *backendsoname;
+       void *handle;
+       bool loaded;
+};
+
+struct dynamic_backend __dynamicdb_backend__ = {
+       NULL,   /* initdb */
+       NULL,   /* cleanupdb */
+       NULL,   /* starttrans */
+       NULL,   /* endtrans */
+       NULL,   /* fetch_key */
+       NULL,   /* store_key */
+       NULL,   /* delete_key */
+       NULL,   /* fetch_key_text */
+       NULL,   /* update_keys */
+       NULL,   /* keyid2uid */
+       NULL,   /* getkeysigs */
+       NULL,   /* cached_getkeysigs */
+       NULL,   /* getfullkeyid */
+       NULL,   /* iteratekeys */
+       NULL,   /* backendsoname */
+       NULL,   /* handle */
+       0       /* loaded */
+};
+
+bool load_backend(void);
+bool close_backend(void);
+bool backend_loaded(void);
+struct dynamic_backend *get_backend(void);
+
+#endif /* __KEYDB_DYNAMIC_H__ */
index f97197cf72694c58167d53ade6b1bb2e205f78f8..0958502b4d57923119fa0f75d337f58bbe8e301f 100644 (file)
@@ -43,6 +43,12 @@ struct onak_config config = {
        NULL,                   /* pg_dbname */
        NULL,                   /* pg_dbuser */
        NULL,                   /* pg_dbpass */
+
+       /*
+        * Options for dynamic backends.
+        */
+       NULL,                   /* db_backend */
+       NULL,                   /* backends_dir */
 };
 
 void readconfig(const char *configfile) {
@@ -127,6 +133,10 @@ void readconfig(const char *configfile) {
                        /*
                         * Not applicable; ignored for compatibility with pksd.
                         */
+               } else if (!strncmp("db_backend ", curline, 11)) {
+                       config.db_backend = strdup(&curline[11]);
+               } else if (!strncmp("backends_dir ", curline, 13)) {
+                       config.backends_dir = strdup(&curline[13]);
                } else {
                        logthing(LOGTHING_ERROR,
                                "Unknown config line: %s", curline);
@@ -182,4 +192,12 @@ void cleanupconfig(void) {
                free(config.logfile);
                config.logfile = NULL;
        }
+       if (config.db_backend != NULL) {
+               free(config.db_backend);
+               config.db_backend = NULL;
+       }
+       if (config.backends_dir != NULL) {
+               free(config.backends_dir);
+               config.backends_dir = NULL;
+       }
 }
index 7b3941528647852fc3a7152e9f5749a53101af65..0a36c9adf6733344b73fecd0e48ecc540f8f8218 100644 (file)
@@ -51,6 +51,12 @@ struct onak_config {
        char *pg_dbname;
        char *pg_dbuser;
        char *pg_dbpass;
+
+       /*
+        * Options for the dynamic backend.
+        */
+       char *db_backend;
+       char *backends_dir;
 };
 
 /*