]> git.sommitrealweird.co.uk Git - onak.git/blobdiff - keydb_db3.c
Fold in some of dsilvers' autoconf changes.
[onak.git] / keydb_db3.c
index 247cbabf3e89f88250be67f9de74da254f6e0efb..7cc3b1ef78d45227262e85744f95a520c2dda5fc 100644 (file)
@@ -4,8 +4,6 @@
  * Jonathan McDowell <noodles@earth.li>
  *
  * Copyright 2002 Project Purple
- *
- * $Id: keydb_db3.c,v 1.24 2004/03/28 21:27:03 noodles Exp $
  */
 
 #include <assert.h>
@@ -30,6 +28,7 @@
 #include "log.h"
 #include "onak-conf.h"
 #include "parsekey.h"
+#include "wordlist.h"
 
 /**
  *     dbenv - our database environment.
@@ -51,6 +50,11 @@ static DB **dbconns = NULL;
  */
 static DB *worddb = NULL;
 
+/**
+ *     id32db - our connection to the 32bit ID database.
+ */
+static DB *id32db = NULL;
+
 /**
  *     txn - our current transaction id.
  */
@@ -65,56 +69,6 @@ DB *keydb(uint64_t keyid)
        return(dbconns[keytrun % numdbs]);
 }
 
-/**
- *     makewordlist - Takes a string and splits it into a set of unique words.
- *     @wordlist: The current word list.
- *     @words: The string to split and add.
- *
- *     We take words and split it on non alpha numeric characters. These get
- *     added to the word list if they're not already present. If the wordlist
- *     is NULL then we start a new list, otherwise it's search for already
- *     added words. Note that words is modified in the process of scanning.
- *
- *     Returns the new word list.
- */
-struct ll *makewordlist(struct ll *wordlist, char *word)
-{
-       char *start = NULL;
-       char *end = NULL;
-
-       /*
-        * Walk through the words string, spliting on non alphanumerics and
-        * then checking if the word already exists in the list. If not then
-        * we add it.
-        */
-       end = word;
-       while (end != NULL && *end != 0) {
-               start = end;
-               while (*start != 0 && !isalnum(*start)) {
-                       start++;
-               }
-               end = start;
-               while (*end != 0 && isalnum(*end)) {
-                       *end = tolower(*end);
-                       end++;
-               }
-               if (end - start > 1) {
-                       if (*end != 0) {
-                               *end = 0;
-                               end++;
-                       }
-                       
-                       if (llfind(wordlist, start,
-                                       strcmp) == NULL) {
-                               wordlist = lladd(wordlist,
-                                               start);
-                       }
-               }
-       }
-
-       return wordlist;
-}
-
 /**
  *     initdb - Initialize the key database.
  *
@@ -201,7 +155,7 @@ void initdb(bool readonly)
                snprintf(buf, 1023, "keydb.%d.db", i);
                flags = DB_CREATE;
                if (readonly) {
-                       flags |= DB_RDONLY;
+                       flags = DB_RDONLY;
                }
                ret = dbconns[i]->open(dbconns[i], buf,
                        NULL,
@@ -234,6 +188,24 @@ void initdb(bool readonly)
                                db_strerror(ret));
                exit(1);
        }
+
+       ret = db_create(&id32db, dbenv, 0);
+       if (ret != 0) {
+               logthing(LOGTHING_CRITICAL, "db_create: %s", db_strerror(ret));
+               exit(1);
+       }
+       ret = id32db->set_flags(id32db, DB_DUP);
+
+       ret = id32db->open(id32db, "id32db", NULL, DB_HASH,
+                       flags,
+                       0664);
+       if (ret != 0) {
+               logthing(LOGTHING_CRITICAL,
+                               "Error opening id32 database: %s (%s)",
+                               "id32db",
+                               db_strerror(ret));
+               exit(1);
+       }
        
        return;
 }
@@ -249,6 +221,8 @@ void cleanupdb(void)
        int i = 0;
 
        txn_checkpoint(dbenv, 0, 0, 0);
+       id32db->close(id32db, 0);
+       id32db = NULL;
        worddb->close(worddb, 0);
        worddb = NULL;
        for (i = 0; i < numdbs; i++) {
@@ -333,6 +307,10 @@ int fetch_key(uint64_t keyid, struct openpgp_publickey **publickey,
        int numkeys = 0;
        struct buffer_ctx fetchbuf;
 
+       if (keyid < 0x100000000LL) {
+               keyid = getfullkeyid(keyid);
+       }
+
        memset(&key, 0, sizeof(key));
        memset(&data, 0, sizeof(data));
 
@@ -341,7 +319,6 @@ int fetch_key(uint64_t keyid, struct openpgp_publickey **publickey,
 
        key.size = sizeof(keyid);
        key.data = &keyid;
-       keyid &= 0xFFFFFFFF;
 
        if (!intrans) {
                starttrans();
@@ -376,7 +353,7 @@ int fetch_key(uint64_t keyid, struct openpgp_publickey **publickey,
        return (numkeys);
 }
 
-int worddb_cmp(const char *d1, const char *d2)
+int worddb_cmp(const void *d1, const void *d2)
 {
        return memcmp(d1, d2, 12);
 }
@@ -510,6 +487,8 @@ int store_key(struct openpgp_publickey *publickey, bool intrans, bool update)
        DBT        key;
        DBT        data;
        uint64_t   keyid = 0;
+       uint32_t   shortkeyid = 0;
+       uint64_t  *subkeyids = NULL;
        char     **uids = NULL;
        char      *primary = NULL;
        unsigned char worddb_data[12];
@@ -558,7 +537,6 @@ int store_key(struct openpgp_publickey *publickey, bool intrans, bool update)
                memset(&data, 0, sizeof(data));
                key.data = &keyid;
                key.size = sizeof(keyid);
-               keyid &= 0xFFFFFFFF;
                data.size = storebuf.offset;
                data.data = storebuf.buffer;
 
@@ -652,6 +630,68 @@ int store_key(struct openpgp_publickey *publickey, bool intrans, bool update)
                endtrans();
        }
 
+       /*
+        * Write the truncated 32 bit keyid so we can lookup the full id for
+        * queries.
+        */
+       if (!deadlock) {
+               shortkeyid = keyid & 0xFFFFFFFF;
+
+               memset(&key, 0, sizeof(key));
+               memset(&data, 0, sizeof(data));
+               key.data = &shortkeyid;
+               key.size = sizeof(shortkeyid);
+               data.data = &keyid;
+               data.size = sizeof(keyid);
+
+               ret = id32db->put(id32db,
+                       txn,
+                       &key,
+                       &data,
+                       0);
+               if (ret != 0) {
+                       logthing(LOGTHING_ERROR,
+                               "Problem storing short keyid: %s",
+                               db_strerror(ret));
+                       if (ret == DB_LOCK_DEADLOCK) {
+                               deadlock = true;
+                       }
+               }
+       }
+
+       if (!deadlock) {
+               subkeyids = keysubkeys(publickey);
+               i = 0;
+               while (subkeyids != NULL && subkeyids[i] != 0) {
+                       shortkeyid = subkeyids[i++] & 0xFFFFFFFF;
+
+                       memset(&key, 0, sizeof(key));
+                       memset(&data, 0, sizeof(data));
+                       key.data = &shortkeyid;
+                       key.size = sizeof(shortkeyid);
+                       data.data = &keyid;
+                       data.size = sizeof(keyid);
+
+                       ret = id32db->put(id32db,
+                               txn,
+                               &key,
+                               &data,
+                               0);
+                       if (ret != 0) {
+                               logthing(LOGTHING_ERROR,
+                                       "Problem storing short keyid: %s",
+                                       db_strerror(ret));
+                               if (ret == DB_LOCK_DEADLOCK) {
+                                       deadlock = true;
+                               }
+                       }
+               }
+               if (subkeyids != NULL) {
+                       free(subkeyids);
+                       subkeyids = NULL;
+               }
+       }
+
        return deadlock ? -1 : 0 ;
 }
 
