1251876Speter/* Licensed to the Apache Software Foundation (ASF) under one or more 2251876Speter * contributor license agreements. See the NOTICE file distributed with 3251876Speter * this work for additional information regarding copyright ownership. 4251876Speter * The ASF licenses this file to You under the Apache License, Version 2.0 5251876Speter * (the "License"); you may not use this file except in compliance with 6251876Speter * the License. You may obtain a copy of the License at 7251876Speter * 8251876Speter * http://www.apache.org/licenses/LICENSE-2.0 9251876Speter * 10251876Speter * Unless required by applicable law or agreed to in writing, software 11251876Speter * distributed under the License is distributed on an "AS IS" BASIS, 12251876Speter * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13251876Speter * See the License for the specific language governing permissions and 14251876Speter * limitations under the License. 15251876Speter */ 16251876Speter 17251876Speter#include "apu_config.h" 18251876Speter#include "apu.h" 19251876Speter#include "apr_strings.h" 20251876Speter 21251876Speter#if APR_HAVE_STDLIB_H 22251876Speter#include <stdlib.h> /* for free() */ 23251876Speter#endif 24251876Speter 25251876Speter#if APU_HAVE_GDBM 26251876Speter#include "apr_dbm_private.h" 27251876Speter 28251876Speter#include <gdbm.h> 29251876Speter 30251876Speter#define APR_DBM_DBMODE_RO GDBM_READER 31251876Speter#define APR_DBM_DBMODE_RW GDBM_WRITER 32251876Speter#define APR_DBM_DBMODE_RWCREATE GDBM_WRCREAT 33251876Speter#define APR_DBM_DBMODE_RWTRUNC GDBM_NEWDB 34251876Speter 35251876Speter/* map a GDBM error to an apr_status_t */ 36251876Speterstatic apr_status_t g2s(int gerr) 37251876Speter{ 38251876Speter if (gerr == -1) { 39251876Speter /* ### need to fix this */ 40251876Speter return APR_EGENERAL; 41251876Speter } 42251876Speter 43251876Speter return APR_SUCCESS; 44251876Speter} 45251876Speter 46251876Speterstatic apr_status_t datum_cleanup(void *dptr) 47251876Speter{ 48251876Speter if (dptr) 49251876Speter free(dptr); 50251876Speter 51251876Speter return APR_SUCCESS; 52251876Speter} 53251876Speter 54251876Speterstatic apr_status_t set_error(apr_dbm_t *dbm, apr_status_t dbm_said) 55251876Speter{ 56251876Speter apr_status_t rv = APR_SUCCESS; 57251876Speter 58251876Speter /* ### ignore whatever the DBM said (dbm_said); ask it explicitly */ 59251876Speter 60251876Speter if ((dbm->errcode = gdbm_errno) == GDBM_NO_ERROR) { 61251876Speter dbm->errmsg = NULL; 62251876Speter } 63251876Speter else { 64251876Speter dbm->errmsg = gdbm_strerror(gdbm_errno); 65251876Speter rv = APR_EGENERAL; /* ### need something better */ 66251876Speter } 67251876Speter 68251876Speter /* captured it. clear it now. */ 69251876Speter gdbm_errno = GDBM_NO_ERROR; 70251876Speter 71251876Speter return rv; 72251876Speter} 73251876Speter 74251876Speter/* -------------------------------------------------------------------------- 75251876Speter** 76251876Speter** DEFINE THE VTABLE FUNCTIONS FOR GDBM 77251876Speter*/ 78251876Speter 79251876Speterstatic apr_status_t vt_gdbm_open(apr_dbm_t **pdb, const char *pathname, 80251876Speter apr_int32_t mode, apr_fileperms_t perm, 81251876Speter apr_pool_t *pool) 82251876Speter{ 83251876Speter GDBM_FILE file; 84251876Speter int dbmode; 85251876Speter 86251876Speter *pdb = NULL; 87251876Speter 88251876Speter switch (mode) { 89251876Speter case APR_DBM_READONLY: 90251876Speter dbmode = APR_DBM_DBMODE_RO; 91251876Speter break; 92251876Speter case APR_DBM_READWRITE: 93251876Speter dbmode = APR_DBM_DBMODE_RW; 94251876Speter break; 95251876Speter case APR_DBM_RWCREATE: 96251876Speter dbmode = APR_DBM_DBMODE_RWCREATE; 97251876Speter break; 98251876Speter case APR_DBM_RWTRUNC: 99251876Speter dbmode = APR_DBM_DBMODE_RWTRUNC; 100251876Speter break; 101251876Speter default: 102251876Speter return APR_EINVAL; 103251876Speter } 104251876Speter 105251876Speter /* Note: stupid cast to get rid of "const" on the pathname */ 106251876Speter file = gdbm_open((char *) pathname, 0, dbmode, apr_posix_perms2mode(perm), 107251876Speter NULL); 108251876Speter 109251876Speter if (file == NULL) 110251876Speter return APR_EGENERAL; /* ### need a better error */ 111251876Speter 112251876Speter /* we have an open database... return it */ 113251876Speter *pdb = apr_pcalloc(pool, sizeof(**pdb)); 114251876Speter (*pdb)->pool = pool; 115251876Speter (*pdb)->type = &apr_dbm_type_gdbm; 116251876Speter (*pdb)->file = file; 117251876Speter 118251876Speter /* ### register a cleanup to close the DBM? */ 119251876Speter 120251876Speter return APR_SUCCESS; 121251876Speter} 122251876Speter 123251876Speterstatic void vt_gdbm_close(apr_dbm_t *dbm) 124251876Speter{ 125251876Speter gdbm_close(dbm->file); 126251876Speter} 127251876Speter 128251876Speterstatic apr_status_t vt_gdbm_fetch(apr_dbm_t *dbm, apr_datum_t key, 129251876Speter apr_datum_t *pvalue) 130251876Speter{ 131251876Speter datum kd, rd; 132251876Speter 133251876Speter kd.dptr = key.dptr; 134251876Speter kd.dsize = key.dsize; 135251876Speter 136251876Speter rd = gdbm_fetch(dbm->file, kd); 137251876Speter 138251876Speter pvalue->dptr = rd.dptr; 139251876Speter pvalue->dsize = rd.dsize; 140251876Speter 141251876Speter if (pvalue->dptr) 142251876Speter apr_pool_cleanup_register(dbm->pool, pvalue->dptr, datum_cleanup, 143251876Speter apr_pool_cleanup_null); 144251876Speter 145251876Speter /* store the error info into DBM, and return a status code. Also, note 146251876Speter that *pvalue should have been cleared on error. */ 147251876Speter return set_error(dbm, APR_SUCCESS); 148251876Speter} 149251876Speter 150251876Speterstatic apr_status_t vt_gdbm_store(apr_dbm_t *dbm, apr_datum_t key, 151251876Speter apr_datum_t value) 152251876Speter{ 153251876Speter int rc; 154251876Speter datum kd, vd; 155251876Speter 156251876Speter kd.dptr = key.dptr; 157251876Speter kd.dsize = key.dsize; 158251876Speter 159251876Speter vd.dptr = value.dptr; 160251876Speter vd.dsize = value.dsize; 161251876Speter 162251876Speter rc = gdbm_store(dbm->file, kd, vd, GDBM_REPLACE); 163251876Speter 164251876Speter /* store any error info into DBM, and return a status code. */ 165251876Speter return set_error(dbm, g2s(rc)); 166251876Speter} 167251876Speter 168251876Speterstatic apr_status_t vt_gdbm_del(apr_dbm_t *dbm, apr_datum_t key) 169251876Speter{ 170251876Speter int rc; 171251876Speter datum kd; 172251876Speter 173251876Speter kd.dptr = key.dptr; 174251876Speter kd.dsize = key.dsize; 175251876Speter 176251876Speter rc = gdbm_delete(dbm->file, kd); 177251876Speter 178251876Speter /* store any error info into DBM, and return a status code. */ 179251876Speter return set_error(dbm, g2s(rc)); 180251876Speter} 181251876Speter 182251876Speterstatic int vt_gdbm_exists(apr_dbm_t *dbm, apr_datum_t key) 183251876Speter{ 184251876Speter datum kd; 185251876Speter 186251876Speter kd.dptr = key.dptr; 187251876Speter kd.dsize = key.dsize; 188251876Speter 189251876Speter return gdbm_exists(dbm->file, kd) != 0; 190251876Speter} 191251876Speter 192251876Speterstatic apr_status_t vt_gdbm_firstkey(apr_dbm_t *dbm, apr_datum_t *pkey) 193251876Speter{ 194251876Speter datum rd; 195251876Speter 196251876Speter rd = gdbm_firstkey(dbm->file); 197251876Speter 198251876Speter pkey->dptr = rd.dptr; 199251876Speter pkey->dsize = rd.dsize; 200251876Speter 201251876Speter if (pkey->dptr) 202251876Speter apr_pool_cleanup_register(dbm->pool, pkey->dptr, datum_cleanup, 203251876Speter apr_pool_cleanup_null); 204251876Speter 205251876Speter /* store any error info into DBM, and return a status code. */ 206251876Speter return set_error(dbm, APR_SUCCESS); 207251876Speter} 208251876Speter 209251876Speterstatic apr_status_t vt_gdbm_nextkey(apr_dbm_t *dbm, apr_datum_t *pkey) 210251876Speter{ 211251876Speter datum kd, rd; 212251876Speter 213251876Speter kd.dptr = pkey->dptr; 214251876Speter kd.dsize = pkey->dsize; 215251876Speter 216251876Speter rd = gdbm_nextkey(dbm->file, kd); 217251876Speter 218251876Speter pkey->dptr = rd.dptr; 219251876Speter pkey->dsize = rd.dsize; 220251876Speter 221251876Speter if (pkey->dptr) 222251876Speter apr_pool_cleanup_register(dbm->pool, pkey->dptr, datum_cleanup, 223251876Speter apr_pool_cleanup_null); 224251876Speter 225251876Speter /* store any error info into DBM, and return a status code. */ 226251876Speter return set_error(dbm, APR_SUCCESS); 227251876Speter} 228251876Speter 229251876Speterstatic void vt_gdbm_freedatum(apr_dbm_t *dbm, apr_datum_t data) 230251876Speter{ 231251876Speter (void) apr_pool_cleanup_run(dbm->pool, data.dptr, datum_cleanup); 232251876Speter} 233251876Speter 234251876Speterstatic void vt_gdbm_usednames(apr_pool_t *pool, const char *pathname, 235251876Speter const char **used1, const char **used2) 236251876Speter{ 237251876Speter *used1 = apr_pstrdup(pool, pathname); 238251876Speter *used2 = NULL; 239251876Speter} 240251876Speter 241251876SpeterAPU_MODULE_DECLARE_DATA const apr_dbm_type_t apr_dbm_type_gdbm = { 242251876Speter "gdbm", 243251876Speter vt_gdbm_open, 244251876Speter vt_gdbm_close, 245251876Speter vt_gdbm_fetch, 246251876Speter vt_gdbm_store, 247251876Speter vt_gdbm_del, 248251876Speter vt_gdbm_exists, 249251876Speter vt_gdbm_firstkey, 250251876Speter vt_gdbm_nextkey, 251251876Speter vt_gdbm_freedatum, 252251876Speter vt_gdbm_usednames 253251876Speter}; 254251876Speter 255251876Speter#endif /* APU_HAVE_GDBM */ 256