blob: 26449c2bef70fe37c8a9cdeb6d973246b86df8cb [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{
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000108 datum drec, krec;
109
110 if (!getargs(key, "s#", &krec.dptr, &krec.dsize) )
111 return NULL;
112
113 drec = dbm_fetch(dp->di_dbm, krec);
114 if ( drec.dptr == 0 ) {
115 err_setstr(KeyError, GETSTRINGVALUE((stringobject *)key));
Guido van Rossum807b7be1995-07-07 22:37:11 +0000116 return NULL;
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000117 }
118 if ( dbm_error(dp->di_dbm) ) {
119 dbm_clearerr(dp->di_dbm);
120 err_setstr(DbmError, "");
Guido van Rossum807b7be1995-07-07 22:37:11 +0000121 return NULL;
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000122 }
123 return newsizedstringobject(drec.dptr, drec.dsize);
124}
125
126static int
127dbm_ass_sub(dp, v, w)
128 dbmobject *dp;
129 object *v, *w;
130{
131 datum krec, drec;
132
133 if ( !getargs(v, "s#", &krec.dptr, &krec.dsize) ) {
134 err_setstr(TypeError, "dbm mappings have string indices only");
135 return -1;
136 }
137 dp->di_size = -1;
138 if (w == NULL) {
139 if ( dbm_delete(dp->di_dbm, krec) < 0 ) {
Guido van Rossumb6775db1994-08-01 11:34:53 +0000140 dbm_clearerr(dp->di_dbm);
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000141 err_setstr(KeyError, GETSTRINGVALUE((stringobject *)v));
142 return -1;
143 }
144 } else {
145 if ( !getargs(w, "s#", &drec.dptr, &drec.dsize) ) {
146 err_setstr(TypeError,
147 "dbm mappings have string elements only");
148 return -1;
149 }
150 if ( dbm_store(dp->di_dbm, krec, drec, DBM_REPLACE) < 0 ) {
Guido van Rossumb6775db1994-08-01 11:34:53 +0000151 dbm_clearerr(dp->di_dbm);
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000152 err_setstr(DbmError, "Cannot add item to database");
153 return -1;
154 }
155 }
156 if ( dbm_error(dp->di_dbm) ) {
157 dbm_clearerr(dp->di_dbm);
158 err_setstr(DbmError, "");
159 return -1;
160 }
161 return 0;
162}
163
164static mapping_methods dbm_as_mapping = {
Guido van Rossumb6775db1994-08-01 11:34:53 +0000165 (inquiry)dbm_length, /*mp_length*/
166 (binaryfunc)dbm_subscript, /*mp_subscript*/
167 (objobjargproc)dbm_ass_sub, /*mp_ass_subscript*/
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000168};
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 dbm_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 Rossumdd9ed831992-06-29 17:10:40 +0000185dbm_keys(dp, args)
186 register dbmobject *dp;
187 object *args;
188{
189 register object *v, *item;
190 datum key;
Guido van Rossumd5039131995-01-30 12:45:38 +0000191 int err;
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000192
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000193 if (!getnoarg(args))
194 return NULL;
195 v = newlistobject(0);
196 if (v == NULL)
197 return NULL;
198 for (key = dbm_firstkey(dp->di_dbm); key.dptr;
Guido van Rossumd5039131995-01-30 12:45:38 +0000199 key = dbm_nextkey(dp->di_dbm)) {
200 item = newsizedstringobject(key.dptr, key.dsize);
201 if (item == NULL) {
202 DECREF(v);
203 return NULL;
204 }
205 err = addlistitem(v, item);
206 DECREF(item);
207 if (err != 0) {
208 DECREF(v);
209 return NULL;
210 }
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000211 }
212 return v;
213}
214
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000215static object *
216dbm_has_key(dp, args)
217 register dbmobject *dp;
218 object *args;
219{
220 datum key, val;
221
222 if (!getargs(args, "s#", &key.dptr, &key.dsize))
223 return NULL;
224 val = dbm_fetch(dp->di_dbm, key);
225 return newintobject(val.dptr != NULL);
226}
227
228static struct methodlist dbm_methods[] = {
Guido van Rossum807b7be1995-07-07 22:37:11 +0000229 {"close", (method)dbm__close},
Guido van Rossumb6775db1994-08-01 11:34:53 +0000230 {"keys", (method)dbm_keys},
231 {"has_key", (method)dbm_has_key},
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000232 {NULL, NULL} /* sentinel */
233};
234
235static object *
236dbm_getattr(dp, name)
237 dbmobject *dp;
238 char *name;
239{
240 return findmethod(dbm_methods, (object *)dp, name);
241}
242
Guido van Rossumb6775db1994-08-01 11:34:53 +0000243static typeobject Dbmtype = {
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000244 OB_HEAD_INIT(&Typetype)
245 0,
Guido van Rossum807b7be1995-07-07 22:37:11 +0000246 "dbm",
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000247 sizeof(dbmobject),
248 0,
Guido van Rossumb6775db1994-08-01 11:34:53 +0000249 (destructor)dbm_dealloc, /*tp_dealloc*/
250 0, /*tp_print*/
251 (getattrfunc)dbm_getattr, /*tp_getattr*/
252 0, /*tp_setattr*/
253 0, /*tp_compare*/
254 0, /*tp_repr*/
255 0, /*tp_as_number*/
256 0, /*tp_as_sequence*/
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000257 &dbm_as_mapping, /*tp_as_mapping*/
258};
259
260/* ----------------------------------------------------------------- */
261
262static object *
263dbmopen(self, args)
264 object *self;
265 object *args;
266{
Guido van Rossum807b7be1995-07-07 22:37:11 +0000267 char *name;
268 char *flags = "r";
269 int iflags;
270 int mode = 0666;
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000271
Guido van Rossum807b7be1995-07-07 22:37:11 +0000272 if ( !newgetargs(args, "s|si", &name, &flags, &mode) )
273 return NULL;
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000274 if ( strcmp(flags, "r") == 0 )
275 iflags = O_RDONLY;
276 else if ( strcmp(flags, "w") == 0 )
Guido van Rossum807b7be1995-07-07 22:37:11 +0000277 iflags = O_RDWR;
278 else if ( strcmp(flags, "rw") == 0 ) /* B/W compat */
279 iflags = O_RDWR|O_CREAT;
280 else if ( strcmp(flags, "c") == 0 )
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000281 iflags = O_RDWR|O_CREAT;
Guido van Rossum807b7be1995-07-07 22:37:11 +0000282 else if ( strcmp(flags, "n") == 0 )
283 iflags = O_RDWR|O_CREAT|O_TRUNC;
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000284 else {
285 err_setstr(DbmError,
Guido van Rossum807b7be1995-07-07 22:37:11 +0000286 "Flags should be one of 'r', 'w', 'c' or 'n'");
287 return NULL;
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000288 }
289 return newdbmobject(name, iflags, mode);
290}
291
292static struct methodlist dbmmodule_methods[] = {
Guido van Rossum807b7be1995-07-07 22:37:11 +0000293 { "open", (method)dbmopen, 1 },
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000294 { 0, 0 },
295};
296
297void
298initdbm() {
299 object *m, *d;
300
301 m = initmodule("dbm", dbmmodule_methods);
302 d = getmoduledict(m);
303 DbmError = newstringobject("dbm.error");
304 if ( DbmError == NULL || dictinsert(d, "error", DbmError) )
305 fatal("can't define dbm.error");
306}