blob: e4829ea102ac4cc8e602219ce075e199f58e0fba [file] [log] [blame]
Guido van Rossum4b4c6641994-08-08 08:06:37 +00001/* GDBM module, hacked from the still-breathing corpse of the
2 DBM module by anthony.baxter@aaii.oz.au. Original copyright
3 follows:
4*/
5/***********************************************************
Guido van Rossum524b5881995-01-04 19:10:35 +00006Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
7The Netherlands.
Guido van Rossum4b4c6641994-08-08 08:06:37 +00008
9 All Rights Reserved
10
Guido van Rossumd266eb41996-10-25 14:44:06 +000011Permission to use, copy, modify, and distribute this software and its
12documentation for any purpose and without fee is hereby granted,
Guido van Rossum4b4c6641994-08-08 08:06:37 +000013provided that the above copyright notice appear in all copies and that
Guido van Rossumd266eb41996-10-25 14:44:06 +000014both that copyright notice and this permission notice appear in
Guido van Rossum4b4c6641994-08-08 08:06:37 +000015supporting documentation, and that the names of Stichting Mathematisch
Guido van Rossumd266eb41996-10-25 14:44:06 +000016Centrum or CWI or Corporation for National Research Initiatives or
17CNRI not be used in advertising or publicity pertaining to
18distribution of the software without specific, written prior
19permission.
Guido van Rossum4b4c6641994-08-08 08:06:37 +000020
Guido van Rossumd266eb41996-10-25 14:44:06 +000021While CWI is the initial source for this software, a modified version
22is made available by the Corporation for National Research Initiatives
23(CNRI) at the Internet address ftp://ftp.python.org.
24
25STICHTING MATHEMATISCH CENTRUM AND CNRI DISCLAIM ALL WARRANTIES WITH
26REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
27MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH
28CENTRUM OR CNRI BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
29DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
30PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
31TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
32PERFORMANCE OF THIS SOFTWARE.
Guido van Rossum4b4c6641994-08-08 08:06:37 +000033
34******************************************************************/
35
36/* DBM module using dictionary interface */
37
38
39#include "allobjects.h"
40#include "modsupport.h"
41
42#include <sys/types.h>
43#include <sys/stat.h>
44#include <fcntl.h>
45#include "gdbm.h"
46
47typedef struct {
48 OB_HEAD
49 int di_size; /* -1 means recompute */
50 GDBM_FILE di_dbm;
51} dbmobject;
52
53staticforward typeobject Dbmtype;
54
55#define is_dbmobject(v) ((v)->ob_type == &Dbmtype)
56
57static object *DbmError;
58
59static object *
60newdbmobject(file, flags, mode)
61 char *file;
62 int flags;
63 int mode;
64{
65 dbmobject *dp;
66
67 dp = NEWOBJ(dbmobject, &Dbmtype);
68 if (dp == NULL)
69 return NULL;
70 dp->di_size = -1;
Guido van Rossumb045afc1995-03-14 15:04:40 +000071 errno = 0;
Guido van Rossum4b4c6641994-08-08 08:06:37 +000072 if ( (dp->di_dbm = gdbm_open(file, 0, flags, mode, NULL)) == 0 ) {
Guido van Rossumb045afc1995-03-14 15:04:40 +000073 if (errno != 0)
74 err_errno(DbmError);
75 else
76 err_setstr(DbmError, (char *) gdbm_strerror(gdbm_errno));
Guido van Rossum4b4c6641994-08-08 08:06:37 +000077 DECREF(dp);
Guido van Rossum807b7be1995-07-07 22:37:11 +000078 return NULL;
Guido van Rossum4b4c6641994-08-08 08:06:37 +000079 }
80 return (object *)dp;
81}
82
83/* Methods */
84
85static void
86dbm_dealloc(dp)
87 register dbmobject *dp;
88{
89 if ( dp->di_dbm )
90 gdbm_close(dp->di_dbm);
91 DEL(dp);
92}
93
94static int
95dbm_length(dp)
96 dbmobject *dp;
97{
98 if ( dp->di_size < 0 ) {
99 datum key,okey;
100 int size;
101 okey.dsize=0;
102
103 size = 0;
104 for ( key=gdbm_firstkey(dp->di_dbm); key.dptr;
105 key = gdbm_nextkey(dp->di_dbm,okey)) {
106 size++;
Sjoerd Mullender2abc4941994-10-13 09:11:13 +0000107 if(okey.dsize) free(okey.dptr);
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000108 okey=key;
109 }
110 dp->di_size = size;
111 }
112 return dp->di_size;
113}
114
115static object *
116dbm_subscript(dp, key)
117 dbmobject *dp;
118 register object *key;
119{
120 object *v;
121 datum drec, krec;
122
123 if (!getargs(key, "s#", &krec.dptr, &krec.dsize) )
124 return NULL;
125
126 drec = gdbm_fetch(dp->di_dbm, krec);
127 if ( drec.dptr == 0 ) {
128 err_setstr(KeyError, GETSTRINGVALUE((stringobject *)key));
Guido van Rossum807b7be1995-07-07 22:37:11 +0000129 return NULL;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000130 }
Guido van Rossumb045afc1995-03-14 15:04:40 +0000131 v = newsizedstringobject(drec.dptr, drec.dsize);
132 free(drec.dptr);
133 return v;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000134}
135
136static int
137dbm_ass_sub(dp, v, w)
138 dbmobject *dp;
139 object *v, *w;
140{
141 datum krec, drec;
142
143 if ( !getargs(v, "s#", &krec.dptr, &krec.dsize) ) {
144 err_setstr(TypeError, "gdbm mappings have string indices only");
145 return -1;
146 }
147 dp->di_size = -1;
148 if (w == NULL) {
149 if ( gdbm_delete(dp->di_dbm, krec) < 0 ) {
150 err_setstr(KeyError, GETSTRINGVALUE((stringobject *)v));
151 return -1;
152 }
153 } else {
154 if ( !getargs(w, "s#", &drec.dptr, &drec.dsize) ) {
155 err_setstr(TypeError,
156 "gdbm mappings have string elements only");
157 return -1;
158 }
Guido van Rossumb045afc1995-03-14 15:04:40 +0000159 errno = 0;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000160 if ( gdbm_store(dp->di_dbm, krec, drec, GDBM_REPLACE) < 0 ) {
Guido van Rossumb045afc1995-03-14 15:04:40 +0000161 if (errno != 0)
162 err_errno(DbmError);
163 else
164 err_setstr(DbmError, (char *) gdbm_strerror(gdbm_errno));
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000165 return -1;
166 }
167 }
168 return 0;
169}
170
171static mapping_methods dbm_as_mapping = {
172 (inquiry)dbm_length, /*mp_length*/
173 (binaryfunc)dbm_subscript, /*mp_subscript*/
174 (objobjargproc)dbm_ass_sub, /*mp_ass_subscript*/
175};
176
177static object *
Guido van Rossum807b7be1995-07-07 22:37:11 +0000178dbm_close(dp, args)
179 register dbmobject *dp;
180 object *args;
181{
182 if ( !getnoarg(args) )
183 return NULL;
184 if ( dp->di_dbm )
185 gdbm_close(dp->di_dbm);
186 dp->di_dbm = NULL;
Guido van Rossum807b7be1995-07-07 22:37:11 +0000187 INCREF(None);
188 return None;
189}
190
191static object *
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000192dbm_keys(dp, args)
193 register dbmobject *dp;
194 object *args;
195{
196 register object *v, *item;
Guido van Rossum3be71401996-07-21 02:32:44 +0000197 datum key, nextkey;
Guido van Rossum66017aa1995-08-28 02:58:00 +0000198 int err;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000199
200 if (dp == NULL || !is_dbmobject(dp)) {
201 err_badcall();
202 return NULL;
203 }
Guido van Rossum3be71401996-07-21 02:32:44 +0000204
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000205 if (!getnoarg(args))
206 return NULL;
Guido van Rossum3be71401996-07-21 02:32:44 +0000207
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000208 v = newlistobject(0);
209 if (v == NULL)
210 return NULL;
Guido van Rossum3be71401996-07-21 02:32:44 +0000211
212 key = gdbm_firstkey(dp->di_dbm);
213 while (key.dptr) {
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000214 item = newsizedstringobject(key.dptr, key.dsize);
Guido van Rossum3be71401996-07-21 02:32:44 +0000215 if (item == NULL) {
216 free(key.dptr);
217 DECREF(v);
218 return NULL;
Guido van Rossum66017aa1995-08-28 02:58:00 +0000219 }
220 err = addlistitem(v, item);
221 DECREF(item);
Guido van Rossum66017aa1995-08-28 02:58:00 +0000222 if (err != 0) {
Guido van Rossum3be71401996-07-21 02:32:44 +0000223 free(key.dptr);
224 DECREF(v);
225 return NULL;
Guido van Rossum66017aa1995-08-28 02:58:00 +0000226 }
Guido van Rossum3be71401996-07-21 02:32:44 +0000227 nextkey = gdbm_nextkey(dp->di_dbm, key);
228 free(key.dptr);
229 key = nextkey;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000230 }
Guido van Rossum3be71401996-07-21 02:32:44 +0000231
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000232 return v;
233}
234
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000235static object *
236dbm_has_key(dp, args)
237 register dbmobject *dp;
238 object *args;
239{
Guido van Rossumb045afc1995-03-14 15:04:40 +0000240 datum key;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000241
242 if (!getargs(args, "s#", &key.dptr, &key.dsize))
243 return NULL;
Guido van Rossumb045afc1995-03-14 15:04:40 +0000244 return newintobject((long) gdbm_exists(dp->di_dbm, key));
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000245}
246
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000247static object *
248dbm_firstkey(dp, args)
249 register dbmobject *dp;
250 object *args;
251{
252 register object *v;
253 datum key;
254
255 if (!getnoarg(args))
256 return NULL;
257 key = gdbm_firstkey(dp->di_dbm);
258 if (key.dptr) {
259 v = newsizedstringobject(key.dptr, key.dsize);
260 free(key.dptr);
261 return v;
262 } else {
263 INCREF(None);
264 return None;
265 }
266}
267
268static object *
269dbm_nextkey(dp, args)
270 register dbmobject *dp;
271 object *args;
272{
273 register object *v;
274 datum key, nextkey;
275
276 if (!getargs(args, "s#", &key.dptr, &key.dsize))
277 return NULL;
278 nextkey = gdbm_nextkey(dp->di_dbm, key);
279 if (nextkey.dptr) {
280 v = newsizedstringobject(nextkey.dptr, nextkey.dsize);
281 free(nextkey.dptr);
282 return v;
283 } else {
284 INCREF(None);
285 return None;
286 }
287}
288
289static object *
290dbm_reorganize(dp, args)
291 register dbmobject *dp;
292 object *args;
293{
294 if (!getnoarg(args))
295 return NULL;
296 errno = 0;
297 if (gdbm_reorganize(dp->di_dbm) < 0) {
298 if (errno != 0)
299 err_errno(DbmError);
300 else
301 err_setstr(DbmError, (char *) gdbm_strerror(gdbm_errno));
302 return NULL;
303 }
304 INCREF(None);
305 return None;
306}
307
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000308static struct methodlist dbm_methods[] = {
Guido van Rossum807b7be1995-07-07 22:37:11 +0000309 {"close", (method)dbm_close},
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000310 {"keys", (method)dbm_keys},
311 {"has_key", (method)dbm_has_key},
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000312 {"firstkey", (method)dbm_firstkey},
313 {"nextkey", (method)dbm_nextkey},
314 {"reorganize", (method)dbm_reorganize},
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000315 {NULL, NULL} /* sentinel */
316};
317
318static object *
319dbm_getattr(dp, name)
320 dbmobject *dp;
321 char *name;
322{
323 return findmethod(dbm_methods, (object *)dp, name);
324}
325
326static typeobject Dbmtype = {
327 OB_HEAD_INIT(&Typetype)
328 0,
Guido van Rossum807b7be1995-07-07 22:37:11 +0000329 "gdbm",
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000330 sizeof(dbmobject),
331 0,
332 (destructor)dbm_dealloc, /*tp_dealloc*/
333 0, /*tp_print*/
334 (getattrfunc)dbm_getattr, /*tp_getattr*/
335 0, /*tp_setattr*/
336 0, /*tp_compare*/
337 0, /*tp_repr*/
338 0, /*tp_as_number*/
339 0, /*tp_as_sequence*/
340 &dbm_as_mapping, /*tp_as_mapping*/
341};
342
343/* ----------------------------------------------------------------- */
344
345static object *
346dbmopen(self, args)
347 object *self;
348 object *args;
349{
Guido van Rossum807b7be1995-07-07 22:37:11 +0000350 char *name;
Guido van Rossume36e1fe1996-01-26 21:08:01 +0000351 char *flags = "r ";
Guido van Rossum807b7be1995-07-07 22:37:11 +0000352 int iflags;
353 int mode = 0666;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000354
Guido van Rossume36e1fe1996-01-26 21:08:01 +0000355/* XXXX add other flags. 2nd character can be "f" meaning open in fast mode. */
356 if ( !newgetargs(args, "s|si", &name, &flags, &mode) )
Guido van Rossum807b7be1995-07-07 22:37:11 +0000357 return NULL;
Guido van Rossume36e1fe1996-01-26 21:08:01 +0000358 switch (flags[0]) {
359 case 'r':
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000360 iflags = GDBM_READER;
Guido van Rossume36e1fe1996-01-26 21:08:01 +0000361 break;
362 case 'w':
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000363 iflags = GDBM_WRITER;
Guido van Rossume36e1fe1996-01-26 21:08:01 +0000364 break;
365 case 'c':
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000366 iflags = GDBM_WRCREAT;
Guido van Rossume36e1fe1996-01-26 21:08:01 +0000367 break;
368 case 'n':
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000369 iflags = GDBM_NEWDB;
Guido van Rossume36e1fe1996-01-26 21:08:01 +0000370 break;
371 default:
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000372 err_setstr(DbmError,
Guido van Rossumb045afc1995-03-14 15:04:40 +0000373 "Flags should be one of 'r', 'w', 'c' or 'n'");
Guido van Rossum807b7be1995-07-07 22:37:11 +0000374 return NULL;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000375 }
Guido van Rossume36e1fe1996-01-26 21:08:01 +0000376 if (flags[1] == 'f')
377 iflags |= GDBM_FAST;
378 return newdbmobject(name, iflags, mode);
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000379}
380
381static struct methodlist dbmmodule_methods[] = {
Guido van Rossum807b7be1995-07-07 22:37:11 +0000382 { "open", (method)dbmopen, 1 },
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000383 { 0, 0 },
384};
385
386void
387initgdbm() {
388 object *m, *d;
389
390 m = initmodule("gdbm", dbmmodule_methods);
391 d = getmoduledict(m);
392 DbmError = newstringobject("gdbm.error");
393 if ( DbmError == NULL || dictinsert(d, "error", DbmError) )
394 fatal("can't define gdbm.error");
395}