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.
18 #include "apr_strings.h"
21 #include <stdlib.h> /* for free() */
25 #include "apr_dbm_private.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
)
38 /* ### need to fix this */
45 static apr_status_t
datum_cleanup(void *dptr
)
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
) {
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
;
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
,
88 case APR_DBM_READONLY
:
89 dbmode
= APR_DBM_DBMODE_RO
;
91 case APR_DBM_READWRITE
:
92 dbmode
= APR_DBM_DBMODE_RW
;
94 case APR_DBM_RWCREATE
:
95 dbmode
= APR_DBM_DBMODE_RWCREATE
;
98 dbmode
= APR_DBM_DBMODE_RWTRUNC
;
104 /* Note: stupid cast to get rid of "const" on the pathname */
105 file
= gdbm_open((char *) pathname
, 0, dbmode
, apr_posix_perms2mode(perm
),
109 return APR_EGENERAL
; /* ### need a better error */
111 /* we have an open database... return it */
112 *pdb
= apr_pcalloc(pool
, sizeof(**pdb
));
114 (*pdb
)->type
= &apr_dbm_type_gdbm
;
117 /* ### register a cleanup to close the DBM? */
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
,
133 kd
.dsize
= key
.dsize
;
135 rd
= gdbm_fetch(dbm
->file
, kd
);
137 pvalue
->dptr
= rd
.dptr
;
138 pvalue
->dsize
= rd
.dsize
;
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
,
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
)
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
)
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
)
195 rd
= gdbm_firstkey(dbm
->file
);
197 pkey
->dptr
= rd
.dptr
;
198 pkey
->dsize
= rd
.dsize
;
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
)
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
;
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
);
240 APU_DECLARE_DATA
const apr_dbm_type_t apr_dbm_type_gdbm
= {
254 #endif /* APU_HAVE_GDBM */