1 /*- 2 * Copyright (c) 1990, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Margo Seltzer. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by the University of 19 * California, Berkeley and its contributors. 20 * 4. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 */ 36 37 #if defined(LIBC_SCCS) && !defined(lint) 38 static char sccsid[] = "@(#)dbm.c 8.6 (Berkeley) 11/7/95"; 39 #endif /* LIBC_SCCS and not lint */ 40 41 #include "db-int.h" 42 43 #include <sys/param.h> 44 45 #include <fcntl.h> 46 #include <stdio.h> 47 #include <string.h> 48 49 #include "db-ndbm.h" 50 #include "db-dbm.h" 51 #include "hash.h" 52 53 /* If the two size fields of datum and DBMT are not equal, then 54 * casting between structures will result in stack garbage being 55 * transferred. Has been observed for DEC Alpha OSF, but will handle 56 * the general case. 57 */ 58 59 #define NEED_COPY 60 61 /* 62 * 63 * This package provides dbm and ndbm compatible interfaces to DB. 64 * First are the DBM routines, which call the NDBM routines, and 65 * the NDBM routines, which call the DB routines. 66 */ 67 static DBM *__cur_db; 68 69 static void no_open_db __P((void)); 70 71 int 72 kdb2_dbminit(char *file) 73 { 74 if (__cur_db != NULL) 75 (void)kdb2_dbm_close(__cur_db); 76 if ((__cur_db = kdb2_dbm_open(file, O_RDWR|O_BINARY, 0)) != NULL) 77 return (0); 78 if ((__cur_db = kdb2_dbm_open(file, O_RDONLY|O_BINARY, 0)) != NULL) 79 return (0); 80 return (-1); 81 } 82 83 datum 84 kdb2_fetch(datum key) 85 { 86 datum item; 87 88 if (__cur_db == NULL) { 89 no_open_db(); 90 item.dptr = 0; 91 item.dsize = 0; 92 return (item); 93 } 94 return (kdb2_dbm_fetch(__cur_db, key)); 95 } 96 97 datum 98 kdb2_firstkey(void) 99 { 100 datum item; 101 102 if (__cur_db == NULL) { 103 no_open_db(); 104 item.dptr = 0; 105 item.dsize = 0; 106 return (item); 107 } 108 return (kdb2_dbm_firstkey(__cur_db)); 109 } 110 111 datum 112 kdb2_nextkey(datum key) 113 { 114 datum item; 115 116 if (__cur_db == NULL) { 117 no_open_db(); 118 item.dptr = 0; 119 item.dsize = 0; 120 return (item); 121 } 122 return (kdb2_dbm_nextkey(__cur_db)); 123 } 124 125 int 126 kdb2_delete(datum key) 127 { 128 if (__cur_db == NULL) { 129 no_open_db(); 130 return (-1); 131 } 132 return (kdb2_dbm_delete(__cur_db, key)); 133 } 134 135 int 136 kdb2_store(datum key, datum dat) 137 { 138 if (__cur_db == NULL) { 139 no_open_db(); 140 return (-1); 141 } 142 return (kdb2_dbm_store(__cur_db, key, dat, DBM_REPLACE)); 143 } 144 145 static void 146 no_open_db(void) 147 { 148 (void)fprintf(stderr, "dbm: no open database.\n"); 149 } 150 151 /* 152 * Returns: 153 * *DBM on success 154 * NULL on failure 155 */ 156 DBM * 157 kdb2_dbm_open(const char *file, int flags, int mode) 158 { 159 HASHINFO info; 160 char path[MAXPATHLEN]; 161 162 info.bsize = 4096; 163 info.ffactor = 40; 164 info.nelem = 1; 165 info.cachesize = 0; 166 info.hash = NULL; 167 info.lorder = 0; 168 (void)strncpy(path, file, sizeof(path) - 1); 169 path[sizeof(path) - 1] = '\0'; 170 (void)strncat(path, DBM_SUFFIX, sizeof(path) - 1 - strlen(path)); 171 return ((DBM *)__hash_open(path, flags, mode, &info, 0)); 172 } 173 174 /* 175 * Returns: 176 * Nothing. 177 */ 178 void 179 kdb2_dbm_close(DBM *db) 180 { 181 (void)(db->close)(db); 182 } 183 184 /* 185 * Returns: 186 * DATUM on success 187 * NULL on failure 188 */ 189 datum 190 kdb2_dbm_fetch(DBM *db, datum key) 191 { 192 datum retval; 193 int status; 194 195 #ifdef NEED_COPY 196 DBT k, r; 197 198 k.data = key.dptr; 199 k.size = key.dsize; 200 status = (db->get)(db, &k, &r, 0); 201 retval.dptr = r.data; 202 retval.dsize = r.size; 203 #else 204 status = (db->get)(db, (DBT *)&key, (DBT *)&retval, 0); 205 #endif 206 if (status) { 207 retval.dptr = NULL; 208 retval.dsize = 0; 209 } 210 return (retval); 211 } 212 213 /* 214 * Returns: 215 * DATUM on success 216 * NULL on failure 217 */ 218 datum 219 kdb2_dbm_firstkey(DBM *db) 220 { 221 int status; 222 datum retkey; 223 224 #ifdef NEED_COPY 225 DBT k, r; 226 227 status = (db->seq)(db, &k, &r, R_FIRST); 228 retkey.dptr = k.data; 229 retkey.dsize = k.size; 230 #else 231 datum retdata; 232 233 status = (db->seq)(db, (DBT *)&retkey, (DBT *)&retdata, R_FIRST); 234 #endif 235 if (status) 236 retkey.dptr = NULL; 237 return (retkey); 238 } 239 240 /* 241 * Returns: 242 * DATUM on success 243 * NULL on failure 244 */ 245 datum 246 kdb2_dbm_nextkey(DBM *db) 247 { 248 int status; 249 datum retkey; 250 251 #ifdef NEED_COPY 252 DBT k, r; 253 254 status = (db->seq)(db, &k, &r, R_NEXT); 255 retkey.dptr = k.data; 256 retkey.dsize = k.size; 257 #else 258 datum retdata; 259 260 status = (db->seq)(db, (DBT *)&retkey, (DBT *)&retdata, R_NEXT); 261 #endif 262 if (status) 263 retkey.dptr = NULL; 264 return (retkey); 265 } 266 267 /* 268 * Returns: 269 * 0 on success 270 * <0 failure 271 */ 272 int 273 kdb2_dbm_delete(DBM *db, datum key) 274 { 275 int status; 276 277 #ifdef NEED_COPY 278 DBT k; 279 280 k.data = key.dptr; 281 k.size = key.dsize; 282 status = (db->del)(db, &k, 0); 283 #else 284 status = (db->del)(db, (DBT *)&key, 0); 285 #endif 286 if (status) 287 return (-1); 288 else 289 return (0); 290 } 291 292 /* 293 * Returns: 294 * 0 on success 295 * <0 failure 296 * 1 if DBM_INSERT and entry exists 297 */ 298 int 299 kdb2_dbm_store(DBM *db, datum key, datum content, int flags) 300 { 301 #ifdef NEED_COPY 302 DBT k, c; 303 304 k.data = key.dptr; 305 k.size = key.dsize; 306 c.data = content.dptr; 307 c.size = content.dsize; 308 return ((db->put)(db, &k, &c, 309 (flags == DBM_INSERT) ? R_NOOVERWRITE : 0)); 310 #else 311 return ((db->put)(db, (DBT *)&key, (DBT *)&content, 312 (flags == DBM_INSERT) ? R_NOOVERWRITE : 0)); 313 #endif 314 } 315 316 int 317 kdb2_dbm_error(DBM *db) 318 { 319 HTAB *hp; 320 321 hp = (HTAB *)db->internal; 322 return (hp->local_errno); 323 } 324 325 int 326 kdb2_dbm_clearerr(DBM *db) 327 { 328 HTAB *hp; 329 330 hp = (HTAB *)db->internal; 331 hp->local_errno = 0; 332 return (0); 333 } 334 335 int 336 kdb2_dbm_dirfno(DBM *db) 337 { 338 return(((HTAB *)db->internal)->fp); 339 } 340