This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Integrate mainline
[perl5.git] / ext / ODBM_File / ODBM_File.xs
CommitLineData
463ee0b2
LW
1#include "EXTERN.h"
2#include "perl.h"
3#include "XSUB.h"
4
8e07c86e 5#ifdef I_DBM
bb636fa4
JH
6/* If using the DB3 emulation, ENTER is defined both
7 * by DB3 and Perl. We drop the Perl definition now.
8 * See also INSTALL section on DB3.
9 * -- Stanislav Brabec <utx@penguin.cz> */
10# undef ENTER
8e07c86e
AD
11# include <dbm.h>
12#else
13# ifdef I_RPCSVC_DBM
14# include <rpcsvc/dbm.h>
15# endif
16#endif
463ee0b2 17
2ef53570
JH
18#ifndef HAS_DBMINIT_PROTO
19int dbminit(char* filename);
20int dbmclose(void);
21datum fetch(datum key);
22int store(datum key, datum dat);
23int delete(datum key);
24datum firstkey(void);
25datum nextkey(datum key);
26#endif
27
1639c7b3 28#ifdef DBM_BUG_DUPLICATE_FREE
29/*
30 * DBM on at least Ultrix and HPUX call dbmclose() from dbminit(),
31 * resulting in duplicate free() because dbmclose() does *not*
32 * check if it has already been called for this DBM.
33 * If some malloc/free calls have been done between dbmclose() and
34 * the next dbminit(), the memory might be used for something else when
35 * it is freed.
36 * Verified to work on ultrix4.3. Probably will work on HP/UX.
37 * Set DBM_BUG_DUPLICATE_FREE in the extension hint file.
38 */
39/* Close the previous dbm, and fail to open a new dbm */
40#define dbmclose() ((void) dbminit("/tmp/x/y/z/z/y"))
41#endif
42
463ee0b2
LW
43#include <fcntl.h>
44
9fe6733a
PM
45typedef struct {
46 void * dbp ;
47 SV * filter_fetch_key ;
48 SV * filter_store_key ;
49 SV * filter_fetch_value ;
50 SV * filter_store_value ;
51 int filtering ;
52 } ODBM_File_type;
53
54typedef ODBM_File_type * ODBM_File ;
55typedef datum datum_key ;
0bf2e707 56typedef datum datum_key_copy ;
9fe6733a
PM
57typedef datum datum_value ;
58
59#define ckFilter(arg,type,name) \
60 if (db->type) { \
61 SV * save_defsv ; \
62 /* printf("filtering %s\n", name) ;*/ \
63 if (db->filtering) \
64 croak("recursion detected in %s", name) ; \
65 db->filtering = TRUE ; \
66 save_defsv = newSVsv(DEFSV) ; \
67 sv_setsv(DEFSV, arg) ; \
68 PUSHMARK(sp) ; \
69 (void) perl_call_sv(db->type, G_DISCARD|G_NOARGS); \
70 sv_setsv(arg, DEFSV) ; \
71 sv_setsv(DEFSV, save_defsv) ; \
72 SvREFCNT_dec(save_defsv) ; \
73 db->filtering = FALSE ; \
74 /*printf("end of filtering %s\n", name) ;*/ \
75 }
76
463ee0b2 77
a0d0e21e
LW
78#define odbm_FETCH(db,key) fetch(key)
79#define odbm_STORE(db,key,value,flags) store(key,value)
80#define odbm_DELETE(db,key) delete(key)
81#define odbm_FIRSTKEY(db) firstkey()
82#define odbm_NEXTKEY(db,key) nextkey(key)
463ee0b2 83
df3728a2
JH
84#define MY_CXT_KEY "ODBM_File::_guts" XS_VERSION
85
86typedef struct {
87 int x_dbmrefcnt;
88} my_cxt_t;
89
90START_MY_CXT
91
92#define dbmrefcnt (MY_CXT.x_dbmrefcnt)
463ee0b2 93
85e6fe83 94#ifndef DBM_REPLACE
463ee0b2 95#define DBM_REPLACE 0
85e6fe83 96#endif
463ee0b2
LW
97
98MODULE = ODBM_File PACKAGE = ODBM_File PREFIX = odbm_
99
df3728a2
JH
100BOOT:
101{
102 MY_CXT_INIT;
103}
104
463ee0b2 105ODBM_File
a0d0e21e 106odbm_TIEHASH(dbtype, filename, flags, mode)
463ee0b2
LW
107 char * dbtype
108 char * filename
109 int flags
110 int mode
111 CODE:
112 {
46fc3d4c 113 char *tmpbuf;
9fe6733a 114 void * dbp ;
df3728a2
JH
115 dMY_CXT;
116
463ee0b2
LW
117 if (dbmrefcnt++)
118 croak("Old dbm can only open one database");
46fc3d4c 119 New(0, tmpbuf, strlen(filename) + 5, char);
120 SAVEFREEPV(tmpbuf);
463ee0b2 121 sprintf(tmpbuf,"%s.dir",filename);
3280af22 122 if (stat(tmpbuf, &PL_statbuf) < 0) {
463ee0b2
LW
123 if (flags & O_CREAT) {
124 if (mode < 0 || close(creat(tmpbuf,mode)) < 0)
125 croak("ODBM_File: Can't create %s", filename);
126 sprintf(tmpbuf,"%s.pag",filename);
127 if (close(creat(tmpbuf,mode)) < 0)
128 croak("ODBM_File: Can't create %s", filename);
129 }
130 else
131 croak("ODBM_FILE: Can't open %s", filename);
132 }
9fe6733a
PM
133 dbp = (void*)(dbminit(filename) >= 0 ? &dbmrefcnt : 0);
134 RETVAL = (ODBM_File)safemalloc(sizeof(ODBM_File_type)) ;
135 Zero(RETVAL, 1, ODBM_File_type) ;
136 RETVAL->dbp = dbp ;
6b88bc9c 137 ST(0) = sv_mortalcopy(&PL_sv_undef);
56431972 138 sv_setptrobj(ST(0), RETVAL, dbtype);
463ee0b2
LW
139 }
140
141void
142DESTROY(db)
143 ODBM_File db
df3728a2
JH
144 PREINIT:
145 dMY_CXT;
463ee0b2
LW
146 CODE:
147 dbmrefcnt--;
148 dbmclose();
eb99164f 149 safefree(db);
463ee0b2 150
1b882d32 151datum_value
a0d0e21e 152odbm_FETCH(db, key)
463ee0b2 153 ODBM_File db
0bf2e707 154 datum_key_copy key
463ee0b2
LW
155
156int
a0d0e21e 157odbm_STORE(db, key, value, flags = DBM_REPLACE)
463ee0b2 158 ODBM_File db
9fe6733a
PM
159 datum_key key
160 datum_value value
463ee0b2 161 int flags
a0d0e21e
LW
162 CLEANUP:
163 if (RETVAL) {
164 if (RETVAL < 0 && errno == EPERM)
165 croak("No write permission to odbm file");
748a9306 166 croak("odbm store returned %d, errno %d, key \"%s\"",
a0d0e21e
LW
167 RETVAL,errno,key.dptr);
168 }
463ee0b2
LW
169
170int
a0d0e21e 171odbm_DELETE(db, key)
463ee0b2 172 ODBM_File db
9fe6733a 173 datum_key key
463ee0b2 174
9fe6733a 175datum_key
a0d0e21e 176odbm_FIRSTKEY(db)
463ee0b2
LW
177 ODBM_File db
178
9fe6733a 179datum_key
a0d0e21e 180odbm_NEXTKEY(db, key)
463ee0b2 181 ODBM_File db
9fe6733a
PM
182 datum_key key
183
184
185#define setFilter(type) \
186 { \
187 if (db->type) \
cad2e5aa
JH
188 RETVAL = sv_mortalcopy(db->type) ; \
189 ST(0) = RETVAL ; \
9fe6733a
PM
190 if (db->type && (code == &PL_sv_undef)) { \
191 SvREFCNT_dec(db->type) ; \
1b882d32 192 db->type = Nullsv ; \
9fe6733a
PM
193 } \
194 else if (code) { \
195 if (db->type) \
196 sv_setsv(db->type, code) ; \
197 else \
198 db->type = newSVsv(code) ; \
199 } \
200 }
201
202
203
204SV *
205filter_fetch_key(db, code)
206 ODBM_File db
207 SV * code
208 SV * RETVAL = &PL_sv_undef ;
209 CODE:
210 setFilter(filter_fetch_key) ;
9fe6733a
PM
211
212SV *
213filter_store_key(db, code)
214 ODBM_File db
215 SV * code
216 SV * RETVAL = &PL_sv_undef ;
217 CODE:
218 setFilter(filter_store_key) ;
9fe6733a
PM
219
220SV *
221filter_fetch_value(db, code)
222 ODBM_File db
223 SV * code
224 SV * RETVAL = &PL_sv_undef ;
225 CODE:
226 setFilter(filter_fetch_value) ;
9fe6733a
PM
227
228SV *
229filter_store_value(db, code)
230 ODBM_File db
231 SV * code
232 SV * RETVAL = &PL_sv_undef ;
233 CODE:
234 setFilter(filter_store_value) ;
463ee0b2 235