From: Ilya Zakharevich <ilya@math.ohio-state.edu>
[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
5#ifdef NULL
e5c9fcd0 6#undef NULL /* XXX Why? */
463ee0b2 7#endif
8e07c86e 8#ifdef I_DBM
9# include <dbm.h>
10#else
11# ifdef I_RPCSVC_DBM
12# include <rpcsvc/dbm.h>
13# endif
14#endif
463ee0b2 15
1639c7b3 16#ifdef DBM_BUG_DUPLICATE_FREE
17/*
18 * DBM on at least Ultrix and HPUX call dbmclose() from dbminit(),
19 * resulting in duplicate free() because dbmclose() does *not*
20 * check if it has already been called for this DBM.
21 * If some malloc/free calls have been done between dbmclose() and
22 * the next dbminit(), the memory might be used for something else when
23 * it is freed.
24 * Verified to work on ultrix4.3. Probably will work on HP/UX.
25 * Set DBM_BUG_DUPLICATE_FREE in the extension hint file.
26 */
27/* Close the previous dbm, and fail to open a new dbm */
28#define dbmclose() ((void) dbminit("/tmp/x/y/z/z/y"))
29#endif
30
463ee0b2 31#include <fcntl.h>
32
9fe6733a 33typedef struct {
34 void * dbp ;
35 SV * filter_fetch_key ;
36 SV * filter_store_key ;
37 SV * filter_fetch_value ;
38 SV * filter_store_value ;
39 int filtering ;
40 } ODBM_File_type;
41
42typedef ODBM_File_type * ODBM_File ;
43typedef datum datum_key ;
44typedef datum datum_value ;
45
46#define ckFilter(arg,type,name) \
47 if (db->type) { \
48 SV * save_defsv ; \
49 /* printf("filtering %s\n", name) ;*/ \
50 if (db->filtering) \
51 croak("recursion detected in %s", name) ; \
52 db->filtering = TRUE ; \
53 save_defsv = newSVsv(DEFSV) ; \
54 sv_setsv(DEFSV, arg) ; \
55 PUSHMARK(sp) ; \
56 (void) perl_call_sv(db->type, G_DISCARD|G_NOARGS); \
57 sv_setsv(arg, DEFSV) ; \
58 sv_setsv(DEFSV, save_defsv) ; \
59 SvREFCNT_dec(save_defsv) ; \
60 db->filtering = FALSE ; \
61 /*printf("end of filtering %s\n", name) ;*/ \
62 }
63
463ee0b2 64
a0d0e21e 65#define odbm_FETCH(db,key) fetch(key)
66#define odbm_STORE(db,key,value,flags) store(key,value)
67#define odbm_DELETE(db,key) delete(key)
68#define odbm_FIRSTKEY(db) firstkey()
69#define odbm_NEXTKEY(db,key) nextkey(key)
463ee0b2 70
71static int dbmrefcnt;
72
85e6fe83 73#ifndef DBM_REPLACE
463ee0b2 74#define DBM_REPLACE 0
85e6fe83 75#endif
463ee0b2 76
77MODULE = ODBM_File PACKAGE = ODBM_File PREFIX = odbm_
78
e5c9fcd0 79#ifndef NULL
80# define NULL 0
81#endif
82
463ee0b2 83ODBM_File
a0d0e21e 84odbm_TIEHASH(dbtype, filename, flags, mode)
463ee0b2 85 char * dbtype
86 char * filename
87 int flags
88 int mode
89 CODE:
90 {
46fc3d4c 91 char *tmpbuf;
9fe6733a 92 void * dbp ;
463ee0b2 93 if (dbmrefcnt++)
94 croak("Old dbm can only open one database");
46fc3d4c 95 New(0, tmpbuf, strlen(filename) + 5, char);
96 SAVEFREEPV(tmpbuf);
463ee0b2 97 sprintf(tmpbuf,"%s.dir",filename);
3280af22 98 if (stat(tmpbuf, &PL_statbuf) < 0) {
463ee0b2 99 if (flags & O_CREAT) {
100 if (mode < 0 || close(creat(tmpbuf,mode)) < 0)
101 croak("ODBM_File: Can't create %s", filename);
102 sprintf(tmpbuf,"%s.pag",filename);
103 if (close(creat(tmpbuf,mode)) < 0)
104 croak("ODBM_File: Can't create %s", filename);
105 }
106 else
107 croak("ODBM_FILE: Can't open %s", filename);
108 }
9fe6733a 109 dbp = (void*)(dbminit(filename) >= 0 ? &dbmrefcnt : 0);
110 RETVAL = (ODBM_File)safemalloc(sizeof(ODBM_File_type)) ;
111 Zero(RETVAL, 1, ODBM_File_type) ;
112 RETVAL->dbp = dbp ;
6b88bc9c 113 ST(0) = sv_mortalcopy(&PL_sv_undef);
42718184 114 sv_setptrobj(ST(0), PTR_CAST RETVAL, dbtype);
463ee0b2 115 }
116
117void
118DESTROY(db)
119 ODBM_File db
120 CODE:
121 dbmrefcnt--;
122 dbmclose();
123
1b882d32 124datum_value
a0d0e21e 125odbm_FETCH(db, key)
463ee0b2 126 ODBM_File db
9fe6733a 127 datum_key key
463ee0b2 128
129int
a0d0e21e 130odbm_STORE(db, key, value, flags = DBM_REPLACE)
463ee0b2 131 ODBM_File db
9fe6733a 132 datum_key key
133 datum_value value
463ee0b2 134 int flags
a0d0e21e 135 CLEANUP:
136 if (RETVAL) {
137 if (RETVAL < 0 && errno == EPERM)
138 croak("No write permission to odbm file");
748a9306 139 croak("odbm store returned %d, errno %d, key \"%s\"",
a0d0e21e 140 RETVAL,errno,key.dptr);
141 }
463ee0b2 142
143int
a0d0e21e 144odbm_DELETE(db, key)
463ee0b2 145 ODBM_File db
9fe6733a 146 datum_key key
463ee0b2 147
9fe6733a 148datum_key
a0d0e21e 149odbm_FIRSTKEY(db)
463ee0b2 150 ODBM_File db
151
9fe6733a 152datum_key
a0d0e21e 153odbm_NEXTKEY(db, key)
463ee0b2 154 ODBM_File db
9fe6733a 155 datum_key key
156
157
158#define setFilter(type) \
159 { \
160 if (db->type) \
cad2e5aa 161 RETVAL = sv_mortalcopy(db->type) ; \
162 ST(0) = RETVAL ; \
9fe6733a 163 if (db->type && (code == &PL_sv_undef)) { \
164 SvREFCNT_dec(db->type) ; \
1b882d32 165 db->type = Nullsv ; \
9fe6733a 166 } \
167 else if (code) { \
168 if (db->type) \
169 sv_setsv(db->type, code) ; \
170 else \
171 db->type = newSVsv(code) ; \
172 } \
173 }
174
175
176
177SV *
178filter_fetch_key(db, code)
179 ODBM_File db
180 SV * code
181 SV * RETVAL = &PL_sv_undef ;
182 CODE:
183 setFilter(filter_fetch_key) ;
9fe6733a 184
185SV *
186filter_store_key(db, code)
187 ODBM_File db
188 SV * code
189 SV * RETVAL = &PL_sv_undef ;
190 CODE:
191 setFilter(filter_store_key) ;
9fe6733a 192
193SV *
194filter_fetch_value(db, code)
195 ODBM_File db
196 SV * code
197 SV * RETVAL = &PL_sv_undef ;
198 CODE:
199 setFilter(filter_fetch_value) ;
9fe6733a 200
201SV *
202filter_store_value(db, code)
203 ODBM_File db
204 SV * code
205 SV * RETVAL = &PL_sv_undef ;
206 CODE:
207 setFilter(filter_store_value) ;
463ee0b2 208