Like dl_hpux, like dl_dld.
[p5sagit/p5-mst-13.2.git] / ext / ODBM_File / ODBM_File.xs
CommitLineData
463ee0b2 1#include "EXTERN.h"
2#include "perl.h"
3#include "XSUB.h"
4
8e07c86e 5#ifdef I_DBM
bb636fa4 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 11# include <dbm.h>
12#else
13# ifdef I_RPCSVC_DBM
14# include <rpcsvc/dbm.h>
15# endif
16#endif
463ee0b2 17
2ef53570 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 43#include <fcntl.h>
44
9fe6733a 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 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 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
84static int dbmrefcnt;
85
85e6fe83 86#ifndef DBM_REPLACE
463ee0b2 87#define DBM_REPLACE 0
85e6fe83 88#endif
463ee0b2 89
90MODULE = ODBM_File PACKAGE = ODBM_File PREFIX = odbm_
91
92ODBM_File
a0d0e21e 93odbm_TIEHASH(dbtype, filename, flags, mode)
463ee0b2 94 char * dbtype
95 char * filename
96 int flags
97 int mode
98 CODE:
99 {
46fc3d4c 100 char *tmpbuf;
9fe6733a 101 void * dbp ;
463ee0b2 102 if (dbmrefcnt++)
103 croak("Old dbm can only open one database");
46fc3d4c 104 New(0, tmpbuf, strlen(filename) + 5, char);
105 SAVEFREEPV(tmpbuf);
463ee0b2 106 sprintf(tmpbuf,"%s.dir",filename);
3280af22 107 if (stat(tmpbuf, &PL_statbuf) < 0) {
463ee0b2 108 if (flags & O_CREAT) {
109 if (mode < 0 || close(creat(tmpbuf,mode)) < 0)
110 croak("ODBM_File: Can't create %s", filename);
111 sprintf(tmpbuf,"%s.pag",filename);
112 if (close(creat(tmpbuf,mode)) < 0)
113 croak("ODBM_File: Can't create %s", filename);
114 }
115 else
116 croak("ODBM_FILE: Can't open %s", filename);
117 }
9fe6733a 118 dbp = (void*)(dbminit(filename) >= 0 ? &dbmrefcnt : 0);
119 RETVAL = (ODBM_File)safemalloc(sizeof(ODBM_File_type)) ;
120 Zero(RETVAL, 1, ODBM_File_type) ;
121 RETVAL->dbp = dbp ;
6b88bc9c 122 ST(0) = sv_mortalcopy(&PL_sv_undef);
56431972 123 sv_setptrobj(ST(0), RETVAL, dbtype);
463ee0b2 124 }
125
126void
127DESTROY(db)
128 ODBM_File db
129 CODE:
130 dbmrefcnt--;
131 dbmclose();
eb99164f 132 safefree(db);
463ee0b2 133
1b882d32 134datum_value
a0d0e21e 135odbm_FETCH(db, key)
463ee0b2 136 ODBM_File db
0bf2e707 137 datum_key_copy key
463ee0b2 138
139int
a0d0e21e 140odbm_STORE(db, key, value, flags = DBM_REPLACE)
463ee0b2 141 ODBM_File db
9fe6733a 142 datum_key key
143 datum_value value
463ee0b2 144 int flags
a0d0e21e 145 CLEANUP:
146 if (RETVAL) {
147 if (RETVAL < 0 && errno == EPERM)
148 croak("No write permission to odbm file");
748a9306 149 croak("odbm store returned %d, errno %d, key \"%s\"",
a0d0e21e 150 RETVAL,errno,key.dptr);
151 }
463ee0b2 152
153int
a0d0e21e 154odbm_DELETE(db, key)
463ee0b2 155 ODBM_File db
9fe6733a 156 datum_key key
463ee0b2 157
9fe6733a 158datum_key
a0d0e21e 159odbm_FIRSTKEY(db)
463ee0b2 160 ODBM_File db
161
9fe6733a 162datum_key
a0d0e21e 163odbm_NEXTKEY(db, key)
463ee0b2 164 ODBM_File db
9fe6733a 165 datum_key key
166
167
168#define setFilter(type) \
169 { \
170 if (db->type) \
cad2e5aa 171 RETVAL = sv_mortalcopy(db->type) ; \
172 ST(0) = RETVAL ; \
9fe6733a 173 if (db->type && (code == &PL_sv_undef)) { \
174 SvREFCNT_dec(db->type) ; \
1b882d32 175 db->type = Nullsv ; \
9fe6733a 176 } \
177 else if (code) { \
178 if (db->type) \
179 sv_setsv(db->type, code) ; \
180 else \
181 db->type = newSVsv(code) ; \
182 } \
183 }
184
185
186
187SV *
188filter_fetch_key(db, code)
189 ODBM_File db
190 SV * code
191 SV * RETVAL = &PL_sv_undef ;
192 CODE:
193 setFilter(filter_fetch_key) ;
9fe6733a 194
195SV *
196filter_store_key(db, code)
197 ODBM_File db
198 SV * code
199 SV * RETVAL = &PL_sv_undef ;
200 CODE:
201 setFilter(filter_store_key) ;
9fe6733a 202
203SV *
204filter_fetch_value(db, code)
205 ODBM_File db
206 SV * code
207 SV * RETVAL = &PL_sv_undef ;
208 CODE:
209 setFilter(filter_fetch_value) ;
9fe6733a 210
211SV *
212filter_store_value(db, code)
213 ODBM_File db
214 SV * code
215 SV * RETVAL = &PL_sv_undef ;
216 CODE:
217 setFilter(filter_store_value) ;
463ee0b2 218