blob: ea628f196eb8dd3698fba476a1b04d8aacede71d [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)
Guido van Rossum77eecfa1997-07-17 22:56:01 +000051#define check_dbmobject_open(v) if ((v)->di_dbm == NULL) \
52 { PyErr_SetString(DbmError, "DBM object has already been closed"); \
53 return NULL; }
Guido van Rossumdd9ed831992-06-29 17:10:40 +000054
Roger E. Masseb0dfe961996-12-10 00:07:00 +000055static PyObject *DbmError;
Guido van Rossumdd9ed831992-06-29 17:10:40 +000056
Roger E. Masseb0dfe961996-12-10 00:07:00 +000057static PyObject *
Guido van Rossumdd9ed831992-06-29 17:10:40 +000058newdbmobject(file, flags, mode)
Roger E. Massee7ee8c31996-12-13 15:55:22 +000059 char *file;
60int flags;
61int mode;
Guido van Rossumdd9ed831992-06-29 17:10:40 +000062{
63 dbmobject *dp;
64
Roger E. Masseb0dfe961996-12-10 00:07:00 +000065 dp = PyObject_NEW(dbmobject, &Dbmtype);
Guido van Rossumdd9ed831992-06-29 17:10:40 +000066 if (dp == NULL)
67 return NULL;
68 dp->di_size = -1;
69 if ( (dp->di_dbm = dbm_open(file, flags, mode)) == 0 ) {
Roger E. Massee7ee8c31996-12-13 15:55:22 +000070 PyErr_SetFromErrno(DbmError);
71 Py_DECREF(dp);
72 return NULL;
Guido van Rossumdd9ed831992-06-29 17:10:40 +000073 }
Roger E. Masseb0dfe961996-12-10 00:07:00 +000074 return (PyObject *)dp;
Guido van Rossumdd9ed831992-06-29 17:10:40 +000075}
76
77/* Methods */
78
79static void
80dbm_dealloc(dp)
81 register dbmobject *dp;
82{
83 if ( dp->di_dbm )
Roger E. Massee7ee8c31996-12-13 15:55:22 +000084 dbm_close(dp->di_dbm);
Roger E. Masseb0dfe961996-12-10 00:07:00 +000085 PyMem_DEL(dp);
Guido van Rossumdd9ed831992-06-29 17:10:40 +000086}
87
88static int
89dbm_length(dp)
90 dbmobject *dp;
91{
Guido van Rossum77eecfa1997-07-17 22:56:01 +000092 if (dp->di_dbm == NULL) {
93 PyErr_SetString(DbmError, "DBM object has already been closed");
94 return -1;
95 }
Guido van Rossumdd9ed831992-06-29 17:10:40 +000096 if ( dp->di_size < 0 ) {
Roger E. Massee7ee8c31996-12-13 15:55:22 +000097 datum key;
98 int size;
Guido van Rossumdd9ed831992-06-29 17:10:40 +000099
Roger E. Massee7ee8c31996-12-13 15:55:22 +0000100 size = 0;
101 for ( key=dbm_firstkey(dp->di_dbm); key.dptr;
102 key = dbm_nextkey(dp->di_dbm))
103 size++;
104 dp->di_size = size;
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000105 }
106 return dp->di_size;
107}
108
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000109static PyObject *
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000110dbm_subscript(dp, key)
111 dbmobject *dp;
Roger E. Massee7ee8c31996-12-13 15:55:22 +0000112register PyObject *key;
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000113{
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000114 datum drec, krec;
115
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000116 if (!PyArg_Parse(key, "s#", &krec.dptr, &krec.dsize) )
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000117 return NULL;
118
Guido van Rossum77eecfa1997-07-17 22:56:01 +0000119 check_dbmobject_open(dp);
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000120 drec = dbm_fetch(dp->di_dbm, krec);
121 if ( drec.dptr == 0 ) {
Roger E. Massee7ee8c31996-12-13 15:55:22 +0000122 PyErr_SetString(PyExc_KeyError,
123 PyString_AS_STRING((PyStringObject *)key));
124 return NULL;
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000125 }
126 if ( dbm_error(dp->di_dbm) ) {
Roger E. Massee7ee8c31996-12-13 15:55:22 +0000127 dbm_clearerr(dp->di_dbm);
128 PyErr_SetString(DbmError, "");
129 return NULL;
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000130 }
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000131 return PyString_FromStringAndSize(drec.dptr, drec.dsize);
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000132}
133
134static int
135dbm_ass_sub(dp, v, w)
136 dbmobject *dp;
Roger E. Massee7ee8c31996-12-13 15:55:22 +0000137PyObject *v, *w;
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000138{
139 datum krec, drec;
140
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000141 if ( !PyArg_Parse(v, "s#", &krec.dptr, &krec.dsize) ) {
Roger E. Massee7ee8c31996-12-13 15:55:22 +0000142 PyErr_SetString(PyExc_TypeError,
143 "dbm mappings have string indices only");
144 return -1;
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000145 }
Guido van Rossum77eecfa1997-07-17 22:56:01 +0000146 if (dp->di_dbm == NULL) {
147 PyErr_SetString(DbmError, "DBM object has already been closed");
148 return -1;
149 }
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000150 dp->di_size = -1;
151 if (w == NULL) {
Roger E. Massee7ee8c31996-12-13 15:55:22 +0000152 if ( dbm_delete(dp->di_dbm, krec) < 0 ) {
153 dbm_clearerr(dp->di_dbm);
154 PyErr_SetString(PyExc_KeyError,
Roger E. Massebd4b9611996-12-13 15:59:22 +0000155 PyString_AS_STRING((PyStringObject *)v));
Roger E. Massee7ee8c31996-12-13 15:55:22 +0000156 return -1;
157 }
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000158 } else {
Roger E. Massee7ee8c31996-12-13 15:55:22 +0000159 if ( !PyArg_Parse(w, "s#", &drec.dptr, &drec.dsize) ) {
160 PyErr_SetString(PyExc_TypeError,
Roger E. Massebd4b9611996-12-13 15:59:22 +0000161 "dbm mappings have string elements only");
Roger E. Massee7ee8c31996-12-13 15:55:22 +0000162 return -1;
163 }
164 if ( dbm_store(dp->di_dbm, krec, drec, DBM_REPLACE) < 0 ) {
165 dbm_clearerr(dp->di_dbm);
Roger E. Massebd4b9611996-12-13 15:59:22 +0000166 PyErr_SetString(DbmError,
167 "Cannot add item to database");
Roger E. Massee7ee8c31996-12-13 15:55:22 +0000168 return -1;
169 }
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000170 }
171 if ( dbm_error(dp->di_dbm) ) {
Roger E. Massee7ee8c31996-12-13 15:55:22 +0000172 dbm_clearerr(dp->di_dbm);
173 PyErr_SetString(DbmError, "");
174 return -1;
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000175 }
176 return 0;
177}
178
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000179static PyMappingMethods dbm_as_mapping = {
Guido van Rossumb6775db1994-08-01 11:34:53 +0000180 (inquiry)dbm_length, /*mp_length*/
181 (binaryfunc)dbm_subscript, /*mp_subscript*/
182 (objobjargproc)dbm_ass_sub, /*mp_ass_subscript*/
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000183};
184
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000185static PyObject *
Guido van Rossum807b7be1995-07-07 22:37:11 +0000186dbm__close(dp, args)
187 register dbmobject *dp;
Roger E. Massee7ee8c31996-12-13 15:55:22 +0000188PyObject *args;
Guido van Rossum807b7be1995-07-07 22:37:11 +0000189{
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000190 if ( !PyArg_NoArgs(args) )
Guido van Rossum807b7be1995-07-07 22:37:11 +0000191 return NULL;
192 if ( dp->di_dbm )
Roger E. Massee7ee8c31996-12-13 15:55:22 +0000193 dbm_close(dp->di_dbm);
Guido van Rossum807b7be1995-07-07 22:37:11 +0000194 dp->di_dbm = NULL;
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000195 Py_INCREF(Py_None);
196 return Py_None;
Guido van Rossum807b7be1995-07-07 22:37:11 +0000197}
198
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000199static PyObject *
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000200dbm_keys(dp, args)
201 register dbmobject *dp;
Roger E. Massee7ee8c31996-12-13 15:55:22 +0000202PyObject *args;
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000203{
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000204 register PyObject *v, *item;
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000205 datum key;
Guido van Rossumd5039131995-01-30 12:45:38 +0000206 int err;
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000207
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000208 if (!PyArg_NoArgs(args))
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000209 return NULL;
Guido van Rossum77eecfa1997-07-17 22:56:01 +0000210 check_dbmobject_open(dp);
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000211 v = PyList_New(0);
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000212 if (v == NULL)
213 return NULL;
214 for (key = dbm_firstkey(dp->di_dbm); key.dptr;
Guido van Rossumd5039131995-01-30 12:45:38 +0000215 key = dbm_nextkey(dp->di_dbm)) {
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000216 item = PyString_FromStringAndSize(key.dptr, key.dsize);
Guido van Rossumd5039131995-01-30 12:45:38 +0000217 if (item == NULL) {
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000218 Py_DECREF(v);
Guido van Rossumd5039131995-01-30 12:45:38 +0000219 return NULL;
220 }
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000221 err = PyList_Append(v, item);
222 Py_DECREF(item);
Guido van Rossumd5039131995-01-30 12:45:38 +0000223 if (err != 0) {
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000224 Py_DECREF(v);
Guido van Rossumd5039131995-01-30 12:45:38 +0000225 return NULL;
226 }
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000227 }
228 return v;
229}
230
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000231static PyObject *
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000232dbm_has_key(dp, args)
233 register dbmobject *dp;
Roger E. Massee7ee8c31996-12-13 15:55:22 +0000234PyObject *args;
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000235{
236 datum key, val;
237
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000238 if (!PyArg_Parse(args, "s#", &key.dptr, &key.dsize))
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000239 return NULL;
Guido van Rossum77eecfa1997-07-17 22:56:01 +0000240 check_dbmobject_open(dp);
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000241 val = dbm_fetch(dp->di_dbm, key);
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000242 return PyInt_FromLong(val.dptr != NULL);
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000243}
244
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000245static PyMethodDef dbm_methods[] = {
246 {"close", (PyCFunction)dbm__close},
247 {"keys", (PyCFunction)dbm_keys},
248 {"has_key", (PyCFunction)dbm_has_key},
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000249 {NULL, NULL} /* sentinel */
250};
251
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000252static PyObject *
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000253dbm_getattr(dp, name)
254 dbmobject *dp;
Roger E. Massee7ee8c31996-12-13 15:55:22 +0000255char *name;
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000256{
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000257 return Py_FindMethod(dbm_methods, (PyObject *)dp, name);
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000258}
259
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000260static PyTypeObject Dbmtype = {
261 PyObject_HEAD_INIT(&PyType_Type)
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000262 0,
Guido van Rossum807b7be1995-07-07 22:37:11 +0000263 "dbm",
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000264 sizeof(dbmobject),
265 0,
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000266 (destructor)dbm_dealloc, /*tp_dealloc*/
267 0, /*tp_print*/
Guido van Rossumb6775db1994-08-01 11:34:53 +0000268 (getattrfunc)dbm_getattr, /*tp_getattr*/
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000269 0, /*tp_setattr*/
270 0, /*tp_compare*/
271 0, /*tp_repr*/
272 0, /*tp_as_number*/
273 0, /*tp_as_sequence*/
274 &dbm_as_mapping, /*tp_as_mapping*/
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000275};
276
277/* ----------------------------------------------------------------- */
278
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000279static PyObject *
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000280dbmopen(self, args)
Roger E. Massee7ee8c31996-12-13 15:55:22 +0000281 PyObject *self;
282PyObject *args;
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000283{
Guido van Rossum807b7be1995-07-07 22:37:11 +0000284 char *name;
285 char *flags = "r";
286 int iflags;
287 int mode = 0666;
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000288
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000289 if ( !PyArg_ParseTuple(args, "s|si", &name, &flags, &mode) )
Roger E. Massee7ee8c31996-12-13 15:55:22 +0000290 return NULL;
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000291 if ( strcmp(flags, "r") == 0 )
Roger E. Massee7ee8c31996-12-13 15:55:22 +0000292 iflags = O_RDONLY;
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000293 else if ( strcmp(flags, "w") == 0 )
Roger E. Massee7ee8c31996-12-13 15:55:22 +0000294 iflags = O_RDWR;
Guido van Rossum807b7be1995-07-07 22:37:11 +0000295 else if ( strcmp(flags, "rw") == 0 ) /* B/W compat */
Roger E. Massee7ee8c31996-12-13 15:55:22 +0000296 iflags = O_RDWR|O_CREAT;
Guido van Rossum807b7be1995-07-07 22:37:11 +0000297 else if ( strcmp(flags, "c") == 0 )
Roger E. Massee7ee8c31996-12-13 15:55:22 +0000298 iflags = O_RDWR|O_CREAT;
Guido van Rossum807b7be1995-07-07 22:37:11 +0000299 else if ( strcmp(flags, "n") == 0 )
Roger E. Massee7ee8c31996-12-13 15:55:22 +0000300 iflags = O_RDWR|O_CREAT|O_TRUNC;
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000301 else {
Roger E. Massee7ee8c31996-12-13 15:55:22 +0000302 PyErr_SetString(DbmError,
303 "Flags should be one of 'r', 'w', 'c' or 'n'");
304 return NULL;
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000305 }
306 return newdbmobject(name, iflags, mode);
307}
308
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000309static PyMethodDef dbmmodule_methods[] = {
Roger E. Massee7ee8c31996-12-13 15:55:22 +0000310 { "open", (PyCFunction)dbmopen, 1 },
311 { 0, 0 },
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000312};
313
314void
315initdbm() {
Roger E. Massee7ee8c31996-12-13 15:55:22 +0000316 PyObject *m, *d;
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000317
Roger E. Massee7ee8c31996-12-13 15:55:22 +0000318 m = Py_InitModule("dbm", dbmmodule_methods);
319 d = PyModule_GetDict(m);
Guido van Rossum0cb96de1997-10-01 04:29:29 +0000320 DbmError = PyErr_NewException("dbm.error", NULL, NULL);
321 if (DbmError != NULL)
322 PyDict_SetItemString(d, "error", DbmError);
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000323}