blob: c0cfb29c15ff739d5d36caa5c3de45f32ba4dddc [file] [log] [blame]
Guido van Rossumdd9ed831992-06-29 17:10:40 +00001
2/* DBM module using dictionary interface */
3
4
Roger E. Masseb0dfe961996-12-10 00:07:00 +00005#include "Python.h"
Guido van Rossumdd9ed831992-06-29 17:10:40 +00006
7#include <sys/types.h>
8#include <sys/stat.h>
9#include <fcntl.h>
10#include <ndbm.h>
11
12typedef struct {
Roger E. Masseb0dfe961996-12-10 00:07:00 +000013 PyObject_HEAD
Guido van Rossumdd9ed831992-06-29 17:10:40 +000014 int di_size; /* -1 means recompute */
15 DBM *di_dbm;
16} dbmobject;
17
Roger E. Masseb0dfe961996-12-10 00:07:00 +000018staticforward PyTypeObject Dbmtype;
Guido van Rossumdd9ed831992-06-29 17:10:40 +000019
20#define is_dbmobject(v) ((v)->ob_type == &Dbmtype)
Guido van Rossum77eecfa1997-07-17 22:56:01 +000021#define check_dbmobject_open(v) if ((v)->di_dbm == NULL) \
22 { PyErr_SetString(DbmError, "DBM object has already been closed"); \
23 return NULL; }
Guido van Rossumdd9ed831992-06-29 17:10:40 +000024
Roger E. Masseb0dfe961996-12-10 00:07:00 +000025static PyObject *DbmError;
Guido van Rossumdd9ed831992-06-29 17:10:40 +000026
Roger E. Masseb0dfe961996-12-10 00:07:00 +000027static PyObject *
Peter Schneider-Kampcb27c352000-07-10 17:06:38 +000028newdbmobject(char *file, int flags, int mode)
Guido van Rossumdd9ed831992-06-29 17:10:40 +000029{
30 dbmobject *dp;
31
Guido van Rossumb18618d2000-05-03 23:44:39 +000032 dp = PyObject_New(dbmobject, &Dbmtype);
Guido van Rossumdd9ed831992-06-29 17:10:40 +000033 if (dp == NULL)
34 return NULL;
35 dp->di_size = -1;
36 if ( (dp->di_dbm = dbm_open(file, flags, mode)) == 0 ) {
Roger E. Massee7ee8c31996-12-13 15:55:22 +000037 PyErr_SetFromErrno(DbmError);
38 Py_DECREF(dp);
39 return NULL;
Guido van Rossumdd9ed831992-06-29 17:10:40 +000040 }
Roger E. Masseb0dfe961996-12-10 00:07:00 +000041 return (PyObject *)dp;
Guido van Rossumdd9ed831992-06-29 17:10:40 +000042}
43
44/* Methods */
45
46static void
Peter Schneider-Kampcb27c352000-07-10 17:06:38 +000047dbm_dealloc(register dbmobject *dp)
Guido van Rossumdd9ed831992-06-29 17:10:40 +000048{
49 if ( dp->di_dbm )
Roger E. Massee7ee8c31996-12-13 15:55:22 +000050 dbm_close(dp->di_dbm);
Guido van Rossumb18618d2000-05-03 23:44:39 +000051 PyObject_Del(dp);
Guido van Rossumdd9ed831992-06-29 17:10:40 +000052}
53
54static int
Peter Schneider-Kampcb27c352000-07-10 17:06:38 +000055dbm_length(dbmobject *dp)
Guido van Rossumdd9ed831992-06-29 17:10:40 +000056{
Guido van Rossum77eecfa1997-07-17 22:56:01 +000057 if (dp->di_dbm == NULL) {
58 PyErr_SetString(DbmError, "DBM object has already been closed");
59 return -1;
60 }
Guido van Rossumdd9ed831992-06-29 17:10:40 +000061 if ( dp->di_size < 0 ) {
Roger E. Massee7ee8c31996-12-13 15:55:22 +000062 datum key;
63 int size;
Guido van Rossumdd9ed831992-06-29 17:10:40 +000064
Roger E. Massee7ee8c31996-12-13 15:55:22 +000065 size = 0;
66 for ( key=dbm_firstkey(dp->di_dbm); key.dptr;
67 key = dbm_nextkey(dp->di_dbm))
68 size++;
69 dp->di_size = size;
Guido van Rossumdd9ed831992-06-29 17:10:40 +000070 }
71 return dp->di_size;
72}
73
Roger E. Masseb0dfe961996-12-10 00:07:00 +000074static PyObject *
Peter Schneider-Kampcb27c352000-07-10 17:06:38 +000075dbm_subscript(dbmobject *dp, register PyObject *key)
Guido van Rossumdd9ed831992-06-29 17:10:40 +000076{
Guido van Rossumdd9ed831992-06-29 17:10:40 +000077 datum drec, krec;
78
Roger E. Masseb0dfe961996-12-10 00:07:00 +000079 if (!PyArg_Parse(key, "s#", &krec.dptr, &krec.dsize) )
Guido van Rossumdd9ed831992-06-29 17:10:40 +000080 return NULL;
81
Guido van Rossum77eecfa1997-07-17 22:56:01 +000082 check_dbmobject_open(dp);
Guido van Rossumdd9ed831992-06-29 17:10:40 +000083 drec = dbm_fetch(dp->di_dbm, krec);
84 if ( drec.dptr == 0 ) {
Roger E. Massee7ee8c31996-12-13 15:55:22 +000085 PyErr_SetString(PyExc_KeyError,
86 PyString_AS_STRING((PyStringObject *)key));
87 return NULL;
Guido van Rossumdd9ed831992-06-29 17:10:40 +000088 }
89 if ( dbm_error(dp->di_dbm) ) {
Roger E. Massee7ee8c31996-12-13 15:55:22 +000090 dbm_clearerr(dp->di_dbm);
91 PyErr_SetString(DbmError, "");
92 return NULL;
Guido van Rossumdd9ed831992-06-29 17:10:40 +000093 }
Roger E. Masseb0dfe961996-12-10 00:07:00 +000094 return PyString_FromStringAndSize(drec.dptr, drec.dsize);
Guido van Rossumdd9ed831992-06-29 17:10:40 +000095}
96
97static int
Peter Schneider-Kampcb27c352000-07-10 17:06:38 +000098dbm_ass_sub(dbmobject *dp, PyObject *v, PyObject *w)
Guido van Rossumdd9ed831992-06-29 17:10:40 +000099{
100 datum krec, drec;
101
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000102 if ( !PyArg_Parse(v, "s#", &krec.dptr, &krec.dsize) ) {
Roger E. Massee7ee8c31996-12-13 15:55:22 +0000103 PyErr_SetString(PyExc_TypeError,
104 "dbm mappings have string indices only");
105 return -1;
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000106 }
Guido van Rossum77eecfa1997-07-17 22:56:01 +0000107 if (dp->di_dbm == NULL) {
108 PyErr_SetString(DbmError, "DBM object has already been closed");
109 return -1;
110 }
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000111 dp->di_size = -1;
112 if (w == NULL) {
Roger E. Massee7ee8c31996-12-13 15:55:22 +0000113 if ( dbm_delete(dp->di_dbm, krec) < 0 ) {
114 dbm_clearerr(dp->di_dbm);
115 PyErr_SetString(PyExc_KeyError,
Roger E. Massebd4b9611996-12-13 15:59:22 +0000116 PyString_AS_STRING((PyStringObject *)v));
Roger E. Massee7ee8c31996-12-13 15:55:22 +0000117 return -1;
118 }
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000119 } else {
Roger E. Massee7ee8c31996-12-13 15:55:22 +0000120 if ( !PyArg_Parse(w, "s#", &drec.dptr, &drec.dsize) ) {
121 PyErr_SetString(PyExc_TypeError,
Roger E. Massebd4b9611996-12-13 15:59:22 +0000122 "dbm mappings have string elements only");
Roger E. Massee7ee8c31996-12-13 15:55:22 +0000123 return -1;
124 }
125 if ( dbm_store(dp->di_dbm, krec, drec, DBM_REPLACE) < 0 ) {
126 dbm_clearerr(dp->di_dbm);
Roger E. Massebd4b9611996-12-13 15:59:22 +0000127 PyErr_SetString(DbmError,
128 "Cannot add item to database");
Roger E. Massee7ee8c31996-12-13 15:55:22 +0000129 return -1;
130 }
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000131 }
132 if ( dbm_error(dp->di_dbm) ) {
Roger E. Massee7ee8c31996-12-13 15:55:22 +0000133 dbm_clearerr(dp->di_dbm);
134 PyErr_SetString(DbmError, "");
135 return -1;
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000136 }
137 return 0;
138}
139
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000140static PyMappingMethods dbm_as_mapping = {
Guido van Rossumb6775db1994-08-01 11:34:53 +0000141 (inquiry)dbm_length, /*mp_length*/
142 (binaryfunc)dbm_subscript, /*mp_subscript*/
143 (objobjargproc)dbm_ass_sub, /*mp_ass_subscript*/
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000144};
145
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000146static PyObject *
Peter Schneider-Kampcb27c352000-07-10 17:06:38 +0000147dbm__close(register dbmobject *dp, PyObject *args)
Guido van Rossum807b7be1995-07-07 22:37:11 +0000148{
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000149 if ( !PyArg_NoArgs(args) )
Guido van Rossum807b7be1995-07-07 22:37:11 +0000150 return NULL;
151 if ( dp->di_dbm )
Roger E. Massee7ee8c31996-12-13 15:55:22 +0000152 dbm_close(dp->di_dbm);
Guido van Rossum807b7be1995-07-07 22:37:11 +0000153 dp->di_dbm = NULL;
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000154 Py_INCREF(Py_None);
155 return Py_None;
Guido van Rossum807b7be1995-07-07 22:37:11 +0000156}
157
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000158static PyObject *
Peter Schneider-Kampcb27c352000-07-10 17:06:38 +0000159dbm_keys(register dbmobject *dp, PyObject *args)
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000160{
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000161 register PyObject *v, *item;
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000162 datum key;
Guido van Rossumd5039131995-01-30 12:45:38 +0000163 int err;
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000164
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000165 if (!PyArg_NoArgs(args))
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000166 return NULL;
Guido van Rossum77eecfa1997-07-17 22:56:01 +0000167 check_dbmobject_open(dp);
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000168 v = PyList_New(0);
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000169 if (v == NULL)
170 return NULL;
171 for (key = dbm_firstkey(dp->di_dbm); key.dptr;
Guido van Rossumd5039131995-01-30 12:45:38 +0000172 key = dbm_nextkey(dp->di_dbm)) {
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000173 item = PyString_FromStringAndSize(key.dptr, key.dsize);
Guido van Rossumd5039131995-01-30 12:45:38 +0000174 if (item == NULL) {
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000175 Py_DECREF(v);
Guido van Rossumd5039131995-01-30 12:45:38 +0000176 return NULL;
177 }
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000178 err = PyList_Append(v, item);
179 Py_DECREF(item);
Guido van Rossumd5039131995-01-30 12:45:38 +0000180 if (err != 0) {
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000181 Py_DECREF(v);
Guido van Rossumd5039131995-01-30 12:45:38 +0000182 return NULL;
183 }
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000184 }
185 return v;
186}
187
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000188static PyObject *
Peter Schneider-Kampcb27c352000-07-10 17:06:38 +0000189dbm_has_key(register dbmobject *dp, PyObject *args)
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000190{
191 datum key, val;
192
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000193 if (!PyArg_Parse(args, "s#", &key.dptr, &key.dsize))
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000194 return NULL;
Guido van Rossum77eecfa1997-07-17 22:56:01 +0000195 check_dbmobject_open(dp);
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000196 val = dbm_fetch(dp->di_dbm, key);
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000197 return PyInt_FromLong(val.dptr != NULL);
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000198}
199
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000200static PyMethodDef dbm_methods[] = {
201 {"close", (PyCFunction)dbm__close},
202 {"keys", (PyCFunction)dbm_keys},
203 {"has_key", (PyCFunction)dbm_has_key},
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000204 {NULL, NULL} /* sentinel */
205};
206
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000207static PyObject *
Peter Schneider-Kampcb27c352000-07-10 17:06:38 +0000208dbm_getattr(dbmobject *dp, char *name)
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000209{
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000210 return Py_FindMethod(dbm_methods, (PyObject *)dp, name);
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000211}
212
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000213static PyTypeObject Dbmtype = {
214 PyObject_HEAD_INIT(&PyType_Type)
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000215 0,
Guido van Rossum807b7be1995-07-07 22:37:11 +0000216 "dbm",
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000217 sizeof(dbmobject),
218 0,
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000219 (destructor)dbm_dealloc, /*tp_dealloc*/
220 0, /*tp_print*/
Guido van Rossumb6775db1994-08-01 11:34:53 +0000221 (getattrfunc)dbm_getattr, /*tp_getattr*/
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000222 0, /*tp_setattr*/
223 0, /*tp_compare*/
224 0, /*tp_repr*/
225 0, /*tp_as_number*/
226 0, /*tp_as_sequence*/
227 &dbm_as_mapping, /*tp_as_mapping*/
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000228};
229
230/* ----------------------------------------------------------------- */
231
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000232static PyObject *
Peter Schneider-Kampcb27c352000-07-10 17:06:38 +0000233dbmopen(PyObject *self, PyObject *args)
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000234{
Guido van Rossum807b7be1995-07-07 22:37:11 +0000235 char *name;
236 char *flags = "r";
237 int iflags;
238 int mode = 0666;
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000239
Guido van Rossum43713e52000-02-29 13:59:29 +0000240 if ( !PyArg_ParseTuple(args, "s|si:open", &name, &flags, &mode) )
Roger E. Massee7ee8c31996-12-13 15:55:22 +0000241 return NULL;
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000242 if ( strcmp(flags, "r") == 0 )
Roger E. Massee7ee8c31996-12-13 15:55:22 +0000243 iflags = O_RDONLY;
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000244 else if ( strcmp(flags, "w") == 0 )
Roger E. Massee7ee8c31996-12-13 15:55:22 +0000245 iflags = O_RDWR;
Guido van Rossum807b7be1995-07-07 22:37:11 +0000246 else if ( strcmp(flags, "rw") == 0 ) /* B/W compat */
Roger E. Massee7ee8c31996-12-13 15:55:22 +0000247 iflags = O_RDWR|O_CREAT;
Guido van Rossum807b7be1995-07-07 22:37:11 +0000248 else if ( strcmp(flags, "c") == 0 )
Roger E. Massee7ee8c31996-12-13 15:55:22 +0000249 iflags = O_RDWR|O_CREAT;
Guido van Rossum807b7be1995-07-07 22:37:11 +0000250 else if ( strcmp(flags, "n") == 0 )
Roger E. Massee7ee8c31996-12-13 15:55:22 +0000251 iflags = O_RDWR|O_CREAT|O_TRUNC;
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000252 else {
Roger E. Massee7ee8c31996-12-13 15:55:22 +0000253 PyErr_SetString(DbmError,
254 "Flags should be one of 'r', 'w', 'c' or 'n'");
255 return NULL;
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000256 }
257 return newdbmobject(name, iflags, mode);
258}
259
Roger E. Masseb0dfe961996-12-10 00:07:00 +0000260static PyMethodDef dbmmodule_methods[] = {
Roger E. Massee7ee8c31996-12-13 15:55:22 +0000261 { "open", (PyCFunction)dbmopen, 1 },
262 { 0, 0 },
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000263};
264
Guido van Rossum3886bb61998-12-04 18:50:17 +0000265DL_EXPORT(void)
Thomas Wouters58d05102000-07-24 14:43:35 +0000266initdbm(void) {
Roger E. Massee7ee8c31996-12-13 15:55:22 +0000267 PyObject *m, *d;
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000268
Roger E. Massee7ee8c31996-12-13 15:55:22 +0000269 m = Py_InitModule("dbm", dbmmodule_methods);
270 d = PyModule_GetDict(m);
Guido van Rossum0cb96de1997-10-01 04:29:29 +0000271 DbmError = PyErr_NewException("dbm.error", NULL, NULL);
272 if (DbmError != NULL)
273 PyDict_SetItemString(d, "error", DbmError);
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000274}