1 /* Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache License, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
20 #include "apr_errno.h"
21 #include "apr_pools.h"
22 #include "apr_strings.h"
23 #define APR_WANT_MEMFUNC
24 #define APR_WANT_STRFUNC
26 #include "apr_general.h"
27 #include "apr_atomic.h"
29 #include "apu_config.h"
31 #include "apu_internal.h"
32 #include "apu_version.h"
33 #include "apr_dbm_private.h"
34 #include "apu_select_dbm.h"
36 #include "apr_dbm_private.h"
38 /* ### note: the setting of DBM_VTABLE will go away once we have multiple
40 ### Well, that day is here. So, do we remove DBM_VTABLE and the old
41 ### API entirely? Oh, what to do. We need an APU_DEFAULT_DBM #define.
42 ### Sounds like a job for autoconf. */
45 #define DBM_VTABLE apr_dbm_type_db
48 #define DBM_VTABLE apr_dbm_type_gdbm
49 #define DBM_NAME "gdbm"
51 #define DBM_VTABLE apr_dbm_type_ndbm
52 #define DBM_NAME "ndbm"
54 #define DBM_VTABLE apr_dbm_type_sdbm
55 #define DBM_NAME "sdbm"
56 #else /* Not in the USE_xDBM list above */
57 #error a DBM implementation was not specified
62 static apr_hash_t *drivers = NULL;
63 static apr_uint32_t initialised = 0, in_init = 1;
65 static apr_status_t dbm_term(void *ptr)
67 /* set drivers to NULL so init can work again */
70 /* Everything else we need is handled by cleanups registered
71 * when we created mutexes and loaded DSOs
76 #endif /* APU_DSO_BUILD */
78 static apr_status_t dbm_open_type(apr_dbm_type_t const* * vtable,
85 if (!strcasecmp(type, "default")) *vtable = &DBM_VTABLE;
87 else if (!strcasecmp(type, "db")) *vtable = &apr_dbm_type_db;
89 else if (*type && !strcasecmp(type + 1, "dbm")) {
91 if (*type == 'G' || *type == 'g') *vtable = &apr_dbm_type_gdbm;
94 if (*type == 'N' || *type == 'n') *vtable = &apr_dbm_type_ndbm;
97 if (*type == 'S' || *type == 's') *vtable = &apr_dbm_type_sdbm;
99 /* avoid empty block */ ;
105 #else /* APU_DSO_BUILD */
109 apr_dso_handle_sym_t symbol;
113 if (!strcasecmp(type, "default")) type = DBM_NAME;
114 else if (!strcasecmp(type, "db")) type = "db";
115 else if (*type && !strcasecmp(type + 1, "dbm")) {
116 if (*type == 'G' || *type == 'g') type = "gdbm";
117 else if (*type == 'N' || *type == 'n') type = "ndbm";
118 else if (*type == 'S' || *type == 's') type = "sdbm";
122 if (apr_atomic_inc32(&initialised)) {
123 apr_atomic_set32(&initialised, 1); /* prevent wrap-around */
125 while (apr_atomic_read32(&in_init)) /* wait until we get fully inited */
131 /* Top level pool scope, need process-scope lifetime */
132 for (parent = apr_pool_parent_get(pool);
133 parent && parent != pool;
134 parent = apr_pool_parent_get(pool))
137 /* deprecate in 2.0 - permit implicit initialization */
140 drivers = apr_hash_make(pool);
141 apr_hash_set(drivers, "sdbm", APR_HASH_KEY_STRING, &apr_dbm_type_sdbm);
143 apr_pool_cleanup_register(pool, NULL, dbm_term,
144 apr_pool_cleanup_null);
146 apr_atomic_dec32(&in_init);
149 rv = apu_dso_mutex_lock();
155 *vtable = apr_hash_get(drivers, type, APR_HASH_KEY_STRING);
157 apu_dso_mutex_unlock();
161 /* The driver DSO must have exactly the same lifetime as the
162 * drivers hash table; ignore the passed-in pool */
163 pool = apr_hash_pool_get(drivers);
166 apr_snprintf(modname, sizeof(modname), "dbm%s.nlm", type);
167 #elif defined(WIN32) || defined (__CYGWIN__)
168 apr_snprintf(modname, sizeof(modname),
169 "apr_dbm_%s-" APU_STRINGIFY(APU_MAJOR_VERSION) ".dll", type);
171 apr_snprintf(modname, sizeof(modname),
172 "apr_dbm_%s-" APU_STRINGIFY(APU_MAJOR_VERSION) ".so", type);
174 apr_snprintf(symname, sizeof(symname), "apr_dbm_type_%s", type);
176 rv = apu_dso_load(NULL, &symbol, modname, symname, pool);
177 if (rv == APR_SUCCESS || rv == APR_EINIT) { /* previously loaded?!? */
180 type = apr_pstrdup(pool, type);
181 apr_hash_set(drivers, type, APR_HASH_KEY_STRING, *vtable);
187 apu_dso_mutex_unlock();
190 #endif /* APU_DSO_BUILD */
193 APU_DECLARE(apr_status_t) apr_dbm_open_ex(apr_dbm_t **pdb, const char *type,
194 const char *pathname,
196 apr_fileperms_t perm,
199 apr_dbm_type_t const* vtable = NULL;
200 apr_status_t rv = dbm_open_type(&vtable, type, pool);
202 if (rv == APR_SUCCESS) {
203 rv = (vtable->open)(pdb, pathname, mode, perm, pool);
208 APU_DECLARE(apr_status_t) apr_dbm_open(apr_dbm_t **pdb, const char *pathname,
209 apr_int32_t mode, apr_fileperms_t perm,
212 return apr_dbm_open_ex(pdb, DBM_NAME, pathname, mode, perm, pool);
215 APU_DECLARE(void) apr_dbm_close(apr_dbm_t *dbm)
217 (*dbm->type->close)(dbm);
220 APU_DECLARE(apr_status_t) apr_dbm_fetch(apr_dbm_t *dbm, apr_datum_t key,
223 return (*dbm->type->fetch)(dbm, key, pvalue);
226 APU_DECLARE(apr_status_t) apr_dbm_store(apr_dbm_t *dbm, apr_datum_t key,
229 return (*dbm->type->store)(dbm, key, value);
232 APU_DECLARE(apr_status_t) apr_dbm_delete(apr_dbm_t *dbm, apr_datum_t key)
234 return (*dbm->type->del)(dbm, key);
237 APU_DECLARE(int) apr_dbm_exists(apr_dbm_t *dbm, apr_datum_t key)
239 return (*dbm->type->exists)(dbm, key);
242 APU_DECLARE(apr_status_t) apr_dbm_firstkey(apr_dbm_t *dbm, apr_datum_t *pkey)
244 return (*dbm->type->firstkey)(dbm, pkey);
247 APU_DECLARE(apr_status_t) apr_dbm_nextkey(apr_dbm_t *dbm, apr_datum_t *pkey)
249 return (*dbm->type->nextkey)(dbm, pkey);
252 APU_DECLARE(void) apr_dbm_freedatum(apr_dbm_t *dbm, apr_datum_t data)
254 (*dbm->type->freedatum)(dbm, data);
257 APU_DECLARE(char *) apr_dbm_geterror(apr_dbm_t *dbm, int *errcode,
258 char *errbuf, apr_size_t errbufsize)
261 *errcode = dbm->errcode;
263 /* assert: errbufsize > 0 */
265 if (dbm->errmsg == NULL)
268 (void) apr_cpystrn(errbuf, dbm->errmsg, errbufsize);
272 APU_DECLARE(apr_status_t) apr_dbm_get_usednames_ex(apr_pool_t *p,
274 const char *pathname,
278 apr_dbm_type_t const* vtable;
279 apr_status_t rv = dbm_open_type(&vtable, type, p);
281 if (rv == APR_SUCCESS) {
282 (vtable->getusednames)(p, pathname, used1, used2);
288 APU_DECLARE(void) apr_dbm_get_usednames(apr_pool_t *p,
289 const char *pathname,
293 apr_dbm_get_usednames_ex(p, DBM_NAME, pathname, used1, used2);
296 /* Most DBM libraries take a POSIX mode for creating files. Don't trust
297 * the mode_t type, some platforms may not support it, int is safe.
299 APU_DECLARE(int) apr_posix_perms2mode(apr_fileperms_t perm)
303 mode |= 0700 & (perm >> 2); /* User is off-by-2 bits */
304 mode |= 0070 & (perm >> 1); /* Group is off-by-1 bit */
305 mode |= 0007 & (perm); /* World maps 1 for 1 */