diff --git a/lib/cache/api.c b/lib/cache/api.c index 3e8351fad403d3399bf3d6d76c39c7c50017b141..d7794eca988d3802cf02771dec1c80a8052eb095 100644 --- a/lib/cache/api.c +++ b/lib/cache/api.c @@ -135,8 +135,8 @@ int kr_cache_open(struct kr_cache *cache, const struct kr_cdb_api *api, struct k ret = cache->api->open(&cache->db, &cache->stats, &opts2, mm); } - char *fpath; - if (asprintf(&fpath, "%s/data.mdb", opts->path) > 0) { + char *fpath = kr_absolutize_path(opts->path, "data.mdb"); + if (fpath) { kr_cache_emergency_file_to_remove = fpath; } else { assert(false); /* non-critical, but still */ diff --git a/lib/cache/cdb_lmdb.c b/lib/cache/cdb_lmdb.c index 3b986df82166ef79dc35f5a199efa4c2228df376..b56d8335e904666a3c60a4eb49a085882ed4a749 100644 --- a/lib/cache/cdb_lmdb.c +++ b/lib/cache/cdb_lmdb.c @@ -297,7 +297,7 @@ static int cdb_open_env(struct lmdb_env *env, const char *path, const size_t map ret = mdb_env_create(&env->env); if (ret != MDB_SUCCESS) return lmdb_error(ret); - env->mdb_data_path = kr_strcatdup(2, path, "/data.mdb"); + env->mdb_data_path = kr_absolutize_path(path, "data.mdb"); if (!env->mdb_data_path) { ret = ENOMEM; goto error_sys; diff --git a/lib/utils.c b/lib/utils.c index fcba71bb0cb19f0a6d1f03e67ce704dbfbea18f7..97179409931658bbf93bf198884387c1d6e1c7db 100644 --- a/lib/utils.c +++ b/lib/utils.c @@ -210,6 +210,31 @@ char* kr_strcatdup(unsigned n, ...) return result; } +char * kr_absolutize_path(const char *dirname, const char *fname) +{ + assert(dirname && fname); + char *result; + int aret; + if (dirname[0] == '/') { // absolute path is easier + aret = asprintf(&result, "%s/%s", dirname, fname); + } else { // relative path, but don't resolve symlinks + char buf[PATH_MAX]; + const char *cwd = getcwd(buf, sizeof(buf)); + if (!cwd) + return NULL; // errno has been set already + if (strcmp(dirname, ".") == 0) { + // get rid of one common case of extraneous "./" + aret = asprintf(&result, "%s/%s", cwd, fname); + } else { + aret = asprintf(&result, "%s/%s/%s", cwd, dirname, fname); + } + } + if (aret > 0) + return result; + errno = -aret; + return NULL; +} + int kr_memreserve(void *baton, void **mem, size_t elm_size, size_t want, size_t *have) { if (*have >= want) { diff --git a/lib/utils.h b/lib/utils.h index 48748d2bb5a61ffa3b32409f19a7c53b491c4ad9..3b017951294208a5c87719d68031cea5decb89ce 100644 --- a/lib/utils.h +++ b/lib/utils.h @@ -223,6 +223,11 @@ typedef array_t(ranked_rr_array_entry_t *) ranked_rr_array_t; KR_EXPORT char* kr_strcatdup(unsigned n, ...); +/** Construct absolute file path, without resolving symlinks. + * \return malloc-ed string or NULL (+errno in that case) */ +KR_EXPORT +char * kr_absolutize_path(const char *dirname, const char *fname); + /** You probably want kr_rand_* convenience functions instead. * This is a buffered version of gnutls_rnd(GNUTLS_RND_NONCE, ..) */ KR_EXPORT