]> the.earth.li Git - onak.git/blobdiff - keydb_db4.c
Cleanup db4 properly if we fail to open it.
[onak.git] / keydb_db4.c
index 0163ed53ea5bfdfb9cfb72c6e8a0b50d0cf7d6ca..3f51cc2515eb5788426b66bb6e7ff3c72e248d91 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * keydb_db4.c - Routines to store and fetch keys in a DB3 database.
+ * keydb_db4.c - Routines to store and fetch keys in a DB4 database.
  *
  * Jonathan McDowell <noodles@earth.li>
  *
@@ -108,14 +108,15 @@ void initdb(bool readonly)
        if (dbconns == NULL) {
                logthing(LOGTHING_CRITICAL,
                                "Couldn't allocate memory for dbconns");
-               exit(1);
+               ret = 1;
        }
 
-       ret = db_env_create(&dbenv, 0);
-       if (ret != 0) {
-               logthing(LOGTHING_CRITICAL,
-                       "db_env_create: %s", db_strerror(ret));
-               exit(1);
+       if (ret == 0) {
+               ret = db_env_create(&dbenv, 0);
+               if (ret != 0) {
+                       logthing(LOGTHING_CRITICAL,
+                               "db_env_create: %s", db_strerror(ret));
+               }
        }
 
        /*
@@ -123,93 +124,121 @@ void initdb(bool readonly)
         * anything. What we really want is simple 2 state locks, but I'm not
         * sure how to make the standard DB functions do that yet.
         */
-       ret = dbenv->set_lk_detect(dbenv, DB_LOCK_DEFAULT);
-       if (ret != 0) {
-               logthing(LOGTHING_CRITICAL,
-                       "db_env_create: %s", db_strerror(ret));
-               exit(1);
+       if (ret == 0) {
+               ret = dbenv->set_lk_detect(dbenv, DB_LOCK_DEFAULT);
+               if (ret != 0) {
+                       logthing(LOGTHING_CRITICAL,
+                               "db_env_create: %s", db_strerror(ret));
+               }
        }
 
-       ret = dbenv->open(dbenv, config.db_dir,
-                       DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_LOCK |
-                       DB_INIT_TXN |
-                       DB_CREATE,
-                       0);
-       if (ret != 0) {
-               logthing(LOGTHING_CRITICAL,
-                               "Error opening db environment: %s (%s)",
-                               config.db_dir,
-                               db_strerror(ret));
-               exit(1);
+       if (ret == 0) {
+               ret = dbenv->open(dbenv, config.db_dir,
+                               DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_LOCK |
+                               DB_INIT_TXN |
+                               DB_CREATE,
+                               0);
+               if (ret != 0) {
+                       logthing(LOGTHING_CRITICAL,
+                                       "Error opening db environment: %s (%s)",
+                                       config.db_dir,
+                                       db_strerror(ret));
+               }
        }
 
-       starttrans();
+       if (ret == 0) {
+               starttrans();
 
-       for (i = 0; i < numdbs; i++) {
-               ret = db_create(&dbconns[i], dbenv, 0);
-               if (ret != 0) {
-                       logthing(LOGTHING_CRITICAL,
-                               "db_create: %s", db_strerror(ret));
-                       exit(1);
+               for (i = 0; !ret && i < numdbs; i++) {
+                       ret = db_create(&dbconns[i], dbenv, 0);
+                       if (ret != 0) {
+                               logthing(LOGTHING_CRITICAL,
+                                       "db_create: %s", db_strerror(ret));
+                       }
+
+                       if (ret == 0) {
+                               snprintf(buf, 1023, "keydb.%d.db", i);
+                               flags = DB_CREATE;
+                               if (readonly) {
+                                       flags = DB_RDONLY;
+                               }
+                               ret = dbconns[i]->open(dbconns[i],
+                                               txn,
+                                               buf,
+                                               "keydb",
+                                               DB_HASH,
+                                               flags,
+                                               0664);
+                               if (ret != 0) {
+                                       logthing(LOGTHING_CRITICAL,
+                                               "Error opening key database:"
+                                               " %s (%s)",
+                                               buf,
+                                               db_strerror(ret));
+                               }
+                       }
                }
 
-               snprintf(buf, 1023, "keydb.%d.db", i);
-               flags = DB_CREATE;
-               if (readonly) {
-                       flags = DB_RDONLY;
+       }
+
+       if (ret == 0) {
+               ret = db_create(&worddb, dbenv, 0);
+               if (ret != 0) {
+                       logthing(LOGTHING_CRITICAL, "db_create: %s",
+                                       db_strerror(ret));
                }
-               ret = dbconns[i]->open(dbconns[i],
-                               txn,
-                               buf,
-                               "keydb",
-                               DB_HASH,
+       }
+
+       if (ret == 0) {
+               ret = worddb->set_flags(worddb, DB_DUP);
+       }
+
+       if (ret == 0) {
+               ret = worddb->open(worddb, txn, "worddb", "worddb", DB_BTREE,
                                flags,
                                0664);
                if (ret != 0) {
                        logthing(LOGTHING_CRITICAL,
-                               "Error opening key database: %s (%s)",
-                               buf,
-                               db_strerror(ret));
-                       exit(1);
+                                       "Error opening word database: %s (%s)",
+                                       "worddb",
+                                       db_strerror(ret));
                }
        }
 
-       ret = db_create(&worddb, dbenv, 0);
-       if (ret != 0) {
-               logthing(LOGTHING_CRITICAL, "db_create: %s", db_strerror(ret));
-               exit(1);
+       if (ret == 0) {
+               ret = db_create(&id32db, dbenv, 0);
+               if (ret != 0) {
+                       logthing(LOGTHING_CRITICAL, "db_create: %s",
+                                       db_strerror(ret));
+               }
        }
-       ret = worddb->set_flags(worddb, DB_DUP);
 
-       ret = worddb->open(worddb, txn, "worddb", "worddb", DB_BTREE,
-                       flags,
-                       0664);
-       if (ret != 0) {
-               logthing(LOGTHING_CRITICAL,
-                               "Error opening word database: %s (%s)",
-                               "worddb",
-                               db_strerror(ret));
-               exit(1);
+       if (ret == 0) {
+               ret = id32db->set_flags(id32db, DB_DUP);
        }
 
-       ret = db_create(&id32db, dbenv, 0);
-       if (ret != 0) {
-               logthing(LOGTHING_CRITICAL, "db_create: %s", db_strerror(ret));
-               exit(1);
+       if (ret == 0) {
+               ret = id32db->open(id32db, txn, "id32db", "id32db", DB_HASH,
+                               flags,
+                               0664);
+               if (ret != 0) {
+                       logthing(LOGTHING_CRITICAL,
+                                       "Error opening id32 database: %s (%s)",
+                                       "id32db",
+                                       db_strerror(ret));
+               }
+       }
+
+       if (txn != NULL) {
+               endtrans();
        }
-       ret = id32db->set_flags(id32db, DB_DUP);
 
-       ret = id32db->open(id32db, txn, "id32db", "id32db", DB_HASH,
-                       flags,
-                       0664);
        if (ret != 0) {
+               cleanupdb();
                logthing(LOGTHING_CRITICAL,
-                               "Error opening id32 database: %s (%s)",
-                               "id32db",
-                               db_strerror(ret));
-               exit(1);
+                               "Error opening database; exiting");
+               exit(EXIT_FAILURE);
        }
-       endtrans();
        
        return;
 }
@@ -978,6 +1007,72 @@ int dumpdb(char *filenamebase)
        return 0;
 }
 
+/**
+ *     iterate_keys - call a function once for each key in the db.
+ *     @iterfunc: The function to call.
+ *     @ctx: A context pointer
+ *
+ *     Calls iterfunc once for each key in the database. ctx is passed
+ *     unaltered to iterfunc. This function is intended to aid database dumps
+ *     and statistic calculations.
+ *
+ *     Returns the number of keys we iterated over.
+ */
+int iterate_keys(void (*iterfunc)(void *ctx, struct openpgp_publickey *key),
+               void *ctx)
+{
+       DBT                         dbkey, data;
+       DBC                        *cursor = NULL;
+       int                         ret = 0;
+       int                         i = 0;
+       int                         numkeys = 0;
+       struct buffer_ctx           fetchbuf;
+       struct openpgp_packet_list *packets = NULL;
+       struct openpgp_publickey   *key = NULL;
+
+       for (i = 0; i < numdbs; i++) {
+               ret = dbconns[i]->cursor(dbconns[i],
+                       NULL,
+                       &cursor,
+                       0);   /* flags */
+
+               memset(&dbkey, 0, sizeof(dbkey));
+               memset(&data, 0, sizeof(data));
+               ret = cursor->c_get(cursor, &dbkey, &data, DB_NEXT);
+               while (ret == 0) {
+                       fetchbuf.buffer = data.data;
+                       fetchbuf.offset = 0;
+                       fetchbuf.size = data.size;
+                       read_openpgp_stream(buffer_fetchchar, &fetchbuf,
+                               &packets, 0);
+                       parse_keys(packets, &key);
+
+                       iterfunc(ctx, key);
+                       
+                       free_publickey(key);
+                       key = NULL;
+                       free_packet_list(packets);
+                       packets = NULL;
+                       
+                       memset(&dbkey, 0, sizeof(dbkey));
+                       memset(&data, 0, sizeof(data));
+                       ret = cursor->c_get(cursor, &dbkey, &data,
+                                       DB_NEXT);
+                       numkeys++;
+               }
+               if (ret != DB_NOTFOUND) {
+                       logthing(LOGTHING_ERROR,
+                               "Problem reading key: %s",
+                               db_strerror(ret));
+               }
+
+               ret = cursor->c_close(cursor);
+               cursor = NULL;
+       }
+       
+       return numkeys;
+}
+
 /**
  *     getfullkeyid - Maps a 32bit key id to a 64bit one.
  *     @keyid: The 32bit keyid.
@@ -1032,4 +1127,5 @@ uint64_t getfullkeyid(uint64_t keyid)
  */
 #define NEED_GETKEYSIGS 1
 #define NEED_KEYID2UID 1
+#define NEED_UPDATEKEYS 1
 #include "keydb.c"