1251876Speter/* Licensed to the Apache Software Foundation (ASF) under one or more 2251876Speter * contributor license agreements. See the NOTICE file distributed with 3251876Speter * this work for additional information regarding copyright ownership. 4251876Speter * The ASF licenses this file to You under the Apache License, Version 2.0 5251876Speter * (the "License"); you may not use this file except in compliance with 6251876Speter * the License. You may obtain a copy of the License at 7251876Speter * 8251876Speter * http://www.apache.org/licenses/LICENSE-2.0 9251876Speter * 10251876Speter * Unless required by applicable law or agreed to in writing, software 11251876Speter * distributed under the License is distributed on an "AS IS" BASIS, 12251876Speter * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13251876Speter * See the License for the specific language governing permissions and 14251876Speter * limitations under the License. 15251876Speter */ 16251876Speter 17251876Speter#include "apr.h" 18251876Speter#include "apr_dso.h" 19251876Speter#include "apr_hash.h" 20251876Speter#include "apr_errno.h" 21251876Speter#include "apr_pools.h" 22251876Speter#include "apr_strings.h" 23251876Speter#define APR_WANT_MEMFUNC 24251876Speter#define APR_WANT_STRFUNC 25251876Speter#include "apr_want.h" 26251876Speter#include "apr_general.h" 27251876Speter#include "apr_atomic.h" 28251876Speter 29251876Speter#include "apu_config.h" 30251876Speter#include "apu.h" 31251876Speter#include "apu_internal.h" 32251876Speter#include "apu_version.h" 33251876Speter#include "apr_dbm_private.h" 34251876Speter#include "apu_select_dbm.h" 35251876Speter#include "apr_dbm.h" 36251876Speter#include "apr_dbm_private.h" 37251876Speter 38251876Speter/* ### note: the setting of DBM_VTABLE will go away once we have multiple 39251876Speter ### DBMs in here. 40251876Speter ### Well, that day is here. So, do we remove DBM_VTABLE and the old 41251876Speter ### API entirely? Oh, what to do. We need an APU_DEFAULT_DBM #define. 42251876Speter ### Sounds like a job for autoconf. */ 43251876Speter 44251876Speter#if APU_USE_DB 45251876Speter#define DBM_VTABLE apr_dbm_type_db 46251876Speter#define DBM_NAME "db" 47251876Speter#elif APU_USE_GDBM 48251876Speter#define DBM_VTABLE apr_dbm_type_gdbm 49251876Speter#define DBM_NAME "gdbm" 50251876Speter#elif APU_USE_NDBM 51251876Speter#define DBM_VTABLE apr_dbm_type_ndbm 52251876Speter#define DBM_NAME "ndbm" 53251876Speter#elif APU_USE_SDBM 54251876Speter#define DBM_VTABLE apr_dbm_type_sdbm 55251876Speter#define DBM_NAME "sdbm" 56251876Speter#else /* Not in the USE_xDBM list above */ 57251876Speter#error a DBM implementation was not specified 58251876Speter#endif 59251876Speter 60251876Speter#if APU_DSO_BUILD 61251876Speter 62251876Speterstatic apr_hash_t *drivers = NULL; 63251876Speterstatic apr_uint32_t initialised = 0, in_init = 1; 64251876Speter 65251876Speterstatic apr_status_t dbm_term(void *ptr) 66251876Speter{ 67251876Speter /* set drivers to NULL so init can work again */ 68251876Speter drivers = NULL; 69251876Speter 70251876Speter /* Everything else we need is handled by cleanups registered 71251876Speter * when we created mutexes and loaded DSOs 72251876Speter */ 73251876Speter return APR_SUCCESS; 74251876Speter} 75251876Speter 76251876Speter#endif /* APU_DSO_BUILD */ 77251876Speter 78251876Speterstatic apr_status_t dbm_open_type(apr_dbm_type_t const* * vtable, 79251876Speter const char *type, 80251876Speter apr_pool_t *pool) 81251876Speter{ 82251876Speter#if !APU_DSO_BUILD 83251876Speter 84251876Speter *vtable = NULL; 85251876Speter if (!strcasecmp(type, "default")) *vtable = &DBM_VTABLE; 86251876Speter#if APU_HAVE_DB 87251876Speter else if (!strcasecmp(type, "db")) *vtable = &apr_dbm_type_db; 88251876Speter#endif 89251876Speter else if (*type && !strcasecmp(type + 1, "dbm")) { 90251876Speter#if APU_HAVE_GDBM 91251876Speter if (*type == 'G' || *type == 'g') *vtable = &apr_dbm_type_gdbm; 92251876Speter#endif 93251876Speter#if APU_HAVE_NDBM 94251876Speter if (*type == 'N' || *type == 'n') *vtable = &apr_dbm_type_ndbm; 95251876Speter#endif 96251876Speter#if APU_HAVE_SDBM 97251876Speter if (*type == 'S' || *type == 's') *vtable = &apr_dbm_type_sdbm; 98251876Speter#endif 99251876Speter /* avoid empty block */ ; 100251876Speter } 101251876Speter if (*vtable) 102251876Speter return APR_SUCCESS; 103251876Speter return APR_ENOTIMPL; 104251876Speter 105251876Speter#else /* APU_DSO_BUILD */ 106251876Speter 107251876Speter char modname[32]; 108251876Speter char symname[34]; 109251876Speter apr_dso_handle_sym_t symbol; 110251876Speter apr_status_t rv; 111251876Speter int usertype = 0; 112251876Speter 113251876Speter if (!strcasecmp(type, "default")) type = DBM_NAME; 114251876Speter else if (!strcasecmp(type, "db")) type = "db"; 115251876Speter else if (*type && !strcasecmp(type + 1, "dbm")) { 116251876Speter if (*type == 'G' || *type == 'g') type = "gdbm"; 117251876Speter else if (*type == 'N' || *type == 'n') type = "ndbm"; 118251876Speter else if (*type == 'S' || *type == 's') type = "sdbm"; 119251876Speter } 120251876Speter else usertype = 1; 121251876Speter 122251876Speter if (apr_atomic_inc32(&initialised)) { 123251876Speter apr_atomic_set32(&initialised, 1); /* prevent wrap-around */ 124251876Speter 125251876Speter while (apr_atomic_read32(&in_init)) /* wait until we get fully inited */ 126251876Speter ; 127251876Speter } 128251876Speter else { 129251876Speter apr_pool_t *parent; 130251876Speter 131251876Speter /* Top level pool scope, need process-scope lifetime */ 132262253Speter for (parent = apr_pool_parent_get(pool); 133262253Speter parent && parent != pool; 134262253Speter parent = apr_pool_parent_get(pool)) 135262253Speter pool = parent; 136251876Speter 137251876Speter /* deprecate in 2.0 - permit implicit initialization */ 138251876Speter apu_dso_init(pool); 139251876Speter 140251876Speter drivers = apr_hash_make(pool); 141251876Speter apr_hash_set(drivers, "sdbm", APR_HASH_KEY_STRING, &apr_dbm_type_sdbm); 142251876Speter 143251876Speter apr_pool_cleanup_register(pool, NULL, dbm_term, 144251876Speter apr_pool_cleanup_null); 145251876Speter 146251876Speter apr_atomic_dec32(&in_init); 147251876Speter } 148251876Speter 149251876Speter rv = apu_dso_mutex_lock(); 150251876Speter if (rv) { 151251876Speter *vtable = NULL; 152251876Speter return rv; 153251876Speter } 154251876Speter 155251876Speter *vtable = apr_hash_get(drivers, type, APR_HASH_KEY_STRING); 156251876Speter if (*vtable) { 157251876Speter apu_dso_mutex_unlock(); 158251876Speter return APR_SUCCESS; 159251876Speter } 160251876Speter 161251876Speter /* The driver DSO must have exactly the same lifetime as the 162251876Speter * drivers hash table; ignore the passed-in pool */ 163251876Speter pool = apr_hash_pool_get(drivers); 164251876Speter 165251876Speter#if defined(NETWARE) 166251876Speter apr_snprintf(modname, sizeof(modname), "dbm%s.nlm", type); 167262253Speter#elif defined(WIN32) || defined (__CYGWIN__) 168251876Speter apr_snprintf(modname, sizeof(modname), 169251876Speter "apr_dbm_%s-" APU_STRINGIFY(APU_MAJOR_VERSION) ".dll", type); 170251876Speter#else 171251876Speter apr_snprintf(modname, sizeof(modname), 172251876Speter "apr_dbm_%s-" APU_STRINGIFY(APU_MAJOR_VERSION) ".so", type); 173251876Speter#endif 174251876Speter apr_snprintf(symname, sizeof(symname), "apr_dbm_type_%s", type); 175251876Speter 176251876Speter rv = apu_dso_load(NULL, &symbol, modname, symname, pool); 177251876Speter if (rv == APR_SUCCESS || rv == APR_EINIT) { /* previously loaded?!? */ 178251876Speter *vtable = symbol; 179251876Speter if (usertype) 180251876Speter type = apr_pstrdup(pool, type); 181251876Speter apr_hash_set(drivers, type, APR_HASH_KEY_STRING, *vtable); 182251876Speter rv = APR_SUCCESS; 183251876Speter } 184251876Speter else 185251876Speter *vtable = NULL; 186251876Speter 187251876Speter apu_dso_mutex_unlock(); 188251876Speter return rv; 189251876Speter 190251876Speter#endif /* APU_DSO_BUILD */ 191251876Speter} 192251876Speter 193251876SpeterAPU_DECLARE(apr_status_t) apr_dbm_open_ex(apr_dbm_t **pdb, const char *type, 194251876Speter const char *pathname, 195251876Speter apr_int32_t mode, 196251876Speter apr_fileperms_t perm, 197251876Speter apr_pool_t *pool) 198251876Speter{ 199251876Speter apr_dbm_type_t const* vtable = NULL; 200251876Speter apr_status_t rv = dbm_open_type(&vtable, type, pool); 201251876Speter 202251876Speter if (rv == APR_SUCCESS) { 203251876Speter rv = (vtable->open)(pdb, pathname, mode, perm, pool); 204251876Speter } 205251876Speter return rv; 206251876Speter} 207251876Speter 208251876SpeterAPU_DECLARE(apr_status_t) apr_dbm_open(apr_dbm_t **pdb, const char *pathname, 209251876Speter apr_int32_t mode, apr_fileperms_t perm, 210251876Speter apr_pool_t *pool) 211251876Speter{ 212251876Speter return apr_dbm_open_ex(pdb, DBM_NAME, pathname, mode, perm, pool); 213251876Speter} 214251876Speter 215251876SpeterAPU_DECLARE(void) apr_dbm_close(apr_dbm_t *dbm) 216251876Speter{ 217251876Speter (*dbm->type->close)(dbm); 218251876Speter} 219251876Speter 220251876SpeterAPU_DECLARE(apr_status_t) apr_dbm_fetch(apr_dbm_t *dbm, apr_datum_t key, 221251876Speter apr_datum_t *pvalue) 222251876Speter{ 223251876Speter return (*dbm->type->fetch)(dbm, key, pvalue); 224251876Speter} 225251876Speter 226251876SpeterAPU_DECLARE(apr_status_t) apr_dbm_store(apr_dbm_t *dbm, apr_datum_t key, 227251876Speter apr_datum_t value) 228251876Speter{ 229251876Speter return (*dbm->type->store)(dbm, key, value); 230251876Speter} 231251876Speter 232251876SpeterAPU_DECLARE(apr_status_t) apr_dbm_delete(apr_dbm_t *dbm, apr_datum_t key) 233251876Speter{ 234251876Speter return (*dbm->type->del)(dbm, key); 235251876Speter} 236251876Speter 237251876SpeterAPU_DECLARE(int) apr_dbm_exists(apr_dbm_t *dbm, apr_datum_t key) 238251876Speter{ 239251876Speter return (*dbm->type->exists)(dbm, key); 240251876Speter} 241251876Speter 242251876SpeterAPU_DECLARE(apr_status_t) apr_dbm_firstkey(apr_dbm_t *dbm, apr_datum_t *pkey) 243251876Speter{ 244251876Speter return (*dbm->type->firstkey)(dbm, pkey); 245251876Speter} 246251876Speter 247251876SpeterAPU_DECLARE(apr_status_t) apr_dbm_nextkey(apr_dbm_t *dbm, apr_datum_t *pkey) 248251876Speter{ 249251876Speter return (*dbm->type->nextkey)(dbm, pkey); 250251876Speter} 251251876Speter 252251876SpeterAPU_DECLARE(void) apr_dbm_freedatum(apr_dbm_t *dbm, apr_datum_t data) 253251876Speter{ 254251876Speter (*dbm->type->freedatum)(dbm, data); 255251876Speter} 256251876Speter 257251876SpeterAPU_DECLARE(char *) apr_dbm_geterror(apr_dbm_t *dbm, int *errcode, 258251876Speter char *errbuf, apr_size_t errbufsize) 259251876Speter{ 260251876Speter if (errcode != NULL) 261251876Speter *errcode = dbm->errcode; 262251876Speter 263251876Speter /* assert: errbufsize > 0 */ 264251876Speter 265251876Speter if (dbm->errmsg == NULL) 266251876Speter *errbuf = '\0'; 267251876Speter else 268251876Speter (void) apr_cpystrn(errbuf, dbm->errmsg, errbufsize); 269251876Speter return errbuf; 270251876Speter} 271251876Speter 272251876SpeterAPU_DECLARE(apr_status_t) apr_dbm_get_usednames_ex(apr_pool_t *p, 273251876Speter const char *type, 274251876Speter const char *pathname, 275251876Speter const char **used1, 276251876Speter const char **used2) 277251876Speter{ 278251876Speter apr_dbm_type_t const* vtable; 279251876Speter apr_status_t rv = dbm_open_type(&vtable, type, p); 280251876Speter 281251876Speter if (rv == APR_SUCCESS) { 282251876Speter (vtable->getusednames)(p, pathname, used1, used2); 283251876Speter return APR_SUCCESS; 284251876Speter } 285251876Speter return rv; 286251876Speter} 287251876Speter 288251876SpeterAPU_DECLARE(void) apr_dbm_get_usednames(apr_pool_t *p, 289251876Speter const char *pathname, 290251876Speter const char **used1, 291251876Speter const char **used2) 292251876Speter{ 293251876Speter apr_dbm_get_usednames_ex(p, DBM_NAME, pathname, used1, used2); 294251876Speter} 295251876Speter 296251876Speter/* Most DBM libraries take a POSIX mode for creating files. Don't trust 297251876Speter * the mode_t type, some platforms may not support it, int is safe. 298251876Speter */ 299251876SpeterAPU_DECLARE(int) apr_posix_perms2mode(apr_fileperms_t perm) 300251876Speter{ 301251876Speter int mode = 0; 302251876Speter 303251876Speter mode |= 0700 & (perm >> 2); /* User is off-by-2 bits */ 304251876Speter mode |= 0070 & (perm >> 1); /* Group is off-by-1 bit */ 305251876Speter mode |= 0007 & (perm); /* World maps 1 for 1 */ 306251876Speter return mode; 307251876Speter} 308