2 * See the file LICENSE for redistribution information.
4 * Copyright (c) 1996-2009 Oracle. All rights reserved.
7 * Copyright (c) 1990, 1993
8 * Margo Seltzer. All rights reserved.
11 * Copyright (c) 1990, 1993
12 * The Regents of the University of California. All rights reserved.
14 * This code is derived from software contributed to Berkeley by
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions
20 * 1. Redistributions of source code must retain the above copyright
21 * notice, this list of conditions and the following disclaimer.
22 * 2. Redistributions in binary form must reproduce the above copyright
23 * notice, this list of conditions and the following disclaimer in the
24 * documentation and/or other materials provided with the distribution.
25 * 3. Neither the name of the University nor the names of its contributors
26 * may be used to endorse or promote products derived from this software
27 * without specific prior written permission.
29 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
30 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
31 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
32 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
33 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
34 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
35 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
37 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
38 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
44 #define DB_DBM_HSEARCH 1
45 #include "db_config.h"
51 * This package provides dbm and ndbm compatible interfaces to DB.
53 * EXTERN: #if DB_DBM_HSEARCH != 0
55 * EXTERN: int __db_ndbm_clearerr __P((DBM *));
56 * EXTERN: void __db_ndbm_close __P((DBM *));
57 * EXTERN: int __db_ndbm_delete __P((DBM *, datum));
58 * EXTERN: int __db_ndbm_dirfno __P((DBM *));
59 * EXTERN: int __db_ndbm_error __P((DBM *));
60 * EXTERN: datum __db_ndbm_fetch __P((DBM *, datum));
61 * EXTERN: datum __db_ndbm_firstkey __P((DBM *));
62 * EXTERN: datum __db_ndbm_nextkey __P((DBM *));
63 * EXTERN: DBM *__db_ndbm_open __P((const char *, int, int));
64 * EXTERN: int __db_ndbm_pagfno __P((DBM *));
65 * EXTERN: int __db_ndbm_rdonly __P((DBM *));
66 * EXTERN: int __db_ndbm_store __P((DBM *, datum, datum, int));
68 * EXTERN: int __db_dbm_close __P((void));
69 * EXTERN: int __db_dbm_delete __P((datum));
70 * EXTERN: datum __db_dbm_fetch __P((datum));
71 * EXTERN: datum __db_dbm_firstkey __P((void));
72 * EXTERN: int __db_dbm_init __P((char *));
73 * EXTERN: datum __db_dbm_nextkey __P((datum));
74 * EXTERN: int __db_dbm_store __P((datum, datum));
80 * The DBM routines, which call the NDBM routines.
84 static void __db_no_open __P((void));
92 if ((__cur_db = dbm_open(file, O_CREAT | O_RDWR, DB_MODE_600)) != NULL)
94 if ((__cur_db = dbm_open(file, O_RDONLY, 0)) != NULL)
102 if (__cur_db != NULL) {
115 if (__cur_db == NULL) {
121 return (dbm_fetch(__cur_db, key));
129 if (__cur_db == NULL) {
135 return (dbm_firstkey(__cur_db));
139 __db_dbm_nextkey(key)
144 COMPQUIET(key.dsize, 0);
146 if (__cur_db == NULL) {
152 return (dbm_nextkey(__cur_db));
159 if (__cur_db == NULL) {
163 return (dbm_delete(__cur_db, key));
167 __db_dbm_store(key, dat)
170 if (__cur_db == NULL) {
174 return (dbm_store(__cur_db, key, dat, DBM_REPLACE));
180 (void)fprintf(stderr, "dbm: no open database.\n");
184 * This package provides dbm and ndbm compatible interfaces to DB.
186 * The NDBM routines, which call the DB routines.
194 __db_ndbm_open(file, oflags, mode)
201 char path[DB_MAXPATHLEN];
205 * Don't use sprintf(3)/snprintf(3) -- the former is dangerous, and
206 * the latter isn't standard, and we're manipulating strings handed
207 * us by the application.
209 if (strlen(file) + strlen(DBM_SUFFIX) + 1 > sizeof(path)) {
210 __os_set_errno(ENAMETOOLONG);
213 (void)strcpy(path, file);
214 (void)strcat(path, DBM_SUFFIX);
215 if ((ret = db_create(&dbp, NULL, 0)) != 0) {
222 * The historic ndbm library corrected for opening O_WRONLY.
224 if (oflags & O_WRONLY) {
229 if ((ret = dbp->set_pagesize(dbp, 4096)) != 0 ||
230 (ret = dbp->set_h_ffactor(dbp, 40)) != 0 ||
231 (ret = dbp->set_h_nelem(dbp, 1)) != 0 ||
232 (ret = dbp->open(dbp, NULL,
233 path, NULL, DB_HASH, __db_openflags(oflags), mode)) != 0) {
238 if ((ret = dbp->cursor(dbp, NULL, &dbc, 0)) != 0) {
239 (void)dbp->close(dbp, 0);
259 (void)dbc->dbp->close(dbc->dbp, 0);
268 __db_ndbm_fetch(dbm, key)
279 DB_INIT_DBT(_key, key.dptr, key.dsize);
280 memset(&_data, 0, sizeof(DBT));
283 * Note that we can't simply use the dbc we have to do a get/SET,
284 * because that cursor is the one used for sequential iteration and
285 * it has to remain stable in the face of intervening gets and puts.
287 if ((ret = dbc->dbp->get(dbc->dbp, NULL, &_key, &_data, 0)) == 0) {
288 data.dptr = _data.data;
289 data.dsize = (int)_data.size;
293 if (ret == DB_NOTFOUND)
294 __os_set_errno(ENOENT);
297 F_SET(dbc->dbp, DB_AM_DBM_ERROR);
309 __db_ndbm_firstkey(dbm)
319 memset(&_key, 0, sizeof(DBT));
320 memset(&_data, 0, sizeof(DBT));
322 if ((ret = dbc->get(dbc, &_key, &_data, DB_FIRST)) == 0) {
323 key.dptr = _key.data;
324 key.dsize = (int)_key.size;
328 if (ret == DB_NOTFOUND)
329 __os_set_errno(ENOENT);
332 F_SET(dbc->dbp, DB_AM_DBM_ERROR);
344 __db_ndbm_nextkey(dbm)
354 memset(&_key, 0, sizeof(DBT));
355 memset(&_data, 0, sizeof(DBT));
357 if ((ret = dbc->get(dbc, &_key, &_data, DB_NEXT)) == 0) {
358 key.dptr = _key.data;
359 key.dsize = (int)_key.size;
363 if (ret == DB_NOTFOUND)
364 __os_set_errno(ENOENT);
367 F_SET(dbc->dbp, DB_AM_DBM_ERROR);
379 __db_ndbm_delete(dbm, key)
389 DB_INIT_DBT(_key, key.dptr, key.dsize);
391 if ((ret = dbc->dbp->del(dbc->dbp, NULL, &_key, 0)) == 0)
394 if (ret == DB_NOTFOUND)
395 __os_set_errno(ENOENT);
398 F_SET(dbc->dbp, DB_AM_DBM_ERROR);
407 * 1 if DBM_INSERT and entry exists
410 __db_ndbm_store(dbm, key, data, flags)
421 DB_INIT_DBT(_key, key.dptr, key.dsize);
422 DB_INIT_DBT(_data, data.dptr, data.dsize);
424 if ((ret = dbc->dbp->put(dbc->dbp, NULL,
425 &_key, &_data, flags == DBM_INSERT ? DB_NOOVERWRITE : 0)) == 0)
428 if (ret == DB_KEYEXIST)
432 F_SET(dbc->dbp, DB_AM_DBM_ERROR);
444 return (F_ISSET(dbc->dbp, DB_AM_DBM_ERROR));
448 __db_ndbm_clearerr(dbm)
455 F_CLR(dbc->dbp, DB_AM_DBM_ERROR);
465 __db_ndbm_rdonly(dbm)
472 return (F_ISSET(dbc->dbp, DB_AM_RDONLY) ? 1 : 0);
477 * We only have a single file descriptor that we can return, not two. Return
478 * the same one for both files. Hopefully, the user is using it for locking
479 * and picked one to use at random.
482 __db_ndbm_dirfno(dbm)
485 return (dbm_pagfno(dbm));
489 __db_ndbm_pagfno(dbm)
497 (void)dbc->dbp->fd(dbc->dbp, &fd);