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