]> git.sur5r.net Git - openldap/blob - libraries/libldbm/ldbm.c
ignore SIGPIPE
[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 #include "syslog.h"
13
14 #ifdef SLAPD_LDBM
15
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <ac/string.h>
19 #include <ac/errno.h>
20
21 #include "ldbm.h"
22
23 #if defined( LDBM_USE_DBHASH ) || defined( LDBM_USE_DBBTREE )
24
25 /*****************************************************************
26  *                                                               *
27  * use berkeley db hash or btree package                         *
28  *                                                               *
29  *****************************************************************/
30
31 #ifdef HAVE_BERKELEY_DB2
32 /*************************************************
33  *                                               *
34  *  A malloc routine for use with DB_DBT_MALLOC  *
35  *                                               *
36  *************************************************/
37
38 void *
39 ldbm_malloc( size_t size )
40 {
41         return( calloc( 1, size ));
42 }
43
44 /*  a dbEnv for BERKELEYv2  */
45 #include "lthread.h"
46
47 DB_ENV           dbEnv;
48 int              dbEnvInit = 0;
49 pthread_mutex_t  dbEnvInit_mutex;
50
51 void
52 ldbm_db_errcall( char *prefix, char *message )
53 {
54
55         syslog( LOG_INFO, "ldbm_db_errcall(): %s %s", prefix, message );
56
57 }
58
59 #endif
60
61
62 LDBM
63 ldbm_open( char *name, int rw, int mode, int dbcachesize )
64 {
65         LDBM            ret = NULL;
66
67 #ifdef HAVE_BERKELEY_DB2
68         DB_INFO         dbinfo;
69
70         /* initialize an environment for the DB application */
71         pthread_mutex_lock( &dbEnvInit_mutex );
72
73         if ( !dbEnvInit ) {
74                 char   *dir;
75                 char    tmp[BUFSIZ];
76                 int     err = 0;
77                 int     envFlags = DB_CREATE | DB_THREAD;
78
79                 strcpy( tmp, name );
80                 if ( ( dir = strrchr( tmp, '/' )) ) {
81
82                         *dir ='\0';
83                         dir = tmp;
84
85                 } else {
86
87                         dir = "/";
88
89                 }
90
91                 memset( &dbEnv, 0, sizeof( dbEnv ));
92
93                 dbEnv.db_errcall   = ldbm_db_errcall;
94                 dbEnv.db_errpfx    = "==>";
95
96                 if ( ( err = db_appinit( NULL, NULL, &dbEnv, envFlags )) ) {
97                         char  error[BUFSIZ];
98
99                         if ( err < 0 ) sprintf( error, "%ld\n", (long) err );
100                         else           sprintf( error, "%s\n", strerror( err ));
101
102                         syslog( LOG_INFO,
103                         "ldbm_open(): FATAL error in db_appinit(%s) : %s\n",
104                                                         dir, error );
105
106                         exit( 1 );
107
108                 }
109
110                 dbEnvInit = 1;
111
112         }
113         pthread_mutex_unlock( &dbEnvInit_mutex );
114
115         memset( &dbinfo, 0, sizeof( dbinfo ));
116         dbinfo.db_cachesize = dbcachesize;
117         dbinfo.db_pagesize  = DEFAULT_DB_PAGE_SIZE;
118         dbinfo.db_malloc    = ldbm_malloc;
119
120     (void) db_open( name, DB_TYPE, rw, mode, &dbEnv, &dbinfo, &ret );
121
122 #else
123         void            *info;
124         BTREEINFO       binfo;
125         HASHINFO        hinfo;
126
127         if ( DB_TYPE == DB_HASH ) {
128                 memset( (char *) &hinfo, '\0', sizeof(hinfo) );
129                 hinfo.cachesize = dbcachesize;
130                 info = &hinfo;
131         } else if ( DB_TYPE == DB_BTREE ) {
132                 memset( (char *) &binfo, '\0', sizeof(binfo) );
133                 binfo.cachesize = dbcachesize;
134                 info = &binfo;
135         } else {
136                 info = NULL;
137         }
138
139         ret = dbopen( name, rw, mode, DB_TYPE, info );
140
141 #endif
142
143         return( ret );
144 }
145
146 void
147 ldbm_close( LDBM ldbm )
148 {
149 #ifdef HAVE_BERKELEY_DB2
150         (*ldbm->close)( ldbm, 0 );
151 #else
152         (*ldbm->close)( ldbm );
153 #endif
154 }
155
156 void
157 ldbm_sync( LDBM ldbm )
158 {
159         (*ldbm->sync)( ldbm, 0 );
160 }
161
162 void
163 ldbm_datum_free( LDBM ldbm, Datum data )
164 {
165         free( data.dptr );
166 }
167
168 Datum
169 ldbm_datum_dup( LDBM ldbm, Datum data )
170 {
171         Datum   dup;
172
173         ldbm_datum_init( dup );
174
175         if ( data.dsize == 0 ) {
176                 return( dup );
177         }
178         dup.dsize = data.dsize;
179         if ( dup.dptr = (char *) malloc( data.dsize ) )
180                 memcpy( dup.dptr, data.dptr, data.dsize );
181
182         return( dup );
183 }
184
185 Datum
186 ldbm_fetch( LDBM ldbm, Datum key )
187 {
188         Datum   data;
189         int     rc;
190
191 #ifdef HAVE_BERKELEY_DB2
192         ldbm_datum_init( data );
193
194         data.flags = DB_DBT_MALLOC;
195
196         if ( (rc = (*ldbm->get)( ldbm, NULL, &key, &data, 0 )) != 0 ) {
197                 if ( data.dptr ) free( data.dptr );
198 #else
199         if ( (rc = (*ldbm->get)( ldbm, &key, &data, 0 )) == 0 ) {
200                 data = ldbm_datum_dup( ldbm, data );
201         } else {
202 #endif
203                 data.dptr = NULL;
204                 data.dsize = 0;
205         }
206
207         return( data );
208 }
209
210 int
211 ldbm_store( LDBM ldbm, Datum key, Datum data, int flags )
212 {
213         int     rc;
214
215 #ifdef HAVE_BERKELEY_DB2
216         rc = (*ldbm->put)( ldbm, NULL, &key, &data, flags & ~LDBM_SYNC );
217         rc = (-1 ) * rc;
218 #else
219         rc = (*ldbm->put)( ldbm, &key, &data, flags & ~LDBM_SYNC );
220 #endif
221
222         if ( flags & LDBM_SYNC )
223                 (*ldbm->sync)( ldbm, 0 );
224         return( rc );
225 }
226
227 int
228 ldbm_delete( LDBM ldbm, Datum key )
229 {
230         int     rc;
231
232 #ifdef HAVE_BERKELEY_DB2
233         rc = (*ldbm->del)( ldbm, NULL, &key, 0 );
234         rc = (-1 ) * rc;
235 #else
236         rc = (*ldbm->del)( ldbm, &key, 0 );
237 #endif
238         (*ldbm->sync)( ldbm, 0 );
239         return( rc );
240 }
241
242 Datum
243 #ifdef HAVE_BERKELEY_DB2
244 ldbm_firstkey( LDBM ldbm, DBC **dbch )
245 #else
246 ldbm_firstkey( LDBM ldbm )
247 #endif
248 {
249         Datum   key, data;
250         int     rc;
251
252 #ifdef HAVE_BERKELEY_DB2
253         DBC  *dbci;
254
255         ldbm_datum_init( key );
256         ldbm_datum_init( data );
257
258         key.flags = data.flags = DB_DBT_MALLOC;
259
260         /* acquire a cursor for the DB */
261
262 #  if defined( DB_VERSION_MAJOR ) && defined( DB_VERSION_MINOR ) && \
263     DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 6
264
265         if ( (*ldbm->cursor)( ldbm, NULL, &dbci )) {
266
267 #  else
268
269         if ( (*ldbm->cursor)( ldbm, NULL, &dbci, 0 )) {
270
271 #  endif
272
273                 return( key );
274         } else {
275                 *dbch = dbci;
276                 if ( (*dbci->c_get)( dbci, &key, &data, DB_NEXT ) == 0 ) {
277                         if ( data.dptr ) free( data.dptr );
278 #else
279         if ( (rc = (*ldbm->seq)( ldbm, &key, &data, R_FIRST )) == 0 ) {
280                 key = ldbm_datum_dup( ldbm, key );
281 #endif
282         } else {
283                 key.dptr = NULL;
284                 key.dsize = 0;
285         }
286
287 #ifdef HAVE_BERKELEY_DB2
288         }
289 #endif
290
291         return( key );
292 }
293
294 Datum
295 #ifdef HAVE_BERKELEY_DB2
296 ldbm_nextkey( LDBM ldbm, Datum key, DBC *dbcp )
297 #else
298 ldbm_nextkey( LDBM ldbm, Datum key )
299 #endif
300 {
301         Datum   data;
302         int     rc;
303
304 #ifdef HAVE_BERKELEY_DB2
305         void *oldKey = key.dptr;
306
307         ldbm_datum_init( data );
308
309         data.flags = DB_DBT_MALLOC;
310
311         if ( (*dbcp->c_get)( dbcp, &key, &data, DB_NEXT ) == 0 ) {
312                 if ( data.dptr ) free( data.dptr );
313 #else
314         if ( (rc = (*ldbm->seq)( ldbm, &key, &data, R_NEXT )) == 0 ) {
315                 key = ldbm_datum_dup( ldbm, key );
316 #endif
317         } else {
318                 key.dptr = NULL;
319                 key.dsize = 0;
320         }
321 #ifdef HAVE_BERKELEY_DB2
322         if ( oldKey ) free( oldKey );
323 #endif
324
325         return( key );
326 }
327
328 int
329 ldbm_errno( LDBM ldbm )
330 {
331         return( errno );
332 }
333
334 #elif defined( HAVE_GDBM )
335
336 #include <sys/stat.h>
337
338 /*****************************************************************
339  *                                                               *
340  * use gdbm                                                      *
341  *                                                               *
342  *****************************************************************/
343
344 LDBM
345 ldbm_open( char *name, int rw, int mode, int dbcachesize )
346 {
347         LDBM            db;
348         struct stat     st;
349
350         if ( (db =  gdbm_open( name, 0, rw | GDBM_FAST, mode, 0 )) == NULL ) {
351                 return( NULL );
352         }
353         if ( dbcachesize > 0 && stat( name, &st ) == 0 ) {
354                 dbcachesize = (dbcachesize / st.st_blksize);
355                 gdbm_setopt( db, GDBM_CACHESIZE, &dbcachesize, sizeof(int) );
356         }
357
358         return( db );
359 }
360
361 void
362 ldbm_close( LDBM ldbm )
363 {
364         gdbm_close( ldbm );
365 }
366
367 void
368 ldbm_sync( LDBM ldbm )
369 {
370         gdbm_sync( ldbm );
371 }
372
373 void
374 ldbm_datum_free( LDBM ldbm, Datum data )
375 {
376         free( data.dptr );
377 }
378
379 Datum
380 ldbm_datum_dup( LDBM ldbm, Datum data )
381 {
382         Datum   dup;
383
384         if ( data.dsize == 0 ) {
385                 dup.dsize = 0;
386                 dup.dptr = NULL;
387
388                 return( dup );
389         }
390         dup.dsize = data.dsize;
391         if ( (dup.dptr = (char *) malloc( data.dsize )) != NULL )
392                 memcpy( dup.dptr, data.dptr, data.dsize );
393
394         return( dup );
395 }
396
397 Datum
398 ldbm_fetch( LDBM ldbm, Datum key )
399 {
400         return( gdbm_fetch( ldbm, key ) );
401 }
402
403 int
404 ldbm_store( LDBM ldbm, Datum key, Datum data, int flags )
405 {
406         int     rc;
407
408         rc = gdbm_store( ldbm, key, data, flags & ~LDBM_SYNC );
409         if ( flags & LDBM_SYNC )
410                 gdbm_sync( ldbm );
411         return( rc );
412 }
413
414 int
415 ldbm_delete( LDBM ldbm, Datum key )
416 {
417         int     rc;
418
419         rc = gdbm_delete( ldbm, key );
420         gdbm_sync( ldbm );
421         return( rc );
422 }
423
424 Datum
425 ldbm_firstkey( LDBM ldbm )
426 {
427         return( gdbm_firstkey( ldbm ) );
428 }
429
430 Datum
431 ldbm_nextkey( LDBM ldbm, Datum key )
432 {
433         return( gdbm_nextkey( ldbm, key ) );
434 }
435
436 int
437 ldbm_errno( LDBM ldbm )
438 {
439         return( (int) gdbm_errno );
440 }
441
442 #elif defined( HAVE_NDBM )
443
444 /*****************************************************************
445  *                                                               *
446  * if no gdbm, fall back to using ndbm, the standard unix thing  *
447  *                                                               *
448  *****************************************************************/
449
450 /* ARGSUSED */
451 LDBM
452 ldbm_open( char *name, int rw, int mode, int dbcachesize )
453 {
454         return( dbm_open( name, rw, mode ) );
455 }
456
457 void
458 ldbm_close( LDBM ldbm )
459 {
460         dbm_close( ldbm );
461 }
462
463 /* ARGSUSED */
464 void
465 ldbm_sync( LDBM ldbm )
466 {
467         return;
468 }
469
470 void
471 ldbm_datum_free( LDBM ldbm, Datum data )
472 {
473         return;
474 }
475
476 Datum
477 ldbm_datum_dup( LDBM ldbm, Datum data )
478 {
479         Datum   dup;
480
481         if ( data.dsize == 0 ) {
482                 dup.dsize = 0;
483                 dup.dptr = NULL;
484
485                 return( dup );
486         }
487         dup.dsize = data.dsize;
488         dup.dptr = (char *) malloc( data.dsize );
489         if ( dup.dptr )
490                 memcpy( dup.dptr, data.dptr, data.dsize );
491
492         return( dup );
493 }
494
495 Datum
496 ldbm_fetch( LDBM ldbm, Datum key )
497 {
498         return( ldbm_datum_dup( ldbm, dbm_fetch( ldbm, key ) ) );
499 }
500
501 int
502 ldbm_store( LDBM ldbm, Datum key, Datum data, int flags )
503 {
504         return( dbm_store( ldbm, key, data, flags ) );
505 }
506
507 int
508 ldbm_delete( LDBM ldbm, Datum key )
509 {
510         return( dbm_delete( ldbm, key ) );
511 }
512
513 Datum
514 ldbm_firstkey( LDBM ldbm )
515 {
516         return( dbm_firstkey( ldbm ) );
517 }
518
519 Datum
520 ldbm_nextkey( LDBM ldbm, Datum key )
521 {
522         return( dbm_nextkey( ldbm ) );
523 }
524
525 int
526 ldbm_errno( LDBM ldbm )
527 {
528         return( dbm_error( ldbm ) );
529 }
530
531 #endif /* ndbm */
532 #endif /* ldbm */