+ * Called if we discover we need to upgrade our DB4 database; ie if
+ * we're running with a newer version of db4 than the database was
+ * created with.
+ */
+static int db4_upgradedb(struct onak_dbctx *dbctx)
+{
+ struct onak_db4_dbctx *privctx = (struct onak_db4_dbctx *) dbctx->priv;
+ DB *curdb = NULL;
+ int ret;
+ int i;
+ char buf[1024];
+ int lockfile_fd;
+ struct stat statbuf;
+ ssize_t written;
+
+ snprintf(buf, sizeof(buf) - 1, "%s/%s", dbctx->config->location,
+ DB4_UPGRADE_FILE);
+ lockfile_fd = open(buf, O_RDWR | O_CREAT | O_EXCL, 0600);
+ if (lockfile_fd < 0) {
+ if (errno == EEXIST) {
+ while (stat(buf, &statbuf) == 0) ;
+ return 0;
+ } else {
+ logthing(LOGTHING_CRITICAL, "Couldn't open database "
+ "update lock file: %s", strerror(errno));
+ return -1;
+ }
+ }
+ snprintf(buf, sizeof(buf) - 1, "%d", getpid());
+ written = write(lockfile_fd, buf, strlen(buf));
+ close(lockfile_fd);
+ if (written != strlen(buf)) {
+ logthing(LOGTHING_CRITICAL, "Couldn't write PID to lockfile: "
+ "%s", strerror(errno));
+ snprintf(buf, sizeof(buf) - 1, "%s/%s", dbctx->config->location,
+ DB4_UPGRADE_FILE);
+ unlink(buf);
+ return -1;
+ }
+
+ logthing(LOGTHING_NOTICE, "Upgrading DB4 database");
+ ret = db_env_create(&privctx->dbenv, 0);
+ if (ret == 0) {
+ privctx->dbenv->set_errcall(privctx->dbenv, &db4_errfunc);
+ privctx->dbenv->remove(privctx->dbenv, dbctx->config->location, 0);
+ privctx->dbenv = NULL;
+ }
+ for (i = 0; i < privctx->numdbs; i++) {
+ ret = db_create(&curdb, NULL, 0);
+ if (ret == 0) {
+ snprintf(buf, sizeof(buf) - 1, "%s/keydb.%d.db",
+ dbctx->config->location, i);
+ logthing(LOGTHING_DEBUG, "Upgrading %s", buf);
+ curdb->upgrade(curdb, buf, 0);
+ curdb->close(curdb, 0);
+ } else {
+ logthing(LOGTHING_ERROR, "Error upgrading DB %s : %s",
+ buf,
+ db_strerror(ret));
+ }
+ }
+
+ ret = db_create(&curdb, NULL, 0);
+ if (ret == 0) {
+ snprintf(buf, sizeof(buf) - 1, "%s/worddb", dbctx->config->location);
+ logthing(LOGTHING_DEBUG, "Upgrading %s", buf);
+ curdb->upgrade(curdb, buf, 0);
+ curdb->close(curdb, 0);
+ } else {
+ logthing(LOGTHING_ERROR, "Error upgrading DB %s : %s",
+ buf,
+ db_strerror(ret));
+ }
+
+ ret = db_create(&curdb, NULL, 0);
+ if (ret == 0) {
+ snprintf(buf, sizeof(buf) - 1, "%s/id32db", dbctx->config->location);
+ logthing(LOGTHING_DEBUG, "Upgrading %s", buf);
+ curdb->upgrade(curdb, buf, 0);
+ curdb->close(curdb, 0);
+ } else {
+ logthing(LOGTHING_ERROR, "Error upgrading DB %s : %s",
+ buf,
+ db_strerror(ret));
+ }
+
+ ret = db_create(&curdb, NULL, 0);
+ if (ret == 0) {
+ snprintf(buf, sizeof(buf) - 1, "%s/id64db", dbctx->config->location);
+ logthing(LOGTHING_DEBUG, "Upgrading %s", buf);
+ curdb->upgrade(curdb, buf, 0);
+ curdb->close(curdb, 0);
+ } else {
+ logthing(LOGTHING_ERROR, "Error upgrading DB %s : %s",
+ buf,
+ db_strerror(ret));
+ }
+
+ ret = db_create(&curdb, NULL, 0);
+ if (ret == 0) {
+ snprintf(buf, sizeof(buf) - 1, "%s/skshashdb", dbctx->config->location);
+ logthing(LOGTHING_DEBUG, "Upgrading %s", buf);
+ curdb->upgrade(curdb, buf, 0);
+ curdb->close(curdb, 0);
+ } else {
+ logthing(LOGTHING_ERROR, "Error upgrading DB %s : %s",
+ buf,
+ db_strerror(ret));
+ }
+
+ ret = db_create(&curdb, NULL, 0);
+ if (ret == 0) {
+ snprintf(buf, sizeof(buf) - 1, "%s/subkeydb", dbctx->config->location);
+ logthing(LOGTHING_DEBUG, "Upgrading %s", buf);
+ curdb->upgrade(curdb, buf, 0);
+ curdb->close(curdb, 0);
+ } else {
+ logthing(LOGTHING_ERROR, "Error upgrading DB %s : %s",
+ buf,
+ db_strerror(ret));
+ }
+
+ snprintf(buf, sizeof(buf) - 1, "%s/%s", dbctx->config->location,
+ DB4_UPGRADE_FILE);
+ unlink(buf);
+
+ return ret;
+}
+
+/**
+ * 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.
+ */
+static uint64_t db4_getfullkeyid(struct onak_dbctx *dbctx, uint64_t keyid)
+{
+ struct onak_db4_dbctx *privctx = (struct onak_db4_dbctx *) dbctx->priv;
+ DBT key, data;
+ DBC *cursor = NULL;
+ uint32_t shortkeyid = 0;
+ int ret = 0;
+ int i;
+
+ if (keyid < 0x100000000LL) {
+ ret = privctx->id32db->cursor(privctx->id32db,
+ privctx->txn,
+ &cursor,
+ 0); /* flags */
+
+ if (ret != 0) {
+ return 0;
+ }
+
+ 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) {
+ if (data.size == 8) {
+ keyid = * (uint64_t *) data.data;
+ } else {
+ keyid = 0;
+ for (i = 12; i < 20; i++) {
+ keyid <<= 8;
+ keyid |= ((uint8_t *) data.data)[i];
+ }
+ }
+
+ if (data.data != NULL) {
+ free(data.data);
+ data.data = NULL;
+ }
+ }
+
+ cursor->c_close(cursor);
+ cursor = NULL;
+ }
+
+ return keyid;
+}
+
+/**
+ * fetch_key_fp - Given a fingerprint fetch the key from storage.