@@ -668,6 +708,8 @@ int delete_key(uint64_t keyid, bool intrans)
        struct openpgp_publickey *publickey = NULL;
        DBT key, data;
        DBC *cursor = NULL;
+       uint32_t   shortkeyid = 0;
+       uint64_t  *subkeyids = NULL;
        int ret = 0;
        int i;
        char **uids = NULL;
@@ -677,8 +719,6 @@ int delete_key(uint64_t keyid, bool intrans)
        struct ll *curword  = NULL;
        bool deadlock = false;
 
-       keyid &= 0xFFFFFFFF;
-
        if (!intrans) {
                starttrans();
        }
@@ -767,6 +807,89 @@ int delete_key(uint64_t keyid, bool intrans)
                publickey = NULL;
        }
 
+       if (!deadlock) {
+               ret = id32db->cursor(id32db,
+                       txn,
+                       &cursor,
+                       0);   /* flags */
+
+               shortkeyid = keyid & 0xFFFFFFFF;
+
+               memset(&key, 0, sizeof(key));
+               memset(&data, 0, sizeof(data));
+               key.data = &shortkeyid;
+               key.size = sizeof(shortkeyid);
+               data.data = &keyid;
+               data.size = sizeof(keyid);
+
+               ret = cursor->c_get(cursor,
+                       &key,
+                       &data,
+                       DB_GET_BOTH);
+
+               if (ret == 0) {
+                       ret = cursor->c_del(cursor, 0);
+                       if (ret != 0) {
+                               logthing(LOGTHING_ERROR,
+                                       "Problem deleting short keyid: %s",
+                                       db_strerror(ret));
+                       }
+               }
+
+               if (ret != 0) {
+                       logthing(LOGTHING_ERROR,
+                               "Problem deleting short keyid: %s",
+                               db_strerror(ret));
+                       if (ret == DB_LOCK_DEADLOCK) {
+                               deadlock = true;
+                       }
+               }
+
+               subkeyids = keysubkeys(publickey);
+               i = 0;
+               while (subkeyids != NULL && subkeyids[i] != 0) {
+                       shortkeyid = subkeyids[i++] & 0xFFFFFFFF;
+
+                       memset(&key, 0, sizeof(key));
+                       memset(&data, 0, sizeof(data));
+                       key.data = &shortkeyid;
+                       key.size = sizeof(shortkeyid);
+                       data.data = &keyid;
+                       data.size = sizeof(keyid);
+
+                       ret = cursor->c_get(cursor,
+                               &key,
+                               &data,
+                               DB_GET_BOTH);
+
+                       if (ret == 0) {
+                               ret = cursor->c_del(cursor, 0);
+                               if (ret != 0) {
+                                       logthing(LOGTHING_ERROR,
+                                               "Problem deleting short"
+                                               " keyid: %s",
+                                               db_strerror(ret));
+                               }
+                       }
+
+                       if (ret != 0) {
+                               logthing(LOGTHING_ERROR,
+                                       "Problem deleting short keyid: %s",
+                                       db_strerror(ret));
+                               if (ret == DB_LOCK_DEADLOCK) {
+                                       deadlock = true;
+                               }
+                       }
+               }
+               if (subkeyids != NULL) {
+                       free(subkeyids);
+                       subkeyids = NULL;
+               }
+
+               ret = cursor->c_close(cursor);
+               cursor = NULL;
+       }
+
        if (!deadlock) {
                key.data = &keyid;
                key.size = sizeof(keyid);
@@ -843,10 +966,58 @@ int dumpdb(char *filenamebase)
        return 0;
 }
 
