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