sdbm, dbm_open, dbm_prep, dbm_close,  dbm_fetch,  dbm_store,  dbm_delete,
     dbm_firstkey, dbm_nextkey, dbm_hash, dbm_rdonly, dbm_error, dbm_clearerr,
     dbm_dirfno, dbm_pagfno - data base subroutines

     #include <sdbm.h>

     typedef struct {
             char *dptr;
             int dsize;
     } datum;

     datum nullitem = { NULL, 0 };

     DBM *dbm_open(char *file, int flags, int mode)

     DBM *dbm_prep(char *dirname, char *pagname, int flags, int mode)

     void dbm_close(DBM *db)

     datum dbm_fetch(DBM *db, key)

     int dbm_store(DBM *db, datum key, datum val, int flags)

     int dbm_delete(DBM *db, datum key)

     datum dbm_firstkey(DBM *db)

     datum dbm_nextkey(DBM *db)

     long dbm_hash(char *string, int len)

     int dbm_rdonly(DBM *db)
     int dbm_error(DBM *db)
     dbm_clearerr(DBM *db)
     int dbm_dirfno(DBM *db)
     int dbm_pagfno(DBM *db)


     This package allows an application to maintain a mapping  of  <key,value>
     pairs  in  disk  files.   This  is  not  to be considered a real database
     system, but is still useful in many simple applications built around fast
     retrieval  of  a  data  value  from  a  key.  This implementation uses an
     external hashing scheme, called Dynamic Hashing, as described by Per-Aake
     Larson  in  BIT  18  (1978)  pp.  184-201.  Retrieval of any item usually
     requires a single disk access.  The application interface  is  compatible
     with the ndbm(3) library.

     An sdbm database is kept in two files usually given the  extensions  .dir
     and  .pag.   The  .dir  file  contains  a bitmap representing a forest of
     binary hash trees, the leaves of which indicate data pages  in  the  .pag

     The application interface uses the datum structure to describe both  keys
     and  values.   A datum specifies a byte sequence of dsize size pointed to
     by dptr.  If you use ASCII strings as  keys  or  values,  then  you  must
     decide whether or not to include the terminating NUL byte which sometimes
     defines strings.  Including it will require larger database files, but it
     will be possible to get sensible output from a strings(1) command applied
     to the data file.

     In order to allow a process using this  package  to  manipulate  multiple
     databases,  the applications interface always requires a handle, a DBM *,
     to identify the database  to  be  manipulated.   Such  a  handle  can  be
     obtained from the only routines that do not require it, namely dbm_open()
     or dbm_prep().  Either of these will open or  create  the  two  necessary
     files.   The  difference  is that the latter allows explicitly naming the
     bitmap and data files whereas dbm_open() will take a base file  name  and
     call  dbm_prep()  with  the  default  extensions.   The  flags  and  mode
     parameters are the same as for open(2).

     To free the resources occupied while a database handle  is  active,  call

     Given a handle, one can retrieve data associated with a key by using  the
     dbm_fetch()  routine,  and  associate  data  with  a  key  by  using  the
     dbm_store() routine.

     The  values  of  the  flags  parameter  for  dbm_store()  can  be  either
     DBM_INSERT, which will not change an existing entry with the same key, or
     DBM_REPLACE, which will replace an existing  entry  with  the  same  key.
     Keys are unique within the database.

     To delete a key and its associated value use the dbm_delete() routine.

     To retrieve every key in the database, use a loop like:

     for (key = dbm_firstkey(db); key.dptr != NULL; key = dbm_nextkey(db))

     The order of retrieval is unspecified.

     If you determine that the performance of the database  is  inadequate  or
     you  notice  clustering  or  other effects that may be due to the hashing
     algorithm used by this package, you can override it by supplying your own
     dbm_hash()  routine.   Doing  so will make the database unintelligable to
     any other applications that do not use your specialized hash function.

     The following macros are defined in the header file:

          dbm_rdonly() returns true if the database has been opened read-only.

          dbm_error() returns true if an I/O error has occurred.

          dbm_clearerr() allows you to clear the error flag if you  think  you
          know what the error was and insist on ignoring it.

          dbm_dirfno() returns the file descriptor associated with the  bitmap

          dbm_pagfno() returns the file descriptor associated  with  the  data


     Functions that return a DBM * handle will use NULL to indicate an  error.
     Functions  that  return  an  int  will  use -1 to indicate an error.  The
     normal return value in that case is 0.  Functions  that  return  a  datum
     will return nullitem to indicate an error.

     As a special case of dbm_store(), if it is  called  with  the  DBM_INSERT
     flag and the key already exists in the database, the return value will be

     In general, if a function parameter is invalid,  errno  will  be  set  to
     EINVAL.  If a write operation is requested on a read-only database, errno
     will be set to ENOPERM.  If a memory allocation (using malloc(3)) failed,
     errno  will  be  set  to  ENOMEM.   For I/O operation failures errno will
     contain the value set by the relevant failed system call, either read(2),
     write(2), or lseek(2).

     Ozan S. Yigit (

     The sum of key and value data sizes must not exceed PAIRMAX (1008 bytes).

     The sum of the key and value data sizes where several keys  hash  to  the
     same value must fit within one bitmap page.

     The .pag file will contain holes, so its apparent size is larger than its
     contents.  When copied through the filesystem the holes will be filled.

     The contents of datum values returned are in volatile  storage.   If  you
     want  to  retain  the  values  pointed to, you must copy them immediately
     before another call to this package.
     The only safe way for multiple processes to (read and) update a  database
     at  the  same time, is to implement a private locking scheme outside this
     package and open and close the database between lock acquisitions.  It is
     safe for multiple processes to concurrently access a database read-only.

     For complete source code compatibility with  the  Berkeley  Unix  ndbm(3)
     library,    the    sdbm.h    header   file   should   be   installed   in

     The nullitem data item, and  the  dbm_prep(),  dbm_hash(),  dbm_rdonly(),
     dbm_dirfno(), and dbm_pagfno() functions are unique to this package.