blob: 85934f2ebfdbe519ba3760c0c0ad51b4bb568e31 [file] [log] [blame]
Guido van Rossumdd9ed831992-06-29 17:10:40 +00001/***********************************************************
Guido van Rossum524b5881995-01-04 19:10:35 +00002Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
3The Netherlands.
Guido van Rossumdd9ed831992-06-29 17:10:40 +00004
5 All Rights Reserved
6
Guido van Rossumd266eb41996-10-25 14:44:06 +00007Permission to use, copy, modify, and distribute this software and its
8documentation for any purpose and without fee is hereby granted,
Guido van Rossumdd9ed831992-06-29 17:10:40 +00009provided that the above copyright notice appear in all copies and that
Guido van Rossumd266eb41996-10-25 14:44:06 +000010both that copyright notice and this permission notice appear in
Guido van Rossumdd9ed831992-06-29 17:10:40 +000011supporting documentation, and that the names of Stichting Mathematisch
Guido van Rossumd266eb41996-10-25 14:44:06 +000012Centrum or CWI or Corporation for National Research Initiatives or
13CNRI not be used in advertising or publicity pertaining to
14distribution of the software without specific, written prior
15permission.
Guido van Rossumdd9ed831992-06-29 17:10:40 +000016
Guido van Rossumd266eb41996-10-25 14:44:06 +000017While CWI is the initial source for this software, a modified version
18is made available by the Corporation for National Research Initiatives
19(CNRI) at the Internet address ftp://ftp.python.org.
20
21STICHTING MATHEMATISCH CENTRUM AND CNRI DISCLAIM ALL WARRANTIES WITH
22REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
23MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH
24CENTRUM OR CNRI BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
25DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
26PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
27TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
28PERFORMANCE OF THIS SOFTWARE.
Guido van Rossumdd9ed831992-06-29 17:10:40 +000029
30******************************************************************/
31
32/* DBM module using dictionary interface */
33
34
35#include "allobjects.h"
36#include "modsupport.h"
37
38#include <sys/types.h>
39#include <sys/stat.h>
40#include <fcntl.h>
41#include <ndbm.h>
42
43typedef struct {
44 OB_HEAD
45 int di_size; /* -1 means recompute */
46 DBM *di_dbm;
47} dbmobject;
48
Guido van Rossumb6775db1994-08-01 11:34:53 +000049staticforward typeobject Dbmtype;
Guido van Rossumdd9ed831992-06-29 17:10:40 +000050
51#define is_dbmobject(v) ((v)->ob_type == &Dbmtype)
52
53static object *DbmError;
54
55static object *
56newdbmobject(file, flags, mode)
57 char *file;
58 int flags;
59 int mode;
60{
61 dbmobject *dp;
62
63 dp = NEWOBJ(dbmobject, &Dbmtype);
64 if (dp == NULL)
65 return NULL;
66 dp->di_size = -1;
67 if ( (dp->di_dbm = dbm_open(file, flags, mode)) == 0 ) {
68 err_errno(DbmError);
69 DECREF(dp);
Guido van Rossum807b7be1995-07-07 22:37:11 +000070 return NULL;
Guido van Rossumdd9ed831992-06-29 17:10:40 +000071 }
72 return (object *)dp;
73}
74
75/* Methods */
76
77static void
78dbm_dealloc(dp)
79 register dbmobject *dp;
80{
81 if ( dp->di_dbm )
82 dbm_close(dp->di_dbm);
83 DEL(dp);
84}
85
86static int
87dbm_length(dp)
88 dbmobject *dp;
89{
90 if ( dp->di_size < 0 ) {
91 datum key;
92 int size;
93
94 size = 0;
95 for ( key=dbm_firstkey(dp->di_dbm); key.dptr;
96 key = dbm_nextkey(dp->di_dbm))
97 size++;
98 dp->di_size = size;
99 }
100 return dp->di_size;
101}
102
103static object *
104dbm_subscript(dp, key)
105 dbmobject *dp;
106 register object *key;
107{
108 object *v;
109 datum drec, krec;
110
111 if (!getargs(key, "s#", &krec.dptr, &krec.dsize) )
112 return NULL;
113
114 drec = dbm_fetch(dp->di_dbm, krec);
115 if ( drec.dptr == 0 ) {
116 err_setstr(KeyError, GETSTRINGVALUE((stringobject *)key));
Guido van Rossum807b7be1995-07-07 22:37:11 +0000117 return NULL;
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000118 }
119 if ( dbm_error(dp->di_dbm) ) {
120 dbm_clearerr(dp->di_dbm);
121 err_setstr(DbmError, "");
Guido van Rossum807b7be1995-07-07 22:37:11 +0000122 return NULL;
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000123 }
124 return newsizedstringobject(drec.dptr, drec.dsize);
125}
126
127static int
128dbm_ass_sub(dp, v, w)
129 dbmobject *dp;
130 object *v, *w;
131{
132 datum krec, drec;
133
134 if ( !getargs(v, "s#", &krec.dptr, &krec.dsize) ) {
135 err_setstr(TypeError, "dbm mappings have string indices only");
136 return -1;
137 }
138 dp->di_size = -1;
139 if (w == NULL) {
140 if ( dbm_delete(dp->di_dbm, krec) < 0 ) {
Guido van Rossumb6775db1994-08-01 11:34:53 +0000141 dbm_clearerr(dp->di_dbm);
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000142 err_setstr(KeyError, GETSTRINGVALUE((stringobject *)v));
143 return -1;
144 }
145 } else {
146 if ( !getargs(w, "s#", &drec.dptr, &drec.dsize) ) {
147 err_setstr(TypeError,
148 "dbm mappings have string elements only");
149 return -1;
150 }
151 if ( dbm_store(dp->di_dbm, krec, drec, DBM_REPLACE) < 0 ) {
Guido van Rossumb6775db1994-08-01 11:34:53 +0000152 dbm_clearerr(dp->di_dbm);
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000153 err_setstr(DbmError, "Cannot add item to database");
154 return -1;
155 }
156 }
157 if ( dbm_error(dp->di_dbm) ) {
158 dbm_clearerr(dp->di_dbm);
159 err_setstr(DbmError, "");
160 return -1;
161 }
162 return 0;
163}
164
165static mapping_methods dbm_as_mapping = {
Guido van Rossumb6775db1994-08-01 11:34:53 +0000166 (inquiry)dbm_length, /*mp_length*/
167 (binaryfunc)dbm_subscript, /*mp_subscript*/
168 (objobjargproc)dbm_ass_sub, /*mp_ass_subscript*/
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000169};
170
171static object *
Guido van Rossum807b7be1995-07-07 22:37:11 +0000172dbm__close(dp, args)
173 register dbmobject *dp;
174 object *args;
175{
176 if ( !getnoarg(args) )
177 return NULL;
178 if ( dp->di_dbm )
179 dbm_close(dp->di_dbm);
180 dp->di_dbm = NULL;
Guido van Rossum807b7be1995-07-07 22:37:11 +0000181 INCREF(None);
182 return None;
183}
184
185static object *
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000186dbm_keys(dp, args)
187 register dbmobject *dp;
188 object *args;
189{
190 register object *v, *item;
191 datum key;
Guido van Rossumd5039131995-01-30 12:45:38 +0000192 int err;
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000193
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000194 if (!getnoarg(args))
195 return NULL;
196 v = newlistobject(0);
197 if (v == NULL)
198 return NULL;
199 for (key = dbm_firstkey(dp->di_dbm); key.dptr;
Guido van Rossumd5039131995-01-30 12:45:38 +0000200 key = dbm_nextkey(dp->di_dbm)) {
201 item = newsizedstringobject(key.dptr, key.dsize);
202 if (item == NULL) {
203 DECREF(v);
204 return NULL;
205 }
206 err = addlistitem(v, item);
207 DECREF(item);
208 if (err != 0) {
209 DECREF(v);
210 return NULL;
211 }
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000212 }
213 return v;
214}
215
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000216static object *
217dbm_has_key(dp, args)
218 register dbmobject *dp;
219 object *args;
220{
221 datum key, val;
222
223 if (!getargs(args, "s#", &key.dptr, &key.dsize))
224 return NULL;
225 val = dbm_fetch(dp->di_dbm, key);
226 return newintobject(val.dptr != NULL);
227}
228
229static struct methodlist dbm_methods[] = {
Guido van Rossum807b7be1995-07-07 22:37:11 +0000230 {"close", (method)dbm__close},
Guido van Rossumb6775db1994-08-01 11:34:53 +0000231 {"keys", (method)dbm_keys},
232 {"has_key", (method)dbm_has_key},
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000233 {NULL, NULL} /* sentinel */
234};
235
236static object *
237dbm_getattr(dp, name)
238 dbmobject *dp;
239 char *name;
240{
241 return findmethod(dbm_methods, (object *)dp, name);
242}
243
Guido van Rossumb6775db1994-08-01 11:34:53 +0000244static typeobject Dbmtype = {
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000245 OB_HEAD_INIT(&Typetype)
246 0,
Guido van Rossum807b7be1995-07-07 22:37:11 +0000247 "dbm",
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000248 sizeof(dbmobject),
249 0,
Guido van Rossumb6775db1994-08-01 11:34:53 +0000250 (destructor)dbm_dealloc, /*tp_dealloc*/
251 0, /*tp_print*/
252 (getattrfunc)dbm_getattr, /*tp_getattr*/
253 0, /*tp_setattr*/
254 0, /*tp_compare*/
255 0, /*tp_repr*/
256 0, /*tp_as_number*/
257 0, /*tp_as_sequence*/
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000258 &dbm_as_mapping, /*tp_as_mapping*/
259};
260
261/* ----------------------------------------------------------------- */
262
263static object *
264dbmopen(self, args)
265 object *self;
266 object *args;
267{
Guido van Rossum807b7be1995-07-07 22:37:11 +0000268 char *name;
269 char *flags = "r";
270 int iflags;
271 int mode = 0666;
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000272
Guido van Rossum807b7be1995-07-07 22:37:11 +0000273 if ( !newgetargs(args, "s|si", &name, &flags, &mode) )
274 return NULL;
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000275 if ( strcmp(flags, "r") == 0 )
276 iflags = O_RDONLY;
277 else if ( strcmp(flags, "w") == 0 )
Guido van Rossum807b7be1995-07-07 22:37:11 +0000278 iflags = O_RDWR;
279 else if ( strcmp(flags, "rw") == 0 ) /* B/W compat */
280 iflags = O_RDWR|O_CREAT;
281 else if ( strcmp(flags, "c") == 0 )
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000282 iflags = O_RDWR|O_CREAT;
Guido van Rossum807b7be1995-07-07 22:37:11 +0000283 else if ( strcmp(flags, "n") == 0 )
284 iflags = O_RDWR|O_CREAT|O_TRUNC;
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000285 else {
286 err_setstr(DbmError,
Guido van Rossum807b7be1995-07-07 22:37:11 +0000287 "Flags should be one of 'r', 'w', 'c' or 'n'");
288 return NULL;
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000289 }
290 return newdbmobject(name, iflags, mode);
291}
292
293static struct methodlist dbmmodule_methods[] = {
Guido van Rossum807b7be1995-07-07 22:37:11 +0000294 { "open", (method)dbmopen, 1 },
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000295 { 0, 0 },
296};
297
298void
299initdbm() {
300 object *m, *d;
301
302 m = initmodule("dbm", dbmmodule_methods);
303 d = getmoduledict(m);
304 DbmError = newstringobject("dbm.error");
305 if ( DbmError == NULL || dictinsert(d, "error", DbmError) )
306 fatal("can't define dbm.error");
307}