#17836 (DB_File-1.805) misses a couple of dTHX declarations
[p5sagit/p5-mst-13.2.git] / ext / DB_File / DB_File.xs
CommitLineData
a0d0e21e 1/*
2
3 DB_File.xs -- Perl 5 interface to Berkeley DB
4
6ca2e664 5 written by Paul Marquess <Paul.Marquess@btinternet.com>
efc79c7d 6 last modified 1st September 2002
7 version 1.805
a0d0e21e 8
9 All comments/suggestions/problems are welcome
10
d63909e4 11 Copyright (c) 1995-2002 Paul Marquess. All rights reserved.
36477c24 12 This program is free software; you can redistribute it and/or
13 modify it under the same terms as Perl itself.
14
3b35bae3 15 Changes:
4633a7c4 16 0.1 - Initial Release
17 0.2 - No longer bombs out if dbopen returns an error.
18 0.3 - Added some support for multiple btree compares
19 1.0 - Complete support for multiple callbacks added.
20 Fixed a problem with pushing a value onto an empty list.
21 1.01 - Fixed a SunOS core dump problem.
22 The return value from TIEHASH wasn't set to NULL when
23 dbopen returned an error.
88108326 24 1.02 - Use ALIAS to define TIEARRAY.
25 Removed some redundant commented code.
26 Merged OS2 code into the main distribution.
27 Allow negative subscripts with RECNO interface.
28 Changed the default flags to O_CREAT|O_RDWR
f6b705ef 29 1.03 - Added EXISTS
610ab055 30 1.04 - fixed a couple of bugs in hash_cb. Patches supplied by
31 Dave Hammen, hammen@gothamcity.jsc.nasa.gov
32 1.05 - Added logic to allow prefix & hash types to be specified via
33 Makefile.PL
ff68c719 34 1.06 - Minor namespace cleanup: Localized PrintBtree.
36477c24 35 1.07 - Fixed bug with RECNO, where bval wasn't defaulting to "\n".
36 1.08 - No change to DB_File.xs
18d2dc8c 37 1.09 - Default mode for dbopen changed to 0666
a0b8c8c1 38 1.10 - Fixed fd method so that it still returns -1 for
39 in-memory files when db 1.86 is used.
778183f3 40 1.11 - No change to DB_File.xs
68dc0745 41 1.12 - No change to DB_File.xs
1f70e1ea 42 1.13 - Tidied up a few casts.
43 1.14 - Made it illegal to tie an associative array to a RECNO
44 database and an ordinary array to a HASH or BTREE database.
45 1.50 - Make work with both DB 1.x or DB 2.x
46 1.51 - Fixed a bug in mapping 1.x O_RDONLY flag to 2.x DB_RDONLY equivalent
47 1.52 - Patch from Gisle Aas <gisle@aas.no> to suppress "use of
a6ed719b 48 undefined value" warning with db_get and db_seq.
1f70e1ea 49 1.53 - Added DB_RENUMBER to flags for recno.
50 1.54 - Fixed bug in the fd method
51 1.55 - Fix for AIX from Jarkko Hietaniemi
52 1.56 - No change to DB_File.xs
045291aa 53 1.57 - added the #undef op to allow building with Threads support.
54 1.58 - Fixed a problem with the use of sv_setpvn. When the
55 size is specified as 0, it does a strlen on the data.
56 This was ok for DB 1.x, but isn't for DB 2.x.
a9fd575d 57 1.59 - No change to DB_File.xs
58 1.60 - Some code tidy up
9d9477b1 59 1.61 - added flagSet macro for DB 2.5.x
60 fixed typo in O_RDONLY test.
6ca2e664 61 1.62 - No change to DB_File.xs
62 1.63 - Fix to alllow DB 2.6.x to build.
20896112 63 1.64 - Tidied up the 1.x to 2.x flags mapping code.
64 Added a patch from Mark Kettenis <kettenis@wins.uva.nl>
65 to fix a flag mapping problem with O_RDONLY on the Hurd
ca63f0d2 66 1.65 - Fixed a bug in the PUSH logic.
67 Added BOOT check that using 2.3.4 or greater
9fe6733a 68 1.66 - Added DBM filter code
cad2e5aa 69 1.67 - Backed off the use of newSVpvn.
70 Fixed DBM Filter code for Perl 5.004.
71 Fixed a small memory leak in the filter code.
2c2d71f5 72 1.68 - fixed backward compatability bug with R_IAFTER & R_IBEFORE
73 merged in the 5.005_58 changes
a62982a8 74 1.69 - fixed a bug in push -- DB_APPEND wasn't working properly.
75 Fixed the R_SETCURSOR bug introduced in 1.68
76 Added a new Perl variable $DB_File::db_ver
e07e3419 77 1.70 - Initialise $DB_File::db_ver and $DB_File::db_version with
78 GV_ADD|GV_ADDMULT -- bug spotted by Nick Ing-Simmons.
79 Added a BOOT check to test for equivalent versions of db.h &
80 libdb.a/so.
ccb44e3b 81 1.71 - Support for Berkeley DB version 3.
82 Support for Berkeley DB 2/3's backward compatability mode.
83 Rewrote push
b90e71be 84 1.72 - No change to DB_File.xs
88c74d4b 85 1.73 - No change to DB_File.xs
3245f058 86 1.74 - A call to open needed parenthesised to stop it clashing
87 with a win32 macro.
88 Added Perl core patches 7703 & 7801.
73969f8f 89 1.75 - Fixed Perl core patch 7703.
90 Added suppport to allow DB_File to be built with
91 Berkeley DB 3.2 -- btree_compare, btree_prefix and hash_cb
92 needed to be changed.
c5da4faf 93 1.76 - No change to DB_File.xs
94 1.77 - Tidied up a few types used in calling newSVpvn.
39793c41 95 1.78 - Core patch 10335, 10372, 10534, 10549, 11051 included.
c6c92ad9 96 1.79 - NEXTKEY ignores the input key.
97 Added lots of casts
07200f1b 98 1.800 - Moved backward compatability code into ppport.h.
99 Use the new constants code.
412e9c57 100 1.801 - No change to DB_File.xs
d63909e4 101 1.802 - No change to DB_File.xs
962cee9f 102 1.803 - FETCH, STORE & DELETE don't map the flags parameter
103 into the equivalent Berkeley DB function anymore.
efc79c7d 104 1.804 - no change.
105 1.805 - recursion detection added to the callbacks
106 Support for 4.1.X added.
107 Filter code can now cope with read-only $_
f6b705ef 108
a0d0e21e 109*/
110
c6c619a9 111#define PERL_NO_GET_CONTEXT
a0d0e21e 112#include "EXTERN.h"
113#include "perl.h"
114#include "XSUB.h"
115
07200f1b 116#ifdef _NOT_CORE
117# include "ppport.h"
cad2e5aa 118#endif
119
640374d0 120/* Mention DB_VERSION_MAJOR_CFG, DB_VERSION_MINOR_CFG, and
121 DB_VERSION_PATCH_CFG here so that Configure pulls them all in. */
122
52e1cb5e 123/* Being the Berkeley DB we prefer the <sys/cdefs.h> (which will be
124 * shortly #included by the <db.h>) __attribute__ to the possibly
125 * already defined __attribute__, for example by GNUC or by Perl. */
1f70e1ea 126
39793c41 127/* #if DB_VERSION_MAJOR_CFG < 2 */
128#ifndef DB_VERSION_MAJOR
129# undef __attribute__
640374d0 130#endif
131
ccb44e3b 132#ifdef COMPAT185
133# include <db_185.h>
134#else
135# include <db.h>
136#endif
a0d0e21e 137
39793c41 138/* Wall starts with 5.7.x */
139
140#if PERL_REVISION > 5 || (PERL_REVISION == 5 && PERL_VERSION >= 7)
141
142/* Since we dropped the gccish definition of __attribute__ we will want
143 * to redefine dNOOP, however (so that dTHX continues to work). Yes,
144 * all this means that we can't do attribute checking on the DB_File,
145 * boo, hiss. */
146# ifndef DB_VERSION_MAJOR
147
148# undef dNOOP
149# define dNOOP extern int Perl___notused
150
151 /* Ditto for dXSARGS. */
152# undef dXSARGS
153# define dXSARGS \
154 dSP; dMARK; \
155 I32 ax = mark - PL_stack_base + 1; \
156 I32 items = sp - mark
157
158# endif
159
160/* avoid -Wall; DB_File xsubs never make use of `ix' setup for ALIASes */
161# undef dXSI32
162# define dXSI32 dNOOP
163
164#endif /* Perl >= 5.7 */
b92372bc 165
a0d0e21e 166#include <fcntl.h>
167
1f70e1ea 168/* #define TRACE */
169
ccb44e3b 170#ifdef TRACE
171# define Trace(x) printf x
172#else
173# define Trace(x)
174#endif
175
1f70e1ea 176
ccb44e3b 177#define DBT_clear(x) Zero(&x, 1, DBT) ;
1f70e1ea 178
179#ifdef DB_VERSION_MAJOR
180
ccb44e3b 181#if DB_VERSION_MAJOR == 2
182# define BERKELEY_DB_1_OR_2
183#endif
184
73969f8f 185#if DB_VERSION_MAJOR > 3 || (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR >= 2)
186# define AT_LEAST_DB_3_2
187#endif
188
efc79c7d 189#if DB_VERSION_MAJOR > 4 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 1)
190# define AT_LEAST_DB_4_1
191#endif
192
1f70e1ea 193/* map version 2 features & constants onto their version 1 equivalent */
194
195#ifdef DB_Prefix_t
2c2d71f5 196# undef DB_Prefix_t
1f70e1ea 197#endif
198#define DB_Prefix_t size_t
199
200#ifdef DB_Hash_t
2c2d71f5 201# undef DB_Hash_t
1f70e1ea 202#endif
203#define DB_Hash_t u_int32_t
204
205/* DBTYPE stays the same */
206/* HASHINFO, RECNOINFO and BTREEINFO map to DB_INFO */
ccb44e3b 207#if DB_VERSION_MAJOR == 2
208 typedef DB_INFO INFO ;
209#else /* DB_VERSION_MAJOR > 2 */
210# define DB_FIXEDLEN (0x8000)
211#endif /* DB_VERSION_MAJOR == 2 */
1f70e1ea 212
213/* version 2 has db_recno_t in place of recno_t */
214typedef db_recno_t recno_t;
215
216
217#define R_CURSOR DB_SET_RANGE
218#define R_FIRST DB_FIRST
219#define R_IAFTER DB_AFTER
220#define R_IBEFORE DB_BEFORE
221#define R_LAST DB_LAST
222#define R_NEXT DB_NEXT
223#define R_NOOVERWRITE DB_NOOVERWRITE
224#define R_PREV DB_PREV
ccb44e3b 225
a62982a8 226#if DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 5
ccb44e3b 227# define R_SETCURSOR 0x800000
a62982a8 228#else
ccb44e3b 229# define R_SETCURSOR (-100)
a62982a8 230#endif
ccb44e3b 231
1f70e1ea 232#define R_RECNOSYNC 0
233#define R_FIXEDLEN DB_FIXEDLEN
234#define R_DUP DB_DUP
235
ccb44e3b 236
1f70e1ea 237#define db_HA_hash h_hash
238#define db_HA_ffactor h_ffactor
239#define db_HA_nelem h_nelem
240#define db_HA_bsize db_pagesize
241#define db_HA_cachesize db_cachesize
242#define db_HA_lorder db_lorder
243
244#define db_BT_compare bt_compare
245#define db_BT_prefix bt_prefix
246#define db_BT_flags flags
247#define db_BT_psize db_pagesize
248#define db_BT_cachesize db_cachesize
249#define db_BT_lorder db_lorder
250#define db_BT_maxkeypage
251#define db_BT_minkeypage
252
253
254#define db_RE_reclen re_len
255#define db_RE_flags flags
256#define db_RE_bval re_pad
257#define db_RE_bfname re_source
258#define db_RE_psize db_pagesize
259#define db_RE_cachesize db_cachesize
260#define db_RE_lorder db_lorder
261
262#define TXN NULL,
263
264#define do_SEQ(db, key, value, flag) (db->cursor->c_get)(db->cursor, &key, &value, flag)
265
266
267#define DBT_flags(x) x.flags = 0
268#define DB_flags(x, v) x |= v
269
9d9477b1 270#if DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 5
ccb44e3b 271# define flagSet(flags, bitmask) ((flags) & (bitmask))
9d9477b1 272#else
ccb44e3b 273# define flagSet(flags, bitmask) (((flags) & DB_OPFLAGS_MASK) == (bitmask))
9d9477b1 274#endif
275
1f70e1ea 276#else /* db version 1.x */
277
73969f8f 278#define BERKELEY_DB_1
ccb44e3b 279#define BERKELEY_DB_1_OR_2
280
1f70e1ea 281typedef union INFO {
282 HASHINFO hash ;
283 RECNOINFO recno ;
284 BTREEINFO btree ;
285 } INFO ;
286
287
610ab055 288#ifdef mDB_Prefix_t
ccb44e3b 289# ifdef DB_Prefix_t
290# undef DB_Prefix_t
291# endif
292# define DB_Prefix_t mDB_Prefix_t
610ab055 293#endif
294
295#ifdef mDB_Hash_t
ccb44e3b 296# ifdef DB_Hash_t
297# undef DB_Hash_t
298# endif
299# define DB_Hash_t mDB_Hash_t
610ab055 300#endif
301
1f70e1ea 302#define db_HA_hash hash.hash
303#define db_HA_ffactor hash.ffactor
304#define db_HA_nelem hash.nelem
305#define db_HA_bsize hash.bsize
306#define db_HA_cachesize hash.cachesize
307#define db_HA_lorder hash.lorder
308
309#define db_BT_compare btree.compare
310#define db_BT_prefix btree.prefix
311#define db_BT_flags btree.flags
312#define db_BT_psize btree.psize
313#define db_BT_cachesize btree.cachesize
314#define db_BT_lorder btree.lorder
315#define db_BT_maxkeypage btree.maxkeypage
316#define db_BT_minkeypage btree.minkeypage
317
318#define db_RE_reclen recno.reclen
319#define db_RE_flags recno.flags
320#define db_RE_bval recno.bval
321#define db_RE_bfname recno.bfname
322#define db_RE_psize recno.psize
323#define db_RE_cachesize recno.cachesize
324#define db_RE_lorder recno.lorder
325
326#define TXN
327
328#define do_SEQ(db, key, value, flag) (db->dbp->seq)(db->dbp, &key, &value, flag)
329#define DBT_flags(x)
330#define DB_flags(x, v)
9d9477b1 331#define flagSet(flags, bitmask) ((flags) & (bitmask))
1f70e1ea 332
333#endif /* db version 1 */
334
335
336
962cee9f 337#define db_DELETE(db, key, flags) ((db->dbp)->del)(db->dbp, TXN &key, 0)
338#define db_STORE(db, key, value, flags) ((db->dbp)->put)(db->dbp, TXN &key, &value, 0)
339#define db_FETCH(db, key, flags) ((db->dbp)->get)(db->dbp, TXN &key, &value, 0)
1f70e1ea 340
341#define db_sync(db, flags) ((db->dbp)->sync)(db->dbp, flags)
342#define db_get(db, key, value, flags) ((db->dbp)->get)(db->dbp, TXN &key, &value, flags)
9d9477b1 343
1f70e1ea 344#ifdef DB_VERSION_MAJOR
efc79c7d 345#define db_DESTROY(db) (!db->aborted && ( db->cursor->c_close(db->cursor),\
346 (db->dbp->close)(db->dbp, 0) ))
1f70e1ea 347#define db_close(db) ((db->dbp)->close)(db->dbp, 0)
9d9477b1 348#define db_del(db, key, flags) (flagSet(flags, R_CURSOR) \
1f70e1ea 349 ? ((db->cursor)->c_del)(db->cursor, 0) \
350 : ((db->dbp)->del)(db->dbp, NULL, &key, flags) )
351
ccb44e3b 352#else /* ! DB_VERSION_MAJOR */
1f70e1ea 353
efc79c7d 354#define db_DESTROY(db) (!db->aborted && ((db->dbp)->close)(db->dbp))
1f70e1ea 355#define db_close(db) ((db->dbp)->close)(db->dbp)
356#define db_del(db, key, flags) ((db->dbp)->del)(db->dbp, &key, flags)
357#define db_put(db, key, value, flags) ((db->dbp)->put)(db->dbp, &key, &value, flags)
358
ccb44e3b 359#endif /* ! DB_VERSION_MAJOR */
1f70e1ea 360
9d9477b1 361
1f70e1ea 362#define db_seq(db, key, value, flags) do_SEQ(db, key, value, flags)
610ab055 363
8e07c86e 364typedef struct {
365 DBTYPE type ;
366 DB * dbp ;
367 SV * compare ;
efc79c7d 368 bool in_compare ;
8e07c86e 369 SV * prefix ;
efc79c7d 370 bool in_prefix ;
8e07c86e 371 SV * hash ;
efc79c7d 372 bool in_hash ;
373 bool aborted ;
a0b8c8c1 374 int in_memory ;
ccb44e3b 375#ifdef BERKELEY_DB_1_OR_2
1f70e1ea 376 INFO info ;
ccb44e3b 377#endif
1f70e1ea 378#ifdef DB_VERSION_MAJOR
379 DBC * cursor ;
380#endif
9fe6733a 381 SV * filter_fetch_key ;
382 SV * filter_store_key ;
383 SV * filter_fetch_value ;
384 SV * filter_store_value ;
385 int filtering ;
9fe6733a 386
8e07c86e 387 } DB_File_type;
388
389typedef DB_File_type * DB_File ;
a0d0e21e 390typedef DBT DBTKEY ;
391
045291aa 392#define my_sv_setpvn(sv, d, s) sv_setpvn(sv, (s ? d : (void*)""), s)
a0d0e21e 393
9fe6733a 394#define OutputValue(arg, name) \
395 { if (RETVAL == 0) { \
396 my_sv_setpvn(arg, name.data, name.size) ; \
efc79c7d 397 TAINT; \
398 SvTAINTED_on(arg); \
6a31061a 399 DBM_ckFilter(arg, filter_fetch_value,"filter_fetch_value") ; \
9fe6733a 400 } \
88108326 401 }
a0d0e21e 402
9fe6733a 403#define OutputKey(arg, name) \
404 { if (RETVAL == 0) \
405 { \
406 if (db->type != DB_RECNO) { \
407 my_sv_setpvn(arg, name.data, name.size); \
408 } \
409 else \
410 sv_setiv(arg, (I32)*(I32*)name.data - 1); \
efc79c7d 411 TAINT; \
412 SvTAINTED_on(arg); \
6a31061a 413 DBM_ckFilter(arg, filter_fetch_key,"filter_fetch_key") ; \
9fe6733a 414 } \
a0d0e21e 415 }
416
c6c92ad9 417#define my_SvUV32(sv) ((u_int32_t)SvUV(sv))
045291aa 418
39793c41 419#ifdef CAN_PROTOTYPE
420extern void __getBerkeleyDBInfo(void);
421#endif
422
a0d0e21e 423/* Internal Global Data */
07200f1b 424
df3728a2 425#define MY_CXT_KEY "DB_File::_guts" XS_VERSION
426
427typedef struct {
428 recno_t x_Value;
429 recno_t x_zero;
430 DB_File x_CurrentDB;
431 DBTKEY x_empty;
432} my_cxt_t;
433
434START_MY_CXT
435
436#define Value (MY_CXT.x_Value)
437#define zero (MY_CXT.x_zero)
438#define CurrentDB (MY_CXT.x_CurrentDB)
439#define empty (MY_CXT.x_empty)
1f70e1ea 440
efc79c7d 441#define ERR_BUFF "DB_File::Error"
442
1f70e1ea 443#ifdef DB_VERSION_MAJOR
444
445static int
2c2d71f5 446#ifdef CAN_PROTOTYPE
b76802f5 447db_put(DB_File db, DBTKEY key, DBT value, u_int flags)
2c2d71f5 448#else
449db_put(db, key, value, flags)
450DB_File db ;
451DBTKEY key ;
452DBT value ;
453u_int flags ;
454#endif
1f70e1ea 455{
456 int status ;
457
2c2d71f5 458 if (flagSet(flags, R_IAFTER) || flagSet(flags, R_IBEFORE)) {
459 DBC * temp_cursor ;
460 DBT l_key, l_value;
461
462#if DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 6
463 if (((db->dbp)->cursor)(db->dbp, NULL, &temp_cursor) != 0)
9d9477b1 464#else
2c2d71f5 465 if (((db->dbp)->cursor)(db->dbp, NULL, &temp_cursor, 0) != 0)
9d9477b1 466#endif
2c2d71f5 467 return (-1) ;
468
469 memset(&l_key, 0, sizeof(l_key));
470 l_key.data = key.data;
471 l_key.size = key.size;
472 memset(&l_value, 0, sizeof(l_value));
473 l_value.data = value.data;
474 l_value.size = value.size;
475
476 if ( temp_cursor->c_get(temp_cursor, &l_key, &l_value, DB_SET) != 0) {
477 (void)temp_cursor->c_close(temp_cursor);
478 return (-1);
479 }
480
481 status = temp_cursor->c_put(temp_cursor, &key, &value, flags);
482 (void)temp_cursor->c_close(temp_cursor);
483
484 return (status) ;
485 }
486
487
488 if (flagSet(flags, R_CURSOR)) {
489 return ((db->cursor)->c_put)(db->cursor, &key, &value, DB_CURRENT);
490 }
9d9477b1 491
2c2d71f5 492 if (flagSet(flags, R_SETCURSOR)) {
493 if ((db->dbp)->put(db->dbp, NULL, &key, &value, 0) != 0)
494 return -1 ;
495 return ((db->cursor)->c_get)(db->cursor, &key, &value, DB_SET_RANGE);
496
1f70e1ea 497 }
498
499 return ((db->dbp)->put)(db->dbp, NULL, &key, &value, flags) ;
500
501}
502
503#endif /* DB_VERSION_MAJOR */
504
efc79c7d 505static void
506tidyUp(DB_File db)
507{
508 /* db_DESTROY(db); */
509 db->aborted = TRUE ;
510}
511
a0d0e21e 512
513static int
73969f8f 514#ifdef AT_LEAST_DB_3_2
515
516#ifdef CAN_PROTOTYPE
517btree_compare(DB * db, const DBT *key1, const DBT *key2)
518#else
519btree_compare(db, key1, key2)
520DB * db ;
521const DBT * key1 ;
522const DBT * key2 ;
523#endif /* CAN_PROTOTYPE */
524
525#else /* Berkeley DB < 3.2 */
526
2c2d71f5 527#ifdef CAN_PROTOTYPE
b76802f5 528btree_compare(const DBT *key1, const DBT *key2)
2c2d71f5 529#else
530btree_compare(key1, key2)
531const DBT * key1 ;
532const DBT * key2 ;
533#endif
73969f8f 534
535#endif
536
a0d0e21e 537{
2c2d71f5 538#ifdef dTHX
b76802f5 539 dTHX;
2c2d71f5 540#endif
a0d0e21e 541 dSP ;
df3728a2 542 dMY_CXT ;
543 void * data1, * data2 ;
a0d0e21e 544 int retval ;
545 int count ;
efc79c7d 546 DB_File keep_CurrentDB = CurrentDB;
a0d0e21e 547
efc79c7d 548
549 if (CurrentDB->in_compare) {
550 tidyUp(CurrentDB);
551 croak ("DB_File btree_compare: recursion detected\n") ;
552 }
553
c5da4faf 554 data1 = (char *) key1->data ;
555 data2 = (char *) key2->data ;
cad2e5aa 556
2c2d71f5 557#ifndef newSVpvn
a0d0e21e 558 /* As newSVpv will assume that the data pointer is a null terminated C
559 string if the size parameter is 0, make sure that data points to an
560 empty string if the length is 0
561 */
562 if (key1->size == 0)
563 data1 = "" ;
564 if (key2->size == 0)
565 data2 = "" ;
2c2d71f5 566#endif
cad2e5aa 567
a0d0e21e 568 ENTER ;
569 SAVETMPS;
570
924508f0 571 PUSHMARK(SP) ;
572 EXTEND(SP,2) ;
2c2d71f5 573 PUSHs(sv_2mortal(newSVpvn(data1,key1->size)));
574 PUSHs(sv_2mortal(newSVpvn(data2,key2->size)));
a0d0e21e 575 PUTBACK ;
576
efc79c7d 577 CurrentDB->in_compare = TRUE;
578
8e07c86e 579 count = perl_call_sv(CurrentDB->compare, G_SCALAR);
a0d0e21e 580
efc79c7d 581 CurrentDB = keep_CurrentDB;
582 CurrentDB->in_compare = FALSE;
583
a0d0e21e 584 SPAGAIN ;
585
efc79c7d 586 if (count != 1){
587 tidyUp(CurrentDB);
ff0cee69 588 croak ("DB_File btree_compare: expected 1 return value from compare sub, got %d\n", count) ;
efc79c7d 589 }
a0d0e21e 590
591 retval = POPi ;
592
593 PUTBACK ;
594 FREETMPS ;
595 LEAVE ;
efc79c7d 596
a0d0e21e 597 return (retval) ;
598
599}
600
ecfc5424 601static DB_Prefix_t
73969f8f 602#ifdef AT_LEAST_DB_3_2
603
604#ifdef CAN_PROTOTYPE
605btree_prefix(DB * db, const DBT *key1, const DBT *key2)
606#else
607btree_prefix(db, key1, key2)
608Db * db ;
609const DBT * key1 ;
610const DBT * key2 ;
611#endif
612
613#else /* Berkeley DB < 3.2 */
614
2c2d71f5 615#ifdef CAN_PROTOTYPE
b76802f5 616btree_prefix(const DBT *key1, const DBT *key2)
2c2d71f5 617#else
618btree_prefix(key1, key2)
619const DBT * key1 ;
620const DBT * key2 ;
621#endif
73969f8f 622
623#endif
a0d0e21e 624{
2c2d71f5 625#ifdef dTHX
b76802f5 626 dTHX;
2c2d71f5 627#endif
a0d0e21e 628 dSP ;
df3728a2 629 dMY_CXT ;
c5da4faf 630 char * data1, * data2 ;
a0d0e21e 631 int retval ;
632 int count ;
efc79c7d 633 DB_File keep_CurrentDB = CurrentDB;
a0d0e21e 634
efc79c7d 635 if (CurrentDB->in_prefix){
636 tidyUp(CurrentDB);
637 croak ("DB_File btree_prefix: recursion detected\n") ;
638 }
639
c5da4faf 640 data1 = (char *) key1->data ;
641 data2 = (char *) key2->data ;
cad2e5aa 642
2c2d71f5 643#ifndef newSVpvn
a0d0e21e 644 /* As newSVpv will assume that the data pointer is a null terminated C
645 string if the size parameter is 0, make sure that data points to an
646 empty string if the length is 0
647 */
648 if (key1->size == 0)
649 data1 = "" ;
650 if (key2->size == 0)
651 data2 = "" ;
2c2d71f5 652#endif
cad2e5aa 653
a0d0e21e 654 ENTER ;
655 SAVETMPS;
656
924508f0 657 PUSHMARK(SP) ;
658 EXTEND(SP,2) ;
2c2d71f5 659 PUSHs(sv_2mortal(newSVpvn(data1,key1->size)));
660 PUSHs(sv_2mortal(newSVpvn(data2,key2->size)));
a0d0e21e 661 PUTBACK ;
662
efc79c7d 663 CurrentDB->in_prefix = TRUE;
664
8e07c86e 665 count = perl_call_sv(CurrentDB->prefix, G_SCALAR);
a0d0e21e 666
efc79c7d 667 CurrentDB = keep_CurrentDB;
668 CurrentDB->in_prefix = FALSE;
669
a0d0e21e 670 SPAGAIN ;
671
efc79c7d 672 if (count != 1){
673 tidyUp(CurrentDB);
ff0cee69 674 croak ("DB_File btree_prefix: expected 1 return value from prefix sub, got %d\n", count) ;
efc79c7d 675 }
a0d0e21e 676
677 retval = POPi ;
678
679 PUTBACK ;
680 FREETMPS ;
681 LEAVE ;
682
683 return (retval) ;
684}
685
3245f058 686
73969f8f 687#ifdef BERKELEY_DB_1
a56128cb 688# define HASH_CB_SIZE_TYPE size_t
689#else
690# define HASH_CB_SIZE_TYPE u_int32_t
691#endif
692
ecfc5424 693static DB_Hash_t
73969f8f 694#ifdef AT_LEAST_DB_3_2
695
696#ifdef CAN_PROTOTYPE
697hash_cb(DB * db, const void *data, u_int32_t size)
698#else
699hash_cb(db, data, size)
700DB * db ;
701const void * data ;
702HASH_CB_SIZE_TYPE size ;
703#endif
704
705#else /* Berkeley DB < 3.2 */
706
2c2d71f5 707#ifdef CAN_PROTOTYPE
a56128cb 708hash_cb(const void *data, HASH_CB_SIZE_TYPE size)
2c2d71f5 709#else
710hash_cb(data, size)
711const void * data ;
a56128cb 712HASH_CB_SIZE_TYPE size ;
2c2d71f5 713#endif
73969f8f 714
715#endif
a0d0e21e 716{
2c2d71f5 717#ifdef dTHX
b76802f5 718 dTHX;
2c2d71f5 719#endif
a0d0e21e 720 dSP ;
df3728a2 721 dMY_CXT;
a0d0e21e 722 int retval ;
723 int count ;
efc79c7d 724 DB_File keep_CurrentDB = CurrentDB;
725
726 if (CurrentDB->in_hash){
727 tidyUp(CurrentDB);
728 croak ("DB_File hash callback: recursion detected\n") ;
729 }
cad2e5aa 730
2c2d71f5 731#ifndef newSVpvn
a0d0e21e 732 if (size == 0)
733 data = "" ;
2c2d71f5 734#endif
cad2e5aa 735
610ab055 736 /* DGH - Next two lines added to fix corrupted stack problem */
737 ENTER ;
738 SAVETMPS;
739
924508f0 740 PUSHMARK(SP) ;
610ab055 741
2c2d71f5 742 XPUSHs(sv_2mortal(newSVpvn((char*)data,size)));
a0d0e21e 743 PUTBACK ;
744
efc79c7d 745 keep_CurrentDB->in_hash = TRUE;
746
8e07c86e 747 count = perl_call_sv(CurrentDB->hash, G_SCALAR);
a0d0e21e 748
efc79c7d 749 CurrentDB = keep_CurrentDB;
750 CurrentDB->in_hash = FALSE;
751
a0d0e21e 752 SPAGAIN ;
753
efc79c7d 754 if (count != 1){
755 tidyUp(CurrentDB);
ff0cee69 756 croak ("DB_File hash_cb: expected 1 return value from hash sub, got %d\n", count) ;
efc79c7d 757 }
a0d0e21e 758
759 retval = POPi ;
760
761 PUTBACK ;
762 FREETMPS ;
763 LEAVE ;
764
765 return (retval) ;
766}
767
efc79c7d 768static void
769#ifdef CAN_PROTOTYPE
770db_errcall_cb(const char * db_errpfx, char * buffer)
771#else
772db_errcall_cb(db_errpfx, buffer)
773const char * db_errpfx;
774char * buffer;
775#endif
776{
9a40e66e 777 dTHX;
efc79c7d 778 SV * sv = perl_get_sv(ERR_BUFF, FALSE) ;
779 if (sv) {
780 if (db_errpfx)
781 sv_setpvf(sv, "%s: %s", db_errpfx, buffer) ;
782 else
783 sv_setpv(sv, buffer) ;
784 }
785}
a0d0e21e 786
ccb44e3b 787#if defined(TRACE) && defined(BERKELEY_DB_1_OR_2)
a0d0e21e 788
789static void
2c2d71f5 790#ifdef CAN_PROTOTYPE
b76802f5 791PrintHash(INFO *hash)
2c2d71f5 792#else
793PrintHash(hash)
794INFO * hash ;
795#endif
a0d0e21e 796{
797 printf ("HASH Info\n") ;
1f70e1ea 798 printf (" hash = %s\n",
799 (hash->db_HA_hash != NULL ? "redefined" : "default")) ;
800 printf (" bsize = %d\n", hash->db_HA_bsize) ;
801 printf (" ffactor = %d\n", hash->db_HA_ffactor) ;
802 printf (" nelem = %d\n", hash->db_HA_nelem) ;
803 printf (" cachesize = %d\n", hash->db_HA_cachesize) ;
804 printf (" lorder = %d\n", hash->db_HA_lorder) ;
a0d0e21e 805
806}
807
808static void
2c2d71f5 809#ifdef CAN_PROTOTYPE
b76802f5 810PrintRecno(INFO *recno)
2c2d71f5 811#else
812PrintRecno(recno)
813INFO * recno ;
814#endif
a0d0e21e 815{
816 printf ("RECNO Info\n") ;
1f70e1ea 817 printf (" flags = %d\n", recno->db_RE_flags) ;
818 printf (" cachesize = %d\n", recno->db_RE_cachesize) ;
819 printf (" psize = %d\n", recno->db_RE_psize) ;
820 printf (" lorder = %d\n", recno->db_RE_lorder) ;
821 printf (" reclen = %ul\n", (unsigned long)recno->db_RE_reclen) ;
822 printf (" bval = %d 0x%x\n", recno->db_RE_bval, recno->db_RE_bval) ;
823 printf (" bfname = %d [%s]\n", recno->db_RE_bfname, recno->db_RE_bfname) ;
a0d0e21e 824}
825
ff68c719 826static void
2c2d71f5 827#ifdef CAN_PROTOTYPE
b76802f5 828PrintBtree(INFO *btree)
2c2d71f5 829#else
830PrintBtree(btree)
831INFO * btree ;
832#endif
a0d0e21e 833{
834 printf ("BTREE Info\n") ;
1f70e1ea 835 printf (" compare = %s\n",
836 (btree->db_BT_compare ? "redefined" : "default")) ;
837 printf (" prefix = %s\n",
838 (btree->db_BT_prefix ? "redefined" : "default")) ;
839 printf (" flags = %d\n", btree->db_BT_flags) ;
840 printf (" cachesize = %d\n", btree->db_BT_cachesize) ;
841 printf (" psize = %d\n", btree->db_BT_psize) ;
842#ifndef DB_VERSION_MAJOR
843 printf (" maxkeypage = %d\n", btree->db_BT_maxkeypage) ;
844 printf (" minkeypage = %d\n", btree->db_BT_minkeypage) ;
845#endif
846 printf (" lorder = %d\n", btree->db_BT_lorder) ;
a0d0e21e 847}
848
849#else
850
851#define PrintRecno(recno)
852#define PrintHash(hash)
853#define PrintBtree(btree)
854
855#endif /* TRACE */
856
857
858static I32
2c2d71f5 859#ifdef CAN_PROTOTYPE
b76802f5 860GetArrayLength(pTHX_ DB_File db)
2c2d71f5 861#else
862GetArrayLength(db)
863DB_File db ;
864#endif
a0d0e21e 865{
866 DBT key ;
867 DBT value ;
868 int RETVAL ;
869
ccb44e3b 870 DBT_clear(key) ;
871 DBT_clear(value) ;
1f70e1ea 872 RETVAL = do_SEQ(db, key, value, R_LAST) ;
a0d0e21e 873 if (RETVAL == 0)
874 RETVAL = *(I32 *)key.data ;
1f70e1ea 875 else /* No key means empty file */
a0d0e21e 876 RETVAL = 0 ;
877
a0b8c8c1 878 return ((I32)RETVAL) ;
a0d0e21e 879}
880
88108326 881static recno_t
2c2d71f5 882#ifdef CAN_PROTOTYPE
b76802f5 883GetRecnoKey(pTHX_ DB_File db, I32 value)
2c2d71f5 884#else
885GetRecnoKey(db, value)
886DB_File db ;
887I32 value ;
888#endif
88108326 889{
890 if (value < 0) {
891 /* Get the length of the array */
b76802f5 892 I32 length = GetArrayLength(aTHX_ db) ;
88108326 893
894 /* check for attempt to write before start of array */
efc79c7d 895 if (length + value + 1 <= 0) {
896 tidyUp(db);
ff0cee69 897 croak("Modification of non-creatable array value attempted, subscript %ld", (long)value) ;
efc79c7d 898 }
88108326 899
900 value = length + value + 1 ;
901 }
902 else
903 ++ value ;
904
905 return value ;
a0d0e21e 906}
907
ccb44e3b 908
a0d0e21e 909static DB_File
2c2d71f5 910#ifdef CAN_PROTOTYPE
b76802f5 911ParseOpenInfo(pTHX_ int isHASH, char *name, int flags, int mode, SV *sv)
2c2d71f5 912#else
913ParseOpenInfo(isHASH, name, flags, mode, sv)
914int isHASH ;
915char * name ;
916int flags ;
917int mode ;
918SV * sv ;
919#endif
a0d0e21e 920{
ccb44e3b 921
922#ifdef BERKELEY_DB_1_OR_2 /* Berkeley DB Version 1 or 2 */
923
a0d0e21e 924 SV ** svp;
925 HV * action ;
045291aa 926 DB_File RETVAL = (DB_File)safemalloc(sizeof(DB_File_type)) ;
a0d0e21e 927 void * openinfo = NULL ;
045291aa 928 INFO * info = &RETVAL->info ;
2d8e6c8d 929 STRLEN n_a;
df3728a2 930 dMY_CXT;
1f70e1ea 931
932/* printf("In ParseOpenInfo name=[%s] flags=[%d] mode = [%d]\n", name, flags, mode) ; */
045291aa 933 Zero(RETVAL, 1, DB_File_type) ;
a0d0e21e 934
88108326 935 /* Default to HASH */
9fe6733a 936 RETVAL->filtering = 0 ;
937 RETVAL->filter_fetch_key = RETVAL->filter_store_key =
938 RETVAL->filter_fetch_value = RETVAL->filter_store_value =
8e07c86e 939 RETVAL->hash = RETVAL->compare = RETVAL->prefix = NULL ;
940 RETVAL->type = DB_HASH ;
a0d0e21e 941
610ab055 942 /* DGH - Next line added to avoid SEGV on existing hash DB */
943 CurrentDB = RETVAL;
944
a0b8c8c1 945 /* fd for 1.86 hash in memory files doesn't return -1 like 1.85 */
946 RETVAL->in_memory = (name == NULL) ;
947
a0d0e21e 948 if (sv)
949 {
950 if (! SvROK(sv) )
951 croak ("type parameter is not a reference") ;
952
36477c24 953 svp = hv_fetch( (HV*)SvRV(sv), "GOT", 3, FALSE) ;
954 if (svp && SvOK(*svp))
955 action = (HV*) SvRV(*svp) ;
956 else
957 croak("internal error") ;
610ab055 958
a0d0e21e 959 if (sv_isa(sv, "DB_File::HASHINFO"))
960 {
05475680 961
962 if (!isHASH)
963 croak("DB_File can only tie an associative array to a DB_HASH database") ;
964
8e07c86e 965 RETVAL->type = DB_HASH ;
610ab055 966 openinfo = (void*)info ;
a0d0e21e 967
968 svp = hv_fetch(action, "hash", 4, FALSE);
969
970 if (svp && SvOK(*svp))
971 {
1f70e1ea 972 info->db_HA_hash = hash_cb ;
8e07c86e 973 RETVAL->hash = newSVsv(*svp) ;
a0d0e21e 974 }
975 else
1f70e1ea 976 info->db_HA_hash = NULL ;
a0d0e21e 977
a0d0e21e 978 svp = hv_fetch(action, "ffactor", 7, FALSE);
1f70e1ea 979 info->db_HA_ffactor = svp ? SvIV(*svp) : 0;
a0d0e21e 980
981 svp = hv_fetch(action, "nelem", 5, FALSE);
1f70e1ea 982 info->db_HA_nelem = svp ? SvIV(*svp) : 0;
a0d0e21e 983
1f70e1ea 984 svp = hv_fetch(action, "bsize", 5, FALSE);
985 info->db_HA_bsize = svp ? SvIV(*svp) : 0;
986
a0d0e21e 987 svp = hv_fetch(action, "cachesize", 9, FALSE);
1f70e1ea 988 info->db_HA_cachesize = svp ? SvIV(*svp) : 0;
a0d0e21e 989
990 svp = hv_fetch(action, "lorder", 6, FALSE);
1f70e1ea 991 info->db_HA_lorder = svp ? SvIV(*svp) : 0;
a0d0e21e 992
993 PrintHash(info) ;
994 }
995 else if (sv_isa(sv, "DB_File::BTREEINFO"))
996 {
05475680 997 if (!isHASH)
998 croak("DB_File can only tie an associative array to a DB_BTREE database");
999
8e07c86e 1000 RETVAL->type = DB_BTREE ;
610ab055 1001 openinfo = (void*)info ;
a0d0e21e 1002
1003 svp = hv_fetch(action, "compare", 7, FALSE);
1004 if (svp && SvOK(*svp))
1005 {
1f70e1ea 1006 info->db_BT_compare = btree_compare ;
8e07c86e 1007 RETVAL->compare = newSVsv(*svp) ;
a0d0e21e 1008 }
1009 else
1f70e1ea 1010 info->db_BT_compare = NULL ;
a0d0e21e 1011
1012 svp = hv_fetch(action, "prefix", 6, FALSE);
1013 if (svp && SvOK(*svp))
1014 {
1f70e1ea 1015 info->db_BT_prefix = btree_prefix ;
8e07c86e 1016 RETVAL->prefix = newSVsv(*svp) ;
a0d0e21e 1017 }
1018 else
1f70e1ea 1019 info->db_BT_prefix = NULL ;
a0d0e21e 1020
1021 svp = hv_fetch(action, "flags", 5, FALSE);
1f70e1ea 1022 info->db_BT_flags = svp ? SvIV(*svp) : 0;
a0d0e21e 1023
1024 svp = hv_fetch(action, "cachesize", 9, FALSE);
1f70e1ea 1025 info->db_BT_cachesize = svp ? SvIV(*svp) : 0;
a0d0e21e 1026
1f70e1ea 1027#ifndef DB_VERSION_MAJOR
a0d0e21e 1028 svp = hv_fetch(action, "minkeypage", 10, FALSE);
610ab055 1029 info->btree.minkeypage = svp ? SvIV(*svp) : 0;
a0d0e21e 1030
1031 svp = hv_fetch(action, "maxkeypage", 10, FALSE);
610ab055 1032 info->btree.maxkeypage = svp ? SvIV(*svp) : 0;
1f70e1ea 1033#endif
a0d0e21e 1034
1035 svp = hv_fetch(action, "psize", 5, FALSE);
1f70e1ea 1036 info->db_BT_psize = svp ? SvIV(*svp) : 0;
a0d0e21e 1037
1038 svp = hv_fetch(action, "lorder", 6, FALSE);
1f70e1ea 1039 info->db_BT_lorder = svp ? SvIV(*svp) : 0;
a0d0e21e 1040
1041 PrintBtree(info) ;
1042
1043 }
1044 else if (sv_isa(sv, "DB_File::RECNOINFO"))
1045 {
05475680 1046 if (isHASH)
1047 croak("DB_File can only tie an array to a DB_RECNO database");
1048
8e07c86e 1049 RETVAL->type = DB_RECNO ;
610ab055 1050 openinfo = (void *)info ;
a0d0e21e 1051
1f70e1ea 1052 info->db_RE_flags = 0 ;
1053
a0d0e21e 1054 svp = hv_fetch(action, "flags", 5, FALSE);
1f70e1ea 1055 info->db_RE_flags = (u_long) (svp ? SvIV(*svp) : 0);
1056
1057 svp = hv_fetch(action, "reclen", 6, FALSE);
1058 info->db_RE_reclen = (size_t) (svp ? SvIV(*svp) : 0);
a0d0e21e 1059
1060 svp = hv_fetch(action, "cachesize", 9, FALSE);
1f70e1ea 1061 info->db_RE_cachesize = (u_int) (svp ? SvIV(*svp) : 0);
a0d0e21e 1062
1063 svp = hv_fetch(action, "psize", 5, FALSE);
1f70e1ea 1064 info->db_RE_psize = (u_int) (svp ? SvIV(*svp) : 0);
a0d0e21e 1065
1066 svp = hv_fetch(action, "lorder", 6, FALSE);
1f70e1ea 1067 info->db_RE_lorder = (int) (svp ? SvIV(*svp) : 0);
1068
1069#ifdef DB_VERSION_MAJOR
1070 info->re_source = name ;
1071 name = NULL ;
1072#endif
1073 svp = hv_fetch(action, "bfname", 6, FALSE);
1074 if (svp && SvOK(*svp)) {
2d8e6c8d 1075 char * ptr = SvPV(*svp,n_a) ;
1f70e1ea 1076#ifdef DB_VERSION_MAJOR
2d8e6c8d 1077 name = (char*) n_a ? ptr : NULL ;
1f70e1ea 1078#else
2d8e6c8d 1079 info->db_RE_bfname = (char*) (n_a ? ptr : NULL) ;
1f70e1ea 1080#endif
1081 }
1082 else
1083#ifdef DB_VERSION_MAJOR
1084 name = NULL ;
1085#else
1086 info->db_RE_bfname = NULL ;
1087#endif
a0d0e21e 1088
1089 svp = hv_fetch(action, "bval", 4, FALSE);
1f70e1ea 1090#ifdef DB_VERSION_MAJOR
a0d0e21e 1091 if (svp && SvOK(*svp))
1092 {
1f70e1ea 1093 int value ;
a0d0e21e 1094 if (SvPOK(*svp))
2d8e6c8d 1095 value = (int)*SvPV(*svp, n_a) ;
a0d0e21e 1096 else
1f70e1ea 1097 value = SvIV(*svp) ;
1098
1099 if (info->flags & DB_FIXEDLEN) {
1100 info->re_pad = value ;
1101 info->flags |= DB_PAD ;
1102 }
1103 else {
1104 info->re_delim = value ;
1105 info->flags |= DB_DELIMITER ;
1106 }
1107
1108 }
1109#else
1110 if (svp && SvOK(*svp))
1111 {
1112 if (SvPOK(*svp))
2d8e6c8d 1113 info->db_RE_bval = (u_char)*SvPV(*svp, n_a) ;
1f70e1ea 1114 else
1115 info->db_RE_bval = (u_char)(unsigned long) SvIV(*svp) ;
1116 DB_flags(info->flags, DB_DELIMITER) ;
1117
a0d0e21e 1118 }
1119 else
1120 {
1f70e1ea 1121 if (info->db_RE_flags & R_FIXEDLEN)
1122 info->db_RE_bval = (u_char) ' ' ;
a0d0e21e 1123 else
1f70e1ea 1124 info->db_RE_bval = (u_char) '\n' ;
1125 DB_flags(info->flags, DB_DELIMITER) ;
a0d0e21e 1126 }
1f70e1ea 1127#endif
a0d0e21e 1128
1f70e1ea 1129#ifdef DB_RENUMBER
1130 info->flags |= DB_RENUMBER ;
1131#endif
1132
a0d0e21e 1133 PrintRecno(info) ;
1134 }
1135 else
1136 croak("type is not of type DB_File::HASHINFO, DB_File::BTREEINFO or DB_File::RECNOINFO");
1137 }
1138
1139
88108326 1140 /* OS2 Specific Code */
1141#ifdef OS2
1142#ifdef __EMX__
1143 flags |= O_BINARY;
1144#endif /* __EMX__ */
1145#endif /* OS2 */
a0d0e21e 1146
1f70e1ea 1147#ifdef DB_VERSION_MAJOR
1148
1149 {
1150 int Flags = 0 ;
1151 int status ;
1152
1153 /* Map 1.x flags to 2.x flags */
1154 if ((flags & O_CREAT) == O_CREAT)
1155 Flags |= DB_CREATE ;
1156
1f70e1ea 1157#if O_RDONLY == 0
1158 if (flags == O_RDONLY)
1159#else
20896112 1160 if ((flags & O_RDONLY) == O_RDONLY && (flags & O_RDWR) != O_RDWR)
1f70e1ea 1161#endif
1162 Flags |= DB_RDONLY ;
1163
20896112 1164#ifdef O_TRUNC
1f70e1ea 1165 if ((flags & O_TRUNC) == O_TRUNC)
1166 Flags |= DB_TRUNCATE ;
1167#endif
1168
1169 status = db_open(name, RETVAL->type, Flags, mode, NULL, openinfo, &RETVAL->dbp) ;
1170 if (status == 0)
6ca2e664 1171#if DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 6
1f70e1ea 1172 status = (RETVAL->dbp->cursor)(RETVAL->dbp, NULL, &RETVAL->cursor) ;
6ca2e664 1173#else
1174 status = (RETVAL->dbp->cursor)(RETVAL->dbp, NULL, &RETVAL->cursor,
1175 0) ;
1176#endif
1f70e1ea 1177
1178 if (status)
1179 RETVAL->dbp = NULL ;
1180
1181 }
1182#else
ccb44e3b 1183
1184#if defined(DB_LIBRARY_COMPATIBILITY_API) && DB_VERSION_MAJOR > 2
1185 RETVAL->dbp = __db185_open(name, flags, mode, RETVAL->type, openinfo) ;
1186#else
88108326 1187 RETVAL->dbp = dbopen(name, flags, mode, RETVAL->type, openinfo) ;
ccb44e3b 1188#endif /* DB_LIBRARY_COMPATIBILITY_API */
1189
1f70e1ea 1190#endif
a0d0e21e 1191
1192 return (RETVAL) ;
ccb44e3b 1193
1194#else /* Berkeley DB Version > 2 */
1195
1196 SV ** svp;
1197 HV * action ;
1198 DB_File RETVAL = (DB_File)safemalloc(sizeof(DB_File_type)) ;
1199 DB * dbp ;
1200 STRLEN n_a;
1201 int status ;
df3728a2 1202 dMY_CXT;
ccb44e3b 1203
1204/* printf("In ParseOpenInfo name=[%s] flags=[%d] mode = [%d]\n", name, flags, mode) ; */
1205 Zero(RETVAL, 1, DB_File_type) ;
1206
1207 /* Default to HASH */
ccb44e3b 1208 RETVAL->filtering = 0 ;
1209 RETVAL->filter_fetch_key = RETVAL->filter_store_key =
1210 RETVAL->filter_fetch_value = RETVAL->filter_store_value =
ccb44e3b 1211 RETVAL->hash = RETVAL->compare = RETVAL->prefix = NULL ;
1212 RETVAL->type = DB_HASH ;
1213
1214 /* DGH - Next line added to avoid SEGV on existing hash DB */
1215 CurrentDB = RETVAL;
1216
1217 /* fd for 1.86 hash in memory files doesn't return -1 like 1.85 */
1218 RETVAL->in_memory = (name == NULL) ;
1219
1220 status = db_create(&RETVAL->dbp, NULL,0) ;
1221 /* printf("db_create returned %d %s\n", status, db_strerror(status)) ; */
1222 if (status) {
1223 RETVAL->dbp = NULL ;
1224 return (RETVAL) ;
1225 }
1226 dbp = RETVAL->dbp ;
1227
1228 if (sv)
1229 {
1230 if (! SvROK(sv) )
1231 croak ("type parameter is not a reference") ;
1232
1233 svp = hv_fetch( (HV*)SvRV(sv), "GOT", 3, FALSE) ;
1234 if (svp && SvOK(*svp))
1235 action = (HV*) SvRV(*svp) ;
1236 else
1237 croak("internal error") ;
1238
1239 if (sv_isa(sv, "DB_File::HASHINFO"))
1240 {
1241
1242 if (!isHASH)
1243 croak("DB_File can only tie an associative array to a DB_HASH database") ;
1244
1245 RETVAL->type = DB_HASH ;
1246
1247 svp = hv_fetch(action, "hash", 4, FALSE);
1248
1249 if (svp && SvOK(*svp))
1250 {
1251 (void)dbp->set_h_hash(dbp, hash_cb) ;
1252 RETVAL->hash = newSVsv(*svp) ;
1253 }
1254
1255 svp = hv_fetch(action, "ffactor", 7, FALSE);
1256 if (svp)
c6c92ad9 1257 (void)dbp->set_h_ffactor(dbp, my_SvUV32(*svp)) ;
ccb44e3b 1258
1259 svp = hv_fetch(action, "nelem", 5, FALSE);
1260 if (svp)
c6c92ad9 1261 (void)dbp->set_h_nelem(dbp, my_SvUV32(*svp)) ;
ccb44e3b 1262
1263 svp = hv_fetch(action, "bsize", 5, FALSE);
1264 if (svp)
c6c92ad9 1265 (void)dbp->set_pagesize(dbp, my_SvUV32(*svp));
ccb44e3b 1266
1267 svp = hv_fetch(action, "cachesize", 9, FALSE);
1268 if (svp)
c6c92ad9 1269 (void)dbp->set_cachesize(dbp, 0, my_SvUV32(*svp), 0) ;
ccb44e3b 1270
1271 svp = hv_fetch(action, "lorder", 6, FALSE);
1272 if (svp)
c6c92ad9 1273 (void)dbp->set_lorder(dbp, (int)SvIV(*svp)) ;
ccb44e3b 1274
1275 PrintHash(info) ;
1276 }
1277 else if (sv_isa(sv, "DB_File::BTREEINFO"))
1278 {
1279 if (!isHASH)
1280 croak("DB_File can only tie an associative array to a DB_BTREE database");
1281
1282 RETVAL->type = DB_BTREE ;
1283
1284 svp = hv_fetch(action, "compare", 7, FALSE);
1285 if (svp && SvOK(*svp))
1286 {
1287 (void)dbp->set_bt_compare(dbp, btree_compare) ;
1288 RETVAL->compare = newSVsv(*svp) ;
1289 }
1290
1291 svp = hv_fetch(action, "prefix", 6, FALSE);
1292 if (svp && SvOK(*svp))
1293 {
1294 (void)dbp->set_bt_prefix(dbp, btree_prefix) ;
1295 RETVAL->prefix = newSVsv(*svp) ;
1296 }
1297
1298 svp = hv_fetch(action, "flags", 5, FALSE);
1299 if (svp)
c6c92ad9 1300 (void)dbp->set_flags(dbp, my_SvUV32(*svp)) ;
ccb44e3b 1301
1302 svp = hv_fetch(action, "cachesize", 9, FALSE);
1303 if (svp)
c6c92ad9 1304 (void)dbp->set_cachesize(dbp, 0, my_SvUV32(*svp), 0) ;
ccb44e3b 1305
1306 svp = hv_fetch(action, "psize", 5, FALSE);
1307 if (svp)
c6c92ad9 1308 (void)dbp->set_pagesize(dbp, my_SvUV32(*svp)) ;
ccb44e3b 1309
1310 svp = hv_fetch(action, "lorder", 6, FALSE);
1311 if (svp)
c6c92ad9 1312 (void)dbp->set_lorder(dbp, (int)SvIV(*svp)) ;
ccb44e3b 1313
1314 PrintBtree(info) ;
1315
1316 }
1317 else if (sv_isa(sv, "DB_File::RECNOINFO"))
1318 {
1319 int fixed = FALSE ;
1320
1321 if (isHASH)
1322 croak("DB_File can only tie an array to a DB_RECNO database");
1323
1324 RETVAL->type = DB_RECNO ;
1325
1326 svp = hv_fetch(action, "flags", 5, FALSE);
1327 if (svp) {
1328 int flags = SvIV(*svp) ;
1329 /* remove FIXDLEN, if present */
1330 if (flags & DB_FIXEDLEN) {
1331 fixed = TRUE ;
1332 flags &= ~DB_FIXEDLEN ;
1333 }
1334 }
1335
1336 svp = hv_fetch(action, "cachesize", 9, FALSE);
1337 if (svp) {
c6c92ad9 1338 status = dbp->set_cachesize(dbp, 0, my_SvUV32(*svp), 0) ;
ccb44e3b 1339 }
1340
1341 svp = hv_fetch(action, "psize", 5, FALSE);
1342 if (svp) {
c6c92ad9 1343 status = dbp->set_pagesize(dbp, my_SvUV32(*svp)) ;
ccb44e3b 1344 }
1345
1346 svp = hv_fetch(action, "lorder", 6, FALSE);
1347 if (svp) {
c6c92ad9 1348 status = dbp->set_lorder(dbp, (int)SvIV(*svp)) ;
ccb44e3b 1349 }
1350
1351 svp = hv_fetch(action, "bval", 4, FALSE);
1352 if (svp && SvOK(*svp))
1353 {
1354 int value ;
1355 if (SvPOK(*svp))
1356 value = (int)*SvPV(*svp, n_a) ;
1357 else
c6c92ad9 1358 value = (int)SvIV(*svp) ;
ccb44e3b 1359
1360 if (fixed) {
1361 status = dbp->set_re_pad(dbp, value) ;
1362 }
1363 else {
1364 status = dbp->set_re_delim(dbp, value) ;
1365 }
1366
1367 }
1368
1369 if (fixed) {
1370 svp = hv_fetch(action, "reclen", 6, FALSE);
1371 if (svp) {
c6c92ad9 1372 u_int32_t len = my_SvUV32(*svp) ;
ccb44e3b 1373 status = dbp->set_re_len(dbp, len) ;
1374 }
1375 }
1376
1377 if (name != NULL) {
1378 status = dbp->set_re_source(dbp, name) ;
1379 name = NULL ;
1380 }
1381
1382 svp = hv_fetch(action, "bfname", 6, FALSE);
1383 if (svp && SvOK(*svp)) {
1384 char * ptr = SvPV(*svp,n_a) ;
1385 name = (char*) n_a ? ptr : NULL ;
1386 }
1387 else
1388 name = NULL ;
1389
1390
c6c92ad9 1391 status = dbp->set_flags(dbp, (u_int32_t)DB_RENUMBER) ;
ccb44e3b 1392
1393 if (flags){
c6c92ad9 1394 (void)dbp->set_flags(dbp, (u_int32_t)flags) ;
ccb44e3b 1395 }
1396 PrintRecno(info) ;
1397 }
1398 else
1399 croak("type is not of type DB_File::HASHINFO, DB_File::BTREEINFO or DB_File::RECNOINFO");
1400 }
1401
1402 {
c6c92ad9 1403 u_int32_t Flags = 0 ;
ccb44e3b 1404 int status ;
1405
1406 /* Map 1.x flags to 3.x flags */
1407 if ((flags & O_CREAT) == O_CREAT)
1408 Flags |= DB_CREATE ;
1409
1410#if O_RDONLY == 0
1411 if (flags == O_RDONLY)
1412#else
1413 if ((flags & O_RDONLY) == O_RDONLY && (flags & O_RDWR) != O_RDWR)
1414#endif
1415 Flags |= DB_RDONLY ;
1416
1417#ifdef O_TRUNC
1418 if ((flags & O_TRUNC) == O_TRUNC)
1419 Flags |= DB_TRUNCATE ;
1420#endif
1421
efc79c7d 1422#ifdef AT_LEAST_DB_4_1
1423 status = (RETVAL->dbp->open)(RETVAL->dbp, NULL, name, NULL, RETVAL->type,
1424 Flags, mode) ;
1425#else
3245f058 1426 status = (RETVAL->dbp->open)(RETVAL->dbp, name, NULL, RETVAL->type,
ccb44e3b 1427 Flags, mode) ;
efc79c7d 1428#endif
ccb44e3b 1429 /* printf("open returned %d %s\n", status, db_strerror(status)) ; */
1430
efc79c7d 1431 if (status == 0) {
1432 RETVAL->dbp->set_errcall(RETVAL->dbp, db_errcall_cb) ;
1433
ccb44e3b 1434 status = (RETVAL->dbp->cursor)(RETVAL->dbp, NULL, &RETVAL->cursor,
1435 0) ;
efc79c7d 1436 /* printf("cursor returned %d %s\n", status, db_strerror(status)) ; */
1437 }
ccb44e3b 1438
1439 if (status)
1440 RETVAL->dbp = NULL ;
1441
1442 }
1443
1444 return (RETVAL) ;
1445
1446#endif /* Berkeley DB Version > 2 */
1447
1448} /* ParseOpenInfo */
a0d0e21e 1449
1450
07200f1b 1451#include "constants.h"
a0d0e21e 1452
1453MODULE = DB_File PACKAGE = DB_File PREFIX = db_
1454
07200f1b 1455INCLUDE: constants.xs
1456
1f70e1ea 1457BOOT:
1458 {
9a40e66e 1459 dTHX;
efc79c7d 1460 SV * sv_err = perl_get_sv(ERR_BUFF, GV_ADD|GV_ADDMULTI) ;
df3728a2 1461 MY_CXT_INIT;
ccb44e3b 1462 __getBerkeleyDBInfo() ;
1f70e1ea 1463
ccb44e3b 1464 DBT_clear(empty) ;
1f70e1ea 1465 empty.data = &zero ;
1466 empty.size = sizeof(recno_t) ;
1f70e1ea 1467 }
1468
a0d0e21e 1469
1470
1471DB_File
05475680 1472db_DoTie_(isHASH, dbtype, name=undef, flags=O_CREAT|O_RDWR, mode=0666, type=DB_HASH)
1473 int isHASH
a0d0e21e 1474 char * dbtype
1475 int flags
1476 int mode
1477 CODE:
1478 {
1479 char * name = (char *) NULL ;
1480 SV * sv = (SV *) NULL ;
2d8e6c8d 1481 STRLEN n_a;
a0d0e21e 1482
05475680 1483 if (items >= 3 && SvOK(ST(2)))
2d8e6c8d 1484 name = (char*) SvPV(ST(2), n_a) ;
a0d0e21e 1485
05475680 1486 if (items == 6)
1487 sv = ST(5) ;
a0d0e21e 1488
b76802f5 1489 RETVAL = ParseOpenInfo(aTHX_ isHASH, name, flags, mode, sv) ;
4633a7c4 1490 if (RETVAL->dbp == NULL)
1491 RETVAL = NULL ;
a0d0e21e 1492 }
1493 OUTPUT:
1494 RETVAL
1495
a0d0e21e 1496int
1497db_DESTROY(db)
1498 DB_File db
df3728a2 1499 PREINIT:
1500 dMY_CXT;
8e07c86e 1501 INIT:
1502 CurrentDB = db ;
efc79c7d 1503 Trace(("DESTROY %p\n", db));
8e07c86e 1504 CLEANUP:
efc79c7d 1505 Trace(("DESTROY %p done\n", db));
8e07c86e 1506 if (db->hash)
1507 SvREFCNT_dec(db->hash) ;
1508 if (db->compare)
1509 SvREFCNT_dec(db->compare) ;
1510 if (db->prefix)
1511 SvREFCNT_dec(db->prefix) ;
9fe6733a 1512 if (db->filter_fetch_key)
1513 SvREFCNT_dec(db->filter_fetch_key) ;
1514 if (db->filter_store_key)
1515 SvREFCNT_dec(db->filter_store_key) ;
1516 if (db->filter_fetch_value)
1517 SvREFCNT_dec(db->filter_fetch_value) ;
1518 if (db->filter_store_value)
1519 SvREFCNT_dec(db->filter_store_value) ;
eb99164f 1520 safefree(db) ;
1f70e1ea 1521#ifdef DB_VERSION_MAJOR
1522 if (RETVAL > 0)
1523 RETVAL = -1 ;
1524#endif
a0d0e21e 1525
1526
1527int
1528db_DELETE(db, key, flags=0)
1529 DB_File db
1530 DBTKEY key
1531 u_int flags
df3728a2 1532 PREINIT:
1533 dMY_CXT;
8e07c86e 1534 INIT:
1535 CurrentDB = db ;
a0d0e21e 1536
f6b705ef 1537
1538int
1539db_EXISTS(db, key)
1540 DB_File db
1541 DBTKEY key
df3728a2 1542 PREINIT:
1543 dMY_CXT;
f6b705ef 1544 CODE:
1545 {
1546 DBT value ;
1547
ccb44e3b 1548 DBT_clear(value) ;
f6b705ef 1549 CurrentDB = db ;
1f70e1ea 1550 RETVAL = (((db->dbp)->get)(db->dbp, TXN &key, &value, 0) == 0) ;
f6b705ef 1551 }
1552 OUTPUT:
1553 RETVAL
1554
c6c619a9 1555void
a0d0e21e 1556db_FETCH(db, key, flags=0)
1557 DB_File db
1558 DBTKEY key
1559 u_int flags
c6c619a9 1560 PREINIT:
07200f1b 1561 dMY_CXT ;
1562 int RETVAL ;
a0d0e21e 1563 CODE:
1564 {
1f70e1ea 1565 DBT value ;
a0d0e21e 1566
ccb44e3b 1567 DBT_clear(value) ;
8e07c86e 1568 CurrentDB = db ;
1f70e1ea 1569 RETVAL = db_get(db, key, value, flags) ;
a0d0e21e 1570 ST(0) = sv_newmortal();
a9fd575d 1571 OutputValue(ST(0), value)
a0d0e21e 1572 }
1573
1574int
1575db_STORE(db, key, value, flags=0)
1576 DB_File db
1577 DBTKEY key
1578 DBT value
1579 u_int flags
df3728a2 1580 PREINIT:
1581 dMY_CXT;
8e07c86e 1582 INIT:
1583 CurrentDB = db ;
a0d0e21e 1584
1585
c6c619a9 1586void
a0d0e21e 1587db_FIRSTKEY(db)
1588 DB_File db
c6c619a9 1589 PREINIT:
07200f1b 1590 dMY_CXT ;
1591 int RETVAL ;
a0d0e21e 1592 CODE:
1593 {
1f70e1ea 1594 DBTKEY key ;
a0d0e21e 1595 DBT value ;
1596
ccb44e3b 1597 DBT_clear(key) ;
1598 DBT_clear(value) ;
8e07c86e 1599 CurrentDB = db ;
1f70e1ea 1600 RETVAL = do_SEQ(db, key, value, R_FIRST) ;
a0d0e21e 1601 ST(0) = sv_newmortal();
a9fd575d 1602 OutputKey(ST(0), key) ;
a0d0e21e 1603 }
1604
c6c619a9 1605void
a0d0e21e 1606db_NEXTKEY(db, key)
1607 DB_File db
0bf2e707 1608 DBTKEY key = NO_INIT
c6c619a9 1609 PREINIT:
07200f1b 1610 dMY_CXT ;
1611 int RETVAL ;
a0d0e21e 1612 CODE:
1613 {
1614 DBT value ;
1615
0bf2e707 1616 DBT_clear(key) ;
ccb44e3b 1617 DBT_clear(value) ;
8e07c86e 1618 CurrentDB = db ;
1f70e1ea 1619 RETVAL = do_SEQ(db, key, value, R_NEXT) ;
a0d0e21e 1620 ST(0) = sv_newmortal();
a9fd575d 1621 OutputKey(ST(0), key) ;
a0d0e21e 1622 }
1623
1624#
1625# These would be nice for RECNO
1626#
1627
1628int
1629unshift(db, ...)
1630 DB_File db
045291aa 1631 ALIAS: UNSHIFT = 1
df3728a2 1632 PREINIT:
1633 dMY_CXT;
a0d0e21e 1634 CODE:
1635 {
1636 DBTKEY key ;
1637 DBT value ;
1638 int i ;
1639 int One ;
2d8e6c8d 1640 STRLEN n_a;
a0d0e21e 1641
ccb44e3b 1642 DBT_clear(key) ;
1643 DBT_clear(value) ;
8e07c86e 1644 CurrentDB = db ;
1f70e1ea 1645#ifdef DB_VERSION_MAJOR
1646 /* get the first value */
1647 RETVAL = do_SEQ(db, key, value, DB_FIRST) ;
1648 RETVAL = 0 ;
1649#else
a0d0e21e 1650 RETVAL = -1 ;
1f70e1ea 1651#endif
a0d0e21e 1652 for (i = items-1 ; i > 0 ; --i)
1653 {
2d8e6c8d 1654 value.data = SvPV(ST(i), n_a) ;
1655 value.size = n_a ;
a0d0e21e 1656 One = 1 ;
1657 key.data = &One ;
1658 key.size = sizeof(int) ;
1f70e1ea 1659#ifdef DB_VERSION_MAJOR
1660 RETVAL = (db->cursor->c_put)(db->cursor, &key, &value, DB_BEFORE) ;
1661#else
b7953727 1662 RETVAL = (db->dbp->put)(db->dbp, &key, &value, R_IBEFORE) ;
1f70e1ea 1663#endif
a0d0e21e 1664 if (RETVAL != 0)
1665 break;
1666 }
1667 }
1668 OUTPUT:
1669 RETVAL
1670
c6c619a9 1671void
a0d0e21e 1672pop(db)
1673 DB_File db
df3728a2 1674 PREINIT:
1675 dMY_CXT;
045291aa 1676 ALIAS: POP = 1
c6c619a9 1677 PREINIT:
07200f1b 1678 I32 RETVAL;
a0d0e21e 1679 CODE:
1680 {
1681 DBTKEY key ;
1682 DBT value ;
1683
ccb44e3b 1684 DBT_clear(key) ;
1685 DBT_clear(value) ;
8e07c86e 1686 CurrentDB = db ;
1f70e1ea 1687
a0d0e21e 1688 /* First get the final value */
1f70e1ea 1689 RETVAL = do_SEQ(db, key, value, R_LAST) ;
a0d0e21e 1690 ST(0) = sv_newmortal();
1691 /* Now delete it */
1692 if (RETVAL == 0)
1693 {
f6b705ef 1694 /* the call to del will trash value, so take a copy now */
a9fd575d 1695 OutputValue(ST(0), value) ;
1f70e1ea 1696 RETVAL = db_del(db, key, R_CURSOR) ;
f6b705ef 1697 if (RETVAL != 0)
6b88bc9c 1698 sv_setsv(ST(0), &PL_sv_undef);
a0d0e21e 1699 }
1700 }
1701
c6c619a9 1702void
a0d0e21e 1703shift(db)
1704 DB_File db
df3728a2 1705 PREINIT:
1706 dMY_CXT;
045291aa 1707 ALIAS: SHIFT = 1
c6c619a9 1708 PREINIT:
07200f1b 1709 I32 RETVAL;
a0d0e21e 1710 CODE:
1711 {
a0d0e21e 1712 DBT value ;
f6b705ef 1713 DBTKEY key ;
a0d0e21e 1714
ccb44e3b 1715 DBT_clear(key) ;
1716 DBT_clear(value) ;
8e07c86e 1717 CurrentDB = db ;
a0d0e21e 1718 /* get the first value */
1f70e1ea 1719 RETVAL = do_SEQ(db, key, value, R_FIRST) ;
a0d0e21e 1720 ST(0) = sv_newmortal();
1721 /* Now delete it */
1722 if (RETVAL == 0)
1723 {
f6b705ef 1724 /* the call to del will trash value, so take a copy now */
a9fd575d 1725 OutputValue(ST(0), value) ;
1f70e1ea 1726 RETVAL = db_del(db, key, R_CURSOR) ;
f6b705ef 1727 if (RETVAL != 0)
6b88bc9c 1728 sv_setsv (ST(0), &PL_sv_undef) ;
a0d0e21e 1729 }
1730 }
1731
1732
1733I32
1734push(db, ...)
1735 DB_File db
df3728a2 1736 PREINIT:
1737 dMY_CXT;
045291aa 1738 ALIAS: PUSH = 1
a0d0e21e 1739 CODE:
1740 {
1741 DBTKEY key ;
1742 DBT value ;
4633a7c4 1743 DB * Db = db->dbp ;
a0d0e21e 1744 int i ;
2d8e6c8d 1745 STRLEN n_a;
ccb44e3b 1746 int keyval ;
a0d0e21e 1747
1f70e1ea 1748 DBT_flags(key) ;
1749 DBT_flags(value) ;
8e07c86e 1750 CurrentDB = db ;
ca63f0d2 1751 /* Set the Cursor to the Last element */
1752 RETVAL = do_SEQ(db, key, value, R_LAST) ;
ccb44e3b 1753#ifndef DB_VERSION_MAJOR
ca63f0d2 1754 if (RETVAL >= 0)
ccb44e3b 1755#endif
ca63f0d2 1756 {
ccb44e3b 1757 if (RETVAL == 0)
1758 keyval = *(int*)key.data ;
1759 else
1760 keyval = 0 ;
1761 for (i = 1 ; i < items ; ++i)
8e07c86e 1762 {
2d8e6c8d 1763 value.data = SvPV(ST(i), n_a) ;
1764 value.size = n_a ;
ccb44e3b 1765 ++ keyval ;
1766 key.data = &keyval ;
1767 key.size = sizeof(int) ;
1768 RETVAL = (Db->put)(Db, TXN &key, &value, 0) ;
8e07c86e 1769 if (RETVAL != 0)
1770 break;
1771 }
a0d0e21e 1772 }
1773 }
1774 OUTPUT:
1775 RETVAL
1776
a0d0e21e 1777I32
1778length(db)
1779 DB_File db
df3728a2 1780 PREINIT:
1781 dMY_CXT;
045291aa 1782 ALIAS: FETCHSIZE = 1
a0d0e21e 1783 CODE:
8e07c86e 1784 CurrentDB = db ;
b76802f5 1785 RETVAL = GetArrayLength(aTHX_ db) ;
a0d0e21e 1786 OUTPUT:
1787 RETVAL
1788
1789
1790#
1791# Now provide an interface to the rest of the DB functionality
1792#
1793
1794int
1795db_del(db, key, flags=0)
1796 DB_File db
1797 DBTKEY key
1798 u_int flags
df3728a2 1799 PREINIT:
1800 dMY_CXT;
1f70e1ea 1801 CODE:
8e07c86e 1802 CurrentDB = db ;
1f70e1ea 1803 RETVAL = db_del(db, key, flags) ;
1804#ifdef DB_VERSION_MAJOR
1805 if (RETVAL > 0)
1806 RETVAL = -1 ;
1807 else if (RETVAL == DB_NOTFOUND)
1808 RETVAL = 1 ;
1809#endif
1810 OUTPUT:
1811 RETVAL
a0d0e21e 1812
1813
1814int
1815db_get(db, key, value, flags=0)
1816 DB_File db
1817 DBTKEY key
a6ed719b 1818 DBT value = NO_INIT
a0d0e21e 1819 u_int flags
df3728a2 1820 PREINIT:
1821 dMY_CXT;
1f70e1ea 1822 CODE:
8e07c86e 1823 CurrentDB = db ;
ccb44e3b 1824 DBT_clear(value) ;
1f70e1ea 1825 RETVAL = db_get(db, key, value, flags) ;
1826#ifdef DB_VERSION_MAJOR
1827 if (RETVAL > 0)
1828 RETVAL = -1 ;
1829 else if (RETVAL == DB_NOTFOUND)
1830 RETVAL = 1 ;
1831#endif
a0d0e21e 1832 OUTPUT:
1f70e1ea 1833 RETVAL
a0d0e21e 1834 value
1835
1836int
1837db_put(db, key, value, flags=0)
1838 DB_File db
1839 DBTKEY key
1840 DBT value
1841 u_int flags
df3728a2 1842 PREINIT:
1843 dMY_CXT;
1f70e1ea 1844 CODE:
8e07c86e 1845 CurrentDB = db ;
1f70e1ea 1846 RETVAL = db_put(db, key, value, flags) ;
1847#ifdef DB_VERSION_MAJOR
1848 if (RETVAL > 0)
1849 RETVAL = -1 ;
1850 else if (RETVAL == DB_KEYEXIST)
1851 RETVAL = 1 ;
1852#endif
a0d0e21e 1853 OUTPUT:
1f70e1ea 1854 RETVAL
9d9477b1 1855 key if (flagSet(flags, R_IAFTER) || flagSet(flags, R_IBEFORE)) OutputKey(ST(1), key);
a0d0e21e 1856
1857int
1858db_fd(db)
1859 DB_File db
df3728a2 1860 PREINIT:
07200f1b 1861 dMY_CXT ;
1f70e1ea 1862 CODE:
8e07c86e 1863 CurrentDB = db ;
1f70e1ea 1864#ifdef DB_VERSION_MAJOR
1865 RETVAL = -1 ;
497b47a8 1866 {
1867 int status = 0 ;
1868 status = (db->in_memory
1869 ? -1
1870 : ((db->dbp)->fd)(db->dbp, &RETVAL) ) ;
1871 if (status != 0)
1872 RETVAL = -1 ;
1873 }
1f70e1ea 1874#else
1875 RETVAL = (db->in_memory
1876 ? -1
1877 : ((db->dbp)->fd)(db->dbp) ) ;
1878#endif
1879 OUTPUT:
1880 RETVAL
a0d0e21e 1881
1882int
1883db_sync(db, flags=0)
1884 DB_File db
1885 u_int flags
df3728a2 1886 PREINIT:
1887 dMY_CXT;
1f70e1ea 1888 CODE:
8e07c86e 1889 CurrentDB = db ;
1f70e1ea 1890 RETVAL = db_sync(db, flags) ;
1891#ifdef DB_VERSION_MAJOR
1892 if (RETVAL > 0)
1893 RETVAL = -1 ;
1894#endif
1895 OUTPUT:
1896 RETVAL
a0d0e21e 1897
1898
1899int
1900db_seq(db, key, value, flags)
1901 DB_File db
1902 DBTKEY key
a6ed719b 1903 DBT value = NO_INIT
a0d0e21e 1904 u_int flags
df3728a2 1905 PREINIT:
1906 dMY_CXT;
1f70e1ea 1907 CODE:
8e07c86e 1908 CurrentDB = db ;
ccb44e3b 1909 DBT_clear(value) ;
1f70e1ea 1910 RETVAL = db_seq(db, key, value, flags);
1911#ifdef DB_VERSION_MAJOR
1912 if (RETVAL > 0)
1913 RETVAL = -1 ;
1914 else if (RETVAL == DB_NOTFOUND)
1915 RETVAL = 1 ;
1916#endif
a0d0e21e 1917 OUTPUT:
1f70e1ea 1918 RETVAL
a0d0e21e 1919 key
1920 value
610ab055 1921
9fe6733a 1922SV *
1923filter_fetch_key(db, code)
1924 DB_File db
1925 SV * code
1926 SV * RETVAL = &PL_sv_undef ;
1927 CODE:
6a31061a 1928 DBM_setFilter(db->filter_fetch_key, code) ;
9fe6733a 1929
1930SV *
1931filter_store_key(db, code)
1932 DB_File db
1933 SV * code
1934 SV * RETVAL = &PL_sv_undef ;
1935 CODE:
6a31061a 1936 DBM_setFilter(db->filter_store_key, code) ;
9fe6733a 1937
1938SV *
1939filter_fetch_value(db, code)
1940 DB_File db
1941 SV * code
1942 SV * RETVAL = &PL_sv_undef ;
1943 CODE:
6a31061a 1944 DBM_setFilter(db->filter_fetch_value, code) ;
9fe6733a 1945
1946SV *
1947filter_store_value(db, code)
1948 DB_File db
1949 SV * code
1950 SV * RETVAL = &PL_sv_undef ;
1951 CODE:
6a31061a 1952 DBM_setFilter(db->filter_store_value, code) ;
9fe6733a 1953