+ 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);
+
+ keydb(keyid)->del(keydb(keyid),
+ txn,
+ &key,
+ 0); /* flags */
+ }
+
+ if (!intrans) {
+ endtrans();
+ }
+
+ return deadlock ? (-1) : (ret == DB_NOTFOUND);
+}
+
+/**
+ * dumpdb - dump the key database
+ * @filenamebase: The base filename to use for the dump.
+ *
+ * Dumps the database into one or more files, which contain pure OpenPGP
+ * that can be reimported into onak or gpg. filenamebase provides a base
+ * file name for the dump; several files may be created, all of which will
+ * begin with this string and then have a unique number and a .pgp
+ * extension.
+ */
+int dumpdb(char *filenamebase)
+{
+ DBT key, data;
+ DBC *cursor = NULL;
+ int ret = 0;
+ int fd = -1;
+ int i = 0;
+ char filename[1024];
+
+ filename[1023] = 0;
+ for (i = 0; i < numdbs; i++) {
+ ret = dbconns[i]->cursor(dbconns[i],
+ NULL,
+ &cursor,
+ 0); /* flags */
+
+ snprintf(filename, 1023, "%s.%d.pgp", filenamebase, i);
+ fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, 0640);
+ if (fd == -1) {
+ logthing(LOGTHING_ERROR,
+ "Error opening keydump file (%s): %s",
+ filename,
+ strerror(errno));
+ } else {
+ memset(&key, 0, sizeof(key));
+ memset(&data, 0, sizeof(data));
+ ret = cursor->c_get(cursor, &key, &data, DB_NEXT);
+ while (ret == 0) {
+ write(fd, data.data, data.size);
+ memset(&key, 0, sizeof(key));
+ memset(&data, 0, sizeof(data));
+ ret = cursor->c_get(cursor, &key, &data,
+ DB_NEXT);
+ }
+ if (ret != DB_NOTFOUND) {
+ logthing(LOGTHING_ERROR,
+ "Problem reading key: %s",
+ db_strerror(ret));
+ }
+ close(fd);
+ }
+
+ ret = cursor->c_close(cursor);
+ cursor = NULL;
+ }
+
+ 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;