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.
17 #include "apu_config.h"
19 #include "apr_strings.h"
22 #include <stdlib.h> /* for free() */
26 #include "apr_dbm_private.h"
30 #define APR_DBM_DBMODE_RO GDBM_READER
31 #define APR_DBM_DBMODE_RW GDBM_WRITER
32 #define APR_DBM_DBMODE_RWCREATE GDBM_WRCREAT
33 #define APR_DBM_DBMODE_RWTRUNC GDBM_NEWDB
35 /* map a GDBM error to an apr_status_t */
36 static apr_status_t g2s(int gerr)
39 /* ### need to fix this */
46 static apr_status_t datum_cleanup(void *dptr)
54 static apr_status_t set_error(apr_dbm_t *dbm, apr_status_t dbm_said)
56 apr_status_t rv = APR_SUCCESS;
58 /* ### ignore whatever the DBM said (dbm_said); ask it explicitly */
60 if ((dbm->errcode = gdbm_errno) == GDBM_NO_ERROR) {
64 dbm->errmsg = gdbm_strerror(gdbm_errno);
65 rv = APR_EGENERAL; /* ### need something better */
68 /* captured it. clear it now. */
69 gdbm_errno = GDBM_NO_ERROR;
74 /* --------------------------------------------------------------------------
76 ** DEFINE THE VTABLE FUNCTIONS FOR GDBM
79 static apr_status_t vt_gdbm_open(apr_dbm_t **pdb, const char *pathname,
80 apr_int32_t mode, apr_fileperms_t perm,
89 case APR_DBM_READONLY:
90 dbmode = APR_DBM_DBMODE_RO;
92 case APR_DBM_READWRITE:
93 dbmode = APR_DBM_DBMODE_RW;
95 case APR_DBM_RWCREATE:
96 dbmode = APR_DBM_DBMODE_RWCREATE;
99 dbmode = APR_DBM_DBMODE_RWTRUNC;
105 /* Note: stupid cast to get rid of "const" on the pathname */
106 file = gdbm_open((char *) pathname, 0, dbmode, apr_posix_perms2mode(perm),
110 return APR_EGENERAL; /* ### need a better error */
112 /* we have an open database... return it */
113 *pdb = apr_pcalloc(pool, sizeof(**pdb));
115 (*pdb)->type = &apr_dbm_type_gdbm;
118 /* ### register a cleanup to close the DBM? */
123 static void vt_gdbm_close(apr_dbm_t *dbm)
125 gdbm_close(dbm->file);
128 static apr_status_t vt_gdbm_fetch(apr_dbm_t *dbm, apr_datum_t key,
134 kd.dsize = key.dsize;
136 rd = gdbm_fetch(dbm->file, kd);
138 pvalue->dptr = rd.dptr;
139 pvalue->dsize = rd.dsize;
142 apr_pool_cleanup_register(dbm->pool, pvalue->dptr, datum_cleanup,
143 apr_pool_cleanup_null);
145 /* store the error info into DBM, and return a status code. Also, note
146 that *pvalue should have been cleared on error. */
147 return set_error(dbm, APR_SUCCESS);
150 static apr_status_t vt_gdbm_store(apr_dbm_t *dbm, apr_datum_t key,
157 kd.dsize = key.dsize;
159 vd.dptr = value.dptr;
160 vd.dsize = value.dsize;
162 rc = gdbm_store(dbm->file, kd, vd, GDBM_REPLACE);
164 /* store any error info into DBM, and return a status code. */
165 return set_error(dbm, g2s(rc));
168 static apr_status_t vt_gdbm_del(apr_dbm_t *dbm, apr_datum_t key)
174 kd.dsize = key.dsize;
176 rc = gdbm_delete(dbm->file, kd);
178 /* store any error info into DBM, and return a status code. */
179 return set_error(dbm, g2s(rc));
182 static int vt_gdbm_exists(apr_dbm_t *dbm, apr_datum_t key)
187 kd.dsize = key.dsize;
189 return gdbm_exists(dbm->file, kd) != 0;
192 static apr_status_t vt_gdbm_firstkey(apr_dbm_t *dbm, apr_datum_t *pkey)
196 rd = gdbm_firstkey(dbm->file);
198 pkey->dptr = rd.dptr;
199 pkey->dsize = rd.dsize;
202 apr_pool_cleanup_register(dbm->pool, pkey->dptr, datum_cleanup,
203 apr_pool_cleanup_null);
205 /* store any error info into DBM, and return a status code. */
206 return set_error(dbm, APR_SUCCESS);
209 static apr_status_t vt_gdbm_nextkey(apr_dbm_t *dbm, apr_datum_t *pkey)
213 kd.dptr = pkey->dptr;
214 kd.dsize = pkey->dsize;
216 rd = gdbm_nextkey(dbm->file, kd);
218 pkey->dptr = rd.dptr;
219 pkey->dsize = rd.dsize;
222 apr_pool_cleanup_register(dbm->pool, pkey->dptr, datum_cleanup,
223 apr_pool_cleanup_null);
225 /* store any error info into DBM, and return a status code. */
226 return set_error(dbm, APR_SUCCESS);
229 static void vt_gdbm_freedatum(apr_dbm_t *dbm, apr_datum_t data)
231 (void) apr_pool_cleanup_run(dbm->pool, data.dptr, datum_cleanup);
234 static void vt_gdbm_usednames(apr_pool_t *pool, const char *pathname,
235 const char **used1, const char **used2)
237 *used1 = apr_pstrdup(pool, pathname);
241 APU_MODULE_DECLARE_DATA const apr_dbm_type_t apr_dbm_type_gdbm = {
255 #endif /* APU_HAVE_GDBM */