2 * keydb_db4.c - Routines to store and fetch keys in a DB4 database.
4 * Copyright 2002-2008 Jonathan McDowell <noodles@earth.li>
20 #include "charfuncs.h"
24 #include "decodekey.h"
25 #include "keystructs.h"
28 #include "onak-conf.h"
32 #define DB4_UPGRADE_FILE "db_upgrade.lck"
35 * dbenv - our database environment.
37 static DB_ENV *dbenv = NULL;
40 * numdb - The number of database files we have.
42 static int numdbs = 16;
45 * dbconn - our connections to the key database files.
47 static DB **dbconns = NULL;
50 * worddb - our connection to the word database.
52 static DB *worddb = NULL;
55 * id32db - our connection to the 32bit ID database.
57 static DB *id32db = NULL;
60 * txn - our current transaction id.
62 static DB_TXN *txn = NULL;
64 DB *keydb(uint64_t keyid)
70 return(dbconns[keytrun % numdbs]);
74 * db4_errfunc - Direct DB errors to logfile
76 * Basic function to take errors from the DB library and output them to
77 * the logfile rather than stderr.
79 #if (DB_VERSION_MAJOR == 4) && (DB_VERSION_MINOR < 3)
80 static void db4_errfunc(const char *errpfx, const char *errmsg)
82 static void db4_errfunc(const DB_ENV *edbenv, const char *errpfx,
87 logthing(LOGTHING_DEBUG, "db4 error: %s:%s", errpfx, errmsg);
89 logthing(LOGTHING_DEBUG, "db4 error: %s", errmsg);
96 * starttrans - Start a transaction.
98 * Start a transaction. Intended to be used if we're about to perform many
99 * operations on the database to help speed it all up, or if we want
100 * something to only succeed if all relevant operations are successful.
102 static bool db4_starttrans(void)
106 log_assert(dbenv != NULL);
107 log_assert(txn == NULL);
109 ret = dbenv->txn_begin(dbenv,
110 NULL, /* No parent transaction */
114 logthing(LOGTHING_CRITICAL,
115 "Error starting transaction: %s",
124 * endtrans - End a transaction.
126 * Ends a transaction.
128 static void db4_endtrans(void)
132 log_assert(dbenv != NULL);
133 log_assert(txn != NULL);
135 ret = txn->commit(txn,
138 logthing(LOGTHING_CRITICAL,
139 "Error ending transaction: %s",
149 * cleanupdb - De-initialize the key database.
151 * This function should be called upon program exit to allow the DB to
152 * cleanup after itself.
154 static void db4_cleanupdb(void)
159 dbenv->txn_checkpoint(dbenv, 0, 0, 0);
160 if (id32db != NULL) {
161 id32db->close(id32db, 0);
164 if (worddb != NULL) {
165 worddb->close(worddb, 0);
168 for (i = 0; i < numdbs; i++) {
169 if (dbconns[i] != NULL) {
170 dbconns[i]->close(dbconns[i], 0);
176 dbenv->close(dbenv, 0);
182 * db4_upgradedb - Upgrade a DB4 database
184 * Called if we discover we need to upgrade our DB4 database; ie if
185 * we're running with a newer version of db4 than the database was
188 static int db4_upgradedb(int numdb)
197 snprintf(buf, sizeof(buf) - 1, "%s/%s", config.db_dir,
199 lockfile_fd = open(buf, O_RDWR | O_CREAT | O_EXCL, 0600);
200 if (lockfile_fd < 0) {
201 if (errno == EEXIST) {
202 while (stat(buf, &statbuf) == 0) ;
205 logthing(LOGTHING_CRITICAL, "Couldn't open database "
206 "update lock file: %s", strerror(errno));
210 snprintf(buf, sizeof(buf) - 1, "%d", getpid());
211 write(lockfile_fd, buf, strlen(buf));
214 logthing(LOGTHING_NOTICE, "Upgrading DB4 database");
215 ret = db_env_create(&dbenv, 0);
216 dbenv->set_errcall(dbenv, &db4_errfunc);
217 dbenv->remove(dbenv, config.db_dir, 0);
219 for (i = 0; i < numdb; i++) {
220 ret = db_create(&curdb, NULL, 0);
222 snprintf(buf, sizeof(buf) - 1, "%s/keydb.%d.db",
224 logthing(LOGTHING_DEBUG, "Upgrading %s", buf);
225 ret = curdb->upgrade(curdb, buf, 0);
226 curdb->close(curdb, 0);
228 logthing(LOGTHING_ERROR, "Error upgrading DB %s : %s",
234 ret = db_create(&curdb, NULL, 0);
236 snprintf(buf, sizeof(buf) - 1, "%s/worddb", config.db_dir);
237 logthing(LOGTHING_DEBUG, "Upgrading %s", buf);
238 ret = curdb->upgrade(curdb, buf, 0);
239 curdb->close(curdb, 0);
241 logthing(LOGTHING_ERROR, "Error upgrading DB %s : %s",
246 ret = db_create(&curdb, NULL, 0);
248 snprintf(buf, sizeof(buf) - 1, "%s/id32db", config.db_dir);
249 logthing(LOGTHING_DEBUG, "Upgrading %s", buf);
250 ret = curdb->upgrade(curdb, buf, 0);
251 curdb->close(curdb, 0);
253 logthing(LOGTHING_ERROR, "Error upgrading DB %s : %s",
258 snprintf(buf, sizeof(buf) - 1, "%s/%s", config.db_dir,
266 * initdb - Initialize the key database.
268 * This function should be called before any of the other functions in
269 * this file are called in order to allow the DB to be initialized ready
272 static void db4_initdb(bool readonly)
282 snprintf(buf, sizeof(buf) - 1, "%s/%s", config.db_dir,
284 ret = stat(buf, &statbuf);
285 while ((ret == 0) || (errno != ENOENT)) {
287 logthing(LOGTHING_CRITICAL, "Couldn't stat upgrade "
288 "lock file: %s (%d)", strerror(errno), ret);
291 logthing(LOGTHING_DEBUG, "DB4 upgrade in progress; waiting.");
293 ret = stat(buf, &statbuf);
297 snprintf(buf, sizeof(buf) - 1, "%s/num_keydb", config.db_dir);
298 numdb = fopen(buf, "r");
300 if (fgets(buf, sizeof(buf), numdb) != NULL) {
304 } else if (!readonly) {
305 logthing(LOGTHING_ERROR, "Couldn't open num_keydb: %s",
307 numdb = fopen(buf, "w");
309 fprintf(numdb, "%d", numdbs);
312 logthing(LOGTHING_ERROR,
313 "Couldn't write num_keydb: %s",
318 dbconns = calloc(numdbs, sizeof (DB *));
319 if (dbconns == NULL) {
320 logthing(LOGTHING_CRITICAL,
321 "Couldn't allocate memory for dbconns");
326 ret = db_env_create(&dbenv, 0);
328 logthing(LOGTHING_CRITICAL,
329 "db_env_create: %s", db_strerror(ret));
334 * Up the number of locks we're allowed at once. We base this on
335 * the maximum number of keys we're going to return.
337 maxlocks = config.maxkeys * 16;
338 if (maxlocks < 1000) {
341 dbenv->set_lk_max_locks(dbenv, maxlocks);
342 dbenv->set_lk_max_objects(dbenv, maxlocks);
345 * Enable deadlock detection so that we don't block indefinitely on
346 * anything. What we really want is simple 2 state locks, but I'm not
347 * sure how to make the standard DB functions do that yet.
350 dbenv->set_errcall(dbenv, &db4_errfunc);
351 ret = dbenv->set_lk_detect(dbenv, DB_LOCK_DEFAULT);
353 logthing(LOGTHING_CRITICAL,
354 "db_env_create: %s", db_strerror(ret));
359 ret = dbenv->open(dbenv, config.db_dir,
360 DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_LOCK |
364 #ifdef DB_VERSION_MISMATCH
365 if (ret == DB_VERSION_MISMATCH) {
366 dbenv->close(dbenv, 0);
368 ret = db4_upgradedb(numdbs);
370 ret = db_env_create(&dbenv, 0);
373 dbenv->set_errcall(dbenv, &db4_errfunc);
374 dbenv->set_lk_detect(dbenv, DB_LOCK_DEFAULT);
375 ret = dbenv->open(dbenv, config.db_dir,
376 DB_INIT_LOG | DB_INIT_MPOOL |
377 DB_INIT_LOCK | DB_INIT_TXN |
378 DB_CREATE | DB_RECOVER,
382 dbenv->txn_checkpoint(dbenv,
391 logthing(LOGTHING_CRITICAL,
392 "Error opening db environment: %s (%s)",
395 dbenv->close(dbenv, 0);
403 for (i = 0; !ret && i < numdbs; i++) {
404 ret = db_create(&dbconns[i], dbenv, 0);
406 logthing(LOGTHING_CRITICAL,
407 "db_create: %s", db_strerror(ret));
411 snprintf(buf, 1023, "keydb.%d.db", i);
416 ret = dbconns[i]->open(dbconns[i],
424 logthing(LOGTHING_CRITICAL,
425 "Error opening key database:"
436 ret = db_create(&worddb, dbenv, 0);
438 logthing(LOGTHING_CRITICAL, "db_create: %s",
444 ret = worddb->set_flags(worddb, DB_DUP);
448 ret = worddb->open(worddb, txn, "worddb", "worddb", DB_BTREE,
452 logthing(LOGTHING_CRITICAL,
453 "Error opening word database: %s (%s)",
460 ret = db_create(&id32db, dbenv, 0);
462 logthing(LOGTHING_CRITICAL, "db_create: %s",
468 ret = id32db->set_flags(id32db, DB_DUP);
472 ret = id32db->open(id32db, txn, "id32db", "id32db", DB_HASH,
476 logthing(LOGTHING_CRITICAL,
477 "Error opening id32 database: %s (%s)",
489 logthing(LOGTHING_CRITICAL,
490 "Error opening database; exiting");
498 * getfullkeyid - Maps a 32bit key id to a 64bit one.
499 * @keyid: The 32bit keyid.
501 * This function maps a 32bit key id to the full 64bit one. It returns the
502 * full keyid. If the key isn't found a keyid of 0 is returned.
504 static uint64_t db4_getfullkeyid(uint64_t keyid)
508 uint32_t shortkeyid = 0;
511 if (keyid < 0x100000000LL) {
512 ret = id32db->cursor(id32db,
517 shortkeyid = keyid & 0xFFFFFFFF;
519 memset(&key, 0, sizeof(key));
520 memset(&data, 0, sizeof(data));
521 key.data = &shortkeyid;
522 key.size = sizeof(shortkeyid);
523 data.flags = DB_DBT_MALLOC;
525 ret = cursor->c_get(cursor,
531 keyid = *(uint64_t *) data.data;
533 if (data.data != NULL) {
539 ret = cursor->c_close(cursor);
547 * fetch_key - Given a keyid fetch the key from storage.
548 * @keyid: The keyid to fetch.
549 * @publickey: A pointer to a structure to return the key in.
550 * @intrans: If we're already in a transaction.
552 * We use the hex representation of the keyid as the filename to fetch the
553 * key from. The key is stored in the file as a binary OpenPGP stream of
554 * packets, so we can just use read_openpgp_stream() to read the packets
555 * in and then parse_keys() to parse the packets into a publickey
558 static int db4_fetch_key(uint64_t keyid, struct openpgp_publickey **publickey,
561 struct openpgp_packet_list *packets = NULL;
565 struct buffer_ctx fetchbuf;
567 if (keyid < 0x100000000LL) {
568 keyid = db4_getfullkeyid(keyid);
571 memset(&key, 0, sizeof(key));
572 memset(&data, 0, sizeof(data));
577 key.size = sizeof(keyid);
584 ret = keydb(keyid)->get(keydb(keyid),
591 fetchbuf.buffer = data.data;
593 fetchbuf.size = data.size;
594 read_openpgp_stream(buffer_fetchchar, &fetchbuf,
596 parse_keys(packets, publickey);
597 free_packet_list(packets);
600 } else if (ret != DB_NOTFOUND) {
601 logthing(LOGTHING_ERROR,
602 "Problem retrieving key: %s",
613 int worddb_cmp(const void *d1, const void *d2)
615 return memcmp(d1, d2, 12);
619 * fetch_key_text - Trys to find the keys that contain the supplied text.
620 * @search: The text to search for.
621 * @publickey: A pointer to a structure to return the key in.
623 * This function searches for the supplied text and returns the keys that
626 static int db4_fetch_key_text(const char *search,
627 struct openpgp_publickey **publickey)
635 char *searchtext = NULL;
636 struct ll *wordlist = NULL;
637 struct ll *curword = NULL;
638 struct keyarray keylist = { NULL, 0, 0 };
639 struct keyarray newkeylist = { NULL, 0, 0 };
643 searchtext = strdup(search);
644 wordlist = makewordlist(wordlist, searchtext);
646 for (curword = wordlist; curword != NULL; curword = curword->next) {
649 ret = worddb->cursor(worddb,
654 memset(&key, 0, sizeof(key));
655 memset(&data, 0, sizeof(data));
656 key.data = curword->object;
657 key.size = strlen(curword->object);
658 data.flags = DB_DBT_MALLOC;
659 ret = cursor->c_get(cursor,
663 while (ret == 0 && strncmp(key.data, curword->object,
665 ((char *) curword->object)[key.size] == 0) {
667 for (i = 4; i < 12; i++) {
669 keyid += ((unsigned char *)
674 * Only add the keys containing this word if this is
675 * our first pass (ie we have no existing key list),
676 * or the key contained a previous word.
678 if (firstpass || array_find(&keylist, keyid)) {
679 array_add(&newkeylist, keyid);
685 ret = cursor->c_get(cursor,
690 array_free(&keylist);
691 keylist = newkeylist;
692 newkeylist.keys = NULL;
693 newkeylist.count = newkeylist.size = 0;
694 if (data.data != NULL) {
698 ret = cursor->c_close(cursor);
703 llfree(wordlist, NULL);
706 if (keylist.count > config.maxkeys) {
707 keylist.count = config.maxkeys;
711 for (i = 0; i < keylist.count; i++) {
712 numkeys += db4_fetch_key(keylist.keys[i],
716 array_free(&keylist);
726 * delete_key - Given a keyid delete the key from storage.
727 * @keyid: The keyid to delete.
728 * @intrans: If we're already in a transaction.
730 * This function deletes a public key from whatever storage mechanism we
731 * are using. Returns 0 if the key existed.
733 static int db4_delete_key(uint64_t keyid, bool intrans)
735 struct openpgp_publickey *publickey = NULL;
738 uint32_t shortkeyid = 0;
739 uint64_t *subkeyids = NULL;
743 char *primary = NULL;
744 unsigned char worddb_data[12];
745 struct ll *wordlist = NULL;
746 struct ll *curword = NULL;
747 bool deadlock = false;
753 db4_fetch_key(keyid, &publickey, true);
756 * Walk through the uids removing the words from the worddb.
758 if (publickey != NULL) {
759 uids = keyuids(publickey, &primary);
762 for (i = 0; ret == 0 && uids[i] != NULL; i++) {
763 wordlist = makewordlist(wordlist, uids[i]);
766 ret = worddb->cursor(worddb,
771 for (curword = wordlist; curword != NULL && !deadlock;
772 curword = curword->next) {
773 memset(&key, 0, sizeof(key));
774 memset(&data, 0, sizeof(data));
775 key.data = curword->object;
776 key.size = strlen(key.data);
777 data.data = worddb_data;
778 data.size = sizeof(worddb_data);
781 * Our data is the key creation time followed by the
784 worddb_data[ 0] = publickey->publickey->data[1];
785 worddb_data[ 1] = publickey->publickey->data[2];
786 worddb_data[ 2] = publickey->publickey->data[3];
787 worddb_data[ 3] = publickey->publickey->data[4];
788 worddb_data[ 4] = (keyid >> 56) & 0xFF;
789 worddb_data[ 5] = (keyid >> 48) & 0xFF;
790 worddb_data[ 6] = (keyid >> 40) & 0xFF;
791 worddb_data[ 7] = (keyid >> 32) & 0xFF;
792 worddb_data[ 8] = (keyid >> 24) & 0xFF;
793 worddb_data[ 9] = (keyid >> 16) & 0xFF;
794 worddb_data[10] = (keyid >> 8) & 0xFF;
795 worddb_data[11] = keyid & 0xFF;
797 ret = cursor->c_get(cursor,
803 ret = cursor->c_del(cursor, 0);
805 logthing(LOGTHING_ERROR,
806 "Problem deleting word: %s",
812 logthing(LOGTHING_ERROR,
813 "Problem deleting word: %s",
815 if (ret == DB_LOCK_DEADLOCK) {
820 ret = cursor->c_close(cursor);
824 * Free our UID and word lists.
826 llfree(wordlist, NULL);
827 for (i = 0; uids[i] != NULL; i++) {
833 free_publickey(publickey);
838 ret = id32db->cursor(id32db,
843 shortkeyid = keyid & 0xFFFFFFFF;
845 memset(&key, 0, sizeof(key));
846 memset(&data, 0, sizeof(data));
847 key.data = &shortkeyid;
848 key.size = sizeof(shortkeyid);
850 data.size = sizeof(keyid);
852 ret = cursor->c_get(cursor,
858 ret = cursor->c_del(cursor, 0);
860 logthing(LOGTHING_ERROR,
861 "Problem deleting short keyid: %s",
867 logthing(LOGTHING_ERROR,
868 "Problem deleting short keyid: %s",
870 if (ret == DB_LOCK_DEADLOCK) {
875 subkeyids = keysubkeys(publickey);
877 while (subkeyids != NULL && subkeyids[i] != 0) {
878 shortkeyid = subkeyids[i++] & 0xFFFFFFFF;
880 memset(&key, 0, sizeof(key));
881 memset(&data, 0, sizeof(data));
882 key.data = &shortkeyid;
883 key.size = sizeof(shortkeyid);
885 data.size = sizeof(keyid);
887 ret = cursor->c_get(cursor,
893 ret = cursor->c_del(cursor, 0);
895 logthing(LOGTHING_ERROR,
896 "Problem deleting short"
903 logthing(LOGTHING_ERROR,
904 "Problem deleting short keyid: %s",
906 if (ret == DB_LOCK_DEADLOCK) {
911 if (subkeyids != NULL) {
916 ret = cursor->c_close(cursor);
922 key.size = sizeof(keyid);
924 keydb(keyid)->del(keydb(keyid),
934 return deadlock ? (-1) : (ret == DB_NOTFOUND);
938 * store_key - Takes a key and stores it.
939 * @publickey: A pointer to the public key to store.
940 * @intrans: If we're already in a transaction.
941 * @update: If true the key exists and should be updated.
943 * Again we just use the hex representation of the keyid as the filename
944 * to store the key to. We flatten the public key to a list of OpenPGP
945 * packets and then use write_openpgp_stream() to write the stream out to
946 * the file. If update is true then we delete the old key first, otherwise
947 * we trust that it doesn't exist.
949 static int db4_store_key(struct openpgp_publickey *publickey, bool intrans,
952 struct openpgp_packet_list *packets = NULL;
953 struct openpgp_packet_list *list_end = NULL;
954 struct openpgp_publickey *next = NULL;
957 struct buffer_ctx storebuf;
961 uint32_t shortkeyid = 0;
962 uint64_t *subkeyids = NULL;
964 char *primary = NULL;
965 unsigned char worddb_data[12];
966 struct ll *wordlist = NULL;
967 struct ll *curword = NULL;
968 bool deadlock = false;
970 keyid = get_keyid(publickey);
977 * Delete the key if we already have it.
979 * TODO: Can we optimize this perhaps? Possibly when other data is
980 * involved as well? I suspect this is easiest and doesn't make a lot
981 * of difference though - the largest chunk of data is the keydata and
982 * it definitely needs updated.
985 deadlock = (db4_delete_key(keyid, true) == -1);
989 * Convert the key to a flat set of binary data.
992 next = publickey->next;
993 publickey->next = NULL;
994 flatten_publickey(publickey, &packets, &list_end);
995 publickey->next = next;
998 storebuf.size = 8192;
999 storebuf.buffer = malloc(8192);
1001 write_openpgp_stream(buffer_putchar, &storebuf, packets);
1004 * Now we have the key data store it in the DB; the keyid is
1007 memset(&key, 0, sizeof(key));
1008 memset(&data, 0, sizeof(data));
1010 key.size = sizeof(keyid);
1011 data.size = storebuf.offset;
1012 data.data = storebuf.buffer;
1014 ret = keydb(keyid)->put(keydb(keyid),
1020 logthing(LOGTHING_ERROR,
1021 "Problem storing key: %s",
1023 if (ret == DB_LOCK_DEADLOCK) {
1028 free(storebuf.buffer);
1029 storebuf.buffer = NULL;
1031 storebuf.offset = 0;
1033 free_packet_list(packets);
1038 * Walk through our uids storing the words into the db with the keyid.
1041 uids = keyuids(publickey, &primary);
1044 for (i = 0; ret == 0 && uids[i] != NULL; i++) {
1045 wordlist = makewordlist(wordlist, uids[i]);
1048 for (curword = wordlist; curword != NULL && !deadlock;
1049 curword = curword->next) {
1050 memset(&key, 0, sizeof(key));
1051 memset(&data, 0, sizeof(data));
1052 key.data = curword->object;
1053 key.size = strlen(key.data);
1054 data.data = worddb_data;
1055 data.size = sizeof(worddb_data);
1058 * Our data is the key creation time followed by the
1061 worddb_data[ 0] = publickey->publickey->data[1];
1062 worddb_data[ 1] = publickey->publickey->data[2];
1063 worddb_data[ 2] = publickey->publickey->data[3];
1064 worddb_data[ 3] = publickey->publickey->data[4];
1065 worddb_data[ 4] = (keyid >> 56) & 0xFF;
1066 worddb_data[ 5] = (keyid >> 48) & 0xFF;
1067 worddb_data[ 6] = (keyid >> 40) & 0xFF;
1068 worddb_data[ 7] = (keyid >> 32) & 0xFF;
1069 worddb_data[ 8] = (keyid >> 24) & 0xFF;
1070 worddb_data[ 9] = (keyid >> 16) & 0xFF;
1071 worddb_data[10] = (keyid >> 8) & 0xFF;
1072 worddb_data[11] = keyid & 0xFF;
1073 ret = worddb->put(worddb,
1079 logthing(LOGTHING_ERROR,
1080 "Problem storing word: %s",
1082 if (ret == DB_LOCK_DEADLOCK) {
1089 * Free our UID and word lists.
1091 llfree(wordlist, NULL);
1092 for (i = 0; uids[i] != NULL; i++) {
1101 * Write the truncated 32 bit keyid so we can lookup the full id for
1105 shortkeyid = keyid & 0xFFFFFFFF;
1107 memset(&key, 0, sizeof(key));
1108 memset(&data, 0, sizeof(data));
1109 key.data = &shortkeyid;
1110 key.size = sizeof(shortkeyid);
1112 data.size = sizeof(keyid);
1114 ret = id32db->put(id32db,
1120 logthing(LOGTHING_ERROR,
1121 "Problem storing short keyid: %s",
1123 if (ret == DB_LOCK_DEADLOCK) {
1130 subkeyids = keysubkeys(publickey);
1132 while (subkeyids != NULL && subkeyids[i] != 0) {
1133 shortkeyid = subkeyids[i++] & 0xFFFFFFFF;
1135 memset(&key, 0, sizeof(key));
1136 memset(&data, 0, sizeof(data));
1137 key.data = &shortkeyid;
1138 key.size = sizeof(shortkeyid);
1140 data.size = sizeof(keyid);
1142 ret = id32db->put(id32db,
1148 logthing(LOGTHING_ERROR,
1149 "Problem storing short keyid: %s",
1151 if (ret == DB_LOCK_DEADLOCK) {
1156 if (subkeyids != NULL) {
1166 return deadlock ? -1 : 0 ;
1170 * iterate_keys - call a function once for each key in the db.
1171 * @iterfunc: The function to call.
1172 * @ctx: A context pointer
1174 * Calls iterfunc once for each key in the database. ctx is passed
1175 * unaltered to iterfunc. This function is intended to aid database dumps
1176 * and statistic calculations.
1178 * Returns the number of keys we iterated over.
1180 static int db4_iterate_keys(void (*iterfunc)(void *ctx,
1181 struct openpgp_publickey *key), void *ctx)
1188 struct buffer_ctx fetchbuf;
1189 struct openpgp_packet_list *packets = NULL;
1190 struct openpgp_publickey *key = NULL;
1192 for (i = 0; i < numdbs; i++) {
1193 ret = dbconns[i]->cursor(dbconns[i],
1198 memset(&dbkey, 0, sizeof(dbkey));
1199 memset(&data, 0, sizeof(data));
1200 ret = cursor->c_get(cursor, &dbkey, &data, DB_NEXT);
1202 fetchbuf.buffer = data.data;
1203 fetchbuf.offset = 0;
1204 fetchbuf.size = data.size;
1205 read_openpgp_stream(buffer_fetchchar, &fetchbuf,
1207 parse_keys(packets, &key);
1211 free_publickey(key);
1213 free_packet_list(packets);
1216 memset(&dbkey, 0, sizeof(dbkey));
1217 memset(&data, 0, sizeof(data));
1218 ret = cursor->c_get(cursor, &dbkey, &data,
1222 if (ret != DB_NOTFOUND) {
1223 logthing(LOGTHING_ERROR,
1224 "Problem reading key: %s",
1228 ret = cursor->c_close(cursor);
1236 * Include the basic keydb routines.
1238 #define NEED_GETKEYSIGS 1
1239 #define NEED_KEYID2UID 1
1240 #define NEED_UPDATEKEYS 1
1243 struct dbfuncs keydb_db4_funcs = {
1244 .initdb = db4_initdb,
1245 .cleanupdb = db4_cleanupdb,
1246 .starttrans = db4_starttrans,
1247 .endtrans = db4_endtrans,
1248 .fetch_key = db4_fetch_key,
1249 .fetch_key_text = db4_fetch_key_text,
1250 .store_key = db4_store_key,
1251 .update_keys = generic_update_keys,
1252 .delete_key = db4_delete_key,
1253 .getkeysigs = generic_getkeysigs,
1254 .cached_getkeysigs = generic_cached_getkeysigs,
1255 .keyid2uid = generic_keyid2uid,
1256 .getfullkeyid = db4_getfullkeyid,
1257 .iterate_keys = db4_iterate_keys,