blob: de5f94a2d8cb8b91e1af796331ee22ce4a1f2500 [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
Roger E. Masseb15bef81996-12-17 19:55:33 +000039#include "Python.h"
Guido van Rossum4b4c6641994-08-08 08:06:37 +000040
41#include <sys/types.h>
42#include <sys/stat.h>
43#include <fcntl.h>
44#include "gdbm.h"
45
46typedef struct {
Roger E. Masseb15bef81996-12-17 19:55:33 +000047 PyObject_HEAD
Guido van Rossum4b4c6641994-08-08 08:06:37 +000048 int di_size; /* -1 means recompute */
49 GDBM_FILE di_dbm;
50} dbmobject;
51
Roger E. Masseb15bef81996-12-17 19:55:33 +000052staticforward PyTypeObject Dbmtype;
Guido van Rossum4b4c6641994-08-08 08:06:37 +000053
54#define is_dbmobject(v) ((v)->ob_type == &Dbmtype)
55
Roger E. Masseb15bef81996-12-17 19:55:33 +000056static PyObject *DbmError;
Guido van Rossum4b4c6641994-08-08 08:06:37 +000057
Roger E. Masseb15bef81996-12-17 19:55:33 +000058static PyObject *
Guido van Rossum4b4c6641994-08-08 08:06:37 +000059newdbmobject(file, flags, mode)
Roger E. Masseb15bef81996-12-17 19:55:33 +000060 char *file;
61int flags;
62int mode;
Guido van Rossum4b4c6641994-08-08 08:06:37 +000063{
64 dbmobject *dp;
65
Roger E. Masseb15bef81996-12-17 19:55:33 +000066 dp = PyObject_NEW(dbmobject, &Dbmtype);
Guido van Rossum4b4c6641994-08-08 08:06:37 +000067 if (dp == NULL)
68 return NULL;
69 dp->di_size = -1;
Guido van Rossumb045afc1995-03-14 15:04:40 +000070 errno = 0;
Guido van Rossum4b4c6641994-08-08 08:06:37 +000071 if ( (dp->di_dbm = gdbm_open(file, 0, flags, mode, NULL)) == 0 ) {
Roger E. Masseb15bef81996-12-17 19:55:33 +000072 if (errno != 0)
73 PyErr_SetFromErrno(DbmError);
74 else
75 PyErr_SetString(DbmError,
76 (char *) gdbm_strerror(gdbm_errno));
77 Py_DECREF(dp);
78 return NULL;
Guido van Rossum4b4c6641994-08-08 08:06:37 +000079 }
Roger E. Masseb15bef81996-12-17 19:55:33 +000080 return (PyObject *)dp;
Guido van Rossum4b4c6641994-08-08 08:06:37 +000081}
82
83/* Methods */
84
85static void
86dbm_dealloc(dp)
87 register dbmobject *dp;
88{
89 if ( dp->di_dbm )
Roger E. Masseb15bef81996-12-17 19:55:33 +000090 gdbm_close(dp->di_dbm);
91 PyMem_DEL(dp);
Guido van Rossum4b4c6641994-08-08 08:06:37 +000092}
93
94static int
95dbm_length(dp)
96 dbmobject *dp;
97{
98 if ( dp->di_size < 0 ) {
Roger E. Masseb15bef81996-12-17 19:55:33 +000099 datum key,okey;
100 int size;
101 okey.dsize=0;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000102
Roger E. Masseb15bef81996-12-17 19:55:33 +0000103 size = 0;
104 for ( key=gdbm_firstkey(dp->di_dbm); key.dptr;
105 key = gdbm_nextkey(dp->di_dbm,okey)) {
106 size++;
107 if(okey.dsize) free(okey.dptr);
108 okey=key;
109 }
110 dp->di_size = size;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000111 }
112 return dp->di_size;
113}
114
Roger E. Masseb15bef81996-12-17 19:55:33 +0000115static PyObject *
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000116dbm_subscript(dp, key)
117 dbmobject *dp;
Roger E. Masseb15bef81996-12-17 19:55:33 +0000118register PyObject *key;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000119{
Roger E. Masseb15bef81996-12-17 19:55:33 +0000120 PyObject *v;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000121 datum drec, krec;
122
Roger E. Masseb15bef81996-12-17 19:55:33 +0000123 if (!PyArg_Parse(key, "s#", &krec.dptr, &krec.dsize) )
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000124 return NULL;
125
126 drec = gdbm_fetch(dp->di_dbm, krec);
127 if ( drec.dptr == 0 ) {
Roger E. Masseb15bef81996-12-17 19:55:33 +0000128 PyErr_SetString(PyExc_KeyError,
129 PyString_AS_STRING((PyStringObject *)key));
130 return NULL;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000131 }
Roger E. Masseb15bef81996-12-17 19:55:33 +0000132 v = PyString_FromStringAndSize(drec.dptr, drec.dsize);
Guido van Rossumb045afc1995-03-14 15:04:40 +0000133 free(drec.dptr);
134 return v;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000135}
136
137static int
138dbm_ass_sub(dp, v, w)
139 dbmobject *dp;
Roger E. Masseb15bef81996-12-17 19:55:33 +0000140PyObject *v, *w;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000141{
142 datum krec, drec;
143
Roger E. Masseb15bef81996-12-17 19:55:33 +0000144 if ( !PyArg_Parse(v, "s#", &krec.dptr, &krec.dsize) ) {
145 PyErr_SetString(PyExc_TypeError,
146 "gdbm mappings have string indices only");
147 return -1;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000148 }
149 dp->di_size = -1;
150 if (w == NULL) {
Roger E. Masseb15bef81996-12-17 19:55:33 +0000151 if ( gdbm_delete(dp->di_dbm, krec) < 0 ) {
152 PyErr_SetString(PyExc_KeyError,
153 PyString_AS_STRING((PyStringObject *)v));
154 return -1;
155 }
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000156 } else {
Roger E. Masseb15bef81996-12-17 19:55:33 +0000157 if ( !PyArg_Parse(w, "s#", &drec.dptr, &drec.dsize) ) {
158 PyErr_SetString(PyExc_TypeError,
159 "gdbm mappings have string elements only");
160 return -1;
161 }
162 errno = 0;
163 if ( gdbm_store(dp->di_dbm, krec, drec, GDBM_REPLACE) < 0 ) {
164 if (errno != 0)
165 PyErr_SetFromErrno(DbmError);
166 else
167 PyErr_SetString(DbmError,
168 (char *) gdbm_strerror(gdbm_errno));
169 return -1;
170 }
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000171 }
172 return 0;
173}
174
Roger E. Masseb15bef81996-12-17 19:55:33 +0000175static PyMappingMethods dbm_as_mapping = {
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000176 (inquiry)dbm_length, /*mp_length*/
177 (binaryfunc)dbm_subscript, /*mp_subscript*/
178 (objobjargproc)dbm_ass_sub, /*mp_ass_subscript*/
179};
180
Roger E. Masseb15bef81996-12-17 19:55:33 +0000181static PyObject *
Guido van Rossum807b7be1995-07-07 22:37:11 +0000182dbm_close(dp, args)
183 register dbmobject *dp;
Roger E. Masseb15bef81996-12-17 19:55:33 +0000184PyObject *args;
Guido van Rossum807b7be1995-07-07 22:37:11 +0000185{
Roger E. Masseb15bef81996-12-17 19:55:33 +0000186 if ( !PyArg_NoArgs(args) )
Guido van Rossum807b7be1995-07-07 22:37:11 +0000187 return NULL;
188 if ( dp->di_dbm )
189 gdbm_close(dp->di_dbm);
190 dp->di_dbm = NULL;
Roger E. Masseb15bef81996-12-17 19:55:33 +0000191 Py_INCREF(Py_None);
192 return Py_None;
Guido van Rossum807b7be1995-07-07 22:37:11 +0000193}
194
Roger E. Masseb15bef81996-12-17 19:55:33 +0000195static PyObject *
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000196dbm_keys(dp, args)
197 register dbmobject *dp;
Roger E. Masseb15bef81996-12-17 19:55:33 +0000198PyObject *args;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000199{
Roger E. Masseb15bef81996-12-17 19:55:33 +0000200 register PyObject *v, *item;
Guido van Rossum3be71401996-07-21 02:32:44 +0000201 datum key, nextkey;
Guido van Rossum66017aa1995-08-28 02:58:00 +0000202 int err;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000203
204 if (dp == NULL || !is_dbmobject(dp)) {
Roger E. Masseb15bef81996-12-17 19:55:33 +0000205 PyErr_BadInternalCall();
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000206 return NULL;
207 }
Guido van Rossum3be71401996-07-21 02:32:44 +0000208
Roger E. Masseb15bef81996-12-17 19:55:33 +0000209 if (!PyArg_NoArgs(args))
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000210 return NULL;
Guido van Rossum3be71401996-07-21 02:32:44 +0000211
Roger E. Masseb15bef81996-12-17 19:55:33 +0000212 v = PyList_New(0);
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000213 if (v == NULL)
214 return NULL;
Guido van Rossum3be71401996-07-21 02:32:44 +0000215
216 key = gdbm_firstkey(dp->di_dbm);
217 while (key.dptr) {
Roger E. Masseb15bef81996-12-17 19:55:33 +0000218 item = PyString_FromStringAndSize(key.dptr, key.dsize);
219 if (item == NULL) {
220 free(key.dptr);
221 Py_DECREF(v);
222 return NULL;
223 }
224 err = PyList_Append(v, item);
225 Py_DECREF(item);
226 if (err != 0) {
227 free(key.dptr);
228 Py_DECREF(v);
229 return NULL;
230 }
231 nextkey = gdbm_nextkey(dp->di_dbm, key);
Guido van Rossum3be71401996-07-21 02:32:44 +0000232 free(key.dptr);
Roger E. Masseb15bef81996-12-17 19:55:33 +0000233 key = nextkey;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000234 }
Guido van Rossum3be71401996-07-21 02:32:44 +0000235
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000236 return v;
237}
238
Roger E. Masseb15bef81996-12-17 19:55:33 +0000239static PyObject *
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000240dbm_has_key(dp, args)
241 register dbmobject *dp;
Roger E. Masseb15bef81996-12-17 19:55:33 +0000242PyObject *args;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000243{
Guido van Rossumb045afc1995-03-14 15:04:40 +0000244 datum key;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000245
Roger E. Masseb15bef81996-12-17 19:55:33 +0000246 if (!PyArg_Parse(args, "s#", &key.dptr, &key.dsize))
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000247 return NULL;
Roger E. Masseb15bef81996-12-17 19:55:33 +0000248 return PyInt_FromLong((long) gdbm_exists(dp->di_dbm, key));
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000249}
250
Roger E. Masseb15bef81996-12-17 19:55:33 +0000251static PyObject *
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000252dbm_firstkey(dp, args)
253 register dbmobject *dp;
Roger E. Masseb15bef81996-12-17 19:55:33 +0000254PyObject *args;
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000255{
Roger E. Masseb15bef81996-12-17 19:55:33 +0000256 register PyObject *v;
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000257 datum key;
258
Roger E. Masseb15bef81996-12-17 19:55:33 +0000259 if (!PyArg_NoArgs(args))
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000260 return NULL;
261 key = gdbm_firstkey(dp->di_dbm);
262 if (key.dptr) {
Roger E. Masseb15bef81996-12-17 19:55:33 +0000263 v = PyString_FromStringAndSize(key.dptr, key.dsize);
264 free(key.dptr);
265 return v;
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000266 } else {
Roger E. Masseb15bef81996-12-17 19:55:33 +0000267 Py_INCREF(Py_None);
268 return Py_None;
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000269 }
270}
271
Roger E. Masseb15bef81996-12-17 19:55:33 +0000272static PyObject *
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000273dbm_nextkey(dp, args)
274 register dbmobject *dp;
Roger E. Masseb15bef81996-12-17 19:55:33 +0000275PyObject *args;
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000276{
Roger E. Masseb15bef81996-12-17 19:55:33 +0000277 register PyObject *v;
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000278 datum key, nextkey;
279
Roger E. Masseb15bef81996-12-17 19:55:33 +0000280 if (!PyArg_Parse(args, "s#", &key.dptr, &key.dsize))
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000281 return NULL;
282 nextkey = gdbm_nextkey(dp->di_dbm, key);
283 if (nextkey.dptr) {
Roger E. Masseb15bef81996-12-17 19:55:33 +0000284 v = PyString_FromStringAndSize(nextkey.dptr, nextkey.dsize);
285 free(nextkey.dptr);
286 return v;
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000287 } else {
Roger E. Masseb15bef81996-12-17 19:55:33 +0000288 Py_INCREF(Py_None);
289 return Py_None;
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000290 }
291}
292
Roger E. Masseb15bef81996-12-17 19:55:33 +0000293static PyObject *
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000294dbm_reorganize(dp, args)
295 register dbmobject *dp;
Roger E. Masseb15bef81996-12-17 19:55:33 +0000296PyObject *args;
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000297{
Roger E. Masseb15bef81996-12-17 19:55:33 +0000298 if (!PyArg_NoArgs(args))
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000299 return NULL;
300 errno = 0;
301 if (gdbm_reorganize(dp->di_dbm) < 0) {
Roger E. Masseb15bef81996-12-17 19:55:33 +0000302 if (errno != 0)
303 PyErr_SetFromErrno(DbmError);
304 else
305 PyErr_SetString(DbmError,
306 (char *) gdbm_strerror(gdbm_errno));
307 return NULL;
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000308 }
Roger E. Masseb15bef81996-12-17 19:55:33 +0000309 Py_INCREF(Py_None);
310 return Py_None;
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000311}
312
Roger E. Masseb15bef81996-12-17 19:55:33 +0000313static PyMethodDef dbm_methods[] = {
314 {"close", (PyCFunction)dbm_close},
315 {"keys", (PyCFunction)dbm_keys},
316 {"has_key", (PyCFunction)dbm_has_key},
317 {"firstkey", (PyCFunction)dbm_firstkey},
318 {"nextkey", (PyCFunction)dbm_nextkey},
319 {"reorganize", (PyCFunction)dbm_reorganize},
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000320 {NULL, NULL} /* sentinel */
321};
322
Roger E. Masseb15bef81996-12-17 19:55:33 +0000323static PyObject *
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000324dbm_getattr(dp, name)
325 dbmobject *dp;
Roger E. Masseb15bef81996-12-17 19:55:33 +0000326char *name;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000327{
Roger E. Masseb15bef81996-12-17 19:55:33 +0000328 return Py_FindMethod(dbm_methods, (PyObject *)dp, name);
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000329}
330
Roger E. Masseb15bef81996-12-17 19:55:33 +0000331static PyTypeObject Dbmtype = {
332 PyObject_HEAD_INIT(&PyType_Type)
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000333 0,
Guido van Rossum807b7be1995-07-07 22:37:11 +0000334 "gdbm",
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000335 sizeof(dbmobject),
336 0,
Roger E. Masseb15bef81996-12-17 19:55:33 +0000337 (destructor)dbm_dealloc, /*tp_dealloc*/
338 0, /*tp_print*/
339 (getattrfunc)dbm_getattr, /*tp_getattr*/
340 0, /*tp_setattr*/
341 0, /*tp_compare*/
342 0, /*tp_repr*/
343 0, /*tp_as_number*/
344 0, /*tp_as_sequence*/
345 &dbm_as_mapping, /*tp_as_mapping*/
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000346};
347
348/* ----------------------------------------------------------------- */
349
Roger E. Masseb15bef81996-12-17 19:55:33 +0000350static PyObject *
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000351dbmopen(self, args)
Roger E. Masseb15bef81996-12-17 19:55:33 +0000352 PyObject *self;
353PyObject *args;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000354{
Roger E. Masseb15bef81996-12-17 19:55:33 +0000355 char *name;
356 char *flags = "r ";
357 int iflags;
358 int mode = 0666;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000359
Guido van Rossume36e1fe1996-01-26 21:08:01 +0000360/* XXXX add other flags. 2nd character can be "f" meaning open in fast mode. */
Roger E. Masseb15bef81996-12-17 19:55:33 +0000361 if ( !PyArg_ParseTuple(args, "s|si", &name, &flags, &mode) )
362 return NULL;
Guido van Rossume36e1fe1996-01-26 21:08:01 +0000363 switch (flags[0]) {
364 case 'r':
Roger E. Masseb15bef81996-12-17 19:55:33 +0000365 iflags = GDBM_READER;
366 break;
Guido van Rossume36e1fe1996-01-26 21:08:01 +0000367 case 'w':
Roger E. Masseb15bef81996-12-17 19:55:33 +0000368 iflags = GDBM_WRITER;
369 break;
Guido van Rossume36e1fe1996-01-26 21:08:01 +0000370 case 'c':
Roger E. Masseb15bef81996-12-17 19:55:33 +0000371 iflags = GDBM_WRCREAT;
372 break;
Guido van Rossume36e1fe1996-01-26 21:08:01 +0000373 case 'n':
Roger E. Masseb15bef81996-12-17 19:55:33 +0000374 iflags = GDBM_NEWDB;
375 break;
376 default:
377 PyErr_SetString(DbmError,
378 "Flags should be one of 'r', 'w', 'c' or 'n'");
379 return NULL;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000380 }
Guido van Rossume36e1fe1996-01-26 21:08:01 +0000381 if (flags[1] == 'f')
Roger E. Masseb15bef81996-12-17 19:55:33 +0000382 iflags |= GDBM_FAST;
383 return newdbmobject(name, iflags, mode);
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000384}
385
Roger E. Masseb15bef81996-12-17 19:55:33 +0000386static PyMethodDef dbmmodule_methods[] = {
387 { "open", (PyCFunction)dbmopen, 1 },
388 { 0, 0 },
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000389};
390
391void
392initgdbm() {
Roger E. Masseb15bef81996-12-17 19:55:33 +0000393 PyObject *m, *d;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000394
Roger E. Masseb15bef81996-12-17 19:55:33 +0000395 m = Py_InitModule("gdbm", dbmmodule_methods);
396 d = PyModule_GetDict(m);
397 DbmError = PyString_FromString("gdbm.error");
398 if ( DbmError == NULL || PyDict_SetItemString(d, "error", DbmError) )
399 Py_FatalError("can't define gdbm.error");
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000400}