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