blob: 4285a4ea90058b5e176a3818d1492459ecf6a9e0 [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)
Roger E. Massee7ee8c31996-12-13 15:55:22 +000056 char *file;
57int flags;
58int mode;
Guido van Rossumdd9ed831992-06-29 17:10:40 +000059{
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. Massee7ee8c31996-12-13 15:55:22 +000067 PyErr_SetFromErrno(DbmError);
68 Py_DECREF(dp);
69 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 )
Roger E. Massee7ee8c31996-12-13 15:55:22 +000081 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 ) {
Roger E. Massee7ee8c31996-12-13 15:55:22 +000090 datum key;
91 int size;
Guido van Rossumdd9ed831992-06-29 17:10:40 +000092
Roger E. Massee7ee8c31996-12-13 15:55:22 +000093 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;
Guido van Rossumdd9ed831992-06-29 17:10:40 +000098 }
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. Massee7ee8c31996-12-13 15:55:22 +0000105register 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. Massee7ee8c31996-12-13 15:55:22 +0000114 PyErr_SetString(PyExc_KeyError,
115 PyString_AS_STRING((PyStringObject *)key));
116 return NULL;
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000117 }
118 if ( dbm_error(dp->di_dbm) ) {
Roger E. Massee7ee8c31996-12-13 15:55:22 +0000119 dbm_clearerr(dp->di_dbm);
120 PyErr_SetString(DbmError, "");
121 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. Massee7ee8c31996-12-13 15:55:22 +0000129PyObject *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) ) {
Roger E. Massee7ee8c31996-12-13 15:55:22 +0000134 PyErr_SetString(PyExc_TypeError,
135 "dbm mappings have string indices only");
136 return -1;
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000137 }
138 dp->di_size = -1;
139 if (w == NULL) {
Roger E. Massee7ee8c31996-12-13 15:55:22 +0000140 if ( dbm_delete(dp->di_dbm, krec) < 0 ) {
141 dbm_clearerr(dp->di_dbm);
142 PyErr_SetString(PyExc_KeyError,
143 PyString_AS_STRING((PyStringObject *)v));
144 return -1;
145 }
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000146 } else {
Roger E. Massee7ee8c31996-12-13 15:55:22 +0000147 if ( !PyArg_Parse(w, "s#", &drec.dptr, &drec.dsize) ) {
148 PyErr_SetString(PyExc_TypeError,
149 "dbm mappings have string elements only");
150 return -1;
151 }
152 if ( dbm_store(dp->di_dbm, krec, drec, DBM_REPLACE) < 0 ) {
153 dbm_clearerr(dp->di_dbm);
154 PyErr_SetString(DbmError, "Cannot add item to database");
155 return -1;
156 }
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000157 }
158 if ( dbm_error(dp->di_dbm) ) {
Roger E. Massee7ee8c31996-12-13 15:55:22 +0000159 dbm_clearerr(dp->di_dbm);
160 PyErr_SetString(DbmError, "");
161 return -1;
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000162 }
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. Massee7ee8c31996-12-13 15:55:22 +0000175PyObject *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 )
Roger E. Massee7ee8c31996-12-13 15:55:22 +0000180 dbm_close(dp->di_dbm);
Guido van Rossum807b7be1995-07-07 22:37:11 +0000181 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. Massee7ee8c31996-12-13 15:55:22 +0000189PyObject *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. Massee7ee8c31996-12-13 15:55:22 +0000220PyObject *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;
Roger E. Massee7ee8c31996-12-13 15:55:22 +0000240char *name;
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000241{
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. Massee7ee8c31996-12-13 15:55:22 +0000266 PyObject *self;
267PyObject *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) )
Roger E. Massee7ee8c31996-12-13 15:55:22 +0000275 return NULL;
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000276 if ( strcmp(flags, "r") == 0 )
Roger E. Massee7ee8c31996-12-13 15:55:22 +0000277 iflags = O_RDONLY;
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000278 else if ( strcmp(flags, "w") == 0 )
Roger E. Massee7ee8c31996-12-13 15:55:22 +0000279 iflags = O_RDWR;
Guido van Rossum807b7be1995-07-07 22:37:11 +0000280 else if ( strcmp(flags, "rw") == 0 ) /* B/W compat */
Roger E. Massee7ee8c31996-12-13 15:55:22 +0000281 iflags = O_RDWR|O_CREAT;
Guido van Rossum807b7be1995-07-07 22:37:11 +0000282 else if ( strcmp(flags, "c") == 0 )
Roger E. Massee7ee8c31996-12-13 15:55:22 +0000283 iflags = O_RDWR|O_CREAT;
Guido van Rossum807b7be1995-07-07 22:37:11 +0000284 else if ( strcmp(flags, "n") == 0 )
Roger E. Massee7ee8c31996-12-13 15:55:22 +0000285 iflags = O_RDWR|O_CREAT|O_TRUNC;
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000286 else {
Roger E. Massee7ee8c31996-12-13 15:55:22 +0000287 PyErr_SetString(DbmError,
288 "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[] = {
Roger E. Massee7ee8c31996-12-13 15:55:22 +0000295 { "open", (PyCFunction)dbmopen, 1 },
296 { 0, 0 },
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000297};
298
299void
300initdbm() {
Roger E. Massee7ee8c31996-12-13 15:55:22 +0000301 PyObject *m, *d;
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000302
Roger E. Massee7ee8c31996-12-13 15:55:22 +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}