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(file) 73 char *file; 74 { 75 if (__cur_db != NULL) 76 (void)kdb2_dbm_close(__cur_db); 77 if ((__cur_db = kdb2_dbm_open(file, O_RDWR|O_BINARY, 0)) != NULL) 78 return (0); 79 if ((__cur_db = kdb2_dbm_open(file, O_RDONLY|O_BINARY, 0)) != NULL) 80 return (0); 81 return (-1); 82 } 83 84 datum 85 kdb2_fetch(key) 86 datum key; 87 { 88 datum item; 89 90 if (__cur_db == NULL) { 91 no_open_db(); 92 item.dptr = 0; 93 item.dsize = 0; 94 return (item); 95 } 96 return (kdb2_dbm_fetch(__cur_db, key)); 97 } 98 99 datum 100 kdb2_firstkey() 101 { 102 datum item; 103 104 if (__cur_db == NULL) { 105 no_open_db(); 106 item.dptr = 0; 107 item.dsize = 0; 108 return (item); 109 } 110 return (kdb2_dbm_firstkey(__cur_db)); 111 } 112 113 datum 114 kdb2_nextkey(key) 115 datum key; 116 { 117 datum item; 118 119 if (__cur_db == NULL) { 120 no_open_db(); 121 item.dptr = 0; 122 item.dsize = 0; 123 return (item); 124 } 125 return (kdb2_dbm_nextkey(__cur_db)); 126 } 127 128 int 129 kdb2_delete(key) 130 datum key; 131 { 132 if (__cur_db == NULL) { 133 no_open_db(); 134 return (-1); 135 } 136 return (kdb2_dbm_delete(__cur_db, key)); 137 } 138 139 int 140 kdb2_store(key, dat) 141 datum key, dat; 142 { 143 if (__cur_db == NULL) { 144 no_open_db(); 145 return (-1); 146 } 147 return (kdb2_dbm_store(__cur_db, key, dat, DBM_REPLACE)); 148 } 149 150 static void 151 no_open_db() 152 { 153 (void)fprintf(stderr, "dbm: no open database.\n"); 154 } 155 156 /* 157 * Returns: 158 * *DBM on success 159 * NULL on failure 160 */ 161 DBM * 162 kdb2_dbm_open(file, flags, mode) 163 const char *file; 164 int flags, mode; 165 { 166 HASHINFO info; 167 char path[MAXPATHLEN]; 168 169 info.bsize = 4096; 170 info.ffactor = 40; 171 info.nelem = 1; 172 info.cachesize = 0; 173 info.hash = NULL; 174 info.lorder = 0; 175 (void)strncpy(path, file, sizeof(path) - 1); 176 path[sizeof(path) - 1] = '\0'; 177 (void)strncat(path, DBM_SUFFIX, sizeof(path) - 1 - strlen(path)); 178 return ((DBM *)__hash_open(path, flags, mode, &info, 0)); 179 } 180 181 /* 182 * Returns: 183 * Nothing. 184 */ 185 void 186 kdb2_dbm_close(db) 187 DBM *db; 188 { 189 (void)(db->close)(db); 190 } 191 192 /* 193 * Returns: 194 * DATUM on success 195 * NULL on failure 196 */ 197 datum 198 kdb2_dbm_fetch(db, key) 199 DBM *db; 200 datum key; 201 { 202 datum retval; 203 int status; 204 205 #ifdef NEED_COPY 206 DBT k, r; 207 208 k.data = key.dptr; 209 k.size = key.dsize; 210 status = (db->get)(db, &k, &r, 0); 211 retval.dptr = r.data; 212 retval.dsize = r.size; 213 #else 214 status = (db->get)(db, (DBT *)&key, (DBT *)&retval, 0); 215 #endif 216 if (status) { 217 retval.dptr = NULL; 218 retval.dsize = 0; 219 } 220 return (retval); 221 } 222 223 /* 224 * Returns: 225 * DATUM on success 226 * NULL on failure 227 */ 228 datum 229 kdb2_dbm_firstkey(db) 230 DBM *db; 231 { 232 int status; 233 datum retkey; 234 235 #ifdef NEED_COPY 236 DBT k, r; 237 238 status = (db->seq)(db, &k, &r, R_FIRST); 239 retkey.dptr = k.data; 240 retkey.dsize = k.size; 241 #else 242 datum retdata; 243 244 status = (db->seq)(db, (DBT *)&retkey, (DBT *)&retdata, R_FIRST); 245 #endif 246 if (status) 247 retkey.dptr = NULL; 248 return (retkey); 249 } 250 251 /* 252 * Returns: 253 * DATUM on success 254 * NULL on failure 255 */ 256 datum 257 kdb2_dbm_nextkey(db) 258 DBM *db; 259 { 260 int status; 261 datum retkey; 262 263 #ifdef NEED_COPY 264 DBT k, r; 265 266 status = (db->seq)(db, &k, &r, R_NEXT); 267 retkey.dptr = k.data; 268 retkey.dsize = k.size; 269 #else 270 datum retdata; 271 272 status = (db->seq)(db, (DBT *)&retkey, (DBT *)&retdata, R_NEXT); 273 #endif 274 if (status) 275 retkey.dptr = NULL; 276 return (retkey); 277 } 278 279 /* 280 * Returns: 281 * 0 on success 282 * <0 failure 283 */ 284 int 285 kdb2_dbm_delete(db, key) 286 DBM *db; 287 datum key; 288 { 289 int status; 290 291 #ifdef NEED_COPY 292 DBT k; 293 294 k.data = key.dptr; 295 k.size = key.dsize; 296 status = (db->del)(db, &k, 0); 297 #else 298 status = (db->del)(db, (DBT *)&key, 0); 299 #endif 300 if (status) 301 return (-1); 302 else 303 return (0); 304 } 305 306 /* 307 * Returns: 308 * 0 on success 309 * <0 failure 310 * 1 if DBM_INSERT and entry exists 311 */ 312 int 313 kdb2_dbm_store(db, key, content, flags) 314 DBM *db; 315 datum key, content; 316 int flags; 317 { 318 #ifdef NEED_COPY 319 DBT k, c; 320 321 k.data = key.dptr; 322 k.size = key.dsize; 323 c.data = content.dptr; 324 c.size = content.dsize; 325 return ((db->put)(db, &k, &c, 326 (flags == DBM_INSERT) ? R_NOOVERWRITE : 0)); 327 #else 328 return ((db->put)(db, (DBT *)&key, (DBT *)&content, 329 (flags == DBM_INSERT) ? R_NOOVERWRITE : 0)); 330 #endif 331 } 332 333 int 334 kdb2_dbm_error(db) 335 DBM *db; 336 { 337 HTAB *hp; 338 339 hp = (HTAB *)db->internal; 340 return (hp->local_errno); 341 } 342 343 int 344 kdb2_dbm_clearerr(db) 345 DBM *db; 346 { 347 HTAB *hp; 348 349 hp = (HTAB *)db->internal; 350 hp->local_errno = 0; 351 return (0); 352 } 353 354 int 355 kdb2_dbm_dirfno(db) 356 DBM *db; 357 { 358 return(((HTAB *)db->internal)->fp); 359 } 360