Revert change to testdate.c (commited by accident)
[apr-util.git] / dbm / apr_dbm_gdbm.c
blobe5462c47b83ec9e9c6123401951e71840c67d6dd
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.h"
18 #include "apr_strings.h"
20 #if APR_HAVE_STDLIB_H
21 #include <stdlib.h> /* for free() */
22 #endif
24 #if APU_HAVE_GDBM
25 #include "apr_dbm_private.h"
27 #include <gdbm.h>
29 #define APR_DBM_DBMODE_RO GDBM_READER
30 #define APR_DBM_DBMODE_RW GDBM_WRITER
31 #define APR_DBM_DBMODE_RWCREATE GDBM_WRCREAT
32 #define APR_DBM_DBMODE_RWTRUNC GDBM_NEWDB
34 /* map a GDBM error to an apr_status_t */
35 static apr_status_t g2s(int gerr)
37 if (gerr == -1) {
38 /* ### need to fix this */
39 return APR_EGENERAL;
42 return APR_SUCCESS;
45 static apr_status_t datum_cleanup(void *dptr)
47 if (dptr)
48 free(dptr);
50 return APR_SUCCESS;
53 static apr_status_t set_error(apr_dbm_t *dbm, apr_status_t dbm_said)
55 apr_status_t rv = APR_SUCCESS;
57 /* ### ignore whatever the DBM said (dbm_said); ask it explicitly */
59 if ((dbm->errcode = gdbm_errno) == GDBM_NO_ERROR) {
60 dbm->errmsg = NULL;
62 else {
63 dbm->errmsg = gdbm_strerror(gdbm_errno);
64 rv = APR_EGENERAL; /* ### need something better */
67 /* captured it. clear it now. */
68 gdbm_errno = GDBM_NO_ERROR;
70 return rv;
73 /* --------------------------------------------------------------------------
75 ** DEFINE THE VTABLE FUNCTIONS FOR GDBM
78 static apr_status_t vt_gdbm_open(apr_dbm_t **pdb, const char *pathname,
79 apr_int32_t mode, apr_fileperms_t perm,
80 apr_pool_t *pool)
82 GDBM_FILE file;
83 int dbmode;
85 *pdb = NULL;
87 switch (mode) {
88 case APR_DBM_READONLY:
89 dbmode = APR_DBM_DBMODE_RO;
90 break;
91 case APR_DBM_READWRITE:
92 dbmode = APR_DBM_DBMODE_RW;
93 break;
94 case APR_DBM_RWCREATE:
95 dbmode = APR_DBM_DBMODE_RWCREATE;
96 break;
97 case APR_DBM_RWTRUNC:
98 dbmode = APR_DBM_DBMODE_RWTRUNC;
99 break;
100 default:
101 return APR_EINVAL;
104 /* Note: stupid cast to get rid of "const" on the pathname */
105 file = gdbm_open((char *) pathname, 0, dbmode, apr_posix_perms2mode(perm),
106 NULL);
108 if (file == NULL)
109 return APR_EGENERAL; /* ### need a better error */
111 /* we have an open database... return it */
112 *pdb = apr_pcalloc(pool, sizeof(**pdb));
113 (*pdb)->pool = pool;
114 (*pdb)->type = &apr_dbm_type_gdbm;
115 (*pdb)->file = file;
117 /* ### register a cleanup to close the DBM? */
119 return APR_SUCCESS;
122 static void vt_gdbm_close(apr_dbm_t *dbm)
124 gdbm_close(dbm->file);
127 static apr_status_t vt_gdbm_fetch(apr_dbm_t *dbm, apr_datum_t key,
128 apr_datum_t *pvalue)
130 datum kd, rd;
132 kd.dptr = key.dptr;
133 kd.dsize = key.dsize;
135 rd = gdbm_fetch(dbm->file, kd);
137 pvalue->dptr = rd.dptr;
138 pvalue->dsize = rd.dsize;
140 if (pvalue->dptr)
141 apr_pool_cleanup_register(dbm->pool, pvalue->dptr, datum_cleanup,
142 apr_pool_cleanup_null);
144 /* store the error info into DBM, and return a status code. Also, note
145 that *pvalue should have been cleared on error. */
146 return set_error(dbm, APR_SUCCESS);
149 static apr_status_t vt_gdbm_store(apr_dbm_t *dbm, apr_datum_t key,
150 apr_datum_t value)
152 int rc;
153 datum kd, vd;
155 kd.dptr = key.dptr;
156 kd.dsize = key.dsize;
158 vd.dptr = value.dptr;
159 vd.dsize = value.dsize;
161 rc = gdbm_store(dbm->file, kd, vd, GDBM_REPLACE);
163 /* store any error info into DBM, and return a status code. */
164 return set_error(dbm, g2s(rc));
167 static apr_status_t vt_gdbm_del(apr_dbm_t *dbm, apr_datum_t key)
169 int rc;
170 datum kd;
172 kd.dptr = key.dptr;
173 kd.dsize = key.dsize;
175 rc = gdbm_delete(dbm->file, kd);
177 /* store any error info into DBM, and return a status code. */
178 return set_error(dbm, g2s(rc));
181 static int vt_gdbm_exists(apr_dbm_t *dbm, apr_datum_t key)
183 datum kd;
185 kd.dptr = key.dptr;
186 kd.dsize = key.dsize;
188 return gdbm_exists(dbm->file, kd) != 0;
191 static apr_status_t vt_gdbm_firstkey(apr_dbm_t *dbm, apr_datum_t *pkey)
193 datum rd;
195 rd = gdbm_firstkey(dbm->file);
197 pkey->dptr = rd.dptr;
198 pkey->dsize = rd.dsize;
200 if (pkey->dptr)
201 apr_pool_cleanup_register(dbm->pool, pkey->dptr, datum_cleanup,
202 apr_pool_cleanup_null);
204 /* store any error info into DBM, and return a status code. */
205 return set_error(dbm, APR_SUCCESS);
208 static apr_status_t vt_gdbm_nextkey(apr_dbm_t *dbm, apr_datum_t *pkey)
210 datum kd, rd;
212 kd.dptr = pkey->dptr;
213 kd.dsize = pkey->dsize;
215 rd = gdbm_nextkey(dbm->file, kd);
217 pkey->dptr = rd.dptr;
218 pkey->dsize = rd.dsize;
220 if (pkey->dptr)
221 apr_pool_cleanup_register(dbm->pool, pkey->dptr, datum_cleanup,
222 apr_pool_cleanup_null);
224 /* store any error info into DBM, and return a status code. */
225 return set_error(dbm, APR_SUCCESS);
228 static void vt_gdbm_freedatum(apr_dbm_t *dbm, apr_datum_t data)
230 (void) apr_pool_cleanup_run(dbm->pool, data.dptr, datum_cleanup);
233 static void vt_gdbm_usednames(apr_pool_t *pool, const char *pathname,
234 const char **used1, const char **used2)
236 *used1 = apr_pstrdup(pool, pathname);
237 *used2 = NULL;
240 APU_DECLARE_DATA const apr_dbm_type_t apr_dbm_type_gdbm = {
241 "gdbm",
242 vt_gdbm_open,
243 vt_gdbm_close,
244 vt_gdbm_fetch,
245 vt_gdbm_store,
246 vt_gdbm_del,
247 vt_gdbm_exists,
248 vt_gdbm_firstkey,
249 vt_gdbm_nextkey,
250 vt_gdbm_freedatum,
251 vt_gdbm_usednames
254 #endif /* APU_HAVE_GDBM */