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 */ 132251876Speter for (parent = pool; parent; parent = apr_pool_parent_get(pool)) 133251876Speter pool = parent; 134251876Speter 135251876Speter /* deprecate in 2.0 - permit implicit initialization */ 136251876Speter apu_dso_init(pool); 137251876Speter 138251876Speter drivers = apr_hash_make(pool); 139251876Speter apr_hash_set(drivers, "sdbm", APR_HASH_KEY_STRING, &apr_dbm_type_sdbm); 140251876Speter 141251876Speter apr_pool_cleanup_register(pool, NULL, dbm_term, 142251876Speter apr_pool_cleanup_null); 143251876Speter 144251876Speter apr_atomic_dec32(&in_init); 145251876Speter } 146251876Speter 147251876Speter rv = apu_dso_mutex_lock(); 148251876Speter if (rv) { 149251876Speter *vtable = NULL; 150251876Speter return rv; 151251876Speter } 152251876Speter 153251876Speter *vtable = apr_hash_get(drivers, type, APR_HASH_KEY_STRING); 154251876Speter if (*vtable) { 155251876Speter apu_dso_mutex_unlock(); 156251876Speter return APR_SUCCESS; 157251876Speter } 158251876Speter 159251876Speter /* The driver DSO must have exactly the same lifetime as the 160251876Speter * drivers hash table; ignore the passed-in pool */ 161251876Speter pool = apr_hash_pool_get(drivers); 162251876Speter 163251876Speter#if defined(NETWARE) 164251876Speter apr_snprintf(modname, sizeof(modname), "dbm%s.nlm", type); 165251876Speter#elif defined(WIN32) 166251876Speter apr_snprintf(modname, sizeof(modname), 167251876Speter "apr_dbm_%s-" APU_STRINGIFY(APU_MAJOR_VERSION) ".dll", type); 168251876Speter#else 169251876Speter apr_snprintf(modname, sizeof(modname), 170251876Speter "apr_dbm_%s-" APU_STRINGIFY(APU_MAJOR_VERSION) ".so", type); 171251876Speter#endif 172251876Speter apr_snprintf(symname, sizeof(symname), "apr_dbm_type_%s", type); 173251876Speter 174251876Speter rv = apu_dso_load(NULL, &symbol, modname, symname, pool); 175251876Speter if (rv == APR_SUCCESS || rv == APR_EINIT) { /* previously loaded?!? */ 176251876Speter *vtable = symbol; 177251876Speter if (usertype) 178251876Speter type = apr_pstrdup(pool, type); 179251876Speter apr_hash_set(drivers, type, APR_HASH_KEY_STRING, *vtable); 180251876Speter rv = APR_SUCCESS; 181251876Speter } 182251876Speter else 183251876Speter *vtable = NULL; 184251876Speter 185251876Speter apu_dso_mutex_unlock(); 186251876Speter return rv; 187251876Speter 188251876Speter#endif /* APU_DSO_BUILD */ 189251876Speter} 190251876Speter 191251876SpeterAPU_DECLARE(apr_status_t) apr_dbm_open_ex(apr_dbm_t **pdb, const char *type, 192251876Speter const char *pathname, 193251876Speter apr_int32_t mode, 194251876Speter apr_fileperms_t perm, 195251876Speter apr_pool_t *pool) 196251876Speter{ 197251876Speter apr_dbm_type_t const* vtable = NULL; 198251876Speter apr_status_t rv = dbm_open_type(&vtable, type, pool); 199251876Speter 200251876Speter if (rv == APR_SUCCESS) { 201251876Speter rv = (vtable->open)(pdb, pathname, mode, perm, pool); 202251876Speter } 203251876Speter return rv; 204251876Speter} 205251876Speter 206251876SpeterAPU_DECLARE(apr_status_t) apr_dbm_open(apr_dbm_t **pdb, const char *pathname, 207251876Speter apr_int32_t mode, apr_fileperms_t perm, 208251876Speter apr_pool_t *pool) 209251876Speter{ 210251876Speter return apr_dbm_open_ex(pdb, DBM_NAME, pathname, mode, perm, pool); 211251876Speter} 212251876Speter 213251876SpeterAPU_DECLARE(void) apr_dbm_close(apr_dbm_t *dbm) 214251876Speter{ 215251876Speter (*dbm->type->close)(dbm); 216251876Speter} 217251876Speter 218251876SpeterAPU_DECLARE(apr_status_t) apr_dbm_fetch(apr_dbm_t *dbm, apr_datum_t key, 219251876Speter apr_datum_t *pvalue) 220251876Speter{ 221251876Speter return (*dbm->type->fetch)(dbm, key, pvalue); 222251876Speter} 223251876Speter 224251876SpeterAPU_DECLARE(apr_status_t) apr_dbm_store(apr_dbm_t *dbm, apr_datum_t key, 225251876Speter apr_datum_t value) 226251876Speter{ 227251876Speter return (*dbm->type->store)(dbm, key, value); 228251876Speter} 229251876Speter 230251876SpeterAPU_DECLARE(apr_status_t) apr_dbm_delete(apr_dbm_t *dbm, apr_datum_t key) 231251876Speter{ 232251876Speter return (*dbm->type->del)(dbm, key); 233251876Speter} 234251876Speter 235251876SpeterAPU_DECLARE(int) apr_dbm_exists(apr_dbm_t *dbm, apr_datum_t key) 236251876Speter{ 237251876Speter return (*dbm->type->exists)(dbm, key); 238251876Speter} 239251876Speter 240251876SpeterAPU_DECLARE(apr_status_t) apr_dbm_firstkey(apr_dbm_t *dbm, apr_datum_t *pkey) 241251876Speter{ 242251876Speter return (*dbm->type->firstkey)(dbm, pkey); 243251876Speter} 244251876Speter 245251876SpeterAPU_DECLARE(apr_status_t) apr_dbm_nextkey(apr_dbm_t *dbm, apr_datum_t *pkey) 246251876Speter{ 247251876Speter return (*dbm->type->nextkey)(dbm, pkey); 248251876Speter} 249251876Speter 250251876SpeterAPU_DECLARE(void) apr_dbm_freedatum(apr_dbm_t *dbm, apr_datum_t data) 251251876Speter{ 252251876Speter (*dbm->type->freedatum)(dbm, data); 253251876Speter} 254251876Speter 255251876SpeterAPU_DECLARE(char *) apr_dbm_geterror(apr_dbm_t *dbm, int *errcode, 256251876Speter char *errbuf, apr_size_t errbufsize) 257251876Speter{ 258251876Speter if (errcode != NULL) 259251876Speter *errcode = dbm->errcode; 260251876Speter 261251876Speter /* assert: errbufsize > 0 */ 262251876Speter 263251876Speter if (dbm->errmsg == NULL) 264251876Speter *errbuf = '\0'; 265251876Speter else 266251876Speter (void) apr_cpystrn(errbuf, dbm->errmsg, errbufsize); 267251876Speter return errbuf; 268251876Speter} 269251876Speter 270251876SpeterAPU_DECLARE(apr_status_t) apr_dbm_get_usednames_ex(apr_pool_t *p, 271251876Speter const char *type, 272251876Speter const char *pathname, 273251876Speter const char **used1, 274251876Speter const char **used2) 275251876Speter{ 276251876Speter apr_dbm_type_t const* vtable; 277251876Speter apr_status_t rv = dbm_open_type(&vtable, type, p); 278251876Speter 279251876Speter if (rv == APR_SUCCESS) { 280251876Speter (vtable->getusednames)(p, pathname, used1, used2); 281251876Speter return APR_SUCCESS; 282251876Speter } 283251876Speter return rv; 284251876Speter} 285251876Speter 286251876SpeterAPU_DECLARE(void) apr_dbm_get_usednames(apr_pool_t *p, 287251876Speter const char *pathname, 288251876Speter const char **used1, 289251876Speter const char **used2) 290251876Speter{ 291251876Speter apr_dbm_get_usednames_ex(p, DBM_NAME, pathname, used1, used2); 292251876Speter} 293251876Speter 294251876Speter/* Most DBM libraries take a POSIX mode for creating files. Don't trust 295251876Speter * the mode_t type, some platforms may not support it, int is safe. 296251876Speter */ 297251876SpeterAPU_DECLARE(int) apr_posix_perms2mode(apr_fileperms_t perm) 298251876Speter{ 299251876Speter int mode = 0; 300251876Speter 301251876Speter mode |= 0700 & (perm >> 2); /* User is off-by-2 bits */ 302251876Speter mode |= 0070 & (perm >> 1); /* Group is off-by-1 bit */ 303251876Speter mode |= 0007 & (perm); /* World maps 1 for 1 */ 304251876Speter return mode; 305251876Speter} 306