]> git.sur5r.net Git - openldap/blob - libraries/libldbm/ldbm.c
Remove Berkeley DB CDB support
[openldap] / libraries / libldbm / ldbm.c
1 /* ldbm.c - ldap dbm compatibility routines */
2 /* $OpenLDAP$ */
3 /*
4  * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved.
5  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
6  */
7
8 /* Patched for Berkeley DB version 2.0; /KSp; 98/02/23
9  *
10  *   - DB version 2.6.4b   ; 1998/12/28, /KSp
11  *   - DB_DBT_MALLOC       ; 1998/03/22, /KSp
12  *   - basic implementation; 1998/02/23, /KSp
13  */
14
15 #include "portable.h"
16
17 #ifdef SLAPD_LDBM
18
19 #include <stdio.h>
20
21 #include <ac/stdlib.h>
22 #include <ac/string.h>
23 #include <ac/errno.h>
24
25 #include "ldbm.h"
26 #include "ldap_pvt_thread.h"
27
28 void
29 ldbm_datum_free( LDBM ldbm, Datum data )
30 {
31         if ( data.dptr ) {
32                 free( data.dptr );
33                 memset( &data, '\0', sizeof( Datum ));
34                 data.dptr = NULL;
35         }
36 }
37
38 Datum
39 ldbm_datum_dup( LDBM ldbm, Datum data )
40 {
41         Datum   dup;
42
43         ldbm_datum_init( dup );
44
45         if ( data.dsize == 0 ) {
46                 dup.dsize = 0;
47                 dup.dptr = NULL;
48
49                 return( dup );
50         }
51         dup.dsize = data.dsize;
52
53         if ( (dup.dptr = (char *) malloc( data.dsize )) != NULL ) {
54                 AC_MEMCPY( dup.dptr, data.dptr, data.dsize );
55         }
56
57         return( dup );
58 }
59
60 static int ldbm_initialized = 0;
61
62 #ifdef USE_BERKELEY_CDB
63         /* not currently supported */
64 #define LDBM_LOCK       ((void) 0)
65 #define LDBM_UNLOCK     ((void) 0)
66 #else
67 static ldap_pvt_thread_mutex_t ldbm_big_mutex;
68 #define LDBM_LOCK       (ldap_pvt_thread_mutex_lock(&ldbm_big_mutex))
69 #define LDBM_UNLOCK     (ldap_pvt_thread_mutex_unlock(&ldbm_big_mutex))
70 #endif
71
72 #if !defined( HAVE_BERKELEY_DB ) || (DB_VERSION_MAJOR < 3)
73         /*  a dbEnv for BERKELEYv2  */
74 DB_ENV *ldbm_Env = NULL;        /* real or fake, depending on db and version */
75 #endif
76
77
78 /*******************************************************************
79  *                                                                 *
80  *  Create some special functions to initialize Berkeley DB for    *
81  *  versions greater than 2.                                       *
82  *                                                                 *
83  *******************************************************************/
84 #if defined( HAVE_BERKELEY_DB ) && (DB_VERSION_MAJOR >= 2)
85
86 void *
87 ldbm_malloc( size_t size )
88 {
89         /* likely should use ber_mem* routines */
90         return( calloc( 1, size ) );
91 }
92
93 #ifdef LDAP_SYSLOG
94 #include <ac/syslog.h>
95 #endif
96
97 static void
98 ldbm_db_errcall( const char *prefix, char *message )
99 {
100 #ifdef LDAP_SYSLOG
101         syslog( LOG_INFO, "ldbm: %s %s", prefix, message );
102 #endif
103 }
104
105 int ldbm_initialize( const char* home )
106 {
107         int     err;
108         u_int32_t       envFlags;
109
110         if(ldbm_initialized++) return 1;
111
112         {
113                 char *version;
114                 int major, minor, patch;
115                 version = db_version( &major, &minor, &patch );
116
117                 if( major != DB_VERSION_MAJOR ||
118                         minor < DB_VERSION_MINOR )
119                 {
120 #ifdef LDAP_SYSLOG
121                         syslog( LOG_INFO,
122                                 "ldbm_initialize(): version mismatch\nexpected: %s\ngot: %s\n",
123                                 DB_VERSION_STRING, version );
124 #endif
125                         return 1;
126                 }
127         }
128
129 #ifndef USE_BERKELEY_CDB
130         ldap_pvt_thread_mutex_init( &ldbm_big_mutex );
131 #endif
132
133
134 #if DB_VERSION_MAJOR < 3
135         ldbm_Env = calloc( 1, sizeof( DB_ENV ));
136
137         if( ldbm_Env == NULL ) return 1;
138
139         ldbm_Env->db_errcall    = ldbm_db_errcall;
140         ldbm_Env->db_errpfx             = "==>";
141
142         envFlags = DB_CREATE | DB_USE_ENVIRON;
143
144         /* add optional flags */
145 #ifdef DB_PRIVATE
146         envFlags |= DB_PRIVATE;
147 #endif
148 #ifdef HAVE_BERKELEY_DB_THREAD
149         envFlags |= DB_THREAD; 
150 #endif
151
152         err = db_appinit( home, NULL, ldbm_Env, envFlags );
153
154         if ( err ) {
155 #ifdef LDAP_SYSLOG
156                 syslog( LOG_INFO, "ldbm_initialize(): "
157                         "FATAL error in db_appinit() : %s (%d)\n",
158                         db_strerror( err ), err );
159 #endif
160                 return( 1 );
161         }
162 #endif
163
164         return 0;
165 }
166
167 int ldbm_shutdown( void )
168 {
169         if( !ldbm_initialized ) return 1;
170
171 #if DB_VERSION_MAJOR < 3
172         db_appexit( ldbm_Env );
173 #endif
174
175 #ifndef USE_BERKELEY_CDB
176         ldap_pvt_thread_mutex_destroy( &ldbm_big_mutex );
177 #endif
178         return 0;
179 }
180
181 #else  /* some DB other than Berkeley V2 or greater */
182
183 int ldbm_initialize( const char * home )
184 {
185         if(ldbm_initialized++) return 1;
186
187         ldap_pvt_thread_mutex_init( &ldbm_big_mutex );
188
189         return 0;
190 }
191
192 int ldbm_shutdown( void )
193 {
194         if( !ldbm_initialized ) return 1;
195
196         ldap_pvt_thread_mutex_destroy( &ldbm_big_mutex );
197
198         return 0;
199 }
200
201 #endif /* HAVE_BERKELEY_DB */
202
203
204 #if defined( HAVE_BERKELEY_DB ) && (DB_VERSION_MAJOR >= 3)
205
206 DB_ENV *ldbm_initialize_env(const char *home, int dbcachesize, int *envdirok)
207 {
208         DB_ENV *env = NULL;    
209         int     err;
210         u_int32_t       envFlags;
211
212         err = db_env_create( &env, 0 );
213
214         if ( err ) {
215 #ifdef LDAP_SYSLOG
216                 syslog( LOG_INFO, "ldbm_initialize_env(): "
217                         "FATAL error in db_env_create() : %s (%d)\n",
218                         db_strerror( err ), err );
219 #endif
220                 return NULL;
221         }
222
223         env->set_errcall( env, ldbm_db_errcall );
224         env->set_errpfx( env, "==>" );
225         if (dbcachesize) {
226                 env->set_cachesize( env, 0, dbcachesize, 0 );
227         }
228
229         envFlags = DB_CREATE | DB_INIT_MPOOL | DB_USE_ENVIRON;
230 #ifdef DB_PRIVATE
231         envFlags |= DB_PRIVATE;
232 #endif
233 #ifdef DB_MPOOL_PRIVATE
234         envFlags |= DB_MPOOL_PRIVATE;
235 #endif
236 #ifdef HAVE_BERKELEY_DB_THREAD
237         envFlags |= DB_THREAD;
238 #endif
239
240 #if DB_VERSION_MAJOR > 3 || DB_VERSION_MINOR > 0
241         err = env->open( env, home, envFlags, 0 );
242 #else
243         /* 3.0.x requires an extra argument */
244         err = env->open( env, home, NULL, envFlags, 0 );
245 #endif
246
247         if ( err != 0 ) {
248 #ifdef LDAP_SYSLOG
249                 syslog( LOG_INFO, "ldbm_initialize_env(): "
250                         "FATAL error in dbEnv->open() : %s (%d)\n",
251                         db_strerror( err ), err );
252 #endif
253                 env->close( env, 0 );
254                 return NULL;
255         }
256
257         *envdirok = 1;
258         return env;
259 }
260
261 void ldbm_shutdown_env(DB_ENV *env)
262 {
263         env->close( env, 0 );
264 }
265
266
267 #else
268
269 DB_ENV *ldbm_initialize_env(const char *home, int dbcachesize, int *envdirok)
270 {
271         return ldbm_Env;
272 }
273
274 void ldbm_shutdown_env(DB_ENV *env)
275 {
276 }
277
278 #endif
279
280
281 #if defined( LDBM_USE_DBHASH ) || defined( LDBM_USE_DBBTREE )
282
283 /*****************************************************************
284  *                                                               *
285  * use berkeley db hash or btree package                         *
286  *                                                               *
287  *****************************************************************/
288
289 LDBM
290 ldbm_open( DB_ENV *env, char *name, int rw, int mode, int dbcachesize )
291 {
292         LDBM            ret = NULL;
293
294 #if DB_VERSION_MAJOR >= 3
295         int err;
296
297         LDBM_LOCK;
298
299         err = db_create( &ret, env, 0 );
300         if ( err != 0 ) {
301                 (void)ret->close(ret, 0);
302                 LDBM_UNLOCK;
303
304                 return NULL;
305         }
306
307         ret->set_pagesize( ret, DEFAULT_DB_PAGE_SIZE );
308
309         /* likely should use ber_mem* routines */
310 #if DB_VERSION_MINOR >= 3
311         ret->set_alloc( ret, ldbm_malloc, NULL, NULL );
312 #else
313         ret->set_malloc( ret, ldbm_malloc );
314 #endif
315
316         /* ret->set_cachesize( ret, 0, dbcachesize, 0 ); */
317
318         err = ret->open( ret, name, NULL, DB_TYPE, rw, mode);
319
320         if ( err != 0 ) {
321                 int tmp = errno;
322                 (void)ret->close(ret, 0);
323                 errno = tmp;
324
325                 LDBM_UNLOCK;
326                 return NULL;
327         }
328
329         LDBM_UNLOCK;
330  
331 #elif DB_VERSION_MAJOR >= 2
332         DB_INFO dbinfo;
333
334         memset( &dbinfo, '\0', sizeof( dbinfo ));
335
336 #if     DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR == 4
337         /*
338          * BerkeleyDB 2.4 do not allow db_cachesize
339          * to be specified if an DB_ENV is.
340          */
341 #else
342         /* set db_cachesize of MPOOL is NOT being used. */
343         if (( ldbm_Env == NULL ) || ( ldbm_Env->mp_info == NULL )) {
344                 dbinfo.db_cachesize = dbcachesize;
345         }
346 #endif
347
348         dbinfo.db_pagesize      = DEFAULT_DB_PAGE_SIZE;
349         dbinfo.db_malloc        = ldbm_malloc;
350
351         LDBM_LOCK;
352         (void) db_open( name, DB_TYPE, rw, mode, ldbm_Env, &dbinfo, &ret );
353         LDBM_UNLOCK;
354
355 #else
356         void            *info;
357         BTREEINFO       binfo;
358         HASHINFO        hinfo;
359
360         if ( DB_TYPE == DB_HASH ) {
361                 memset( (char *) &hinfo, '\0', sizeof(hinfo) );
362                 hinfo.cachesize = dbcachesize;
363                 info = &hinfo;
364         } else if ( DB_TYPE == DB_BTREE ) {
365                 memset( (char *) &binfo, '\0', sizeof(binfo) );
366                 binfo.cachesize = dbcachesize;
367                 info = &binfo;
368         } else {
369                 info = NULL;
370         }
371
372         LDBM_LOCK;
373         ret = dbopen( name, rw, mode, DB_TYPE, info );
374         LDBM_UNLOCK;
375 #endif
376
377         return ret;
378 }
379
380 void
381 ldbm_close( LDBM ldbm )
382 {
383         LDBM_LOCK;
384 #if DB_VERSION_MAJOR >= 3
385         ldbm->close( ldbm, 0 );
386 #elif DB_VERSION_MAJOR >= 2
387         (*ldbm->close)( ldbm, 0 );
388 #else
389         (*ldbm->close)( ldbm );
390 #endif
391         LDBM_UNLOCK;
392 }
393
394 void
395 ldbm_sync( LDBM ldbm )
396 {
397         LDBM_LOCK;
398         (*ldbm->sync)( ldbm, 0 );
399         LDBM_UNLOCK;
400 }
401
402 Datum
403 ldbm_fetch( LDBM ldbm, Datum key )
404 {
405         Datum   data;
406         int     rc;
407
408         LDBM_LOCK;
409
410 #if DB_VERSION_MAJOR >= 3
411         ldbm_datum_init( data );
412
413         data.flags = DB_DBT_MALLOC;
414
415         if ( (rc = ldbm->get( ldbm, NULL, &key, &data, 0 )) != 0 ) {
416                 ldbm_datum_free( ldbm, data );
417                 data.dptr = NULL;
418                 data.dsize = 0;
419         }
420
421 #elif DB_VERSION_MAJOR >= 2
422         ldbm_datum_init( data );
423
424         data.flags = DB_DBT_MALLOC;
425
426         if ( (rc = (*ldbm->get)( ldbm, NULL, &key, &data, 0 )) != 0 ) {
427                 ldbm_datum_free( ldbm, data );
428                 data.dptr = NULL;
429                 data.dsize = 0;
430         }
431 #else
432
433         if ( (rc = (*ldbm->get)( ldbm, &key, &data, 0 )) == 0 ) {
434                 /* Berkeley DB 1.85 don't malloc the data for us */
435                 /* duplicate it for to ensure reentrancy */
436                 data = ldbm_datum_dup( ldbm, data );
437         } else {
438                 data.dptr = NULL;
439                 data.dsize = 0;
440         }
441 #endif
442
443         LDBM_UNLOCK;
444
445         return( data );
446 }
447
448 int
449 ldbm_store( LDBM ldbm, Datum key, Datum data, int flags )
450 {
451         int     rc;
452
453         LDBM_LOCK;
454
455 #if DB_VERSION_MAJOR >= 3
456         rc = ldbm->put( ldbm, NULL, &key, &data, flags & ~LDBM_SYNC );
457         rc = (-1) * rc;
458
459 #elif DB_VERSION_MAJOR >= 2
460         rc = (*ldbm->put)( ldbm, NULL, &key, &data, flags & ~LDBM_SYNC );
461         rc = (-1) * rc;
462 #else
463         rc = (*ldbm->put)( ldbm, &key, &data, flags & ~LDBM_SYNC );
464 #endif
465
466         if ( flags & LDBM_SYNC )
467                 (*ldbm->sync)( ldbm, 0 );
468
469         LDBM_UNLOCK;
470
471         return( rc );
472 }
473
474 int
475 ldbm_delete( LDBM ldbm, Datum key )
476 {
477         int     rc;
478
479         LDBM_LOCK;
480
481 #if DB_VERSION_MAJOR >= 3
482         rc = ldbm->del( ldbm, NULL, &key, 0 );
483         rc = (-1) * rc;
484 #elif DB_VERSION_MAJOR >= 2
485         rc = (*ldbm->del)( ldbm, NULL, &key, 0 );
486         rc = (-1) * rc;
487 #else
488         rc = (*ldbm->del)( ldbm, &key, 0 );
489 #endif
490         (*ldbm->sync)( ldbm, 0 );
491
492         LDBM_UNLOCK;
493
494         return( rc );
495 }
496
497 Datum
498 ldbm_firstkey( LDBM ldbm, LDBMCursor **dbch )
499 {
500         Datum   key, data;
501
502 #if DB_VERSION_MAJOR >= 2
503         LDBMCursor  *dbci;
504
505         ldbm_datum_init( key );
506         ldbm_datum_init( data );
507
508         key.flags = data.flags = DB_DBT_MALLOC;
509
510         LDBM_LOCK;
511
512         /* acquire a cursor for the DB */
513 # if DB_VERSION_MAJOR >= 3
514         if ( ldbm->cursor( ldbm, NULL, &dbci, 0 ) )
515 # elif defined( DB_VERSION_MAJOR ) && defined( DB_VERSION_MINOR ) && \
516         (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 6)
517
518         if ( (*ldbm->cursor)( ldbm, NULL, &dbci ))
519
520 #  else
521         if ( (*ldbm->cursor)( ldbm, NULL, &dbci, 0 ))
522 #  endif
523         {
524                 key.dptr = NULL;
525                 return( key );
526         } else {
527                 *dbch = dbci;
528                 if ( (*dbci->c_get)( dbci, &key, &data, DB_NEXT ) == 0 ) {
529                         ldbm_datum_free( ldbm, data );
530                 }
531         else {
532 #else
533         int     rc;
534
535         LDBM_LOCK;
536
537         if ( (rc = (*ldbm->seq)( ldbm, &key, &data, R_FIRST )) == 0 ) {
538                 key = ldbm_datum_dup( ldbm, key );
539         }
540         else {
541 #endif
542                 key.dptr = NULL;
543                 key.dsize = 0;
544         }
545
546 #if DB_VERSION_MAJOR >= 2
547         }
548 #endif
549
550         LDBM_UNLOCK;
551
552         return( key );
553 }
554
555 Datum
556 ldbm_nextkey( LDBM ldbm, Datum key, LDBMCursor *dbcp )
557 {
558         Datum   data;
559
560 #if DB_VERSION_MAJOR >= 2
561         ldbm_datum_init( data );
562
563         ldbm_datum_free( ldbm, key );
564         key.flags = data.flags = DB_DBT_MALLOC;
565
566         LDBM_LOCK;
567
568         if ( (*dbcp->c_get)( dbcp, &key, &data, DB_NEXT ) == 0 ) {
569                 ldbm_datum_free( ldbm, data );
570         }
571         else {
572 #else
573         int     rc;
574
575         LDBM_LOCK;
576
577         if ( (rc = (*ldbm->seq)( ldbm, &key, &data, R_NEXT )) == 0 ) {
578                 key = ldbm_datum_dup( ldbm, key );
579         }
580         else {
581 #endif
582                 key.dptr = NULL;
583                 key.dsize = 0;
584         }
585
586         LDBM_UNLOCK;
587
588         return( key );
589 }
590
591 int
592 ldbm_errno( LDBM ldbm )
593 {
594         return( errno );
595 }
596
597 /******************************************************************
598  *                                                                *
599  *         END Berkeley section                                   *
600  *                                                                *
601  ******************************************************************/
602
603 #elif defined( HAVE_GDBM )
604
605 #ifdef HAVE_ST_BLKSIZE
606 #include <sys/stat.h>
607 #endif
608
609 /*****************************************************************
610  *                                                               *
611  * use gdbm                                                      *
612  *                                                               *
613  *****************************************************************/
614
615 LDBM
616 ldbm_open( DB_ENV *env, char *name, int rw, int mode, int dbcachesize )
617 {
618         LDBM            db;
619 #ifdef HAVE_ST_BLKSIZE
620                 struct stat     st;
621 #endif
622
623         LDBM_LOCK;
624
625         if ( (db =  gdbm_open( name, 0, rw | GDBM_FAST, mode, 0 )) == NULL ) {
626                 LDBM_UNLOCK;
627                 return( NULL );
628         }
629
630 #ifdef HAVE_ST_BLKSIZE
631         if ( dbcachesize > 0 && stat( name, &st ) == 0 ) {
632                 dbcachesize /= st.st_blksize;
633                 if( dbcachesize == 0 ) dbcachesize = 1;
634                 gdbm_setopt( db, GDBM_CACHESIZE, &dbcachesize, sizeof(int) );
635         }
636 #else
637         if ( dbcachesize > 0 ) {
638                 dbcachesize /= 4096;
639                 if( dbcachesize == 0 ) dbcachesize = 1;
640                 gdbm_setopt( db, GDBM_CACHESIZE, &dbcachesize, sizeof(int) );
641         }
642 #endif
643
644         LDBM_UNLOCK;
645
646         return( db );
647 }
648
649 void
650 ldbm_close( LDBM ldbm )
651 {
652         LDBM_LOCK;
653         gdbm_close( ldbm );
654         LDBM_UNLOCK;
655 }
656
657 void
658 ldbm_sync( LDBM ldbm )
659 {
660         LDBM_LOCK;
661         gdbm_sync( ldbm );
662         LDBM_UNLOCK;
663 }
664
665 Datum
666 ldbm_fetch( LDBM ldbm, Datum key )
667 {
668         Datum d;
669
670         LDBM_LOCK;
671         d = gdbm_fetch( ldbm, key );
672         LDBM_UNLOCK;
673
674         return d;
675 }
676
677 int
678 ldbm_store( LDBM ldbm, Datum key, Datum data, int flags )
679 {
680         int     rc;
681
682         LDBM_LOCK;
683         rc = gdbm_store( ldbm, key, data, flags & ~LDBM_SYNC );
684         if ( flags & LDBM_SYNC )
685                 gdbm_sync( ldbm );
686         LDBM_UNLOCK;
687
688         return( rc );
689 }
690
691 int
692 ldbm_delete( LDBM ldbm, Datum key )
693 {
694         int     rc;
695
696         LDBM_LOCK;
697         rc = gdbm_delete( ldbm, key );
698         gdbm_sync( ldbm );
699         LDBM_UNLOCK;
700
701         return( rc );
702 }
703
704 Datum
705 ldbm_firstkey( LDBM ldbm, LDBMCursor **dbcp )
706 {
707         Datum d;
708
709         LDBM_LOCK;
710         d = gdbm_firstkey( ldbm );
711         LDBM_UNLOCK;
712
713         if ( d.dptr != NULL ) {
714                 *dbcp = (Datum *) malloc( sizeof( Datum ) );
715                 **dbcp = ldbm_datum_dup( ldbm, d );
716         }
717
718         return d;
719 }
720
721 Datum
722 ldbm_nextkey( LDBM ldbm, Datum key, LDBMCursor *dbcp )
723 {
724         Datum d;
725
726         LDBM_LOCK;
727         d = gdbm_nextkey( ldbm, *dbcp );
728         LDBM_UNLOCK;
729
730         ldbm_datum_free( ldbm, *dbcp );
731
732         if ( d.dptr != NULL ) {
733                 *dbcp = ldbm_datum_dup( ldbm, d );
734         } else {
735                 free( dbcp );
736         }
737
738         return d;
739 }
740
741 int
742 ldbm_errno( LDBM ldbm )
743 {
744         int err;
745
746         LDBM_LOCK;
747         err = gdbm_errno;
748         LDBM_UNLOCK;
749
750         return( err );
751 }
752
753 #elif HAVE_MDBM
754
755 /* MMAPED DBM HASHING DATABASE */
756
757 #include <ac/string.h>
758
759 /* #define MDBM_DEBUG */
760
761 #ifdef MDBM_DEBUG
762 #include <stdio.h>
763 #endif
764
765 #define NO_NULL_KEY
766 /* #define MDBM_CHAIN */
767
768 #ifdef MDBM_CHAIN
769
770 /* Use chaining */
771
772
773 #define mdbm_store      mdbm_chain_store
774 #define mdbm_fetch      mdbm_chain_fetch
775 #define mdbm_delete     mdbm_chain_delete
776 #define mdbm_first      mdbm_chain_first
777 #define mdbm_next       mdbm_chain_next
778
779 #endif
780
781 #define MDBM_PG_SZ      (4*1024)
782
783 /*****************************************************************
784  *                                                               *
785  * use mdbm                                                      *
786  *                                                               *
787  *****************************************************************/
788
789 LDBM
790 ldbm_open( DB_ENV *env, char *name, int rw, int mode, int dbcachesize )
791 {
792         LDBM            db;
793
794 #ifdef MDBM_DEBUG
795         fprintf( stdout,
796                  "==>(mdbm)ldbm_open(name=%s,rw=%x,mode=%x,cachesize=%d)\n",
797                  name ? name : "NULL", rw, mode, dbcachesize );
798         fflush( stdout );
799 #endif
800
801         LDBM_LOCK;      /* We need locking here, this is the only non-thread
802                          * safe function we have.
803                          */
804
805         if ( (db =  mdbm_open( name, rw, mode, MDBM_PG_SZ )) == NULL ) {
806
807                 LDBM_UNLOCK;
808 #ifdef MDBM_DEBUG
809                 fprintf( stdout, "<==(mdbm)ldbm_open(db=NULL)\n" );
810                 fflush( stdout );
811 #endif
812                 return( NULL );
813
814         }
815
816 #ifdef MDBM_CHAIN
817         (void)mdbm_set_chain(db);
818 #endif
819
820         LDBM_UNLOCK;
821
822 #ifdef MDBM_DEBUG
823         fprintf( stdout, "<==(mdbm)ldbm_open(db=%p)\n", db );
824         fflush( stdout );
825 #endif
826
827         return( db );
828
829 }
830
831
832
833
834 void
835 ldbm_close( LDBM ldbm )
836 {
837
838         /* Open and close are not reentrant so we need to use locks here */
839
840 #ifdef MDBM_DEBUG
841         fprintf( stdout,
842                  "==>(mdbm)ldbm_close(db=%p)\n", ldbm );
843         fflush( stdout );
844 #endif
845
846         LDBM_LOCK;
847         mdbm_close( ldbm );
848         LDBM_UNLOCK;
849
850 #ifdef MDBM_DEBUG
851         fprintf( stdout, "<==(mdbm)ldbm_close()\n" );
852         fflush( stdout );
853 #endif
854
855 }
856
857
858
859
860 void
861 ldbm_sync( LDBM ldbm )
862 {
863         /* XXX: Not sure if this is re-entrant need to check code, if so
864          * you can leave LOCKS out.
865          */
866
867         LDBM_LOCK;
868         mdbm_sync( ldbm );
869         LDBM_UNLOCK;
870 }
871
872
873 #define MAX_MDBM_RETRY  5
874
875 Datum
876 ldbm_fetch( LDBM ldbm, Datum key )
877 {
878         Datum   d;
879         kvpair  k;
880         int     retry = 0;
881
882         /* This hack is needed because MDBM does not take keys
883          * which begin with NULL when working in the chaining
884          * mode.
885          */
886
887         /* LDBM_LOCK; */
888
889 #ifdef NO_NULL_KEY
890         k.key.dsize = key.dsize + 1;                    
891         k.key.dptr = malloc(k.key.dsize);
892         *(k.key.dptr) = 'l';
893         AC_MEMCPY( (void *)(k.key.dptr + 1), key.dptr, key.dsize );     
894 #else
895         k.key = key;
896 #endif  
897
898         k.val.dptr = NULL;
899         k.val.dsize = 0;
900
901         do {
902
903                 d = mdbm_fetch( ldbm, k );
904
905                 if ( d.dsize > 0 ) {
906
907                         if ( k.val.dptr != NULL ) {
908                                 free( k.val.dptr );
909                         }
910
911                         if ( (k.val.dptr = malloc( d.dsize )) != NULL ) {
912                 
913                                 k.val.dsize = d.dsize;
914                                 d = mdbm_fetch( ldbm, k );
915
916                         } else { 
917
918                                 d.dsize = 0;
919                                 break;
920                         
921                         }
922
923                 }/* if ( d.dsize > 0 ) */
924
925         } while ((d.dsize > k.val.dsize) && (++retry < MAX_MDBM_RETRY));
926
927         /* LDBM_UNLOCK; */
928
929 #ifdef NO_NULL_KEY
930         free(k.key.dptr);
931 #endif
932
933         return d;
934
935 }
936
937
938
939
940 int
941 ldbm_store( LDBM ldbm, Datum key, Datum data, int flags )
942 {
943         int     rc;
944         Datum   int_key;        /* Internal key */
945
946 #ifdef MDBM_DEBUG
947         fprintf( stdout,
948                  "==>(mdbm)ldbm_store(db=%p, key(dptr=%p,sz=%d), data(dptr=%p,sz=%d), flags=%x)\n",
949                  ldbm, key.dptr, key.dsize, data.dptr, data.dsize, flags );
950         fflush( stdout );
951 #endif
952
953         /* LDBM_LOCK; */
954
955 #ifdef NO_NULL_KEY
956         int_key.dsize = key.dsize + 1;
957         int_key.dptr = malloc( int_key.dsize );
958         *(int_key.dptr) = 'l';  /* Must not be NULL !*/
959         AC_MEMCPY( (void *)(int_key.dptr + 1), key.dptr, key.dsize );
960 #else
961         int_key = key;
962 #endif
963
964         rc = mdbm_store( ldbm, int_key, data, flags );
965         if ( flags & LDBM_SYNC ) {
966                 mdbm_sync( ldbm );
967         }
968
969         /* LDBM_UNLOCK; */
970
971 #ifdef MDBM_DEBUG
972         fprintf( stdout, "<==(mdbm)ldbm_store(rc=%d)\n", rc );
973         fflush( stdout );
974 #endif
975
976 #ifdef NO_NULL_KEY
977         free(int_key.dptr);
978 #endif
979
980         return( rc );
981
982 }
983
984
985
986 int
987 ldbm_delete( LDBM ldbm, Datum key )
988 {
989         int     rc;
990         Datum   int_key;
991
992         /* LDBM_LOCK; */
993
994 #ifdef NO_NULL_KEY
995         int_key.dsize = key.dsize + 1;
996         int_key.dptr = malloc(int_key.dsize);
997         *(int_key.dptr) = 'l';
998         AC_MEMCPY( (void *)(int_key.dptr + 1), key.dptr, key.dsize );   
999 #else
1000         int_key = key;
1001 #endif
1002         
1003         rc = mdbm_delete( ldbm, int_key );
1004
1005         /* LDBM_UNLOCK; */
1006 #ifdef NO_NULL_KEY
1007         free(int_key.dptr);
1008 #endif
1009
1010         return( rc );
1011 }
1012
1013
1014
1015
1016 static Datum
1017 ldbm_get_next( LDBM ldbm, kvpair (*fptr)(MDBM *, kvpair) ) 
1018 {
1019         kvpair  out;
1020         kvpair  in;
1021         Datum   ret;
1022         size_t  sz = MDBM_PAGE_SIZE(ldbm);
1023 #ifdef NO_NULL_KEY
1024         int     delta = 1;
1025 #else
1026         int     delta = 0;
1027 #endif
1028
1029         /* LDBM_LOCK; */
1030
1031         in.key.dsize = sz;      /* Assume first key in one pg */
1032         in.key.dptr = malloc(sz);
1033         
1034         in.val.dptr = NULL;     /* Don't need data just key */ 
1035         in.val.dsize = 0;
1036
1037         ret.dptr = NULL;
1038         ret.dsize = NULL;
1039
1040         out = fptr( ldbm, in );
1041
1042         if (out.key.dsize > 0) {
1043                 ret.dsize = out.key.dsize - delta;
1044
1045                 if ((ret.dptr = (char *)malloc(ret.dsize)) == NULL) { 
1046                         ret.dsize = 0;
1047                         ret.dptr = NULL;
1048
1049                 } else {
1050                         AC_MEMCPY(ret.dptr, (void *)(out.key.dptr + delta),
1051                                 ret.dsize );
1052             }
1053         }
1054
1055         /* LDBM_UNLOCK; */
1056         
1057         free(in.key.dptr);
1058         return ret;
1059 }
1060
1061 Datum
1062 ldbm_firstkey( LDBM ldbm, LDBMCursor **dbcp )
1063 {
1064         return ldbm_get_next( ldbm, mdbm_first );
1065 }
1066
1067 Datum
1068 ldbm_nextkey( LDBM ldbm, Datum key, LDBMCursor *dbcp )
1069 {
1070         /* XXX:
1071          * don't know if this will affect the LDAP server operation 
1072          * but mdbm cannot take and input key.
1073          */
1074
1075         return ldbm_get_next( ldbm, mdbm_next );
1076 }
1077
1078 int
1079 ldbm_errno( LDBM ldbm )
1080 {
1081         /* XXX: best we can do with current  mdbm interface */
1082         return( errno );
1083 }
1084
1085
1086
1087
1088 #elif defined( HAVE_NDBM )
1089
1090 /*****************************************************************
1091  *                                                               *
1092  * if no gdbm or mdbm, fall back to using ndbm, the standard unix thing  *
1093  *                                                               *
1094  *****************************************************************/
1095
1096 /* ARGSUSED */
1097 LDBM
1098 ldbm_open( DB_ENV *env, char *name, int rw, int mode, int dbcachesize )
1099 {
1100         LDBM ldbm;
1101
1102         LDBM_LOCK;
1103         ldbm = dbm_open( name, rw, mode );
1104         LDBM_UNLOCK;
1105
1106         return( ldbm );
1107 }
1108
1109 void
1110 ldbm_close( LDBM ldbm )
1111 {
1112         LDBM_LOCK;
1113         dbm_close( ldbm );
1114         LDBM_UNLOCK;
1115 }
1116
1117 /* ARGSUSED */
1118 void
1119 ldbm_sync( LDBM ldbm )
1120 {
1121         return;
1122 }
1123
1124 Datum
1125 ldbm_fetch( LDBM ldbm, Datum key )
1126 {
1127         Datum d;
1128
1129         LDBM_LOCK;
1130         d = ldbm_datum_dup( ldbm, dbm_fetch( ldbm, key ) );
1131         LDBM_UNLOCK;
1132
1133         return d;
1134 }
1135
1136 int
1137 ldbm_store( LDBM ldbm, Datum key, Datum data, int flags )
1138 {
1139         int rc;
1140
1141         LDBM_LOCK;
1142         rc = dbm_store( ldbm, key, data, flags );
1143         LDBM_UNLOCK;
1144
1145         return rc;
1146 }
1147
1148 int
1149 ldbm_delete( LDBM ldbm, Datum key )
1150 {
1151         int rc;
1152
1153         LDBM_LOCK;
1154         rc = dbm_delete( ldbm, key );
1155         LDBM_UNLOCK;
1156
1157         return rc;
1158 }
1159
1160 Datum
1161 ldbm_firstkey( LDBM ldbm, LDBMCursor **dbcp )
1162 {
1163         Datum d;
1164
1165         LDBM_LOCK;
1166         d = dbm_firstkey( ldbm );
1167         LDBM_UNLOCK;
1168
1169         return d;
1170 }
1171
1172 Datum
1173 ldbm_nextkey( LDBM ldbm, Datum key, LDBMCursor *dbcp )
1174 {
1175         Datum d;
1176
1177         LDBM_LOCK;
1178         d = dbm_nextkey( ldbm );
1179         LDBM_UNLOCK;
1180
1181         return d;
1182 }
1183
1184 int
1185 ldbm_errno( LDBM ldbm )
1186 {
1187         int err;
1188
1189         LDBM_LOCK;
1190         err = dbm_error( ldbm );
1191         LDBM_UNLOCK;
1192
1193         return err;
1194 }
1195
1196 #endif /* ndbm */
1197 #endif /* ldbm */