blob: a48c756bcbcd9b64c84e2530500eaa0971a36d05 [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
11Permission to use, copy, modify, and distribute this software and its
12documentation for any purpose and without fee is hereby granted,
13provided that the above copyright notice appear in all copies and that
14both that copyright notice and this permission notice appear in
15supporting documentation, and that the names of Stichting Mathematisch
16Centrum or CWI not be used in advertising or publicity pertaining to
17distribution of the software without specific, written prior permission.
18
19STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
20THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
21FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
22FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
23WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
24ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
25OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
26
27******************************************************************/
28
29/* DBM module using dictionary interface */
30
31
32#include "allobjects.h"
33#include "modsupport.h"
34
35#include <sys/types.h>
36#include <sys/stat.h>
37#include <fcntl.h>
38#include "gdbm.h"
39
40typedef struct {
41 OB_HEAD
42 int di_size; /* -1 means recompute */
43 GDBM_FILE di_dbm;
44} dbmobject;
45
46staticforward typeobject Dbmtype;
47
48#define is_dbmobject(v) ((v)->ob_type == &Dbmtype)
49
50static object *DbmError;
51
52static object *
53newdbmobject(file, flags, mode)
54 char *file;
55 int flags;
56 int mode;
57{
58 dbmobject *dp;
59
60 dp = NEWOBJ(dbmobject, &Dbmtype);
61 if (dp == NULL)
62 return NULL;
63 dp->di_size = -1;
Guido van Rossumb045afc1995-03-14 15:04:40 +000064 errno = 0;
Guido van Rossum4b4c6641994-08-08 08:06:37 +000065 if ( (dp->di_dbm = gdbm_open(file, 0, flags, mode, NULL)) == 0 ) {
Guido van Rossumb045afc1995-03-14 15:04:40 +000066 if (errno != 0)
67 err_errno(DbmError);
68 else
69 err_setstr(DbmError, (char *) gdbm_strerror(gdbm_errno));
Guido van Rossum4b4c6641994-08-08 08:06:37 +000070 DECREF(dp);
Guido van Rossum807b7be1995-07-07 22:37:11 +000071 return NULL;
Guido van Rossum4b4c6641994-08-08 08:06:37 +000072 }
73 return (object *)dp;
74}
75
76/* Methods */
77
78static void
79dbm_dealloc(dp)
80 register dbmobject *dp;
81{
82 if ( dp->di_dbm )
83 gdbm_close(dp->di_dbm);
84 DEL(dp);
85}
86
87static int
88dbm_length(dp)
89 dbmobject *dp;
90{
91 if ( dp->di_size < 0 ) {
92 datum key,okey;
93 int size;
94 okey.dsize=0;
95
96 size = 0;
97 for ( key=gdbm_firstkey(dp->di_dbm); key.dptr;
98 key = gdbm_nextkey(dp->di_dbm,okey)) {
99 size++;
Sjoerd Mullender2abc4941994-10-13 09:11:13 +0000100 if(okey.dsize) free(okey.dptr);
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000101 okey=key;
102 }
103 dp->di_size = size;
104 }
105 return dp->di_size;
106}
107
108static object *
109dbm_subscript(dp, key)
110 dbmobject *dp;
111 register object *key;
112{
113 object *v;
114 datum drec, krec;
115
116 if (!getargs(key, "s#", &krec.dptr, &krec.dsize) )
117 return NULL;
118
119 drec = gdbm_fetch(dp->di_dbm, krec);
120 if ( drec.dptr == 0 ) {
121 err_setstr(KeyError, GETSTRINGVALUE((stringobject *)key));
Guido van Rossum807b7be1995-07-07 22:37:11 +0000122 return NULL;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000123 }
Guido van Rossumb045afc1995-03-14 15:04:40 +0000124 v = newsizedstringobject(drec.dptr, drec.dsize);
125 free(drec.dptr);
126 return v;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000127}
128
129static int
130dbm_ass_sub(dp, v, w)
131 dbmobject *dp;
132 object *v, *w;
133{
134 datum krec, drec;
135
136 if ( !getargs(v, "s#", &krec.dptr, &krec.dsize) ) {
137 err_setstr(TypeError, "gdbm mappings have string indices only");
138 return -1;
139 }
140 dp->di_size = -1;
141 if (w == NULL) {
142 if ( gdbm_delete(dp->di_dbm, krec) < 0 ) {
143 err_setstr(KeyError, GETSTRINGVALUE((stringobject *)v));
144 return -1;
145 }
146 } else {
147 if ( !getargs(w, "s#", &drec.dptr, &drec.dsize) ) {
148 err_setstr(TypeError,
149 "gdbm mappings have string elements only");
150 return -1;
151 }
Guido van Rossumb045afc1995-03-14 15:04:40 +0000152 errno = 0;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000153 if ( gdbm_store(dp->di_dbm, krec, drec, GDBM_REPLACE) < 0 ) {
Guido van Rossumb045afc1995-03-14 15:04:40 +0000154 if (errno != 0)
155 err_errno(DbmError);
156 else
157 err_setstr(DbmError, (char *) gdbm_strerror(gdbm_errno));
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000158 return -1;
159 }
160 }
161 return 0;
162}
163
164static mapping_methods dbm_as_mapping = {
165 (inquiry)dbm_length, /*mp_length*/
166 (binaryfunc)dbm_subscript, /*mp_subscript*/
167 (objobjargproc)dbm_ass_sub, /*mp_ass_subscript*/
168};
169
170static object *
Guido van Rossum807b7be1995-07-07 22:37:11 +0000171dbm_close(dp, args)
172 register dbmobject *dp;
173 object *args;
174{
175 if ( !getnoarg(args) )
176 return NULL;
177 if ( dp->di_dbm )
178 gdbm_close(dp->di_dbm);
179 dp->di_dbm = NULL;
Guido van Rossum807b7be1995-07-07 22:37:11 +0000180 INCREF(None);
181 return None;
182}
183
184static object *
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000185dbm_keys(dp, args)
186 register dbmobject *dp;
187 object *args;
188{
189 register object *v, *item;
Guido van Rossum3be71401996-07-21 02:32:44 +0000190 datum key, nextkey;
Guido van Rossum66017aa1995-08-28 02:58:00 +0000191 int err;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000192
193 if (dp == NULL || !is_dbmobject(dp)) {
194 err_badcall();
195 return NULL;
196 }
Guido van Rossum3be71401996-07-21 02:32:44 +0000197
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000198 if (!getnoarg(args))
199 return NULL;
Guido van Rossum3be71401996-07-21 02:32:44 +0000200
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000201 v = newlistobject(0);
202 if (v == NULL)
203 return NULL;
Guido van Rossum3be71401996-07-21 02:32:44 +0000204
205 key = gdbm_firstkey(dp->di_dbm);
206 while (key.dptr) {
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000207 item = newsizedstringobject(key.dptr, key.dsize);
Guido van Rossum3be71401996-07-21 02:32:44 +0000208 if (item == NULL) {
209 free(key.dptr);
210 DECREF(v);
211 return NULL;
Guido van Rossum66017aa1995-08-28 02:58:00 +0000212 }
213 err = addlistitem(v, item);
214 DECREF(item);
Guido van Rossum66017aa1995-08-28 02:58:00 +0000215 if (err != 0) {
Guido van Rossum3be71401996-07-21 02:32:44 +0000216 free(key.dptr);
217 DECREF(v);
218 return NULL;
Guido van Rossum66017aa1995-08-28 02:58:00 +0000219 }
Guido van Rossum3be71401996-07-21 02:32:44 +0000220 nextkey = gdbm_nextkey(dp->di_dbm, key);
221 free(key.dptr);
222 key = nextkey;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000223 }
Guido van Rossum3be71401996-07-21 02:32:44 +0000224
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000225 return v;
226}
227
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000228static object *
229dbm_has_key(dp, args)
230 register dbmobject *dp;
231 object *args;
232{
Guido van Rossumb045afc1995-03-14 15:04:40 +0000233 datum key;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000234
235 if (!getargs(args, "s#", &key.dptr, &key.dsize))
236 return NULL;
Guido van Rossumb045afc1995-03-14 15:04:40 +0000237 return newintobject((long) gdbm_exists(dp->di_dbm, key));
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000238}
239
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000240static object *
241dbm_firstkey(dp, args)
242 register dbmobject *dp;
243 object *args;
244{
245 register object *v;
246 datum key;
247
248 if (!getnoarg(args))
249 return NULL;
250 key = gdbm_firstkey(dp->di_dbm);
251 if (key.dptr) {
252 v = newsizedstringobject(key.dptr, key.dsize);
253 free(key.dptr);
254 return v;
255 } else {
256 INCREF(None);
257 return None;
258 }
259}
260
261static object *
262dbm_nextkey(dp, args)
263 register dbmobject *dp;
264 object *args;
265{
266 register object *v;
267 datum key, nextkey;
268
269 if (!getargs(args, "s#", &key.dptr, &key.dsize))
270 return NULL;
271 nextkey = gdbm_nextkey(dp->di_dbm, key);
272 if (nextkey.dptr) {
273 v = newsizedstringobject(nextkey.dptr, nextkey.dsize);
274 free(nextkey.dptr);
275 return v;
276 } else {
277 INCREF(None);
278 return None;
279 }
280}
281
282static object *
283dbm_reorganize(dp, args)
284 register dbmobject *dp;
285 object *args;
286{
287 if (!getnoarg(args))
288 return NULL;
289 errno = 0;
290 if (gdbm_reorganize(dp->di_dbm) < 0) {
291 if (errno != 0)
292 err_errno(DbmError);
293 else
294 err_setstr(DbmError, (char *) gdbm_strerror(gdbm_errno));
295 return NULL;
296 }
297 INCREF(None);
298 return None;
299}
300
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000301static struct methodlist dbm_methods[] = {
Guido van Rossum807b7be1995-07-07 22:37:11 +0000302 {"close", (method)dbm_close},
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000303 {"keys", (method)dbm_keys},
304 {"has_key", (method)dbm_has_key},
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000305 {"firstkey", (method)dbm_firstkey},
306 {"nextkey", (method)dbm_nextkey},
307 {"reorganize", (method)dbm_reorganize},
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000308 {NULL, NULL} /* sentinel */
309};
310
311static object *
312dbm_getattr(dp, name)
313 dbmobject *dp;
314 char *name;
315{
316 return findmethod(dbm_methods, (object *)dp, name);
317}
318
319static typeobject Dbmtype = {
320 OB_HEAD_INIT(&Typetype)
321 0,
Guido van Rossum807b7be1995-07-07 22:37:11 +0000322 "gdbm",
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000323 sizeof(dbmobject),
324 0,
325 (destructor)dbm_dealloc, /*tp_dealloc*/
326 0, /*tp_print*/
327 (getattrfunc)dbm_getattr, /*tp_getattr*/
328 0, /*tp_setattr*/
329 0, /*tp_compare*/
330 0, /*tp_repr*/
331 0, /*tp_as_number*/
332 0, /*tp_as_sequence*/
333 &dbm_as_mapping, /*tp_as_mapping*/
334};
335
336/* ----------------------------------------------------------------- */
337
338static object *
339dbmopen(self, args)
340 object *self;
341 object *args;
342{
Guido van Rossum807b7be1995-07-07 22:37:11 +0000343 char *name;
Guido van Rossume36e1fe1996-01-26 21:08:01 +0000344 char *flags = "r ";
Guido van Rossum807b7be1995-07-07 22:37:11 +0000345 int iflags;
346 int mode = 0666;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000347
Guido van Rossume36e1fe1996-01-26 21:08:01 +0000348/* XXXX add other flags. 2nd character can be "f" meaning open in fast mode. */
349 if ( !newgetargs(args, "s|si", &name, &flags, &mode) )
Guido van Rossum807b7be1995-07-07 22:37:11 +0000350 return NULL;
Guido van Rossume36e1fe1996-01-26 21:08:01 +0000351 switch (flags[0]) {
352 case 'r':
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000353 iflags = GDBM_READER;
Guido van Rossume36e1fe1996-01-26 21:08:01 +0000354 break;
355 case 'w':
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000356 iflags = GDBM_WRITER;
Guido van Rossume36e1fe1996-01-26 21:08:01 +0000357 break;
358 case 'c':
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000359 iflags = GDBM_WRCREAT;
Guido van Rossume36e1fe1996-01-26 21:08:01 +0000360 break;
361 case 'n':
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000362 iflags = GDBM_NEWDB;
Guido van Rossume36e1fe1996-01-26 21:08:01 +0000363 break;
364 default:
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000365 err_setstr(DbmError,
Guido van Rossumb045afc1995-03-14 15:04:40 +0000366 "Flags should be one of 'r', 'w', 'c' or 'n'");
Guido van Rossum807b7be1995-07-07 22:37:11 +0000367 return NULL;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000368 }
Guido van Rossume36e1fe1996-01-26 21:08:01 +0000369 if (flags[1] == 'f')
370 iflags |= GDBM_FAST;
371 return newdbmobject(name, iflags, mode);
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000372}
373
374static struct methodlist dbmmodule_methods[] = {
Guido van Rossum807b7be1995-07-07 22:37:11 +0000375 { "open", (method)dbmopen, 1 },
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000376 { 0, 0 },
377};
378
379void
380initgdbm() {
381 object *m, *d;
382
383 m = initmodule("gdbm", dbmmodule_methods);
384 d = getmoduledict(m);
385 DbmError = newstringobject("gdbm.error");
386 if ( DbmError == NULL || dictinsert(d, "error", DbmError) )
387 fatal("can't define gdbm.error");
388}