X-Git-Url: https://the.earth.li/gitweb/?p=onak.git;a=blobdiff_plain;f=keydb_fs.c;h=0bf922f1475a419781226b33dc22e154e4234c63;hp=eacf1c65b15cf1dae48c79e9e59f52503655f873;hb=adc800dbc424a1e246dd4a82a0c2e88eeda25531;hpb=e0dd4d10f385cd19da389ec66622eea8aa66ae59 diff --git a/keydb_fs.c b/keydb_fs.c index eacf1c6..0bf922f 100644 --- a/keydb_fs.c +++ b/keydb_fs.c @@ -13,8 +13,7 @@ * more details. * * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 51 - * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * this program. If not, see . */ #include @@ -22,6 +21,8 @@ #include #include #include +#include +#include #include #include #include @@ -36,6 +37,7 @@ #include "keystructs.h" #include "ll.h" #include "mem.h" +#include "onak.h" #include "onak-conf.h" #include "parsekey.h" #include "log.h" @@ -46,8 +48,10 @@ #define PATH_MAX 1024 #endif -static int keydb_lockfile_fd = -1; -static bool keydb_lockfile_readonly; +struct onak_fs_dbctx { + int lockfile_fd; + bool lockfile_readonly; +}; /*****************************************************************************/ @@ -70,41 +74,43 @@ static uint32_t calchash(uint8_t * ptr) } -static void keypath(char *buffer, size_t length, uint64_t _keyid) +static void keypath(char *buffer, size_t length, uint64_t _keyid, + char *basepath) { uint64_t keyid = _keyid << 32; snprintf(buffer, length, "%s/key/%02X/%02X/%08X/%016" PRIX64, - config.db_dir, (uint8_t) ((keyid >> 56) & 0xFF), + basepath, (uint8_t) ((keyid >> 56) & 0xFF), (uint8_t) ((keyid >> 48) & 0xFF), (uint32_t) (keyid >> 32), _keyid); } -static void keydir(char *buffer, size_t length, uint64_t _keyid) +static void keydir(char *buffer, size_t length, uint64_t _keyid, + char *basepath) { uint64_t keyid = _keyid << 32; - snprintf(buffer, length, "%s/key/%02X/%02X/%08X", config.db_dir, + snprintf(buffer, length, "%s/key/%02X/%02X/%08X", basepath, (uint8_t) ((keyid >> 56) & 0xFF), (uint8_t) ((keyid >> 48) & 0xFF), (uint32_t) (keyid >> 32)); } -static void prove_path_to(uint64_t keyid, char *what) +static void prove_path_to(uint64_t keyid, char *what, char *basepath) { static char buffer[PATH_MAX]; - snprintf(buffer, sizeof(buffer), "%s/%s", config.db_dir, what); + snprintf(buffer, sizeof(buffer), "%s/%s", basepath, what); mkdir(buffer, 0777); - snprintf(buffer, sizeof(buffer), "%s/%s/%02X", config.db_dir, what, + snprintf(buffer, sizeof(buffer), "%s/%s/%02X", basepath, what, (uint8_t) ((keyid >> 24) & 0xFF)); mkdir(buffer, 0777); - snprintf(buffer, sizeof(buffer), "%s/%s/%02X/%02X", config.db_dir, + snprintf(buffer, sizeof(buffer), "%s/%s/%02X/%02X", basepath, what, (uint8_t) ((keyid >> 24) & 0xFF), (uint8_t) ((keyid >> 16) & 0xFF)); mkdir(buffer, 0777); - snprintf(buffer, sizeof(buffer), "%s/%s/%02X/%02X/%08X", config.db_dir, + snprintf(buffer, sizeof(buffer), "%s/%s/%02X/%02X/%08X", basepath, what, (uint8_t) ((keyid >> 24) & 0xFF), (uint8_t) ((keyid >> 16) & 0xFF), (uint32_t) (keyid)); @@ -112,37 +118,48 @@ static void prove_path_to(uint64_t keyid, char *what) } static void wordpath(char *buffer, size_t length, char *word, uint32_t hash, - uint64_t keyid) + uint64_t keyid, char *basepath) { snprintf(buffer, length, "%s/words/%02X/%02X/%08X/%s/%016" PRIX64, - config.db_dir, (uint8_t) ((hash >> 24) & 0xFF), + basepath, (uint8_t) ((hash >> 24) & 0xFF), (uint8_t) ((hash >> 16) & 0xFF), hash, word, keyid); } -static void worddir(char *buffer, size_t length, char *word, uint32_t hash) +static void worddir(char *buffer, size_t length, char *word, uint32_t hash, + char *basepath) { - snprintf(buffer, length, "%s/words/%02X/%02X/%08X/%s", config.db_dir, + snprintf(buffer, length, "%s/words/%02X/%02X/%08X/%s", basepath, (uint8_t) ((hash >> 24) & 0xFF), (uint8_t) ((hash >> 16) & 0xFF), hash, word); } static void subkeypath(char *buffer, size_t length, uint64_t subkey, - uint64_t keyid) + char *basepath) { snprintf(buffer, length, "%s/subkeys/%02X/%02X/%08X/%016" PRIX64, - config.db_dir, + basepath, (uint8_t) ((subkey >> 24) & 0xFF), (uint8_t) ((subkey >> 16) & 0xFF), (uint32_t) (subkey & 0xFFFFFFFF), - keyid); + subkey); +} + +static void subkeydir(char *buffer, size_t length, uint64_t subkey, + char *basepath) +{ + snprintf(buffer, length, "%s/subkeys/%02X/%02X/%08X", + basepath, + (uint8_t) ((subkey >> 24) & 0xFF), + (uint8_t) ((subkey >> 16) & 0xFF), + (uint32_t) (subkey & 0xFFFFFFFF)); } static void skshashpath(char *buffer, size_t length, - const struct skshash *hash) + const struct skshash *hash, char *basepath) { snprintf(buffer, length, "%s/skshash/%02X/%02X/%02X%02X%02X%02X/" "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X", - config.db_dir, + basepath, hash->hash[0], hash->hash[1], hash->hash[0], hash->hash[1], hash->hash[2], hash->hash[3], hash->hash[4], hash->hash[5], hash->hash[6], hash->hash[7], @@ -150,76 +167,24 @@ static void skshashpath(char *buffer, size_t length, hash->hash[12], hash->hash[13], hash->hash[14], hash->hash[15]); } -static void subkeydir(char *buffer, size_t length, uint64_t subkey) -{ - snprintf(buffer, length, "%s/subkeys/%02X/%02X/%08X", - config.db_dir, - (uint8_t) ((subkey >> 24) & 0xFF), - (uint8_t) ((subkey >> 16) & 0xFF), - (uint32_t) (subkey & 0xFFFFFFFF)); -} /*****************************************************************************/ -/** - * initdb - Initialize the key database. - */ -static void fs_initdb(bool readonly) -{ - char buffer[PATH_MAX]; - - keydb_lockfile_readonly = readonly; - - snprintf(buffer, sizeof(buffer), "%s/.lock", config.db_dir); - - if (access(config.db_dir, R_OK | W_OK | X_OK) == -1) { - if (errno != ENOENT) { - logthing(LOGTHING_CRITICAL, - "Unable to access keydb_fs root of '%s'. (%s)", - config.db_dir, strerror(errno)); - exit(1); /* Lacking rwx on the key dir */ - } - mkdir(config.db_dir, 0777); - keydb_lockfile_fd = open(buffer, O_RDWR | O_CREAT, 0600); - } - chdir(config.db_dir); - if (keydb_lockfile_fd == -1) - keydb_lockfile_fd = open(buffer, - (keydb_lockfile_readonly) ? - O_RDONLY : O_RDWR); - if (keydb_lockfile_fd == -1) - keydb_lockfile_fd = open(buffer, O_RDWR | O_CREAT, 0600); - if (keydb_lockfile_fd == -1) { - logthing(LOGTHING_CRITICAL, - "Unable to open lockfile '%s'. (%s)", - buffer, strerror(errno)); - exit(1); /* Lacking rwx on the key dir */ - } -} - -/** - * cleanupdb - De-initialize the key database. - */ -static void fs_cleanupdb(void) -{ - /* Mmmm nothing to do here? */ - close(keydb_lockfile_fd); -} - /** * starttrans - Start a transaction. */ -static bool fs_starttrans(void) +static bool fs_starttrans(struct onak_dbctx *dbctx) { + struct onak_fs_dbctx *privctx = (struct onak_fs_dbctx *) dbctx->priv; struct flock lockstruct; int remaining = 20; lockstruct.l_type = - F_RDLCK | ((keydb_lockfile_readonly) ? 0 : F_WRLCK); + F_RDLCK | ((privctx->lockfile_readonly) ? 0 : F_WRLCK); lockstruct.l_whence = SEEK_SET; lockstruct.l_start = 0; lockstruct.l_len = 1; - while (fcntl(keydb_lockfile_fd, F_SETLK, &lockstruct) == -1) { + while (fcntl(privctx->lockfile_fd, F_SETLK, &lockstruct) == -1) { if (remaining-- == 0) return false; /* Hope to hell that noodles DTRT */ usleep(100); @@ -230,25 +195,26 @@ static bool fs_starttrans(void) /** * endtrans - End a transaction. */ -static void fs_endtrans(void) +static void fs_endtrans(struct onak_dbctx *dbctx) { + struct onak_fs_dbctx *privctx = (struct onak_fs_dbctx *) dbctx->priv; struct flock lockstruct; lockstruct.l_type = F_UNLCK; lockstruct.l_whence = SEEK_SET; lockstruct.l_start = 0; lockstruct.l_len = 1; - fcntl(keydb_lockfile_fd, F_SETLK, &lockstruct); + fcntl(privctx->lockfile_fd, F_SETLK, &lockstruct); } -static uint64_t fs_getfullkeyid(uint64_t keyid) +static uint64_t fs_getfullkeyid(struct onak_dbctx *dbctx, uint64_t keyid) { static char buffer[PATH_MAX]; DIR *d = NULL; struct dirent *de = NULL; uint64_t ret = 0; - keydir(buffer, sizeof(buffer), keyid); + keydir(buffer, sizeof(buffer), keyid, dbctx->config->location); d = opendir(buffer); if (d) { @@ -262,7 +228,8 @@ static uint64_t fs_getfullkeyid(uint64_t keyid) } if (ret == 0) { - subkeydir(buffer, sizeof(buffer), keyid); + subkeydir(buffer, sizeof(buffer), keyid, + dbctx->config->location); d = opendir(buffer); if (d) { @@ -285,7 +252,9 @@ static uint64_t fs_getfullkeyid(uint64_t keyid) * @publickey: A pointer to a structure to return the key in. * @intrans: If we're already in a transaction. */ -static int fs_fetch_key(uint64_t keyid, struct openpgp_publickey **publickey, +static int fs_fetch_key_id(struct onak_dbctx *dbctx, + uint64_t keyid, + struct openpgp_publickey **publickey, bool intrans) { static char buffer[PATH_MAX]; @@ -293,13 +262,20 @@ static int fs_fetch_key(uint64_t keyid, struct openpgp_publickey **publickey, struct openpgp_packet_list *packets = NULL; if (!intrans) - fs_starttrans(); + fs_starttrans(dbctx); if ((keyid >> 32) == 0) - keyid = fs_getfullkeyid(keyid); + keyid = fs_getfullkeyid(dbctx, keyid); + + keypath(buffer, sizeof(buffer), keyid, dbctx->config->location); + fd = open(buffer, O_RDONLY); + if (fd == -1 && errno == ENOENT) { + subkeypath(buffer, sizeof(buffer), keyid, + dbctx->config->location); + fd = open(buffer, O_RDONLY); + } - keypath(buffer, sizeof(buffer), keyid); - if ((fd = open(buffer, O_RDONLY)) != -1) { + if (fd != -1) { /* File is present, load it in... */ read_openpgp_stream(file_fetchchar, &fd, &packets, 0); parse_keys(packets, publickey); @@ -310,7 +286,7 @@ static int fs_fetch_key(uint64_t keyid, struct openpgp_publickey **publickey, } if (!intrans) - fs_endtrans(); + fs_endtrans(dbctx); return ret; } @@ -320,7 +296,8 @@ static int fs_fetch_key(uint64_t keyid, struct openpgp_publickey **publickey, * @intrans: If we're already in a transaction. * @update: If true the key exists and should be updated. */ -static int fs_store_key(struct openpgp_publickey *publickey, bool intrans, +static int fs_store_key(struct onak_dbctx *dbctx, + struct openpgp_publickey *publickey, bool intrans, bool update) { static char buffer[PATH_MAX]; @@ -332,17 +309,20 @@ static int fs_store_key(struct openpgp_publickey *publickey, bool intrans, uint64_t keyid; struct ll *wordlist = NULL, *wl = NULL; struct skshash hash; - uint64_t *subkeyids = NULL; + struct openpgp_fingerprint *subkeyids = NULL; uint32_t hashid; int i = 0; - get_keyid(publickey, &keyid); + if (get_keyid(publickey, &keyid) != ONAK_E_OK) { + logthing(LOGTHING_ERROR, "Couldn't find key ID for key."); + return 0; + } if (!intrans) - fs_starttrans(); + fs_starttrans(dbctx); - prove_path_to(keyid, "key"); - keypath(buffer, sizeof(buffer), keyid); + prove_path_to(keyid, "key", dbctx->config->location); + keypath(buffer, sizeof(buffer), keyid, dbctx->config->location); if ((fd = open(buffer, O_WRONLY | (update ? O_TRUNC : O_CREAT), @@ -363,12 +343,13 @@ static int fs_store_key(struct openpgp_publickey *publickey, bool intrans, wl = wordlist = makewordlistfromkey(wordlist, publickey); while (wl) { uint32_t hash = calchash((uint8_t *) (wl->object)); - prove_path_to(hash, "words"); + prove_path_to(hash, "words", dbctx->config->location); - worddir(wbuffer, sizeof(wbuffer), wl->object, hash); + worddir(wbuffer, sizeof(wbuffer), wl->object, hash, + dbctx->config->location); mkdir(wbuffer, 0777); wordpath(wbuffer, sizeof(wbuffer), wl->object, hash, - keyid); + keyid, dbctx->config->location); link(buffer, wbuffer); wl = wl->next; @@ -377,13 +358,17 @@ static int fs_store_key(struct openpgp_publickey *publickey, bool intrans, subkeyids = keysubkeys(publickey); i = 0; - while (subkeyids != NULL && subkeyids[i] != 0) { - prove_path_to(subkeyids[i], "subkeys"); + while (subkeyids != NULL && subkeyids[i].length != 0) { + keyid = fingerprint2keyid(&subkeyids[i]); + + prove_path_to(keyid, "subkeys", + dbctx->config->location); - subkeydir(wbuffer, sizeof(wbuffer), subkeyids[i]); + subkeydir(wbuffer, sizeof(wbuffer), keyid, + dbctx->config->location); mkdir(wbuffer, 0777); - subkeypath(wbuffer, sizeof(wbuffer), subkeyids[i], - keyid); + subkeypath(wbuffer, sizeof(wbuffer), keyid, + dbctx->config->location); link(buffer, wbuffer); i++; @@ -396,13 +381,14 @@ static int fs_store_key(struct openpgp_publickey *publickey, bool intrans, get_skshash(publickey, &hash); hashid = (hash.hash[0] << 24) + (hash.hash[1] << 16) + (hash.hash[2] << 8) + hash.hash[3]; - prove_path_to(hashid, "skshash"); - skshashpath(wbuffer, sizeof(wbuffer), &hash); + prove_path_to(hashid, "skshash", dbctx->config->location); + skshashpath(wbuffer, sizeof(wbuffer), &hash, + dbctx->config->location); link(buffer, wbuffer); } if (!intrans) - fs_endtrans(); + fs_endtrans(dbctx); return ret; } @@ -411,23 +397,24 @@ static int fs_store_key(struct openpgp_publickey *publickey, bool intrans, * @keyid: The keyid to delete. * @intrans: If we're already in a transaction. */ -static int fs_delete_key(uint64_t keyid, bool intrans) +static int fs_delete_key(struct onak_dbctx *dbctx, uint64_t keyid, bool intrans) { static char buffer[PATH_MAX]; int ret; struct openpgp_publickey *pk = NULL; struct skshash hash; struct ll *wordlist = NULL, *wl = NULL; - uint64_t *subkeyids = NULL; + struct openpgp_fingerprint *subkeyids = NULL; + uint64_t subkeyid; int i = 0; if ((keyid >> 32) == 0) - keyid = fs_getfullkeyid(keyid); + keyid = fs_getfullkeyid(dbctx, keyid); if (!intrans) - fs_starttrans(); + fs_starttrans(dbctx); - ret = fs_fetch_key(keyid, &pk, true); + ret = fs_fetch_key_id(dbctx, keyid, &pk, true); if (ret) { logthing(LOGTHING_DEBUG, "Wordlist for key %016" PRIX64, @@ -437,10 +424,10 @@ static int fs_delete_key(uint64_t keyid, bool intrans) "Wordlist for key %016" PRIX64 " done", keyid); while (wl) { uint32_t hash = calchash((uint8_t *) (wl->object)); - prove_path_to(hash, "words"); + prove_path_to(hash, "words", dbctx->config->location); wordpath(buffer, sizeof(buffer), wl->object, hash, - keyid); + keyid, dbctx->config->location); unlink(buffer); wl = wl->next; @@ -448,11 +435,13 @@ static int fs_delete_key(uint64_t keyid, bool intrans) subkeyids = keysubkeys(pk); i = 0; - while (subkeyids != NULL && subkeyids[i] != 0) { - prove_path_to(subkeyids[i], "subkeys"); + while (subkeyids != NULL && subkeyids[i].length != 0) { + subkeyid = fingerprint2keyid(&subkeyids[i]); + prove_path_to(subkeyid, "subkeys", + dbctx->config->location); - subkeypath(buffer, sizeof(buffer), subkeyids[i], - keyid); + subkeypath(buffer, sizeof(buffer), subkeyid, + dbctx->config->location); unlink(buffer); i++; @@ -463,19 +452,21 @@ static int fs_delete_key(uint64_t keyid, bool intrans) } get_skshash(pk, &hash); - skshashpath(buffer, sizeof(buffer), &hash); + skshashpath(buffer, sizeof(buffer), &hash, + dbctx->config->location); unlink(buffer); } - keypath(buffer, sizeof(buffer), keyid); + keypath(buffer, sizeof(buffer), keyid, dbctx->config->location); unlink(buffer); if (!intrans) - fs_endtrans(); + fs_endtrans(dbctx); return 1; } -static struct ll *internal_get_key_by_word(char *word, struct ll *mct) +static struct ll *internal_get_key_by_word(char *word, struct ll *mct, + char *basepath) { struct ll *keys = NULL; DIR *d = NULL; @@ -483,11 +474,11 @@ static struct ll *internal_get_key_by_word(char *word, struct ll *mct) uint32_t hash = calchash((uint8_t *) (word)); struct dirent *de; - worddir(buffer, sizeof(buffer), word, hash); + worddir(buffer, sizeof(buffer), word, hash, basepath); d = opendir(buffer); logthing(LOGTHING_DEBUG, "Scanning for word %s in dir %s", word, buffer); - if (d) + if (d) { do { de = readdir(d); if (de && de->d_name[0] != '.') { @@ -505,7 +496,8 @@ static struct ll *internal_get_key_by_word(char *word, struct ll *mct) } } } while (de); - closedir(d); + closedir(d); + } return keys; } @@ -515,7 +507,8 @@ static struct ll *internal_get_key_by_word(char *word, struct ll *mct) * @search: The text to search for. * @publickey: A pointer to a structure to return the key in. */ -static int fs_fetch_key_text(const char *search, +static int fs_fetch_key_text(struct onak_dbctx *dbctx, + const char *search, struct openpgp_publickey **publickey) { struct ll *wordlist = NULL, *wl = NULL; @@ -528,7 +521,8 @@ static int fs_fetch_key_text(const char *search, searchtext = strdup(search); wl = wordlist = makewordlist(wordlist, searchtext); - keylist = internal_get_key_by_word(wordlist->object, NULL); + keylist = internal_get_key_by_word(wordlist->object, NULL, + dbctx->config->location); if (!keylist) { llfree(wordlist, NULL); @@ -540,7 +534,8 @@ static int fs_fetch_key_text(const char *search, wl = wl->next; while (wl) { struct ll *nkl = - internal_get_key_by_word(wl->object, keylist); + internal_get_key_by_word(wl->object, keylist, + dbctx->config->location); if (!nkl) { llfree(wordlist, NULL); llfree(keylist, free); @@ -560,7 +555,8 @@ static int fs_fetch_key_text(const char *search, while (wl) { logthing(LOGTHING_DEBUG, "Adding key: %s", wl->object); addedkeys += - fs_fetch_key(strtoull(wl->object, NULL, 16), publickey, + fs_fetch_key_id(dbctx, + strtoull(wl->object, NULL, 16), publickey, false); if (addedkeys >= config.maxkeys) break; @@ -580,14 +576,15 @@ static int fs_fetch_key_text(const char *search, * @publickey: A pointer to a structure to return the key in. * @intrans: If we're already in a transaction. */ -static int fs_fetch_key_skshash(const struct skshash *hash, +static int fs_fetch_key_skshash(struct onak_dbctx *dbctx, + const struct skshash *hash, struct openpgp_publickey **publickey) { static char buffer[PATH_MAX]; int ret = 0, fd; struct openpgp_packet_list *packets = NULL; - skshashpath(buffer, sizeof(buffer), hash); + skshashpath(buffer, sizeof(buffer), hash, dbctx->config->location); if ((fd = open(buffer, O_RDONLY)) != -1) { read_openpgp_stream(file_fetchchar, &fd, &packets, 0); parse_keys(packets, publickey); @@ -611,7 +608,8 @@ static int fs_fetch_key_skshash(const struct skshash *hash, * * Returns the number of keys we iterated over. */ -static int fs_iterate_keys(void (*iterfunc)(void *ctx, +static int fs_iterate_keys(struct onak_dbctx *dbctx, + void (*iterfunc)(void *ctx, struct openpgp_publickey *key), void *ctx) { return 0; @@ -623,22 +621,90 @@ static int fs_iterate_keys(void (*iterfunc)(void *ctx, #define NEED_KEYID2UID 1 #define NEED_GETKEYSIGS 1 #define NEED_UPDATEKEYS 1 +#define NEED_GET_FP 1 #include "keydb.c" -struct dbfuncs keydb_fs_funcs = { - .initdb = fs_initdb, - .cleanupdb = fs_cleanupdb, - .starttrans = fs_starttrans, - .endtrans = fs_endtrans, - .fetch_key = fs_fetch_key, - .fetch_key_text = fs_fetch_key_text, - .fetch_key_skshash = fs_fetch_key_skshash, - .store_key = fs_store_key, - .update_keys = generic_update_keys, - .delete_key = fs_delete_key, - .getkeysigs = generic_getkeysigs, - .cached_getkeysigs = generic_cached_getkeysigs, - .keyid2uid = generic_keyid2uid, - .getfullkeyid = fs_getfullkeyid, - .iterate_keys = fs_iterate_keys, -}; +/** + * cleanupdb - De-initialize the key database. + */ +static void fs_cleanupdb(struct onak_dbctx *dbctx) +{ + struct onak_fs_dbctx *privctx = (struct onak_fs_dbctx *) dbctx->priv; + + /* Mmmm nothing to do here? */ + close(privctx->lockfile_fd); +} + +/** + * initdb - Initialize the key database. + */ +struct onak_dbctx *keydb_fs_init(struct onak_db_config *dbcfg, bool readonly) +{ + char buffer[PATH_MAX]; + struct onak_dbctx *dbctx; + struct onak_fs_dbctx *privctx; + + dbctx = malloc(sizeof(struct onak_dbctx)); + if (dbctx == NULL) { + return NULL; + } + dbctx->config = dbcfg; + dbctx->priv = privctx = malloc(sizeof(*privctx)); + if (privctx == NULL) { + free(dbctx); + return NULL; + } + + privctx->lockfile_readonly = readonly; + + snprintf(buffer, sizeof(buffer), "%s/.lock", dbcfg->location); + + if (access(dbcfg->location, R_OK | W_OK | X_OK) == -1) { + if (errno != ENOENT) { + logthing(LOGTHING_CRITICAL, + "Unable to access keydb_fs root of '%s'. (%s)", + dbcfg->location, strerror(errno)); + exit(1); /* Lacking rwx on the key dir */ + } + mkdir(dbcfg->location, 0777); + privctx->lockfile_fd = open(buffer, O_RDWR | O_CREAT, 0600); + } + if (chdir(dbcfg->location) == -1) { + /* Shouldn't happen after the above */ + logthing(LOGTHING_CRITICAL, + "Couldn't change to database directory: %s", + strerror(errno)); + free(dbctx->priv); + free(dbctx); + return NULL; + } + privctx->lockfile_fd = open(buffer, + (privctx->lockfile_readonly) ? + O_RDONLY : O_RDWR); + if (privctx->lockfile_fd == -1) + privctx->lockfile_fd = open(buffer, O_RDWR | O_CREAT, 0600); + if (privctx->lockfile_fd == -1) { + logthing(LOGTHING_CRITICAL, + "Unable to open lockfile '%s'. (%s)", + buffer, strerror(errno)); + exit(1); /* Lacking rwx on the key dir */ + } + + dbctx->cleanupdb = fs_cleanupdb; + dbctx->starttrans = fs_starttrans; + dbctx->endtrans = fs_endtrans; + dbctx->fetch_key_id = fs_fetch_key_id; + dbctx->fetch_key_fp = generic_fetch_key_fp; + dbctx->fetch_key_text = fs_fetch_key_text; + dbctx->fetch_key_skshash = fs_fetch_key_skshash; + dbctx->store_key = fs_store_key; + dbctx->update_keys = generic_update_keys; + dbctx->delete_key = fs_delete_key; + dbctx->getkeysigs = generic_getkeysigs; + dbctx->cached_getkeysigs = generic_cached_getkeysigs; + dbctx->keyid2uid = generic_keyid2uid; + dbctx->getfullkeyid = fs_getfullkeyid; + dbctx->iterate_keys = fs_iterate_keys; + + return dbctx; +}