Main Page | Class Hierarchy | Data Structures | Directories | File List | Data Fields | Related Pages

dbm.c

00001 /*-
00002  * See the file LICENSE for redistribution information.
00003  *
00004  * Copyright (c) 1996-2005
00005  *      Sleepycat Software.  All rights reserved.
00006  */
00007 /*
00008  * Copyright (c) 1990, 1993
00009  *      Margo Seltzer.  All rights reserved.
00010  */
00011 /*
00012  * Copyright (c) 1990, 1993
00013  *      The Regents of the University of California.  All rights reserved.
00014  *
00015  * This code is derived from software contributed to Berkeley by
00016  * Margo Seltzer.
00017  *
00018  * Redistribution and use in source and binary forms, with or without
00019  * modification, are permitted provided that the following conditions
00020  * are met:
00021  * 1. Redistributions of source code must retain the above copyright
00022  *    notice, this list of conditions and the following disclaimer.
00023  * 2. Redistributions in binary form must reproduce the above copyright
00024  *    notice, this list of conditions and the following disclaimer in the
00025  *    documentation and/or other materials provided with the distribution.
00026  * 3. Neither the name of the University nor the names of its contributors
00027  *    may be used to endorse or promote products derived from this software
00028  *    without specific prior written permission.
00029  *
00030  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
00031  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00032  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00033  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
00034  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00035  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00036  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00037  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00038  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00039  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00040  * SUCH DAMAGE.
00041  *
00042  * $Id: dbm.c,v 12.2 2005/06/16 20:21:49 bostic Exp $
00043  */
00044 
00045 #include "db_config.h"
00046 
00047 #ifndef NO_SYSTEM_INCLUDES
00048 #include <sys/types.h>
00049 
00050 #include <fcntl.h>
00051 #include <string.h>
00052 #endif
00053 
00054 #define DB_DBM_HSEARCH  1
00055 #include "db_int.h"
00056 
00057 /*
00058  *
00059  * This package provides dbm and ndbm compatible interfaces to DB.
00060  *
00061  * EXTERN: #if DB_DBM_HSEARCH != 0
00062  *
00063  * EXTERN: int   __db_ndbm_clearerr __P((DBM *));
00064  * EXTERN: void  __db_ndbm_close __P((DBM *));
00065  * EXTERN: int   __db_ndbm_delete __P((DBM *, datum));
00066  * EXTERN: int   __db_ndbm_dirfno __P((DBM *));
00067  * EXTERN: int   __db_ndbm_error __P((DBM *));
00068  * EXTERN: datum __db_ndbm_fetch __P((DBM *, datum));
00069  * EXTERN: datum __db_ndbm_firstkey __P((DBM *));
00070  * EXTERN: datum __db_ndbm_nextkey __P((DBM *));
00071  * EXTERN: DBM  *__db_ndbm_open __P((const char *, int, int));
00072  * EXTERN: int   __db_ndbm_pagfno __P((DBM *));
00073  * EXTERN: int   __db_ndbm_rdonly __P((DBM *));
00074  * EXTERN: int   __db_ndbm_store __P((DBM *, datum, datum, int));
00075  *
00076  * EXTERN: int   __db_dbm_close __P((void));
00077  * EXTERN: int   __db_dbm_delete __P((datum));
00078  * EXTERN: datum __db_dbm_fetch __P((datum));
00079  * EXTERN: datum __db_dbm_firstkey __P((void));
00080  * EXTERN: int   __db_dbm_init __P((char *));
00081  * EXTERN: datum __db_dbm_nextkey __P((datum));
00082  * EXTERN: int   __db_dbm_store __P((datum, datum));
00083  *
00084  * EXTERN: #endif
00085  */
00086 
00087 /*
00088  * The DBM routines, which call the NDBM routines.
00089  */
00090 static DBM *__cur_db;
00091 
00092 static void __db_no_open __P((void));
00093 
00094 int
00095 __db_dbm_init(file)
00096         char *file;
00097 {
00098         if (__cur_db != NULL)
00099                 dbm_close(__cur_db);
00100         if ((__cur_db =
00101             dbm_open(file, O_CREAT | O_RDWR, __db_omode(OWNER_RW))) != NULL)
00102                 return (0);
00103         if ((__cur_db = dbm_open(file, O_RDONLY, 0)) != NULL)
00104                 return (0);
00105         return (-1);
00106 }
00107 
00108 int
00109 __db_dbm_close()
00110 {
00111         if (__cur_db != NULL) {
00112                 dbm_close(__cur_db);
00113                 __cur_db = NULL;
00114         }
00115         return (0);
00116 }
00117 
00118 datum
00119 __db_dbm_fetch(key)
00120         datum key;
00121 {
00122         datum item;
00123 
00124         if (__cur_db == NULL) {
00125                 __db_no_open();
00126                 item.dptr = NULL;
00127                 item.dsize = 0;
00128                 return (item);
00129         }
00130         return (dbm_fetch(__cur_db, key));
00131 }
00132 
00133 datum
00134 __db_dbm_firstkey()
00135 {
00136         datum item;
00137 
00138         if (__cur_db == NULL) {
00139                 __db_no_open();
00140                 item.dptr = NULL;
00141                 item.dsize = 0;
00142                 return (item);
00143         }
00144         return (dbm_firstkey(__cur_db));
00145 }
00146 
00147 datum
00148 __db_dbm_nextkey(key)
00149         datum key;
00150 {
00151         datum item;
00152 
00153         COMPQUIET(key.dsize, 0);
00154 
00155         if (__cur_db == NULL) {
00156                 __db_no_open();
00157                 item.dptr = NULL;
00158                 item.dsize = 0;
00159                 return (item);
00160         }
00161         return (dbm_nextkey(__cur_db));
00162 }
00163 
00164 int
00165 __db_dbm_delete(key)
00166         datum key;
00167 {
00168         if (__cur_db == NULL) {
00169                 __db_no_open();
00170                 return (-1);
00171         }
00172         return (dbm_delete(__cur_db, key));
00173 }
00174 
00175 int
00176 __db_dbm_store(key, dat)
00177         datum key, dat;
00178 {
00179         if (__cur_db == NULL) {
00180                 __db_no_open();
00181                 return (-1);
00182         }
00183         return (dbm_store(__cur_db, key, dat, DBM_REPLACE));
00184 }
00185 
00186 static void
00187 __db_no_open()
00188 {
00189         (void)fprintf(stderr, "dbm: no open database.\n");
00190 }
00191 
00192 /*
00193  * This package provides dbm and ndbm compatible interfaces to DB.
00194  *
00195  * The NDBM routines, which call the DB routines.
00196  */
00197 /*
00198  * Returns:
00199  *      *DBM on success
00200  *       NULL on failure
00201  */
00202 DBM *
00203 __db_ndbm_open(file, oflags, mode)
00204         const char *file;
00205         int oflags, mode;
00206 {
00207         DB *dbp;
00208         DBC *dbc;
00209         int ret;
00210         char path[MAXPATHLEN];
00211 
00212         /*
00213          * !!!
00214          * Don't use sprintf(3)/snprintf(3) -- the former is dangerous, and
00215          * the latter isn't standard, and we're manipulating strings handed
00216          * us by the application.
00217          */
00218         if (strlen(file) + strlen(DBM_SUFFIX) + 1 > sizeof(path)) {
00219                 __os_set_errno(ENAMETOOLONG);
00220                 return (NULL);
00221         }
00222         (void)strcpy(path, file);
00223         (void)strcat(path, DBM_SUFFIX);
00224         if ((ret = db_create(&dbp, NULL, 0)) != 0) {
00225                 __os_set_errno(ret);
00226                 return (NULL);
00227         }
00228 
00229         /*
00230          * !!!
00231          * The historic ndbm library corrected for opening O_WRONLY.
00232          */
00233         if (oflags & O_WRONLY) {
00234                 oflags &= ~O_WRONLY;
00235                 oflags |= O_RDWR;
00236         }
00237 
00238         if ((ret = dbp->set_pagesize(dbp, 4096)) != 0 ||
00239             (ret = dbp->set_h_ffactor(dbp, 40)) != 0 ||
00240             (ret = dbp->set_h_nelem(dbp, 1)) != 0 ||
00241             (ret = dbp->open(dbp, NULL,
00242             path, NULL, DB_HASH, __db_oflags(oflags), mode)) != 0) {
00243                 __os_set_errno(ret);
00244                 return (NULL);
00245         }
00246 
00247         if ((ret = dbp->cursor(dbp, NULL, &dbc, 0)) != 0) {
00248                 (void)dbp->close(dbp, 0);
00249                 __os_set_errno(ret);
00250                 return (NULL);
00251         }
00252 
00253         return ((DBM *)dbc);
00254 }
00255 
00256 /*
00257  * Returns:
00258  *      Nothing.
00259  */
00260 void
00261 __db_ndbm_close(dbm)
00262         DBM *dbm;
00263 {
00264         DBC *dbc;
00265 
00266         dbc = (DBC *)dbm;
00267 
00268         (void)dbc->dbp->close(dbc->dbp, 0);
00269 }
00270 
00271 /*
00272  * Returns:
00273  *      DATUM on success
00274  *      NULL on failure
00275  */
00276 datum
00277 __db_ndbm_fetch(dbm, key)
00278         DBM *dbm;
00279         datum key;
00280 {
00281         DBC *dbc;
00282         DBT _key, _data;
00283         datum data;
00284         int ret;
00285 
00286         dbc = (DBC *)dbm;
00287 
00288         memset(&_key, 0, sizeof(DBT));
00289         memset(&_data, 0, sizeof(DBT));
00290         _key.size = (u_int32_t)key.dsize;
00291         _key.data = key.dptr;
00292 
00293         /*
00294          * Note that we can't simply use the dbc we have to do a c_get/SET,
00295          * because that cursor is the one used for sequential iteration and
00296          * it has to remain stable in the face of intervening gets and puts.
00297          */
00298         if ((ret = dbc->dbp->get(dbc->dbp, NULL, &_key, &_data, 0)) == 0) {
00299                 data.dptr = _data.data;
00300                 data.dsize = (int)_data.size;
00301         } else {
00302                 data.dptr = NULL;
00303                 data.dsize = 0;
00304                 if (ret == DB_NOTFOUND)
00305                         __os_set_errno(ENOENT);
00306                 else {
00307                         __os_set_errno(ret);
00308                         F_SET(dbc->dbp, DB_AM_DBM_ERROR);
00309                 }
00310         }
00311         return (data);
00312 }
00313 
00314 /*
00315  * Returns:
00316  *      DATUM on success
00317  *      NULL on failure
00318  */
00319 datum
00320 __db_ndbm_firstkey(dbm)
00321         DBM *dbm;
00322 {
00323         DBC *dbc;
00324         DBT _key, _data;
00325         datum key;
00326         int ret;
00327 
00328         dbc = (DBC *)dbm;
00329 
00330         memset(&_key, 0, sizeof(DBT));
00331         memset(&_data, 0, sizeof(DBT));
00332 
00333         if ((ret = dbc->c_get(dbc, &_key, &_data, DB_FIRST)) == 0) {
00334                 key.dptr = _key.data;
00335                 key.dsize = (int)_key.size;
00336         } else {
00337                 key.dptr = NULL;
00338                 key.dsize = 0;
00339                 if (ret == DB_NOTFOUND)
00340                         __os_set_errno(ENOENT);
00341                 else {
00342                         __os_set_errno(ret);
00343                         F_SET(dbc->dbp, DB_AM_DBM_ERROR);
00344                 }
00345         }
00346         return (key);
00347 }
00348 
00349 /*
00350  * Returns:
00351  *      DATUM on success
00352  *      NULL on failure
00353  */
00354 datum
00355 __db_ndbm_nextkey(dbm)
00356         DBM *dbm;
00357 {
00358         DBC *dbc;
00359         DBT _key, _data;
00360         datum key;
00361         int ret;
00362 
00363         dbc = (DBC *)dbm;
00364 
00365         memset(&_key, 0, sizeof(DBT));
00366         memset(&_data, 0, sizeof(DBT));
00367 
00368         if ((ret = dbc->c_get(dbc, &_key, &_data, DB_NEXT)) == 0) {
00369                 key.dptr = _key.data;
00370                 key.dsize = (int)_key.size;
00371         } else {
00372                 key.dptr = NULL;
00373                 key.dsize = 0;
00374                 if (ret == DB_NOTFOUND)
00375                         __os_set_errno(ENOENT);
00376                 else {
00377                         __os_set_errno(ret);
00378                         F_SET(dbc->dbp, DB_AM_DBM_ERROR);
00379                 }
00380         }
00381         return (key);
00382 }
00383 
00384 /*
00385  * Returns:
00386  *       0 on success
00387  *      <0 failure
00388  */
00389 int
00390 __db_ndbm_delete(dbm, key)
00391         DBM *dbm;
00392         datum key;
00393 {
00394         DBC *dbc;
00395         DBT _key;
00396         int ret;
00397 
00398         dbc = (DBC *)dbm;
00399 
00400         memset(&_key, 0, sizeof(DBT));
00401         _key.data = key.dptr;
00402         _key.size = (u_int32_t)key.dsize;
00403 
00404         if ((ret = dbc->dbp->del(dbc->dbp, NULL, &_key, 0)) == 0)
00405                 return (0);
00406 
00407         if (ret == DB_NOTFOUND)
00408                 __os_set_errno(ENOENT);
00409         else {
00410                 __os_set_errno(ret);
00411                 F_SET(dbc->dbp, DB_AM_DBM_ERROR);
00412         }
00413         return (-1);
00414 }
00415 
00416 /*
00417  * Returns:
00418  *       0 on success
00419  *      <0 failure
00420  *       1 if DBM_INSERT and entry exists
00421  */
00422 int
00423 __db_ndbm_store(dbm, key, data, flags)
00424         DBM *dbm;
00425         datum key, data;
00426         int flags;
00427 {
00428         DBC *dbc;
00429         DBT _key, _data;
00430         int ret;
00431 
00432         dbc = (DBC *)dbm;
00433 
00434         memset(&_key, 0, sizeof(DBT));
00435         _key.data = key.dptr;
00436         _key.size = (u_int32_t)key.dsize;
00437 
00438         memset(&_data, 0, sizeof(DBT));
00439         _data.data = data.dptr;
00440         _data.size = (u_int32_t)data.dsize;
00441 
00442         if ((ret = dbc->dbp->put(dbc->dbp, NULL,
00443             &_key, &_data, flags == DBM_INSERT ? DB_NOOVERWRITE : 0)) == 0)
00444                 return (0);
00445 
00446         if (ret == DB_KEYEXIST)
00447                 return (1);
00448 
00449         __os_set_errno(ret);
00450         F_SET(dbc->dbp, DB_AM_DBM_ERROR);
00451         return (-1);
00452 }
00453 
00454 int
00455 __db_ndbm_error(dbm)
00456         DBM *dbm;
00457 {
00458         DBC *dbc;
00459 
00460         dbc = (DBC *)dbm;
00461 
00462         return (F_ISSET(dbc->dbp, DB_AM_DBM_ERROR));
00463 }
00464 
00465 int
00466 __db_ndbm_clearerr(dbm)
00467         DBM *dbm;
00468 {
00469         DBC *dbc;
00470 
00471         dbc = (DBC *)dbm;
00472 
00473         F_CLR(dbc->dbp, DB_AM_DBM_ERROR);
00474         return (0);
00475 }
00476 
00477 /*
00478  * Returns:
00479  *      1 if read-only
00480  *      0 if not read-only
00481  */
00482 int
00483 __db_ndbm_rdonly(dbm)
00484         DBM *dbm;
00485 {
00486         DBC *dbc;
00487 
00488         dbc = (DBC *)dbm;
00489 
00490         return (F_ISSET(dbc->dbp, DB_AM_RDONLY) ? 1 : 0);
00491 }
00492 
00493 /*
00494  * XXX
00495  * We only have a single file descriptor that we can return, not two.  Return
00496  * the same one for both files.  Hopefully, the user is using it for locking
00497  * and picked one to use at random.
00498  */
00499 int
00500 __db_ndbm_dirfno(dbm)
00501         DBM *dbm;
00502 {
00503         return (dbm_pagfno(dbm));
00504 }
00505 
00506 int
00507 __db_ndbm_pagfno(dbm)
00508         DBM *dbm;
00509 {
00510         DBC *dbc;
00511         int fd;
00512 
00513         dbc = (DBC *)dbm;
00514 
00515         (void)dbc->dbp->fd(dbc->dbp, &fd);
00516         return (fd);
00517 }

Generated on Sun Dec 25 12:14:24 2005 for Berkeley DB 4.4.16 by  doxygen 1.4.2