1 /* ldbm.c - ldap dbm compatibility routines */
3 /* Patched for Berkeley DB version 2.0; /KSp; 98/02/23
5 * - DB version 2.6.4b ; 1998/12/28, /KSp
6 * - DB_DBT_MALLOC ; 1998/03/22, /KSp
7 * - basic implementation; 1998/02/23, /KSp
18 #include <ac/string.h>
22 #include "ldap_pvt_thread.h"
26 ldbm_datum_free( LDBM ldbm, Datum data )
34 ldbm_datum_dup( LDBM ldbm, Datum data )
38 if ( data.dsize == 0 ) {
44 dup.dsize = data.dsize;
45 if ( (dup.dptr = (char *) malloc( data.dsize )) != NULL )
46 memcpy( dup.dptr, data.dptr, data.dsize );
51 #ifndef HAVE_BERKELEY_DB2
52 /* Everything but DB2 is non-reentrant */
54 static ldap_pvt_thread_mutex_t ldbm_big_mutex;
55 #define LDBM_LOCK (ldap_pvt_thread_mutex_lock(&ldbm_big_mutex))
56 #define LDBM_UNLOCK (ldap_pvt_thread_mutex_unlock(&ldbm_big_mutex))
58 void ldbm_initialize( void )
60 static int initialized = 0;
62 if(initialized++) return;
64 ldap_pvt_thread_mutex_init( &ldbm_big_mutex );
70 ldbm_malloc( size_t size )
72 return( calloc( 1, size ));
76 ldbm_db_errcall( const char *prefix, char *message )
79 syslog( LOG_INFO, "ldbm_db_errcall(): %s %s", prefix, message );
83 /* a dbEnv for BERKELEYv2 */
84 static DB_ENV ldbm_Env;
86 /* Berkeley DB 2.x is reentrant */
87 #define LDBM_LOCK ((void)0)
88 #define LDBM_UNLOCK ((void)0)
90 void ldbm_initialize( void )
92 static int initialized = 0;
97 if(initialized++) return;
99 memset( &ldbm_Env, 0, sizeof( ldbm_Env ));
101 ldbm_Env.db_errcall = ldbm_db_errcall;
102 ldbm_Env.db_errpfx = "==>";
104 envFlags = DB_CREATE | DB_THREAD;
106 if ( ( err = db_appinit( NULL, NULL, &ldbm_Env, envFlags )) ) {
110 sprintf( error, "%ld\n", (long) err );
112 sprintf( error, "%s\n", strerror( err ));
116 "ldbm_initialize(): FATAL error in db_appinit() : %s\n",
124 #if defined( LDBM_USE_DBHASH ) || defined( LDBM_USE_DBBTREE )
126 /*****************************************************************
128 * use berkeley db hash or btree package *
130 *****************************************************************/
133 ldbm_open( char *name, int rw, int mode, int dbcachesize )
137 #ifdef HAVE_BERKELEY_DB2
140 memset( &dbinfo, 0, sizeof( dbinfo ));
142 dbinfo.db_pagesize = DEFAULT_DB_PAGE_SIZE;
143 dbinfo.db_malloc = ldbm_malloc;
145 #if defined( DB_VERSION_MAJOR ) && defined( DB_VERSION_MINOR ) \
146 && DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR != 4
148 if( ldbm_Env.mp_info == NULL ) {
149 /* set a cachesize if we aren't using a memory pool */
150 dbinfo.db_cachesize = dbcachesize;
156 (void) db_open( name, DB_TYPE, rw, mode, &ldbm_Env, &dbinfo, &ret );
164 if ( DB_TYPE == DB_HASH ) {
165 memset( (char *) &hinfo, '\0', sizeof(hinfo) );
166 hinfo.cachesize = dbcachesize;
168 } else if ( DB_TYPE == DB_BTREE ) {
169 memset( (char *) &binfo, '\0', sizeof(binfo) );
170 binfo.cachesize = dbcachesize;
177 ret = dbopen( name, rw, mode, DB_TYPE, info );
186 ldbm_close( LDBM ldbm )
189 #ifdef HAVE_BERKELEY_DB2
190 (*ldbm->close)( ldbm, 0 );
192 (*ldbm->close)( ldbm );
198 ldbm_sync( LDBM ldbm )
201 (*ldbm->sync)( ldbm, 0 );
206 ldbm_fetch( LDBM ldbm, Datum key )
213 #ifdef HAVE_BERKELEY_DB2
214 ldbm_datum_init( data );
216 data.flags = DB_DBT_MALLOC;
218 if ( (rc = (*ldbm->get)( ldbm, NULL, &key, &data, 0 )) != 0 ) {
219 if ( data.dptr ) free( data.dptr );
221 if ( (rc = (*ldbm->get)( ldbm, &key, &data, 0 )) == 0 ) {
222 /* Berkeley DB 1.85 don't malloc the data for us */
223 /* duplicate it for to ensure reentrancy */
224 data = ldbm_datum_dup( ldbm, data );
237 ldbm_store( LDBM ldbm, Datum key, Datum data, int flags )
243 #ifdef HAVE_BERKELEY_DB2
244 rc = (*ldbm->put)( ldbm, NULL, &key, &data, flags & ~LDBM_SYNC );
247 rc = (*ldbm->put)( ldbm, &key, &data, flags & ~LDBM_SYNC );
250 if ( flags & LDBM_SYNC )
251 (*ldbm->sync)( ldbm, 0 );
259 ldbm_delete( LDBM ldbm, Datum key )
265 #ifdef HAVE_BERKELEY_DB2
266 rc = (*ldbm->del)( ldbm, NULL, &key, 0 );
269 rc = (*ldbm->del)( ldbm, &key, 0 );
271 (*ldbm->sync)( ldbm, 0 );
279 #ifdef HAVE_BERKELEY_DB2
280 ldbm_firstkey( LDBM ldbm, DBC **dbch )
282 ldbm_firstkey( LDBM ldbm )
288 #ifdef HAVE_BERKELEY_DB2
291 ldbm_datum_init( key );
292 ldbm_datum_init( data );
294 key.flags = data.flags = DB_DBT_MALLOC;
298 /* acquire a cursor for the DB */
300 # if defined( DB_VERSION_MAJOR ) && defined( DB_VERSION_MINOR ) && \
301 DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 6
303 if ( (*ldbm->cursor)( ldbm, NULL, &dbci ))
306 if ( (*ldbm->cursor)( ldbm, NULL, &dbci, 0 ))
312 if ( (*dbci->c_get)( dbci, &key, &data, DB_NEXT ) == 0 ) {
321 if ( (rc = (*ldbm->seq)( ldbm, &key, &data, R_FIRST )) == 0 ) {
322 key = ldbm_datum_dup( ldbm, key );
330 #ifdef HAVE_BERKELEY_DB2
340 #ifdef HAVE_BERKELEY_DB2
341 ldbm_nextkey( LDBM ldbm, Datum key, DBC *dbcp )
343 ldbm_nextkey( LDBM ldbm, Datum key )
349 #ifdef HAVE_BERKELEY_DB2
350 void *oldKey = key.dptr;
352 ldbm_datum_init( data );
354 data.flags = DB_DBT_MALLOC;
358 if ( (*dbcp->c_get)( dbcp, &key, &data, DB_NEXT ) == 0 ) {
359 if ( data.dptr ) free( data.dptr );
365 if ( (rc = (*ldbm->seq)( ldbm, &key, &data, R_NEXT )) == 0 ) {
366 key = ldbm_datum_dup( ldbm, key );
376 #ifdef HAVE_BERKELEY_DB2
377 if ( oldKey ) free( oldKey );
384 ldbm_errno( LDBM ldbm )
389 #elif defined( HAVE_GDBM )
391 #include <sys/stat.h>
393 /*****************************************************************
397 *****************************************************************/
400 ldbm_open( char *name, int rw, int mode, int dbcachesize )
407 if ( (db = gdbm_open( name, 0, rw | GDBM_FAST, mode, 0 )) == NULL ) {
411 if ( dbcachesize > 0 && stat( name, &st ) == 0 ) {
412 dbcachesize = (dbcachesize / st.st_blksize);
413 gdbm_setopt( db, GDBM_CACHESIZE, &dbcachesize, sizeof(int) );
422 ldbm_close( LDBM ldbm )
430 ldbm_sync( LDBM ldbm )
438 ldbm_fetch( LDBM ldbm, Datum key )
443 d = gdbm_fetch( ldbm, key );
450 ldbm_store( LDBM ldbm, Datum key, Datum data, int flags )
455 rc = gdbm_store( ldbm, key, data, flags & ~LDBM_SYNC );
456 if ( flags & LDBM_SYNC )
464 ldbm_delete( LDBM ldbm, Datum key )
469 rc = gdbm_delete( ldbm, key );
477 ldbm_firstkey( LDBM ldbm )
482 d = gdbm_firstkey( ldbm );
489 ldbm_nextkey( LDBM ldbm, Datum key )
494 d = gdbm_nextkey( ldbm, key );
501 ldbm_errno( LDBM ldbm )
512 #elif defined( HAVE_MDBM )
514 /* MMAPED DBM HASHING DATABASE */
516 #include <ac/string.h>
518 /* #define MDBM_DEBUG */
525 /* #define MDBM_CHAIN */
532 #define mdbm_store mdbm_chain_store
533 #define mdbm_fetch mdbm_chain_fetch
534 #define mdbm_delete mdbm_chain_delete
535 #define mdbm_first mdbm_chain_first
536 #define mdbm_next mdbm_chain_next
540 #define MDBM_PG_SZ (4*1024)
542 /*****************************************************************
546 *****************************************************************/
549 ldbm_open( char *name, int rw, int mode, int dbcachesize )
555 "==>(mdbm)ldbm_open(name=%s,rw=%x,mode=%x,cachesize=%d)\n",
556 name ? name : "NULL", rw, mode, dbcachesize );
560 LDBM_LOCK; /* We need locking here, this is the only non-thread
561 * safe function we have.
564 if ( (db = mdbm_open( name, rw, mode, MDBM_PG_SZ )) == NULL ) {
568 fprintf( stdout, "<==(mdbm)ldbm_open(db=NULL)\n" );
576 (void)mdbm_set_chain(db);
582 fprintf( stdout, "<==(mdbm)ldbm_open(db=%p)\n", db );
588 }/* LDBM ldbm_open() */
594 ldbm_close( LDBM ldbm )
597 /* Open and close are not reentrant so we need to use locks here */
601 "==>(mdbm)ldbm_close(db=%p)\n", ldbm );
610 fprintf( stdout, "<==(mdbm)ldbm_close()\n" );
614 }/* void ldbm_close() */
620 ldbm_sync( LDBM ldbm )
623 /* XXX: Not sure if this is re-entrant need to check code, if so
624 * you can leave LOCKS out.
631 }/* void ldbm_sync() */
634 #define MAX_MDBM_RETRY 5
637 ldbm_fetch( LDBM ldbm, Datum key )
643 /* This hack is needed because MDBM does not take keys
644 * which begin with NULL when working in the chaining
651 k.key.dsize = key.dsize + 1;
652 k.key.dptr = malloc(k.key.dsize);
654 memcpy( (void *)(k.key.dptr + 1), key.dptr, key.dsize );
664 d = mdbm_fetch( ldbm, k );
668 if ( k.val.dptr != NULL ) {
674 if ( (k.val.dptr = malloc( d.dsize )) != NULL ) {
676 k.val.dsize = d.dsize;
677 d = mdbm_fetch( ldbm, k );
686 }/* if ( d.dsize > 0 ) */
688 } while ((d.dsize > k.val.dsize) && (++retry < MAX_MDBM_RETRY));
698 }/* Datum ldbm_fetch() */
704 ldbm_store( LDBM ldbm, Datum key, Datum data, int flags )
707 Datum int_key; /* Internal key */
711 "==>(mdbm)ldbm_store(db=%p, key(dptr=%p,sz=%d), data(dptr=%p,sz=%d), flags=%x)\n",
712 ldbm, key.dptr, key.dsize, data.dptr, data.dsize, flags );
719 int_key.dsize = key.dsize + 1;
720 int_key.dptr = malloc( int_key.dsize );
721 *(int_key.dptr) = 'l'; /* Must not be NULL !*/
722 memcpy( (void *)(int_key.dptr + 1), key.dptr, key.dsize );
727 rc = mdbm_store( ldbm, int_key, data, flags );
728 if ( flags & LDBM_SYNC ) {
735 fprintf( stdout, "<==(mdbm)ldbm_store(rc=%d)\n", rc );
745 }/* int ldbm_store() */
751 ldbm_delete( LDBM ldbm, Datum key )
759 int_key.dsize = key.dsize + 1;
760 int_key.dptr = malloc(int_key.dsize);
761 *(int_key.dptr) = 'l';
762 memcpy( (void *)(int_key.dptr + 1), key.dptr, key.dsize );
767 rc = mdbm_delete( ldbm, int_key );
776 }/* int ldbm_delete() */
782 ldbm_get_next( LDBM ldbm, kvpair (*fptr)(MDBM *, kvpair) )
788 size_t sz = MDBM_PAGE_SIZE(ldbm);
797 in.key.dsize = sz; /* Assume first key in one pg */
798 in.key.dptr = malloc(sz);
800 in.val.dptr = NULL; /* Don't need data just key */
806 out = fptr( ldbm, in );
808 if (out.key.dsize > 0) {
810 ret.dsize = out.key.dsize - delta;
811 if ((ret.dptr = (char *)malloc(ret.dsize)) == NULL) {
818 memcpy(ret.dptr, (void *)(out.key.dptr + delta),
831 }/* static Datum ldbm_get_next() */
837 ldbm_firstkey( LDBM ldbm )
840 return ldbm_get_next( ldbm, mdbm_first );
842 }/* Datum ldbm_firstkey() */
848 ldbm_nextkey( LDBM ldbm, Datum key )
852 * don't know if this will affect the LDAP server opertaion
853 * but mdbm cannot take and input key.
856 return ldbm_get_next( ldbm, mdbm_next );
858 }/* Datum ldbm_nextkey() */
861 ldbm_errno( LDBM ldbm )
863 /* XXX: best we can do with current mdbm interface */
866 }/* int ldbm_errno() */
869 #elif defined( HAVE_NDBM )
871 /*****************************************************************
873 * if no gdbm, fall back to using ndbm, the standard unix thing *
875 *****************************************************************/
879 ldbm_open( char *name, int rw, int mode, int dbcachesize )
884 ldbm = dbm_open( name, rw, mode );
891 ldbm_close( LDBM ldbm )
900 ldbm_sync( LDBM ldbm )
906 ldbm_fetch( LDBM ldbm, Datum key )
911 d = ldbm_datum_dup( ldbm, dbm_fetch( ldbm, key ) );
918 ldbm_store( LDBM ldbm, Datum key, Datum data, int flags )
923 rc = dbm_store( ldbm, key, data, flags );
930 ldbm_delete( LDBM ldbm, Datum key )
935 rc = dbm_delete( ldbm, key );
942 ldbm_firstkey( LDBM ldbm )
947 d = dbm_firstkey( ldbm );
954 ldbm_nextkey( LDBM ldbm, Datum key )
959 d = dbm_nextkey( ldbm );
966 ldbm_errno( LDBM ldbm )
971 err = dbm_error( ldbm );