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 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 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. 15 */ 16 17#include "apr_strings.h" 18 19#if APR_HAVE_STDLIB_H 20#include <stdlib.h> /* for free() */ 21#endif 22 23#include "apu_config.h" 24#include "apu.h" 25 26#if APU_HAVE_NDBM 27#include "apr_dbm_private.h" 28 29#include <ndbm.h> 30#include <sys/types.h> 31#include <sys/stat.h> 32#include <fcntl.h> 33 34#define APR_DBM_DBMODE_RO O_RDONLY 35#define APR_DBM_DBMODE_RW O_RDWR 36#define APR_DBM_DBMODE_RWCREATE (O_RDWR|O_CREAT) 37#define APR_DBM_DBMODE_RWTRUNC (O_RDWR|O_CREAT|O_TRUNC) 38 39/* map a NDBM error to an apr_status_t */ 40static apr_status_t ndbm2s(int ndbmerr) 41{ 42 if (ndbmerr == -1) { 43 /* ### need to fix this */ 44 return APR_EGENERAL; 45 } 46 47 return APR_SUCCESS; 48} 49 50static apr_status_t set_error(apr_dbm_t *dbm, apr_status_t dbm_said) 51{ 52 apr_status_t rv = APR_SUCCESS; 53 54 /* ### ignore whatever the DBM said (dbm_said); ask it explicitly */ 55 56 dbm->errmsg = NULL; 57 if (dbm_error((DBM*)dbm->file)) { 58 dbm->errmsg = NULL; 59 rv = APR_EGENERAL; /* ### need something better */ 60 } 61 62 /* captured it. clear it now. */ 63 dbm_clearerr((DBM*)dbm->file); 64 65 return rv; 66} 67 68/* -------------------------------------------------------------------------- 69** 70** DEFINE THE VTABLE FUNCTIONS FOR NDBM 71*/ 72 73static apr_status_t vt_ndbm_open(apr_dbm_t **pdb, const char *pathname, 74 apr_int32_t mode, apr_fileperms_t perm, 75 apr_pool_t *pool) 76{ 77 DBM *file; 78 int dbmode; 79 80 *pdb = NULL; 81 82 switch (mode) { 83 case APR_DBM_READONLY: 84 dbmode = APR_DBM_DBMODE_RO; 85 break; 86 case APR_DBM_READWRITE: 87 dbmode = APR_DBM_DBMODE_RW; 88 break; 89 case APR_DBM_RWCREATE: 90 dbmode = APR_DBM_DBMODE_RWCREATE; 91 break; 92 case APR_DBM_RWTRUNC: 93 dbmode = APR_DBM_DBMODE_RWTRUNC; 94 break; 95 default: 96 return APR_EINVAL; 97 } 98 99 { 100 file = dbm_open(pathname, dbmode, apr_posix_perms2mode(perm)); 101 if (file == NULL) 102 return APR_EGENERAL; /* ### need a better error */ 103 } 104 105 /* we have an open database... return it */ 106 *pdb = apr_pcalloc(pool, sizeof(**pdb)); 107 (*pdb)->pool = pool; 108 (*pdb)->type = &apr_dbm_type_ndbm; 109 (*pdb)->file = file; 110 111 /* ### register a cleanup to close the DBM? */ 112 113 return APR_SUCCESS; 114} 115 116static void vt_ndbm_close(apr_dbm_t *dbm) 117{ 118 dbm_close(dbm->file); 119} 120 121static apr_status_t vt_ndbm_fetch(apr_dbm_t *dbm, apr_datum_t key, 122 apr_datum_t *pvalue) 123{ 124 datum kd, rd; 125 126 kd.dptr = key.dptr; 127 kd.dsize = key.dsize; 128 129 rd = dbm_fetch(dbm->file, kd); 130 131 pvalue->dptr = rd.dptr; 132 pvalue->dsize = rd.dsize; 133 134 /* store the error info into DBM, and return a status code. Also, note 135 that *pvalue should have been cleared on error. */ 136 return set_error(dbm, APR_SUCCESS); 137} 138 139static apr_status_t vt_ndbm_store(apr_dbm_t *dbm, apr_datum_t key, 140 apr_datum_t value) 141{ 142 int rc; 143 datum kd, vd; 144 145 kd.dptr = key.dptr; 146 kd.dsize = key.dsize; 147 148 vd.dptr = value.dptr; 149 vd.dsize = value.dsize; 150 151 rc = dbm_store(dbm->file, kd, vd, DBM_REPLACE); 152 153 /* store any error info into DBM, and return a status code. */ 154 return set_error(dbm, ndbm2s(rc)); 155} 156 157static apr_status_t vt_ndbm_del(apr_dbm_t *dbm, apr_datum_t key) 158{ 159 int rc; 160 datum kd; 161 162 kd.dptr = key.dptr; 163 kd.dsize = key.dsize; 164 165 rc = dbm_delete(dbm->file, kd); 166 167 /* store any error info into DBM, and return a status code. */ 168 return set_error(dbm, ndbm2s(rc)); 169} 170 171static int vt_ndbm_exists(apr_dbm_t *dbm, apr_datum_t key) 172{ 173 datum kd, rd; 174 175 kd.dptr = key.dptr; 176 kd.dsize = key.dsize; 177 178 rd = dbm_fetch(dbm->file, kd); 179 180 return rd.dptr != NULL; 181} 182 183static apr_status_t vt_ndbm_firstkey(apr_dbm_t *dbm, apr_datum_t *pkey) 184{ 185 datum rd; 186 187 rd = dbm_firstkey(dbm->file); 188 189 pkey->dptr = rd.dptr; 190 pkey->dsize = rd.dsize; 191 192 /* store any error info into DBM, and return a status code. */ 193 return set_error(dbm, APR_SUCCESS); 194} 195 196static apr_status_t vt_ndbm_nextkey(apr_dbm_t *dbm, apr_datum_t *pkey) 197{ 198 datum kd, rd; 199 200 kd.dptr = pkey->dptr; 201 kd.dsize = pkey->dsize; 202 203 rd = dbm_nextkey(dbm->file); 204 205 pkey->dptr = rd.dptr; 206 pkey->dsize = rd.dsize; 207 208 /* store any error info into DBM, and return a status code. */ 209 return set_error(dbm, APR_SUCCESS); 210} 211 212static void vt_ndbm_freedatum(apr_dbm_t *dbm, apr_datum_t data) 213{ 214 /* nothing to do */ 215} 216 217static void vt_ndbm_usednames(apr_pool_t *pool, const char *pathname, 218 const char **used1, const char **used2) 219{ 220 *used1 = apr_pstrdup(pool, pathname); 221 *used2 = NULL; 222} 223 224APU_MODULE_DECLARE_DATA const apr_dbm_type_t apr_dbm_type_ndbm = { 225 "ndbm", 226 vt_ndbm_open, 227 vt_ndbm_close, 228 vt_ndbm_fetch, 229 vt_ndbm_store, 230 vt_ndbm_del, 231 vt_ndbm_exists, 232 vt_ndbm_firstkey, 233 vt_ndbm_nextkey, 234 vt_ndbm_freedatum, 235 vt_ndbm_usednames 236}; 237 238#endif /* APU_HAVE_NDBM */ 239