+/**
+ *     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)
+{
+       DBT       key, data;
+       DBC      *cursor = NULL;
+       uint32_t  shortkeyid = 0;
+       int       ret = 0;
+
+       if (keyid < 0x100000000LL) {
+               ret = id32db->cursor(id32db,
+                               txn,
+                               &cursor,
+                               0);   /* flags */
+
+               shortkeyid = keyid & 0xFFFFFFFF;
+
+               memset(&key, 0, sizeof(key));
+               memset(&data, 0, sizeof(data));
+               key.data = &shortkeyid;
+               key.size = sizeof(shortkeyid);
+               data.flags = DB_DBT_MALLOC;
+
+               ret = cursor->c_get(cursor,
+                       &key,
+                       &data,
+                       DB_SET);
+
+               if (ret == 0) {
+                       keyid = *(uint64_t *) data.data;
+
+                       if (data.data != NULL) {
+                               free(data.data);
+                               data.data = NULL;
+                       }
+               }
+
+               ret = cursor->c_close(cursor);
+               cursor = NULL;
+       }
+       
+       return keyid;
+}
+
 /*
  * Include the basic keydb routines.
  */
-#define NEED_GETFULLKEYID 1
 #define NEED_GETKEYSIGS 1
 #define NEED_KEYID2UID 1
 #include "keydb.c"