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