blob: 4c82a9f9b7ffaef90258ebd0eeddbb64e2f2eb38 [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,
Roger E. Massebd4b9611996-12-13 15:59:22 +0000143 PyString_AS_STRING((PyStringObject *)v));
Roger E. Massee7ee8c31996-12-13 15:55:22 +0000144 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,
Roger E. Massebd4b9611996-12-13 15:59:22 +0000149 "dbm mappings have string elements only");
Roger E. Massee7ee8c31996-12-13 15:55:22 +0000150 return -1;
151 }
152 if ( dbm_store(dp->di_dbm, krec, drec, DBM_REPLACE) < 0 ) {
153 dbm_clearerr(dp->di_dbm);
Roger E. Massebd4b9611996-12-13 15:59:22 +0000154 PyErr_SetString(DbmError,
155 "Cannot add item to database");
Roger E. Massee7ee8c31996-12-13 15:55:22 +0000156 return -1;
157 }
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000158 }
159 if ( dbm_error(dp->di_dbm) ) {
Roger E. Massee7ee8c31996-12-13 15:55:22 +0000160 dbm_clearerr(dp->di_dbm);
161 PyErr_SetString(DbmError, "");
162 return -1;
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000163 }
164 return 0;
165}
166
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000167static PyMappingMethods dbm_as_mapping = {
Guido van Rossumb6775db1994-08-01 11:34:53 +0000168 (inquiry)dbm_length, /*mp_length*/
169 (binaryfunc)dbm_subscript, /*mp_subscript*/
170 (objobjargproc)dbm_ass_sub, /*mp_ass_subscript*/
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000171};
172
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000173static PyObject *
Guido van Rossum807b7be1995-07-07 22:37:11 +0000174dbm__close(dp, args)
175 register dbmobject *dp;
Roger E. Massee7ee8c31996-12-13 15:55:22 +0000176PyObject *args;
Guido van Rossum807b7be1995-07-07 22:37:11 +0000177{
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000178 if ( !PyArg_NoArgs(args) )
Guido van Rossum807b7be1995-07-07 22:37:11 +0000179 return NULL;
180 if ( dp->di_dbm )
Roger E. Massee7ee8c31996-12-13 15:55:22 +0000181 dbm_close(dp->di_dbm);
Guido van Rossum807b7be1995-07-07 22:37:11 +0000182 dp->di_dbm = NULL;
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000183 Py_INCREF(Py_None);
184 return Py_None;
Guido van Rossum807b7be1995-07-07 22:37:11 +0000185}
186
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000187static PyObject *
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000188dbm_keys(dp, args)
189 register dbmobject *dp;
Roger E. Massee7ee8c31996-12-13 15:55:22 +0000190PyObject *args;
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000191{
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000192 register PyObject *v, *item;
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000193 datum key;
Guido van Rossumd5039131995-01-30 12:45:38 +0000194 int err;
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000195
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000196 if (!PyArg_NoArgs(args))
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000197 return NULL;
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000198 v = PyList_New(0);
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000199 if (v == NULL)
200 return NULL;
201 for (key = dbm_firstkey(dp->di_dbm); key.dptr;
Guido van Rossumd5039131995-01-30 12:45:38 +0000202 key = dbm_nextkey(dp->di_dbm)) {
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000203 item = PyString_FromStringAndSize(key.dptr, key.dsize);
Guido van Rossumd5039131995-01-30 12:45:38 +0000204 if (item == NULL) {
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000205 Py_DECREF(v);
Guido van Rossumd5039131995-01-30 12:45:38 +0000206 return NULL;
207 }
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000208 err = PyList_Append(v, item);
209 Py_DECREF(item);
Guido van Rossumd5039131995-01-30 12:45:38 +0000210 if (err != 0) {
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000211 Py_DECREF(v);
Guido van Rossumd5039131995-01-30 12:45:38 +0000212 return NULL;
213 }
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000214 }
215 return v;
216}
217
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000218static PyObject *
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000219dbm_has_key(dp, args)
220 register dbmobject *dp;
Roger E. Massee7ee8c31996-12-13 15:55:22 +0000221PyObject *args;
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000222{
223 datum key, val;
224
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000225 if (!PyArg_Parse(args, "s#", &key.dptr, &key.dsize))
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000226 return NULL;
227 val = dbm_fetch(dp->di_dbm, key);
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000228 return PyInt_FromLong(val.dptr != NULL);
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000229}
230
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000231static PyMethodDef dbm_methods[] = {
232 {"close", (PyCFunction)dbm__close},
233 {"keys", (PyCFunction)dbm_keys},
234 {"has_key", (PyCFunction)dbm_has_key},
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000235 {NULL, NULL} /* sentinel */
236};
237
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000238static PyObject *
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000239dbm_getattr(dp, name)
240 dbmobject *dp;
Roger E. Massee7ee8c31996-12-13 15:55:22 +0000241char *name;
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000242{
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000243 return Py_FindMethod(dbm_methods, (PyObject *)dp, name);
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000244}
245
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000246static PyTypeObject Dbmtype = {
247 PyObject_HEAD_INIT(&PyType_Type)
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000248 0,
Guido van Rossum807b7be1995-07-07 22:37:11 +0000249 "dbm",
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000250 sizeof(dbmobject),
251 0,
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000252 (destructor)dbm_dealloc, /*tp_dealloc*/
253 0, /*tp_print*/
Guido van Rossumb6775db1994-08-01 11:34:53 +0000254 (getattrfunc)dbm_getattr, /*tp_getattr*/
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000255 0, /*tp_setattr*/
256 0, /*tp_compare*/
257 0, /*tp_repr*/
258 0, /*tp_as_number*/
259 0, /*tp_as_sequence*/
260 &dbm_as_mapping, /*tp_as_mapping*/
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000261};
262
263/* ----------------------------------------------------------------- */
264
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000265static PyObject *
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000266dbmopen(self, args)
Roger E. Massee7ee8c31996-12-13 15:55:22 +0000267 PyObject *self;
268PyObject *args;
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000269{
Guido van Rossum807b7be1995-07-07 22:37:11 +0000270 char *name;
271 char *flags = "r";
272 int iflags;
273 int mode = 0666;
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000274
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000275 if ( !PyArg_ParseTuple(args, "s|si", &name, &flags, &mode) )
Roger E. Massee7ee8c31996-12-13 15:55:22 +0000276 return NULL;
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000277 if ( strcmp(flags, "r") == 0 )
Roger E. Massee7ee8c31996-12-13 15:55:22 +0000278 iflags = O_RDONLY;
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000279 else if ( strcmp(flags, "w") == 0 )
Roger E. Massee7ee8c31996-12-13 15:55:22 +0000280 iflags = O_RDWR;
Guido van Rossum807b7be1995-07-07 22:37:11 +0000281 else if ( strcmp(flags, "rw") == 0 ) /* B/W compat */
Roger E. Massee7ee8c31996-12-13 15:55:22 +0000282 iflags = O_RDWR|O_CREAT;
Guido van Rossum807b7be1995-07-07 22:37:11 +0000283 else if ( strcmp(flags, "c") == 0 )
Roger E. Massee7ee8c31996-12-13 15:55:22 +0000284 iflags = O_RDWR|O_CREAT;
Guido van Rossum807b7be1995-07-07 22:37:11 +0000285 else if ( strcmp(flags, "n") == 0 )
Roger E. Massee7ee8c31996-12-13 15:55:22 +0000286 iflags = O_RDWR|O_CREAT|O_TRUNC;
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000287 else {
Roger E. Massee7ee8c31996-12-13 15:55:22 +0000288 PyErr_SetString(DbmError,
289 "Flags should be one of 'r', 'w', 'c' or 'n'");
290 return NULL;
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000291 }
292 return newdbmobject(name, iflags, mode);
293}
294
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000295static PyMethodDef dbmmodule_methods[] = {
Roger E. Massee7ee8c31996-12-13 15:55:22 +0000296 { "open", (PyCFunction)dbmopen, 1 },
297 { 0, 0 },
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000298};
299
300void
301initdbm() {
Roger E. Massee7ee8c31996-12-13 15:55:22 +0000302 PyObject *m, *d;
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000303
Roger E. Massee7ee8c31996-12-13 15:55:22 +0000304 m = Py_InitModule("dbm", dbmmodule_methods);
305 d = PyModule_GetDict(m);
306 DbmError = PyString_FromString("dbm.error");
307 if ( DbmError == NULL || PyDict_SetItemString(d, "error", DbmError) )
308 Py_FatalError("can't define dbm.error");
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000309}