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