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