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 */
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;
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) {
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