apr_dbm_gdbm.c revision 251886
160484Sobrien/* Licensed to the Apache Software Foundation (ASF) under one or more 260484Sobrien * contributor license agreements. See the NOTICE file distributed with 360484Sobrien * this work for additional information regarding copyright ownership. 460484Sobrien * The ASF licenses this file to You under the Apache License, Version 2.0 560484Sobrien * (the "License"); you may not use this file except in compliance with 660484Sobrien * the License. You may obtain a copy of the License at 760484Sobrien * 860484Sobrien * http://www.apache.org/licenses/LICENSE-2.0 960484Sobrien * 1060484Sobrien * Unless required by applicable law or agreed to in writing, software 1160484Sobrien * distributed under the License is distributed on an "AS IS" BASIS, 1260484Sobrien * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1360484Sobrien * See the License for the specific language governing permissions and 1460484Sobrien * limitations under the License. 1560484Sobrien */ 1660484Sobrien 1760484Sobrien#include "apu_config.h" 1860484Sobrien#include "apu.h" 1960484Sobrien#include "apr_strings.h" 2060484Sobrien 2160484Sobrien#if APR_HAVE_STDLIB_H 2260484Sobrien#include <stdlib.h> /* for free() */ 2360484Sobrien#endif 2460484Sobrien 2560484Sobrien#if APU_HAVE_GDBM 2660484Sobrien#include "apr_dbm_private.h" 27130561Sobrien 28130561Sobrien#include <gdbm.h> 2960484Sobrien 3060484Sobrien#define APR_DBM_DBMODE_RO GDBM_READER 3160484Sobrien#define APR_DBM_DBMODE_RW GDBM_WRITER 3260484Sobrien#define APR_DBM_DBMODE_RWCREATE GDBM_WRCREAT 3360484Sobrien#define APR_DBM_DBMODE_RWTRUNC GDBM_NEWDB 3460484Sobrien 3560484Sobrien/* map a GDBM error to an apr_status_t */ 3660484Sobrienstatic apr_status_t g2s(int gerr) 3760484Sobrien{ 3860484Sobrien if (gerr == -1) { 3960484Sobrien /* ### need to fix this */ 4060484Sobrien return APR_EGENERAL; 4160484Sobrien } 4260484Sobrien 4360484Sobrien return APR_SUCCESS; 4460484Sobrien} 4560484Sobrien 4660484Sobrienstatic apr_status_t datum_cleanup(void *dptr) 4760484Sobrien{ 4860484Sobrien if (dptr) 4960484Sobrien free(dptr); 5060484Sobrien 5160484Sobrien return APR_SUCCESS; 5260484Sobrien} 5360484Sobrien 5460484Sobrienstatic apr_status_t set_error(apr_dbm_t *dbm, apr_status_t dbm_said) 5560484Sobrien{ 5660484Sobrien apr_status_t rv = APR_SUCCESS; 5760484Sobrien 5860484Sobrien /* ### ignore whatever the DBM said (dbm_said); ask it explicitly */ 5960484Sobrien 6060484Sobrien if ((dbm->errcode = gdbm_errno) == GDBM_NO_ERROR) { 6160484Sobrien dbm->errmsg = NULL; 6260484Sobrien } 6360484Sobrien else { 6460484Sobrien dbm->errmsg = gdbm_strerror(gdbm_errno); 6560484Sobrien rv = APR_EGENERAL; /* ### need something better */ 6660484Sobrien } 6760484Sobrien 6860484Sobrien /* captured it. clear it now. */ 6960484Sobrien gdbm_errno = GDBM_NO_ERROR; 7060484Sobrien 7160484Sobrien return rv; 7260484Sobrien} 7360484Sobrien 7460484Sobrien/* -------------------------------------------------------------------------- 7560484Sobrien** 7660484Sobrien** DEFINE THE VTABLE FUNCTIONS FOR GDBM 7760484Sobrien*/ 7860484Sobrien 7960484Sobrienstatic apr_status_t vt_gdbm_open(apr_dbm_t **pdb, const char *pathname, 8060484Sobrien apr_int32_t mode, apr_fileperms_t perm, 8160484Sobrien apr_pool_t *pool) 8260484Sobrien{ 8360484Sobrien GDBM_FILE file; 8460484Sobrien int dbmode; 8560484Sobrien 8660484Sobrien *pdb = NULL; 8760484Sobrien 8860484Sobrien switch (mode) { 8960484Sobrien case APR_DBM_READONLY: 9060484Sobrien dbmode = APR_DBM_DBMODE_RO; 9160484Sobrien break; 9260484Sobrien case APR_DBM_READWRITE: 9360484Sobrien dbmode = APR_DBM_DBMODE_RW; 9460484Sobrien break; 9560484Sobrien case APR_DBM_RWCREATE: 9660484Sobrien dbmode = APR_DBM_DBMODE_RWCREATE; 9760484Sobrien break; 9860484Sobrien case APR_DBM_RWTRUNC: 9960484Sobrien dbmode = APR_DBM_DBMODE_RWTRUNC; 10060484Sobrien break; 10160484Sobrien default: 10260484Sobrien return APR_EINVAL; 10360484Sobrien } 10460484Sobrien 10560484Sobrien /* Note: stupid cast to get rid of "const" on the pathname */ 10660484Sobrien file = gdbm_open((char *) pathname, 0, dbmode, apr_posix_perms2mode(perm), 10760484Sobrien NULL); 10860484Sobrien 10960484Sobrien if (file == NULL) 11060484Sobrien return APR_EGENERAL; /* ### need a better error */ 11160484Sobrien 11260484Sobrien /* we have an open database... return it */ 11360484Sobrien *pdb = apr_pcalloc(pool, sizeof(**pdb)); 11460484Sobrien (*pdb)->pool = pool; 11560484Sobrien (*pdb)->type = &apr_dbm_type_gdbm; 116130561Sobrien (*pdb)->file = file; 11760484Sobrien 118130561Sobrien /* ### register a cleanup to close the DBM? */ 11960484Sobrien 12060484Sobrien return APR_SUCCESS; 12160484Sobrien} 12260484Sobrien 12360484Sobrienstatic void vt_gdbm_close(apr_dbm_t *dbm) 12460484Sobrien{ 12560484Sobrien gdbm_close(dbm->file); 12660484Sobrien} 12760484Sobrien 128130561Sobrienstatic apr_status_t vt_gdbm_fetch(apr_dbm_t *dbm, apr_datum_t key, 12960484Sobrien apr_datum_t *pvalue) 13060484Sobrien{ 13160484Sobrien datum kd, rd; 13260484Sobrien 13360484Sobrien kd.dptr = key.dptr; 13460484Sobrien kd.dsize = key.dsize; 13560484Sobrien 13660484Sobrien rd = gdbm_fetch(dbm->file, kd); 13760484Sobrien 13860484Sobrien pvalue->dptr = rd.dptr; 13960484Sobrien pvalue->dsize = rd.dsize; 14060484Sobrien 14160484Sobrien if (pvalue->dptr) 14260484Sobrien apr_pool_cleanup_register(dbm->pool, pvalue->dptr, datum_cleanup, 14360484Sobrien apr_pool_cleanup_null); 14460484Sobrien 14560484Sobrien /* store the error info into DBM, and return a status code. Also, note 14660484Sobrien that *pvalue should have been cleared on error. */ 14760484Sobrien return set_error(dbm, APR_SUCCESS); 14860484Sobrien} 14960484Sobrien 15060484Sobrienstatic apr_status_t vt_gdbm_store(apr_dbm_t *dbm, apr_datum_t key, 15160484Sobrien apr_datum_t value) 15260484Sobrien{ 15360484Sobrien int rc; 15460484Sobrien datum kd, vd; 15560484Sobrien 15660484Sobrien kd.dptr = key.dptr; 15760484Sobrien kd.dsize = key.dsize; 158130561Sobrien 15960484Sobrien vd.dptr = value.dptr; 160130561Sobrien vd.dsize = value.dsize; 16160484Sobrien 16260484Sobrien rc = gdbm_store(dbm->file, kd, vd, GDBM_REPLACE); 163130561Sobrien 16460484Sobrien /* store any error info into DBM, and return a status code. */ 16560484Sobrien return set_error(dbm, g2s(rc)); 16660484Sobrien} 16760484Sobrien 16860484Sobrienstatic apr_status_t vt_gdbm_del(apr_dbm_t *dbm, apr_datum_t key) 16960484Sobrien{ 17060484Sobrien int rc; 17160484Sobrien datum kd; 17260484Sobrien 17360484Sobrien kd.dptr = key.dptr; 17460484Sobrien kd.dsize = key.dsize; 17560484Sobrien 176130561Sobrien rc = gdbm_delete(dbm->file, kd); 177130561Sobrien 178130561Sobrien /* store any error info into DBM, and return a status code. */ 179130561Sobrien return set_error(dbm, g2s(rc)); 18060484Sobrien} 181130561Sobrien 18260484Sobrienstatic int vt_gdbm_exists(apr_dbm_t *dbm, apr_datum_t key) 18360484Sobrien{ 18460484Sobrien datum kd; 18560484Sobrien 18660484Sobrien kd.dptr = key.dptr; 18760484Sobrien kd.dsize = key.dsize; 18860484Sobrien 18960484Sobrien return gdbm_exists(dbm->file, kd) != 0; 19060484Sobrien} 19160484Sobrien 19260484Sobrienstatic apr_status_t vt_gdbm_firstkey(apr_dbm_t *dbm, apr_datum_t *pkey) 19360484Sobrien{ 19460484Sobrien datum rd; 19560484Sobrien 19660484Sobrien rd = gdbm_firstkey(dbm->file); 19760484Sobrien 19860484Sobrien pkey->dptr = rd.dptr; 19960484Sobrien pkey->dsize = rd.dsize; 20060484Sobrien 20160484Sobrien if (pkey->dptr) 20260484Sobrien apr_pool_cleanup_register(dbm->pool, pkey->dptr, datum_cleanup, 20360484Sobrien apr_pool_cleanup_null); 20460484Sobrien 20560484Sobrien /* store any error info into DBM, and return a status code. */ 20660484Sobrien return set_error(dbm, APR_SUCCESS); 20760484Sobrien} 20860484Sobrien 20960484Sobrienstatic apr_status_t vt_gdbm_nextkey(apr_dbm_t *dbm, apr_datum_t *pkey) 21060484Sobrien{ 21160484Sobrien datum kd, rd; 21260484Sobrien 21360484Sobrien kd.dptr = pkey->dptr; 21460484Sobrien kd.dsize = pkey->dsize; 21560484Sobrien 21660484Sobrien rd = gdbm_nextkey(dbm->file, kd); 21760484Sobrien 21860484Sobrien pkey->dptr = rd.dptr; 21960484Sobrien pkey->dsize = rd.dsize; 22060484Sobrien 22160484Sobrien if (pkey->dptr) 22260484Sobrien apr_pool_cleanup_register(dbm->pool, pkey->dptr, datum_cleanup, 22360484Sobrien apr_pool_cleanup_null); 22460484Sobrien 22560484Sobrien /* store any error info into DBM, and return a status code. */ 22660484Sobrien return set_error(dbm, APR_SUCCESS); 22760484Sobrien} 22860484Sobrien 22960484Sobrienstatic void vt_gdbm_freedatum(apr_dbm_t *dbm, apr_datum_t data) 23060484Sobrien{ 23160484Sobrien (void) apr_pool_cleanup_run(dbm->pool, data.dptr, datum_cleanup); 23260484Sobrien} 23360484Sobrien 23460484Sobrienstatic void vt_gdbm_usednames(apr_pool_t *pool, const char *pathname, 23560484Sobrien const char **used1, const char **used2) 23660484Sobrien{ 23760484Sobrien *used1 = apr_pstrdup(pool, pathname); 23860484Sobrien *used2 = NULL; 23960484Sobrien} 24060484Sobrien 24160484SobrienAPU_MODULE_DECLARE_DATA const apr_dbm_type_t apr_dbm_type_gdbm = { 24260484Sobrien "gdbm", 24360484Sobrien vt_gdbm_open, 24460484Sobrien vt_gdbm_close, 24560484Sobrien vt_gdbm_fetch, 24660484Sobrien vt_gdbm_store, 24760484Sobrien vt_gdbm_del, 24860484Sobrien vt_gdbm_exists, 24960484Sobrien vt_gdbm_firstkey, 25060484Sobrien vt_gdbm_nextkey, 25160484Sobrien vt_gdbm_freedatum, 25260484Sobrien vt_gdbm_usednames 25360484Sobrien}; 254 255#endif /* APU_HAVE_GDBM */ 256