]> git.sur5r.net Git - openldap/blob - libraries/libldbm/ldbm.c
Cyrus SASL uses screwy terms.
[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         if ( d.dptr != NULL ) {
533                 *dbcp = (Datum *) malloc( sizeof( Datum ) );
534                 **dbcp = ldbm_datum_dup( ldbm, d );
535         }
536
537         return d;
538 }
539
540 Datum
541 ldbm_nextkey( LDBM ldbm, Datum key, LDBMCursor *dbcp )
542 {
543         Datum d;
544
545         LDBM_LOCK;
546         d = gdbm_nextkey( ldbm, *dbcp );
547         LDBM_UNLOCK;
548
549         ldbm_datum_free( ldbm, *dbcp );
550
551         if ( d.dptr != NULL ) {
552                 *dbcp = ldbm_datum_dup( ldbm, d );
553         } else {
554                 free( dbcp );
555         }
556
557         return d;
558 }
559
560 int
561 ldbm_errno( LDBM ldbm )
562 {
563         int err;
564
565         LDBM_LOCK;
566         err = gdbm_errno;
567         LDBM_UNLOCK;
568
569         return( err );
570 }
571
572 #elif HAVE_MDBM
573
574 /* MMAPED DBM HASHING DATABASE */
575
576 #include <ac/string.h>
577
578 /* #define MDBM_DEBUG */
579
580 #ifdef MDBM_DEBUG
581 #include <stdio.h>
582 #endif
583
584 #define NO_NULL_KEY
585 /* #define MDBM_CHAIN */
586
587 #ifdef MDBM_CHAIN
588
589 /* Use chaining */
590
591
592 #define mdbm_store      mdbm_chain_store
593 #define mdbm_fetch      mdbm_chain_fetch
594 #define mdbm_delete     mdbm_chain_delete
595 #define mdbm_first      mdbm_chain_first
596 #define mdbm_next       mdbm_chain_next
597
598 #endif
599
600 #define MDBM_PG_SZ      (4*1024)
601
602 /*****************************************************************
603  *                                                               *
604  * use mdbm                                                      *
605  *                                                               *
606  *****************************************************************/
607
608 LDBM
609 ldbm_open( char *name, int rw, int mode, int dbcachesize )
610 {
611         LDBM            db;
612
613 #ifdef MDBM_DEBUG
614         fprintf( stdout,
615                  "==>(mdbm)ldbm_open(name=%s,rw=%x,mode=%x,cachesize=%d)\n",
616                  name ? name : "NULL", rw, mode, dbcachesize );
617         fflush( stdout );
618 #endif
619
620         LDBM_LOCK;      /* We need locking here, this is the only non-thread
621                          * safe function we have.
622                          */
623
624         if ( (db =  mdbm_open( name, rw, mode, MDBM_PG_SZ )) == NULL ) {
625
626                 LDBM_UNLOCK;
627 #ifdef MDBM_DEBUG
628                 fprintf( stdout, "<==(mdbm)ldbm_open(db=NULL)\n" );
629                 fflush( stdout );
630 #endif
631                 return( NULL );
632
633         }
634
635 #ifdef MDBM_CHAIN
636         (void)mdbm_set_chain(db);
637 #endif
638
639         LDBM_UNLOCK;
640
641 #ifdef MDBM_DEBUG
642         fprintf( stdout, "<==(mdbm)ldbm_open(db=%p)\n", db );
643         fflush( stdout );
644 #endif
645
646         return( db );
647
648 }
649
650
651
652
653 void
654 ldbm_close( LDBM ldbm )
655 {
656
657         /* Open and close are not reentrant so we need to use locks here */
658
659 #ifdef MDBM_DEBUG
660         fprintf( stdout,
661                  "==>(mdbm)ldbm_close(db=%p)\n", ldbm );
662         fflush( stdout );
663 #endif
664
665         LDBM_LOCK;
666         mdbm_close( ldbm );
667         LDBM_UNLOCK;
668
669 #ifdef MDBM_DEBUG
670         fprintf( stdout, "<==(mdbm)ldbm_close()\n" );
671         fflush( stdout );
672 #endif
673
674 }
675
676
677
678
679 void
680 ldbm_sync( LDBM ldbm )
681 {
682
683         /* XXX: Not sure if this is re-entrant need to check code, if so
684          * you can leave LOCKS out.
685          */
686
687         LDBM_LOCK;
688         mdbm_sync( ldbm );
689         LDBM_UNLOCK;
690
691 }
692
693
694 #define MAX_MDBM_RETRY  5
695
696 Datum
697 ldbm_fetch( LDBM ldbm, Datum key )
698 {
699         Datum   d;
700         kvpair  k;
701         int     retry = 0;
702
703         /* This hack is needed because MDBM does not take keys
704          * which begin with NULL when working in the chaining
705          * mode.
706          */
707
708         /* LDBM_LOCK; */
709
710 #ifdef NO_NULL_KEY
711         k.key.dsize = key.dsize + 1;                    
712         k.key.dptr = malloc(k.key.dsize);
713         *(k.key.dptr) = 'l';
714         memcpy( (void *)(k.key.dptr + 1), key.dptr, key.dsize );        
715 #else
716         k.key = key;
717 #endif  
718
719         k.val.dptr = NULL;
720         k.val.dsize = 0;
721
722         do {
723
724                 d = mdbm_fetch( ldbm, k );
725
726                 if ( d.dsize > 0 ) {
727
728                         if ( k.val.dptr != NULL ) {
729                             
730                             free( k.val.dptr );
731
732                         }
733
734                         if ( (k.val.dptr = malloc( d.dsize )) != NULL ) {
735                 
736                                 k.val.dsize = d.dsize;
737                                 d = mdbm_fetch( ldbm, k );
738
739                         } else { 
740
741                                 d.dsize = 0;
742                                 break;
743                         
744                         }
745
746                 }/* if ( d.dsize > 0 ) */
747
748         } while ((d.dsize > k.val.dsize) && (++retry < MAX_MDBM_RETRY));
749
750         /* LDBM_UNLOCK; */
751
752 #ifdef NO_NULL_KEY
753         free(k.key.dptr);
754 #endif
755
756         return d;
757
758 }
759
760
761
762
763 int
764 ldbm_store( LDBM ldbm, Datum key, Datum data, int flags )
765 {
766         int     rc;
767         Datum   int_key;        /* Internal key */
768
769 #ifdef MDBM_DEBUG
770         fprintf( stdout,
771                  "==>(mdbm)ldbm_store(db=%p, key(dptr=%p,sz=%d), data(dptr=%p,sz=%d), flags=%x)\n",
772                  ldbm, key.dptr, key.dsize, data.dptr, data.dsize, flags );
773         fflush( stdout );
774 #endif
775
776         /* LDBM_LOCK; */
777
778 #ifdef NO_NULL_KEY
779         int_key.dsize = key.dsize + 1;
780         int_key.dptr = malloc( int_key.dsize );
781         *(int_key.dptr) = 'l';  /* Must not be NULL !*/
782         memcpy( (void *)(int_key.dptr + 1), key.dptr, key.dsize );
783 #else
784         int_key = key;
785 #endif
786
787         rc = mdbm_store( ldbm, int_key, data, flags );
788         if ( flags & LDBM_SYNC ) {
789                 mdbm_sync( ldbm );
790         }
791
792         /* LDBM_UNLOCK; */
793
794 #ifdef MDBM_DEBUG
795         fprintf( stdout, "<==(mdbm)ldbm_store(rc=%d)\n", rc );
796         fflush( stdout );
797 #endif
798
799 #ifdef NO_NULL_KEY
800         free(int_key.dptr);
801 #endif
802
803         return( rc );
804
805 }
806
807
808
809 int
810 ldbm_delete( LDBM ldbm, Datum key )
811 {
812         int     rc;
813         Datum   int_key;
814
815         /* LDBM_LOCK; */
816
817 #ifdef NO_NULL_KEY
818         int_key.dsize = key.dsize + 1;
819         int_key.dptr = malloc(int_key.dsize);
820         *(int_key.dptr) = 'l';
821         memcpy( (void *)(int_key.dptr + 1), key.dptr, key.dsize );      
822 #else
823         int_key = key;
824 #endif
825         
826         rc = mdbm_delete( ldbm, int_key );
827
828         /* LDBM_UNLOCK; */
829 #ifdef NO_NULL_KEY
830         free(int_key.dptr);
831 #endif
832
833         return( rc );
834
835 }
836
837
838
839
840 static Datum
841 ldbm_get_next( LDBM ldbm, kvpair (*fptr)(MDBM *, kvpair) ) 
842 {
843
844         kvpair  out;
845         kvpair  in;
846         Datum   ret;
847         size_t  sz = MDBM_PAGE_SIZE(ldbm);
848 #ifdef NO_NULL_KEY
849         int     delta = 1;
850 #else
851         int     delta = 0;
852 #endif
853
854         /* LDBM_LOCK; */
855
856         in.key.dsize = sz;      /* Assume first key in one pg */
857         in.key.dptr = malloc(sz);
858         
859         in.val.dptr = NULL;     /* Don't need data just key */ 
860         in.val.dsize = 0;
861
862         ret.dptr = NULL;
863         ret.dsize = NULL;
864
865         out = fptr( ldbm, in );
866
867         if (out.key.dsize > 0) {
868
869             ret.dsize = out.key.dsize - delta;
870             if ((ret.dptr = (char *)malloc(ret.dsize)) == NULL) { 
871
872                 ret.dsize = 0;
873                 ret.dptr = NULL;
874
875             } else {
876
877                 memcpy(ret.dptr, (void *)(out.key.dptr + delta),
878                        ret.dsize );
879
880             }
881
882         }
883
884         /* LDBM_UNLOCK; */
885         
886         free(in.key.dptr);
887
888         return ret;
889
890 }
891
892
893
894
895 Datum
896 ldbm_firstkey( LDBM ldbm, LDBMCursor **dbcp )
897 {
898
899         return ldbm_get_next( ldbm, mdbm_first );
900
901 }
902
903
904
905
906 Datum
907 ldbm_nextkey( LDBM ldbm, Datum key, LDBMCursor *dbcp )
908 {
909
910         /* XXX:
911          * don't know if this will affect the LDAP server opertaion 
912          * but mdbm cannot take and input key.
913          */
914
915         return ldbm_get_next( ldbm, mdbm_next );
916
917 }
918
919 int
920 ldbm_errno( LDBM ldbm )
921 {
922         /* XXX: best we can do with current  mdbm interface */
923         return( errno );
924
925 }
926
927
928
929
930 #elif defined( HAVE_NDBM )
931
932 /*****************************************************************
933  *                                                               *
934  * if no gdbm or mdbm, fall back to using ndbm, the standard unix thing  *
935  *                                                               *
936  *****************************************************************/
937
938 /* ARGSUSED */
939 LDBM
940 ldbm_open( char *name, int rw, int mode, int dbcachesize )
941 {
942         LDBM ldbm;
943
944         LDBM_LOCK;
945         ldbm = dbm_open( name, rw, mode );
946         LDBM_UNLOCK;
947
948         return( ldbm );
949 }
950
951 void
952 ldbm_close( LDBM ldbm )
953 {
954         LDBM_LOCK;
955         dbm_close( ldbm );
956         LDBM_UNLOCK;
957 }
958
959 /* ARGSUSED */
960 void
961 ldbm_sync( LDBM ldbm )
962 {
963         return;
964 }
965
966 Datum
967 ldbm_fetch( LDBM ldbm, Datum key )
968 {
969         Datum d;
970
971         LDBM_LOCK;
972         d = ldbm_datum_dup( ldbm, dbm_fetch( ldbm, key ) );
973         LDBM_UNLOCK;
974
975         return d;
976 }
977
978 int
979 ldbm_store( LDBM ldbm, Datum key, Datum data, int flags )
980 {
981         int rc;
982
983         LDBM_LOCK;
984         rc = dbm_store( ldbm, key, data, flags );
985         LDBM_UNLOCK;
986
987         return rc;
988 }
989
990 int
991 ldbm_delete( LDBM ldbm, Datum key )
992 {
993         int rc;
994
995         LDBM_LOCK;
996         rc = dbm_delete( ldbm, key );
997         LDBM_UNLOCK;
998
999         return rc;
1000 }
1001
1002 Datum
1003 ldbm_firstkey( LDBM ldbm, LDBMCursor **dbcp )
1004 {
1005         Datum d;
1006
1007         LDBM_LOCK;
1008         d = dbm_firstkey( ldbm );
1009         LDBM_UNLOCK;
1010
1011         return d;
1012 }
1013
1014 Datum
1015 ldbm_nextkey( LDBM ldbm, Datum key, LDBMCursor *dbcp )
1016 {
1017         Datum d;
1018
1019         LDBM_LOCK;
1020         d = dbm_nextkey( ldbm );
1021         LDBM_UNLOCK;
1022
1023         return d;
1024 }
1025
1026 int
1027 ldbm_errno( LDBM ldbm )
1028 {
1029         int err;
1030
1031         LDBM_LOCK;
1032         err = dbm_error( ldbm );
1033         LDBM_UNLOCK;
1034
1035         return err;
1036 }
1037
1038 #endif /* ndbm */
1039 #endif /* ldbm */