]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - contrib/apr-util/dbm/apr_dbm.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / contrib / apr-util / dbm / apr_dbm.c
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
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 #include "apr.h"
18 #include "apr_dso.h"
19 #include "apr_hash.h"
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
25 #include "apr_want.h"
26 #include "apr_general.h"
27 #include "apr_atomic.h"
28
29 #include "apu_config.h"
30 #include "apu.h"
31 #include "apu_internal.h"
32 #include "apu_version.h"
33 #include "apr_dbm_private.h"
34 #include "apu_select_dbm.h"
35 #include "apr_dbm.h"
36 #include "apr_dbm_private.h"
37
38 /* ### note: the setting of DBM_VTABLE will go away once we have multiple
39    ### DBMs in here. 
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. */
43
44 #if APU_USE_DB
45 #define DBM_VTABLE apr_dbm_type_db
46 #define DBM_NAME   "db"
47 #elif APU_USE_GDBM
48 #define DBM_VTABLE apr_dbm_type_gdbm
49 #define DBM_NAME   "gdbm"
50 #elif APU_USE_NDBM
51 #define DBM_VTABLE apr_dbm_type_ndbm
52 #define DBM_NAME   "ndbm"
53 #elif APU_USE_SDBM
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
58 #endif
59
60 #if APU_DSO_BUILD
61
62 static apr_hash_t *drivers = NULL;
63 static apr_uint32_t initialised = 0, in_init = 1;
64
65 static apr_status_t dbm_term(void *ptr)
66 {
67     /* set drivers to NULL so init can work again */
68     drivers = NULL;
69
70     /* Everything else we need is handled by cleanups registered
71      * when we created mutexes and loaded DSOs
72      */
73     return APR_SUCCESS;
74 }
75
76 #endif /* APU_DSO_BUILD */
77
78 static apr_status_t dbm_open_type(apr_dbm_type_t const* * vtable,
79                                   const char *type, 
80                                   apr_pool_t *pool)
81 {
82 #if !APU_DSO_BUILD
83
84     *vtable = NULL;
85     if (!strcasecmp(type, "default"))     *vtable = &DBM_VTABLE;
86 #if APU_HAVE_DB
87     else if (!strcasecmp(type, "db"))     *vtable = &apr_dbm_type_db;
88 #endif
89     else if (*type && !strcasecmp(type + 1, "dbm")) {
90 #if APU_HAVE_GDBM
91         if (*type == 'G' || *type == 'g') *vtable = &apr_dbm_type_gdbm;
92 #endif
93 #if APU_HAVE_NDBM
94         if (*type == 'N' || *type == 'n') *vtable = &apr_dbm_type_ndbm;
95 #endif
96 #if APU_HAVE_SDBM
97         if (*type == 'S' || *type == 's') *vtable = &apr_dbm_type_sdbm;
98 #endif
99         /* avoid empty block */ ;
100     }
101     if (*vtable)
102         return APR_SUCCESS;
103     return APR_ENOTIMPL;
104
105 #else /* APU_DSO_BUILD */
106
107     char modname[32];
108     char symname[34];
109     apr_dso_handle_sym_t symbol;
110     apr_status_t rv;
111     int usertype = 0;
112
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"; 
119     }
120     else usertype = 1;
121
122     if (apr_atomic_inc32(&initialised)) {
123         apr_atomic_set32(&initialised, 1); /* prevent wrap-around */
124
125         while (apr_atomic_read32(&in_init)) /* wait until we get fully inited */
126             ;
127     }
128     else {
129         apr_pool_t *parent;
130
131         /* Top level pool scope, need process-scope lifetime */
132         for (parent = pool;  parent; parent = apr_pool_parent_get(pool))
133              pool = parent;
134
135         /* deprecate in 2.0 - permit implicit initialization */
136         apu_dso_init(pool);
137
138         drivers = apr_hash_make(pool);
139         apr_hash_set(drivers, "sdbm", APR_HASH_KEY_STRING, &apr_dbm_type_sdbm);
140
141         apr_pool_cleanup_register(pool, NULL, dbm_term,
142                                   apr_pool_cleanup_null);
143
144         apr_atomic_dec32(&in_init);
145     }
146
147     rv = apu_dso_mutex_lock();
148     if (rv) {
149         *vtable = NULL;
150         return rv;
151     }
152
153     *vtable = apr_hash_get(drivers, type, APR_HASH_KEY_STRING);
154     if (*vtable) {
155         apu_dso_mutex_unlock();
156         return APR_SUCCESS;
157     }
158
159     /* The driver DSO must have exactly the same lifetime as the
160      * drivers hash table; ignore the passed-in pool */
161     pool = apr_hash_pool_get(drivers);
162
163 #if defined(NETWARE)
164     apr_snprintf(modname, sizeof(modname), "dbm%s.nlm", type);
165 #elif defined(WIN32)
166     apr_snprintf(modname, sizeof(modname),
167                  "apr_dbm_%s-" APU_STRINGIFY(APU_MAJOR_VERSION) ".dll", type);
168 #else
169     apr_snprintf(modname, sizeof(modname),
170                  "apr_dbm_%s-" APU_STRINGIFY(APU_MAJOR_VERSION) ".so", type);
171 #endif
172     apr_snprintf(symname, sizeof(symname), "apr_dbm_type_%s", type);
173
174     rv = apu_dso_load(NULL, &symbol, modname, symname, pool);
175     if (rv == APR_SUCCESS || rv == APR_EINIT) { /* previously loaded?!? */
176         *vtable = symbol;
177         if (usertype)
178             type = apr_pstrdup(pool, type);
179         apr_hash_set(drivers, type, APR_HASH_KEY_STRING, *vtable);
180         rv = APR_SUCCESS;
181     }
182     else
183         *vtable = NULL;
184
185     apu_dso_mutex_unlock();
186     return rv;
187
188 #endif /* APU_DSO_BUILD */
189 }
190
191 APU_DECLARE(apr_status_t) apr_dbm_open_ex(apr_dbm_t **pdb, const char *type, 
192                                           const char *pathname, 
193                                           apr_int32_t mode,
194                                           apr_fileperms_t perm,
195                                           apr_pool_t *pool)
196 {
197     apr_dbm_type_t const* vtable = NULL;
198     apr_status_t rv = dbm_open_type(&vtable, type, pool);
199
200     if (rv == APR_SUCCESS) {
201         rv = (vtable->open)(pdb, pathname, mode, perm, pool);
202     }
203     return rv;
204
205
206 APU_DECLARE(apr_status_t) apr_dbm_open(apr_dbm_t **pdb, const char *pathname, 
207                                        apr_int32_t mode, apr_fileperms_t perm,
208                                        apr_pool_t *pool)
209 {
210     return apr_dbm_open_ex(pdb, DBM_NAME, pathname, mode, perm, pool);
211 }
212
213 APU_DECLARE(void) apr_dbm_close(apr_dbm_t *dbm)
214 {
215     (*dbm->type->close)(dbm);
216 }
217
218 APU_DECLARE(apr_status_t) apr_dbm_fetch(apr_dbm_t *dbm, apr_datum_t key,
219                                         apr_datum_t *pvalue)
220 {
221     return (*dbm->type->fetch)(dbm, key, pvalue);
222 }
223
224 APU_DECLARE(apr_status_t) apr_dbm_store(apr_dbm_t *dbm, apr_datum_t key,
225                                         apr_datum_t value)
226 {
227     return (*dbm->type->store)(dbm, key, value);
228 }
229
230 APU_DECLARE(apr_status_t) apr_dbm_delete(apr_dbm_t *dbm, apr_datum_t key)
231 {
232     return (*dbm->type->del)(dbm, key);
233 }
234
235 APU_DECLARE(int) apr_dbm_exists(apr_dbm_t *dbm, apr_datum_t key)
236 {
237     return (*dbm->type->exists)(dbm, key);
238 }
239
240 APU_DECLARE(apr_status_t) apr_dbm_firstkey(apr_dbm_t *dbm, apr_datum_t *pkey)
241 {
242     return (*dbm->type->firstkey)(dbm, pkey);
243 }
244
245 APU_DECLARE(apr_status_t) apr_dbm_nextkey(apr_dbm_t *dbm, apr_datum_t *pkey)
246 {
247     return (*dbm->type->nextkey)(dbm, pkey);
248 }
249
250 APU_DECLARE(void) apr_dbm_freedatum(apr_dbm_t *dbm, apr_datum_t data)
251 {
252     (*dbm->type->freedatum)(dbm, data);
253 }
254
255 APU_DECLARE(char *) apr_dbm_geterror(apr_dbm_t *dbm, int *errcode,
256                                      char *errbuf, apr_size_t errbufsize)
257 {
258     if (errcode != NULL)
259         *errcode = dbm->errcode;
260
261     /* assert: errbufsize > 0 */
262
263     if (dbm->errmsg == NULL)
264         *errbuf = '\0';
265     else
266         (void) apr_cpystrn(errbuf, dbm->errmsg, errbufsize);
267     return errbuf;
268 }
269
270 APU_DECLARE(apr_status_t) apr_dbm_get_usednames_ex(apr_pool_t *p, 
271                                                    const char *type, 
272                                                    const char *pathname,
273                                                    const char **used1,
274                                                    const char **used2)
275 {
276     apr_dbm_type_t const* vtable;
277     apr_status_t rv = dbm_open_type(&vtable, type, p);
278
279     if (rv == APR_SUCCESS) {
280         (vtable->getusednames)(p, pathname, used1, used2);
281         return APR_SUCCESS;
282     }
283     return rv;
284
285
286 APU_DECLARE(void) apr_dbm_get_usednames(apr_pool_t *p,
287                                         const char *pathname,
288                                         const char **used1,
289                                         const char **used2)
290 {
291     apr_dbm_get_usednames_ex(p, DBM_NAME, pathname, used1, used2); 
292 }
293
294 /* Most DBM libraries take a POSIX mode for creating files.  Don't trust
295  * the mode_t type, some platforms may not support it, int is safe.
296  */
297 APU_DECLARE(int) apr_posix_perms2mode(apr_fileperms_t perm)
298 {
299     int mode = 0;
300
301     mode |= 0700 & (perm >> 2); /* User  is off-by-2 bits */
302     mode |= 0070 & (perm >> 1); /* Group is off-by-1 bit */
303     mode |= 0007 & (perm);      /* World maps 1 for 1 */
304     return mode;
305 }