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