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