blob: 1e9135cd96bc35ba3116e4dd154bcf00121dd002 [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
Roger E. Masseb0dfe961996-12-10 00:07:00 +000035#include "Python.h"
Guido van Rossumdd9ed831992-06-29 17:10:40 +000036
37#include <sys/types.h>
38#include <sys/stat.h>
39#include <fcntl.h>
40#include <ndbm.h>
41
42typedef struct {
Roger E. Masseb0dfe961996-12-10 00:07:00 +000043 PyObject_HEAD
Guido van Rossumdd9ed831992-06-29 17:10:40 +000044 int di_size; /* -1 means recompute */
45 DBM *di_dbm;
46} dbmobject;
47
Roger E. Masseb0dfe961996-12-10 00:07:00 +000048staticforward PyTypeObject Dbmtype;
Guido van Rossumdd9ed831992-06-29 17:10:40 +000049
50#define is_dbmobject(v) ((v)->ob_type == &Dbmtype)
51
Roger E. Masseb0dfe961996-12-10 00:07:00 +000052static PyObject *DbmError;
Guido van Rossumdd9ed831992-06-29 17:10:40 +000053
Roger E. Masseb0dfe961996-12-10 00:07:00 +000054static PyObject *
Guido van Rossumdd9ed831992-06-29 17:10:40 +000055newdbmobject(file, flags, mode)
56 char *file;
57 int flags;
58 int mode;
59{
60 dbmobject *dp;
61
Roger E. Masseb0dfe961996-12-10 00:07:00 +000062 dp = PyObject_NEW(dbmobject, &Dbmtype);
Guido van Rossumdd9ed831992-06-29 17:10:40 +000063 if (dp == NULL)
64 return NULL;
65 dp->di_size = -1;
66 if ( (dp->di_dbm = dbm_open(file, flags, mode)) == 0 ) {
Roger E. Masseb0dfe961996-12-10 00:07:00 +000067 PyErr_SetFromErrno(DbmError);
68 Py_DECREF(dp);
Guido van Rossum807b7be1995-07-07 22:37:11 +000069 return NULL;
Guido van Rossumdd9ed831992-06-29 17:10:40 +000070 }
Roger E. Masseb0dfe961996-12-10 00:07:00 +000071 return (PyObject *)dp;
Guido van Rossumdd9ed831992-06-29 17:10:40 +000072}
73
74/* Methods */
75
76static void
77dbm_dealloc(dp)
78 register dbmobject *dp;
79{
80 if ( dp->di_dbm )
81 dbm_close(dp->di_dbm);
Roger E. Masseb0dfe961996-12-10 00:07:00 +000082 PyMem_DEL(dp);
Guido van Rossumdd9ed831992-06-29 17:10:40 +000083}
84
85static int
86dbm_length(dp)
87 dbmobject *dp;
88{
89 if ( dp->di_size < 0 ) {
90 datum key;
91 int size;
92
93 size = 0;
94 for ( key=dbm_firstkey(dp->di_dbm); key.dptr;
95 key = dbm_nextkey(dp->di_dbm))
96 size++;
97 dp->di_size = size;
98 }
99 return dp->di_size;
100}
101
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000102static PyObject *
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000103dbm_subscript(dp, key)
104 dbmobject *dp;
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000105 register PyObject *key;
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000106{
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000107 datum drec, krec;
108
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000109 if (!PyArg_Parse(key, "s#", &krec.dptr, &krec.dsize) )
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000110 return NULL;
111
112 drec = dbm_fetch(dp->di_dbm, krec);
113 if ( drec.dptr == 0 ) {
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000114 PyErr_SetString(PyExc_KeyError,
115 PyString_AS_STRING((PyStringObject *)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);
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000120 PyErr_SetString(DbmError, "");
Guido van Rossum807b7be1995-07-07 22:37:11 +0000121 return NULL;
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000122 }
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000123 return PyString_FromStringAndSize(drec.dptr, drec.dsize);
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000124}
125
126static int
127dbm_ass_sub(dp, v, w)
128 dbmobject *dp;
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000129 PyObject *v, *w;
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000130{
131 datum krec, drec;
132
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000133 if ( !PyArg_Parse(v, "s#", &krec.dptr, &krec.dsize) ) {
134 PyErr_SetString(PyExc_TypeError,
135 "dbm mappings have string indices only");
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000136 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);
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000142 PyErr_SetString(PyExc_KeyError,
143 PyString_AS_STRING((PyStringObject *)v));
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000144 return -1;
145 }
146 } else {
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000147 if ( !PyArg_Parse(w, "s#", &drec.dptr, &drec.dsize) ) {
148 PyErr_SetString(PyExc_TypeError,
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000149 "dbm mappings have string elements only");
150 return -1;
151 }
152 if ( dbm_store(dp->di_dbm, krec, drec, DBM_REPLACE) < 0 ) {
Guido van Rossumb6775db1994-08-01 11:34:53 +0000153 dbm_clearerr(dp->di_dbm);
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000154 PyErr_SetString(DbmError, "Cannot add item to database");
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000155 return -1;
156 }
157 }
158 if ( dbm_error(dp->di_dbm) ) {
159 dbm_clearerr(dp->di_dbm);
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000160 PyErr_SetString(DbmError, "");
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000161 return -1;
162 }
163 return 0;
164}
165
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000166static PyMappingMethods dbm_as_mapping = {
Guido van Rossumb6775db1994-08-01 11:34:53 +0000167 (inquiry)dbm_length, /*mp_length*/
168 (binaryfunc)dbm_subscript, /*mp_subscript*/
169 (objobjargproc)dbm_ass_sub, /*mp_ass_subscript*/
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000170};
171
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000172static PyObject *
Guido van Rossum807b7be1995-07-07 22:37:11 +0000173dbm__close(dp, args)
174 register dbmobject *dp;
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000175 PyObject *args;
Guido van Rossum807b7be1995-07-07 22:37:11 +0000176{
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000177 if ( !PyArg_NoArgs(args) )
Guido van Rossum807b7be1995-07-07 22:37:11 +0000178 return NULL;
179 if ( dp->di_dbm )
180 dbm_close(dp->di_dbm);
181 dp->di_dbm = NULL;
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000182 Py_INCREF(Py_None);
183 return Py_None;
Guido van Rossum807b7be1995-07-07 22:37:11 +0000184}
185
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000186static PyObject *
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000187dbm_keys(dp, args)
188 register dbmobject *dp;
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000189 PyObject *args;
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000190{
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000191 register PyObject *v, *item;
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000192 datum key;
Guido van Rossumd5039131995-01-30 12:45:38 +0000193 int err;
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000194
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000195 if (!PyArg_NoArgs(args))
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000196 return NULL;
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000197 v = PyList_New(0);
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000198 if (v == NULL)
199 return NULL;
200 for (key = dbm_firstkey(dp->di_dbm); key.dptr;
Guido van Rossumd5039131995-01-30 12:45:38 +0000201 key = dbm_nextkey(dp->di_dbm)) {
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000202 item = PyString_FromStringAndSize(key.dptr, key.dsize);
Guido van Rossumd5039131995-01-30 12:45:38 +0000203 if (item == NULL) {
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000204 Py_DECREF(v);
Guido van Rossumd5039131995-01-30 12:45:38 +0000205 return NULL;
206 }
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000207 err = PyList_Append(v, item);
208 Py_DECREF(item);
Guido van Rossumd5039131995-01-30 12:45:38 +0000209 if (err != 0) {
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000210 Py_DECREF(v);
Guido van Rossumd5039131995-01-30 12:45:38 +0000211 return NULL;
212 }
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000213 }
214 return v;
215}
216
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000217static PyObject *
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000218dbm_has_key(dp, args)
219 register dbmobject *dp;
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000220 PyObject *args;
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000221{
222 datum key, val;
223
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000224 if (!PyArg_Parse(args, "s#", &key.dptr, &key.dsize))
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000225 return NULL;
226 val = dbm_fetch(dp->di_dbm, key);
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000227 return PyInt_FromLong(val.dptr != NULL);
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000228}
229
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000230static PyMethodDef dbm_methods[] = {
231 {"close", (PyCFunction)dbm__close},
232 {"keys", (PyCFunction)dbm_keys},
233 {"has_key", (PyCFunction)dbm_has_key},
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000234 {NULL, NULL} /* sentinel */
235};
236
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000237static PyObject *
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000238dbm_getattr(dp, name)
239 dbmobject *dp;
240 char *name;
241{
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000242 return Py_FindMethod(dbm_methods, (PyObject *)dp, name);
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000243}
244
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000245static PyTypeObject Dbmtype = {
246 PyObject_HEAD_INIT(&PyType_Type)
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000247 0,
Guido van Rossum807b7be1995-07-07 22:37:11 +0000248 "dbm",
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000249 sizeof(dbmobject),
250 0,
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000251 (destructor)dbm_dealloc, /*tp_dealloc*/
252 0, /*tp_print*/
Guido van Rossumb6775db1994-08-01 11:34:53 +0000253 (getattrfunc)dbm_getattr, /*tp_getattr*/
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000254 0, /*tp_setattr*/
255 0, /*tp_compare*/
256 0, /*tp_repr*/
257 0, /*tp_as_number*/
258 0, /*tp_as_sequence*/
259 &dbm_as_mapping, /*tp_as_mapping*/
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000260};
261
262/* ----------------------------------------------------------------- */
263
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000264static PyObject *
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000265dbmopen(self, args)
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000266 PyObject *self;
267 PyObject *args;
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000268{
Guido van Rossum807b7be1995-07-07 22:37:11 +0000269 char *name;
270 char *flags = "r";
271 int iflags;
272 int mode = 0666;
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000273
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000274 if ( !PyArg_ParseTuple(args, "s|si", &name, &flags, &mode) )
Guido van Rossum807b7be1995-07-07 22:37:11 +0000275 return NULL;
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000276 if ( strcmp(flags, "r") == 0 )
277 iflags = O_RDONLY;
278 else if ( strcmp(flags, "w") == 0 )
Guido van Rossum807b7be1995-07-07 22:37:11 +0000279 iflags = O_RDWR;
280 else if ( strcmp(flags, "rw") == 0 ) /* B/W compat */
281 iflags = O_RDWR|O_CREAT;
282 else if ( strcmp(flags, "c") == 0 )
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000283 iflags = O_RDWR|O_CREAT;
Guido van Rossum807b7be1995-07-07 22:37:11 +0000284 else if ( strcmp(flags, "n") == 0 )
285 iflags = O_RDWR|O_CREAT|O_TRUNC;
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000286 else {
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000287 PyErr_SetString(DbmError,
Guido van Rossum807b7be1995-07-07 22:37:11 +0000288 "Flags should be one of 'r', 'w', 'c' or 'n'");
289 return NULL;
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000290 }
291 return newdbmobject(name, iflags, mode);
292}
293
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000294static PyMethodDef dbmmodule_methods[] = {
295 { "open", (PyCFunction)dbmopen, 1 },
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000296 { 0, 0 },
297};
298
299void
300initdbm() {
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000301 PyObject *m, *d;
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000302
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000303 m = Py_InitModule("dbm", dbmmodule_methods);
304 d = PyModule_GetDict(m);
305 DbmError = PyString_FromString("dbm.error");
306 if ( DbmError == NULL || PyDict_SetItemString(d, "error", DbmError) )
307 Py_FatalError("can't define dbm.error");
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000308}