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