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