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