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