]> git.sur5r.net Git - openldap/blob - libraries/libldbm/ldbm.c
Update NT port with support for -lldap_r and -lldbm.
[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         free( data.dptr );
27         data.dptr = NULL;
28 }
29
30
31 Datum
32 ldbm_datum_dup( LDBM ldbm, Datum data )
33 {
34         Datum   dup;
35
36         if ( data.dsize == 0 ) {
37                 dup.dsize = 0;
38                 dup.dptr = NULL;
39
40                 return( dup );
41         }
42         dup.dsize = data.dsize;
43         if ( (dup.dptr = (char *) malloc( data.dsize )) != NULL )
44                 memcpy( dup.dptr, data.dptr, data.dsize );
45
46         return( dup );
47 }
48
49 static int ldbm_initialized = 0;
50
51 #ifndef HAVE_BERKELEY_DB2
52 /* Everything but DB2 is non-reentrant */
53
54 static ldap_pvt_thread_mutex_t ldbm_big_mutex;
55 #define LDBM_LOCK       (ldap_pvt_thread_mutex_lock(&ldbm_big_mutex))
56 #define LDBM_UNLOCK     (ldap_pvt_thread_mutex_unlock(&ldbm_big_mutex))
57
58 int ldbm_initialize( void )
59 {
60         if(ldbm_initialized++) return 1;
61
62         ldap_pvt_thread_mutex_init( &ldbm_big_mutex );
63
64         return 0;
65 }
66
67 int ldbm_shutdown( void )
68 {
69         if( !ldbm_initialized ) return 1;
70
71         ldap_pvt_thread_mutex_destroy( &ldbm_big_mutex );
72
73         return 0;
74 }
75
76 #else
77
78 #ifdef HAVE_SYSLOG
79 #include "syslog.h"
80 #else
81 /* quick hack */
82 #define LOG_INFO 1
83 extern int syslog(int, char*, ...);
84 #endif
85
86 void *
87 ldbm_malloc( size_t size )
88 {
89         return( calloc( 1, size ));
90 }
91
92 static void
93 ldbm_db_errcall( const char *prefix, char *message )
94 {
95         syslog( LOG_INFO, "ldbm_db_errcall(): %s %s", prefix, message );
96 }
97
98 /*  a dbEnv for BERKELEYv2  */
99 DB_ENV           ldbm_Env;
100
101 /* Berkeley DB 2.x is reentrant */
102 #define LDBM_LOCK       ((void)0)
103 #define LDBM_UNLOCK     ((void)0)
104
105 int ldbm_initialize( void )
106 {
107         int     err;
108         int     envFlags;
109
110         if(ldbm_initialized++) return 1;
111
112         memset( &ldbm_Env, 0, sizeof( ldbm_Env ));
113
114         ldbm_Env.db_errcall   = ldbm_db_errcall;
115         ldbm_Env.db_errpfx    = "==>";
116
117         envFlags = DB_CREATE | DB_THREAD;
118
119         if ( ( err = db_appinit( NULL, NULL, &ldbm_Env, envFlags )) ) {
120                 char  error[BUFSIZ];
121
122                 if ( err < 0 ) {
123                         sprintf( error, "%ld\n", (long) err );
124                 } else {
125                         sprintf( error, "%s\n", strerror( err ));
126                 }
127
128                 syslog( LOG_INFO,
129                         "ldbm_initialize(): FATAL error in db_appinit() : %s\n",
130                         error );
131                 return( 1 );
132         }
133
134         return 0;
135 }
136
137 int ldbm_shutdown( void )
138 {
139         if( !ldbm_initialized ) return 1;
140
141         db_appexit( &ldbm_Env );
142
143         return 0;
144 }
145
146 #endif
147
148 #if defined( LDBM_USE_DBHASH ) || defined( LDBM_USE_DBBTREE )
149
150 /*****************************************************************
151  *                                                               *
152  * use berkeley db hash or btree package                         *
153  *                                                               *
154  *****************************************************************/
155
156 LDBM
157 ldbm_open( char *name, int rw, int mode, int dbcachesize )
158 {
159         LDBM            ret = NULL;
160
161 #ifdef HAVE_BERKELEY_DB2
162         DB_INFO dbinfo;
163
164         memset( &dbinfo, 0, sizeof( dbinfo ));
165         if ( ldbm_Env.mp_info == NULL )
166                 dbinfo.db_cachesize = dbcachesize;
167         dbinfo.db_pagesize  = DEFAULT_DB_PAGE_SIZE;
168         dbinfo.db_malloc    = ldbm_malloc;
169
170         LDBM_LOCK;
171     (void) db_open( name, DB_TYPE, rw, mode, &ldbm_Env, &dbinfo, &ret );
172         LDBM_UNLOCK;
173
174 #else
175         void            *info;
176         BTREEINFO       binfo;
177         HASHINFO        hinfo;
178
179         if ( DB_TYPE == DB_HASH ) {
180                 memset( (char *) &hinfo, '\0', sizeof(hinfo) );
181                 hinfo.cachesize = dbcachesize;
182                 info = &hinfo;
183         } else if ( DB_TYPE == DB_BTREE ) {
184                 memset( (char *) &binfo, '\0', sizeof(binfo) );
185                 binfo.cachesize = dbcachesize;
186                 info = &binfo;
187         } else {
188                 info = NULL;
189         }
190
191         LDBM_LOCK;
192         ret = dbopen( name, rw, mode, DB_TYPE, info );
193         LDBM_UNLOCK;
194
195 #endif
196
197         return( ret );
198 }
199
200 void
201 ldbm_close( LDBM ldbm )
202 {
203         LDBM_LOCK;
204 #ifdef HAVE_BERKELEY_DB2
205         (*ldbm->close)( ldbm, 0 );
206 #else
207         (*ldbm->close)( ldbm );
208 #endif
209         LDBM_UNLOCK;
210 }
211
212 void
213 ldbm_sync( LDBM ldbm )
214 {
215         LDBM_LOCK;
216         (*ldbm->sync)( ldbm, 0 );
217         LDBM_UNLOCK;
218 }
219
220 Datum
221 ldbm_fetch( LDBM ldbm, Datum key )
222 {
223         Datum   data;
224         int     rc;
225
226         LDBM_LOCK;
227
228 #ifdef HAVE_BERKELEY_DB2
229         ldbm_datum_init( data );
230
231         data.flags = DB_DBT_MALLOC;
232
233         if ( (rc = (*ldbm->get)( ldbm, NULL, &key, &data, 0 )) != 0 ) {
234                 if ( data.dptr ) free( data.dptr );
235 #else
236         if ( (rc = (*ldbm->get)( ldbm, &key, &data, 0 )) == 0 ) {
237                 /* Berkeley DB 1.85 don't malloc the data for us */
238                 /* duplicate it for to ensure reentrancy */
239                 data = ldbm_datum_dup( ldbm, data );
240         } else {
241 #endif
242                 data.dptr = NULL;
243                 data.dsize = 0;
244         }
245
246         LDBM_UNLOCK;
247
248         return( data );
249 }
250
251 int
252 ldbm_store( LDBM ldbm, Datum key, Datum data, int flags )
253 {
254         int     rc;
255
256         LDBM_LOCK;
257
258 #ifdef HAVE_BERKELEY_DB2
259         rc = (*ldbm->put)( ldbm, NULL, &key, &data, flags & ~LDBM_SYNC );
260         rc = (-1 ) * rc;
261 #else
262         rc = (*ldbm->put)( ldbm, &key, &data, flags & ~LDBM_SYNC );
263 #endif
264
265         if ( flags & LDBM_SYNC )
266                 (*ldbm->sync)( ldbm, 0 );
267
268         LDBM_UNLOCK;
269
270         return( rc );
271 }
272
273 int
274 ldbm_delete( LDBM ldbm, Datum key )
275 {
276         int     rc;
277
278         LDBM_LOCK;
279
280 #ifdef HAVE_BERKELEY_DB2
281         rc = (*ldbm->del)( ldbm, NULL, &key, 0 );
282         rc = (-1 ) * rc;
283 #else
284         rc = (*ldbm->del)( ldbm, &key, 0 );
285 #endif
286         (*ldbm->sync)( ldbm, 0 );
287
288         LDBM_UNLOCK;
289
290         return( rc );
291 }
292
293 Datum
294 #ifdef HAVE_BERKELEY_DB2
295 ldbm_firstkey( LDBM ldbm, DBC **dbch )
296 #else
297 ldbm_firstkey( LDBM ldbm )
298 #endif
299 {
300         Datum   key, data;
301
302 #ifdef HAVE_BERKELEY_DB2
303         DBC  *dbci;
304
305         ldbm_datum_init( key );
306         ldbm_datum_init( data );
307
308         key.flags = data.flags = DB_DBT_MALLOC;
309
310         LDBM_LOCK;
311
312         /* acquire a cursor for the DB */
313
314 #  if defined( DB_VERSION_MAJOR ) && defined( DB_VERSION_MINOR ) && \
315     DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 6
316
317         if ( (*ldbm->cursor)( ldbm, NULL, &dbci )) 
318
319 #  else
320         if ( (*ldbm->cursor)( ldbm, NULL, &dbci, 0 ))
321 #  endif
322         {
323                 return( key );
324         } else {
325                 *dbch = dbci;
326                 if ( (*dbci->c_get)( dbci, &key, &data, DB_NEXT ) == 0 ) {
327                         if ( data.dptr ) {
328                                 free( data.dptr );
329                         }       
330                 }
331 #else
332         int     rc;
333
334         LDBM_LOCK;
335
336         if ( (rc = (*ldbm->seq)( ldbm, &key, &data, R_FIRST )) == 0 ) {
337                 key = ldbm_datum_dup( ldbm, key );
338         }
339 #endif
340         else {
341                 key.dptr = NULL;
342                 key.dsize = 0;
343         }
344
345 #ifdef HAVE_BERKELEY_DB2
346         }
347 #endif
348
349         LDBM_UNLOCK;
350
351         return( key );
352 }
353
354 Datum
355 #ifdef HAVE_BERKELEY_DB2
356 ldbm_nextkey( LDBM ldbm, Datum key, DBC *dbcp )
357 #else
358 ldbm_nextkey( LDBM ldbm, Datum key )
359 #endif
360 {
361         Datum   data;
362
363 #ifdef HAVE_BERKELEY_DB2
364         void *oldKey = key.dptr;
365
366         ldbm_datum_init( data );
367
368         data.flags = DB_DBT_MALLOC;
369
370         LDBM_LOCK;
371
372         if ( (*dbcp->c_get)( dbcp, &key, &data, DB_NEXT ) == 0 ) {
373                 if ( data.dptr ) free( data.dptr );
374         }
375 #else
376         int     rc;
377
378         LDBM_LOCK;
379
380         if ( (rc = (*ldbm->seq)( ldbm, &key, &data, R_NEXT )) == 0 ) {
381                 key = ldbm_datum_dup( ldbm, key );
382         }
383 #endif
384         else {
385                 key.dptr = NULL;
386                 key.dsize = 0;
387         }
388
389         LDBM_UNLOCK;
390
391 #ifdef HAVE_BERKELEY_DB2
392         if ( oldKey ) free( oldKey );
393 #endif
394
395         return( key );
396 }
397
398 int
399 ldbm_errno( LDBM ldbm )
400 {
401         return( errno );
402 }
403
404 #elif defined( HAVE_GDBM )
405
406 #include <sys/stat.h>
407
408 /*****************************************************************
409  *                                                               *
410  * use gdbm                                                      *
411  *                                                               *
412  *****************************************************************/
413
414 LDBM
415 ldbm_open( char *name, int rw, int mode, int dbcachesize )
416 {
417         LDBM            db;
418         struct stat     st;
419
420         LDBM_LOCK;
421
422         if ( (db =  gdbm_open( name, 0, rw | GDBM_FAST, mode, 0 )) == NULL ) {
423                 LDBM_UNLOCK;
424                 return( NULL );
425         }
426         if ( dbcachesize > 0 && stat( name, &st ) == 0 ) {
427                 dbcachesize = (dbcachesize / st.st_blksize);
428                 gdbm_setopt( db, GDBM_CACHESIZE, &dbcachesize, sizeof(int) );
429         }
430
431         LDBM_UNLOCK;
432
433         return( db );
434 }
435
436 void
437 ldbm_close( LDBM ldbm )
438 {
439         LDBM_LOCK;
440         gdbm_close( ldbm );
441         LDBM_UNLOCK;
442 }
443
444 void
445 ldbm_sync( LDBM ldbm )
446 {
447         LDBM_LOCK;
448         gdbm_sync( ldbm );
449         LDBM_UNLOCK;
450 }
451
452 Datum
453 ldbm_fetch( LDBM ldbm, Datum key )
454 {
455         Datum d;
456
457         LDBM_LOCK;
458         d = gdbm_fetch( ldbm, key );
459         LDBM_UNLOCK;
460
461         return d;
462 }
463
464 int
465 ldbm_store( LDBM ldbm, Datum key, Datum data, int flags )
466 {
467         int     rc;
468
469         LDBM_LOCK;
470         rc = gdbm_store( ldbm, key, data, flags & ~LDBM_SYNC );
471         if ( flags & LDBM_SYNC )
472                 gdbm_sync( ldbm );
473         LDBM_UNLOCK;
474
475         return( rc );
476 }
477
478 int
479 ldbm_delete( LDBM ldbm, Datum key )
480 {
481         int     rc;
482
483         LDBM_LOCK;
484         rc = gdbm_delete( ldbm, key );
485         gdbm_sync( ldbm );
486         LDBM_UNLOCK;
487
488         return( rc );
489 }
490
491 Datum
492 ldbm_firstkey( LDBM ldbm )
493 {
494         Datum d;
495
496         LDBM_LOCK;
497         d = gdbm_firstkey( ldbm );
498         LDBM_UNLOCK;
499
500         return d;
501 }
502
503 Datum
504 ldbm_nextkey( LDBM ldbm, Datum key )
505 {
506         Datum d;
507
508         LDBM_LOCK;
509         d = gdbm_nextkey( ldbm, key );
510         LDBM_UNLOCK;
511
512         return d;
513 }
514
515 int
516 ldbm_errno( LDBM ldbm )
517 {
518         int err;
519
520         LDBM_LOCK;
521         err = gdbm_errno;
522         LDBM_UNLOCK;
523
524         return( err );
525 }
526
527 #elif defined( HAVE_NDBM )
528
529 /*****************************************************************
530  *                                                               *
531  * if no gdbm, fall back to using ndbm, the standard unix thing  *
532  *                                                               *
533  *****************************************************************/
534
535 /* ARGSUSED */
536 LDBM
537 ldbm_open( char *name, int rw, int mode, int dbcachesize )
538 {
539         LDBM ldbm;
540
541         LDBM_LOCK;
542         ldbm = dbm_open( name, rw, mode );
543         LDBM_UNLOCK;
544
545         return( ldbm );
546 }
547
548 void
549 ldbm_close( LDBM ldbm )
550 {
551         LDBM_LOCK;
552         dbm_close( ldbm );
553         LDBM_UNLOCK;
554 }
555
556 /* ARGSUSED */
557 void
558 ldbm_sync( LDBM ldbm )
559 {
560         return;
561 }
562
563 Datum
564 ldbm_fetch( LDBM ldbm, Datum key )
565 {
566         Datum d;
567
568         LDBM_LOCK;
569         d = ldbm_datum_dup( ldbm, dbm_fetch( ldbm, key ) );
570         LDBM_UNLOCK;
571
572         return d;
573 }
574
575 int
576 ldbm_store( LDBM ldbm, Datum key, Datum data, int flags )
577 {
578         int rc;
579
580         LDBM_LOCK;
581         rc = dbm_store( ldbm, key, data, flags );
582         LDBM_UNLOCK;
583
584         return rc;
585 }
586
587 int
588 ldbm_delete( LDBM ldbm, Datum key )
589 {
590         int rc;
591
592         LDBM_LOCK;
593         rc = dbm_delete( ldbm, key );
594         LDBM_UNLOCK;
595
596         return rc;
597 }
598
599 Datum
600 ldbm_firstkey( LDBM ldbm )
601 {
602         Datum d;
603
604         LDBM_LOCK;
605         d = dbm_firstkey( ldbm );
606         LDBM_UNLOCK;
607
608         return d;
609 }
610
611 Datum
612 ldbm_nextkey( LDBM ldbm, Datum key )
613 {
614         Datum d;
615
616         LDBM_LOCK;
617         d = dbm_nextkey( ldbm );
618         LDBM_UNLOCK;
619
620         return d;
621 }
622
623 int
624 ldbm_errno( LDBM ldbm )
625 {
626         int err;
627
628         LDBM_LOCK;
629         err = dbm_error( ldbm );
630         LDBM_UNLOCK;
631
632         return err;
633 }
634
635 #endif /* ndbm */
636 #endif /* ldbm */