* Jonathan McDowell <noodles@earth.li>
*
* Copyright 2002 Project Purple
- *
- * $Id: keydb_db3.c,v 1.23 2004/03/23 12:33:46 noodles Exp $
*/
#include <assert.h>
#include "log.h"
#include "onak-conf.h"
#include "parsekey.h"
+#include "wordlist.h"
/**
* dbenv - our database environment.
*/
static DB *worddb = NULL;
+/**
+ * id32db - our connection to the 32bit ID database.
+ */
+static DB *id32db = NULL;
+
/**
* txn - our current transaction id.
*/
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.
*
*/
void initdb(bool readonly)
{
- char buf[1024];
- FILE *numdb = NULL;
- int ret = 0;
- int i = 0;
+ char buf[1024];
+ FILE *numdb = NULL;
+ int ret = 0;
+ int i = 0;
+ u_int32_t flags = 0;
snprintf(buf, sizeof(buf) - 1, "%s/num_keydb", config.db_dir);
numdb = fopen(buf, "r");
numdbs = atoi(buf);
}
fclose(numdb);
- } else {
+ } else if (!readonly) {
logthing(LOGTHING_ERROR, "Couldn't open num_keydb: %s",
strerror(errno));
numdb = fopen(buf, "w");
}
snprintf(buf, 1023, "keydb.%d.db", i);
+ flags = DB_CREATE;
+ if (readonly) {
+ flags = DB_RDONLY;
+ }
ret = dbconns[i]->open(dbconns[i], buf,
NULL,
DB_HASH,
- DB_CREATE,
+ flags,
0664);
if (ret != 0) {
logthing(LOGTHING_CRITICAL,
ret = worddb->set_flags(worddb, DB_DUP);
ret = worddb->open(worddb, "worddb", NULL, DB_BTREE,
- DB_CREATE,
+ flags,
0664);
if (ret != 0) {
logthing(LOGTHING_CRITICAL,
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;
}
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++) {
int numkeys = 0;
struct buffer_ctx fetchbuf;
+ if (keyid < 0x100000000LL) {
+ keyid = getfullkeyid(keyid);
+ }
+
memset(&key, 0, sizeof(key));
memset(&data, 0, sizeof(data));
key.size = sizeof(keyid);
key.data = &keyid;
- keyid &= 0xFFFFFFFF;
if (!intrans) {
starttrans();
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);
}
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];
memset(&data, 0, sizeof(data));
key.data = &keyid;
key.size = sizeof(keyid);
- keyid &= 0xFFFFFFFF;
data.size = storebuf.offset;
data.data = storebuf.buffer;
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 ;
}
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;
struct ll *curword = NULL;
bool deadlock = false;
- keyid &= 0xFFFFFFFF;
-
if (!intrans) {
starttrans();
}
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);
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"