blob: 8d3e048dff5c272901e8602e4f288939c04b8304 [file] [log] [blame]
Guido van Rossum4b4c6641994-08-08 08:06:37 +00001
2/* DBM module using dictionary interface */
Guido van Rossumbfc49e81998-03-03 22:02:24 +00003/* Author: Anthony Baxter, after dbmmodule.c */
4/* Doc strings: Mitch Chapman */
Guido van Rossum4b4c6641994-08-08 08:06:37 +00005
6
Roger E. Masseb15bef81996-12-17 19:55:33 +00007#include "Python.h"
Guido van Rossum4b4c6641994-08-08 08:06:37 +00008
9#include <sys/types.h>
10#include <sys/stat.h>
11#include <fcntl.h>
12#include "gdbm.h"
13
Tim Peters5687ffe2001-02-28 16:44:18 +000014#if defined(WIN32) && !defined(__CYGWIN__)
Guido van Rossumb6e2a991998-10-03 05:13:27 +000015#include "gdbmerrno.h"
16extern const char * gdbm_strerror(gdbm_error);
17#endif
18
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +000019PyDoc_STRVAR(gdbmmodule__doc__,
20"This module provides an interface to the GNU DBM (GDBM) library.\n\
Guido van Rossumbfc49e81998-03-03 22:02:24 +000021\n\
22This module is quite similar to the dbm module, but uses GDBM instead to\n\
23provide some additional functionality. Please note that the file formats\n\
24created by GDBM and dbm are incompatible. \n\
25\n\
26GDBM objects behave like mappings (dictionaries), except that keys and\n\
27values are always strings. Printing a GDBM object doesn't print the\n\
28keys and values, and the items() and values() methods are not\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +000029supported.");
Guido van Rossumbfc49e81998-03-03 22:02:24 +000030
Guido van Rossum4b4c6641994-08-08 08:06:37 +000031typedef struct {
Fred Drakee3a41c62000-07-08 05:00:07 +000032 PyObject_HEAD
33 int di_size; /* -1 means recompute */
34 GDBM_FILE di_dbm;
Guido van Rossum4b4c6641994-08-08 08:06:37 +000035} dbmobject;
36
Jeremy Hylton938ace62002-07-17 16:30:39 +000037static PyTypeObject Dbmtype;
Guido van Rossum4b4c6641994-08-08 08:06:37 +000038
Christian Heimese93237d2007-12-19 02:37:44 +000039#define is_dbmobject(v) (Py_TYPE(v) == &Dbmtype)
Guido van Rossum77eecfa1997-07-17 22:56:01 +000040#define check_dbmobject_open(v) if ((v)->di_dbm == NULL) \
Fred Drakee3a41c62000-07-08 05:00:07 +000041 { PyErr_SetString(DbmError, "GDBM object has already been closed"); \
42 return NULL; }
Guido van Rossum77eecfa1997-07-17 22:56:01 +000043
44
Guido van Rossum4b4c6641994-08-08 08:06:37 +000045
Roger E. Masseb15bef81996-12-17 19:55:33 +000046static PyObject *DbmError;
Guido van Rossum4b4c6641994-08-08 08:06:37 +000047
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +000048PyDoc_STRVAR(gdbm_object__doc__,
49"This object represents a GDBM database.\n\
Guido van Rossumbfc49e81998-03-03 22:02:24 +000050GDBM objects behave like mappings (dictionaries), except that keys and\n\
51values are always strings. Printing a GDBM object doesn't print the\n\
52keys and values, and the items() and values() methods are not\n\
53supported.\n\
54\n\
55GDBM objects also support additional operations such as firstkey,\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +000056nextkey, reorganize, and sync.");
Guido van Rossumbfc49e81998-03-03 22:02:24 +000057
Roger E. Masseb15bef81996-12-17 19:55:33 +000058static PyObject *
Fred Drakee3a41c62000-07-08 05:00:07 +000059newdbmobject(char *file, int flags, int mode)
Guido van Rossum4b4c6641994-08-08 08:06:37 +000060{
Fred Drakee3a41c62000-07-08 05:00:07 +000061 dbmobject *dp;
Guido van Rossum4b4c6641994-08-08 08:06:37 +000062
Fred Drakee3a41c62000-07-08 05:00:07 +000063 dp = PyObject_New(dbmobject, &Dbmtype);
64 if (dp == NULL)
65 return NULL;
66 dp->di_size = -1;
67 errno = 0;
68 if ((dp->di_dbm = gdbm_open(file, 0, flags, mode, NULL)) == 0) {
69 if (errno != 0)
70 PyErr_SetFromErrno(DbmError);
71 else
72 PyErr_SetString(DbmError, gdbm_strerror(gdbm_errno));
73 Py_DECREF(dp);
74 return NULL;
75 }
76 return (PyObject *)dp;
Guido van Rossum4b4c6641994-08-08 08:06:37 +000077}
78
79/* Methods */
80
81static void
Fred Drakee3a41c62000-07-08 05:00:07 +000082dbm_dealloc(register dbmobject *dp)
Guido van Rossum4b4c6641994-08-08 08:06:37 +000083{
Fred Drakee3a41c62000-07-08 05:00:07 +000084 if (dp->di_dbm)
85 gdbm_close(dp->di_dbm);
86 PyObject_Del(dp);
Guido van Rossum4b4c6641994-08-08 08:06:37 +000087}
88
Martin v. Löwis18e16552006-02-15 17:27:45 +000089static Py_ssize_t
Fred Drakee3a41c62000-07-08 05:00:07 +000090dbm_length(dbmobject *dp)
Guido van Rossum4b4c6641994-08-08 08:06:37 +000091{
Fred Drakee3a41c62000-07-08 05:00:07 +000092 if (dp->di_dbm == NULL) {
93 PyErr_SetString(DbmError, "GDBM object has already been closed");
94 return -1;
95 }
96 if (dp->di_size < 0) {
97 datum key,okey;
98 int size;
99 okey.dsize=0;
Thomas Woutersa5fa2a82006-03-01 22:54:36 +0000100 okey.dptr=NULL;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000101
Fred Drakee3a41c62000-07-08 05:00:07 +0000102 size = 0;
103 for (key=gdbm_firstkey(dp->di_dbm); key.dptr;
104 key = gdbm_nextkey(dp->di_dbm,okey)) {
105 size++;
106 if(okey.dsize) free(okey.dptr);
107 okey=key;
108 }
109 dp->di_size = size;
110 }
111 return dp->di_size;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000112}
113
Roger E. Masseb15bef81996-12-17 19:55:33 +0000114static PyObject *
Fred Drakee3a41c62000-07-08 05:00:07 +0000115dbm_subscript(dbmobject *dp, register PyObject *key)
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000116{
Fred Drakee3a41c62000-07-08 05:00:07 +0000117 PyObject *v;
118 datum drec, krec;
Fred Drakeda8d2162000-02-07 17:19:41 +0000119
Fred Drakee3a41c62000-07-08 05:00:07 +0000120 if (!PyArg_Parse(key, "s#", &krec.dptr, &krec.dsize) )
121 return NULL;
122
123 if (dp->di_dbm == NULL) {
124 PyErr_SetString(DbmError,
125 "GDBM object has already been closed");
126 return NULL;
127 }
128 drec = gdbm_fetch(dp->di_dbm, krec);
129 if (drec.dptr == 0) {
130 PyErr_SetString(PyExc_KeyError,
131 PyString_AS_STRING((PyStringObject *)key));
132 return NULL;
133 }
134 v = PyString_FromStringAndSize(drec.dptr, drec.dsize);
135 free(drec.dptr);
136 return v;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000137}
138
139static int
Fred Drakee3a41c62000-07-08 05:00:07 +0000140dbm_ass_sub(dbmobject *dp, PyObject *v, PyObject *w)
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000141{
Fred Drakee3a41c62000-07-08 05:00:07 +0000142 datum krec, drec;
143
144 if (!PyArg_Parse(v, "s#", &krec.dptr, &krec.dsize) ) {
145 PyErr_SetString(PyExc_TypeError,
146 "gdbm mappings have string indices only");
147 return -1;
148 }
149 if (dp->di_dbm == NULL) {
150 PyErr_SetString(DbmError,
151 "GDBM object has already been closed");
152 return -1;
153 }
154 dp->di_size = -1;
155 if (w == NULL) {
156 if (gdbm_delete(dp->di_dbm, krec) < 0) {
157 PyErr_SetString(PyExc_KeyError,
158 PyString_AS_STRING((PyStringObject *)v));
159 return -1;
Guido van Rossum77eecfa1997-07-17 22:56:01 +0000160 }
Fred Drakee3a41c62000-07-08 05:00:07 +0000161 }
162 else {
163 if (!PyArg_Parse(w, "s#", &drec.dptr, &drec.dsize)) {
164 PyErr_SetString(PyExc_TypeError,
165 "gdbm mappings have string elements only");
166 return -1;
167 }
168 errno = 0;
169 if (gdbm_store(dp->di_dbm, krec, drec, GDBM_REPLACE) < 0) {
170 if (errno != 0)
171 PyErr_SetFromErrno(DbmError);
172 else
173 PyErr_SetString(DbmError,
174 gdbm_strerror(gdbm_errno));
175 return -1;
176 }
177 }
178 return 0;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000179}
180
Facundo Batistadf419892008-02-25 22:33:55 +0000181static int
182dbm_contains(register dbmobject *dp, PyObject *v)
183{
184 datum key;
185
186 if (PyString_AsStringAndSize(v, &key.dptr, &key.dsize)) {
187 return -1;
188 }
189
190 check_dbmobject_open(dp);
191
192 return gdbm_exists(dp->di_dbm, key);
193}
194
195static PySequenceMethods dbm_as_sequence = {
196 (lenfunc)dbm_length, /*_length*/
197 0, /*sq_concat*/
198 0, /*sq_repeat*/
199 0, /*sq_item*/
200 0, /*sq_slice*/
201 0, /*sq_ass_item*/
202 0, /*sq_ass_slice*/
203 (objobjproc)dbm_contains, /*sq_contains*/
204 0, /*sq_inplace_concat*/
205 0 /*sq_inplace_repeat*/
206};
207
Roger E. Masseb15bef81996-12-17 19:55:33 +0000208static PyMappingMethods dbm_as_mapping = {
Martin v. Löwis18e16552006-02-15 17:27:45 +0000209 (lenfunc)dbm_length, /*mp_length*/
Fred Drakee3a41c62000-07-08 05:00:07 +0000210 (binaryfunc)dbm_subscript, /*mp_subscript*/
211 (objobjargproc)dbm_ass_sub, /*mp_ass_subscript*/
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000212};
213
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000214PyDoc_STRVAR(dbm_close__doc__,
215"close() -> None\n\
216Closes the database.");
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000217
Roger E. Masseb15bef81996-12-17 19:55:33 +0000218static PyObject *
Georg Brandl96a8c392006-05-29 21:04:52 +0000219dbm_close(register dbmobject *dp, PyObject *unused)
Guido van Rossum807b7be1995-07-07 22:37:11 +0000220{
Fred Drakee3a41c62000-07-08 05:00:07 +0000221 if (dp->di_dbm)
222 gdbm_close(dp->di_dbm);
223 dp->di_dbm = NULL;
224 Py_INCREF(Py_None);
225 return Py_None;
Guido van Rossum807b7be1995-07-07 22:37:11 +0000226}
227
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000228PyDoc_STRVAR(dbm_keys__doc__,
229"keys() -> list_of_keys\n\
230Get a list of all keys in the database.");
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000231
Roger E. Masseb15bef81996-12-17 19:55:33 +0000232static PyObject *
Georg Brandl96a8c392006-05-29 21:04:52 +0000233dbm_keys(register dbmobject *dp, PyObject *unused)
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000234{
Fred Drakee3a41c62000-07-08 05:00:07 +0000235 register PyObject *v, *item;
236 datum key, nextkey;
237 int err;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000238
Fred Drakee3a41c62000-07-08 05:00:07 +0000239 if (dp == NULL || !is_dbmobject(dp)) {
240 PyErr_BadInternalCall();
241 return NULL;
242 }
Fred Drakee3a41c62000-07-08 05:00:07 +0000243 check_dbmobject_open(dp);
Guido van Rossum3be71401996-07-21 02:32:44 +0000244
Fred Drakee3a41c62000-07-08 05:00:07 +0000245 v = PyList_New(0);
246 if (v == NULL)
247 return NULL;
Guido van Rossum77eecfa1997-07-17 22:56:01 +0000248
Fred Drakee3a41c62000-07-08 05:00:07 +0000249 key = gdbm_firstkey(dp->di_dbm);
250 while (key.dptr) {
251 item = PyString_FromStringAndSize(key.dptr, key.dsize);
252 if (item == NULL) {
253 free(key.dptr);
254 Py_DECREF(v);
255 return NULL;
256 }
257 err = PyList_Append(v, item);
258 Py_DECREF(item);
259 if (err != 0) {
260 free(key.dptr);
261 Py_DECREF(v);
262 return NULL;
263 }
264 nextkey = gdbm_nextkey(dp->di_dbm, key);
265 free(key.dptr);
266 key = nextkey;
267 }
268 return v;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000269}
270
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000271PyDoc_STRVAR(dbm_has_key__doc__,
272"has_key(key) -> boolean\n\
273Find out whether or not the database contains a given key.");
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000274
Roger E. Masseb15bef81996-12-17 19:55:33 +0000275static PyObject *
Fred Drakee3a41c62000-07-08 05:00:07 +0000276dbm_has_key(register dbmobject *dp, PyObject *args)
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000277{
Fred Drakee3a41c62000-07-08 05:00:07 +0000278 datum key;
279
280 if (!PyArg_ParseTuple(args, "s#:has_key", &key.dptr, &key.dsize))
281 return NULL;
282 check_dbmobject_open(dp);
283 return PyInt_FromLong((long) gdbm_exists(dp->di_dbm, key));
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000284}
285
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000286PyDoc_STRVAR(dbm_firstkey__doc__,
287"firstkey() -> key\n\
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000288It's possible to loop over every key in the database using this method\n\
289and the nextkey() method. The traversal is ordered by GDBM's internal\n\
290hash values, and won't be sorted by the key values. This method\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000291returns the starting key.");
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000292
Roger E. Masseb15bef81996-12-17 19:55:33 +0000293static PyObject *
Georg Brandl96a8c392006-05-29 21:04:52 +0000294dbm_firstkey(register dbmobject *dp, PyObject *unused)
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000295{
Fred Drakee3a41c62000-07-08 05:00:07 +0000296 register PyObject *v;
297 datum key;
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000298
Fred Drakee3a41c62000-07-08 05:00:07 +0000299 check_dbmobject_open(dp);
300 key = gdbm_firstkey(dp->di_dbm);
301 if (key.dptr) {
302 v = PyString_FromStringAndSize(key.dptr, key.dsize);
303 free(key.dptr);
304 return v;
305 }
306 else {
307 Py_INCREF(Py_None);
308 return Py_None;
309 }
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000310}
311
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000312PyDoc_STRVAR(dbm_nextkey__doc__,
313"nextkey(key) -> next_key\n\
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000314Returns the key that follows key in the traversal.\n\
315The following code prints every key in the database db, without having\n\
316to create a list in memory that contains them all:\n\
317\n\
318 k = db.firstkey()\n\
319 while k != None:\n\
320 print k\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000321 k = db.nextkey(k)");
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000322
Roger E. Masseb15bef81996-12-17 19:55:33 +0000323static PyObject *
Fred Drakee3a41c62000-07-08 05:00:07 +0000324dbm_nextkey(register dbmobject *dp, PyObject *args)
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000325{
Fred Drakee3a41c62000-07-08 05:00:07 +0000326 register PyObject *v;
327 datum key, nextkey;
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000328
Fred Drakee3a41c62000-07-08 05:00:07 +0000329 if (!PyArg_ParseTuple(args, "s#:nextkey", &key.dptr, &key.dsize))
330 return NULL;
331 check_dbmobject_open(dp);
332 nextkey = gdbm_nextkey(dp->di_dbm, key);
333 if (nextkey.dptr) {
334 v = PyString_FromStringAndSize(nextkey.dptr, nextkey.dsize);
335 free(nextkey.dptr);
336 return v;
337 }
338 else {
339 Py_INCREF(Py_None);
340 return Py_None;
341 }
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000342}
343
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000344PyDoc_STRVAR(dbm_reorganize__doc__,
345"reorganize() -> None\n\
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000346If you have carried out a lot of deletions and would like to shrink\n\
347the space used by the GDBM file, this routine will reorganize the\n\
348database. GDBM will not shorten the length of a database file except\n\
349by using this reorganization; otherwise, deleted file space will be\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000350kept and reused as new (key,value) pairs are added.");
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000351
Roger E. Masseb15bef81996-12-17 19:55:33 +0000352static PyObject *
Georg Brandl96a8c392006-05-29 21:04:52 +0000353dbm_reorganize(register dbmobject *dp, PyObject *unused)
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000354{
Fred Drakee3a41c62000-07-08 05:00:07 +0000355 check_dbmobject_open(dp);
356 errno = 0;
357 if (gdbm_reorganize(dp->di_dbm) < 0) {
358 if (errno != 0)
359 PyErr_SetFromErrno(DbmError);
360 else
361 PyErr_SetString(DbmError, gdbm_strerror(gdbm_errno));
362 return NULL;
363 }
364 Py_INCREF(Py_None);
365 return Py_None;
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000366}
367
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000368PyDoc_STRVAR(dbm_sync__doc__,
369"sync() -> None\n\
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000370When the database has been opened in fast mode, this method forces\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000371any unwritten data to be written to the disk.");
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000372
Roger E. Massee5a9c8f1997-03-25 17:39:56 +0000373static PyObject *
Georg Brandl96a8c392006-05-29 21:04:52 +0000374dbm_sync(register dbmobject *dp, PyObject *unused)
Roger E. Massee5a9c8f1997-03-25 17:39:56 +0000375{
Fred Drakee3a41c62000-07-08 05:00:07 +0000376 check_dbmobject_open(dp);
377 gdbm_sync(dp->di_dbm);
378 Py_INCREF(Py_None);
379 return Py_None;
Roger E. Massee5a9c8f1997-03-25 17:39:56 +0000380}
381
Roger E. Masseb15bef81996-12-17 19:55:33 +0000382static PyMethodDef dbm_methods[] = {
Georg Brandl96a8c392006-05-29 21:04:52 +0000383 {"close", (PyCFunction)dbm_close, METH_NOARGS, dbm_close__doc__},
384 {"keys", (PyCFunction)dbm_keys, METH_NOARGS, dbm_keys__doc__},
Fred Drakee3a41c62000-07-08 05:00:07 +0000385 {"has_key", (PyCFunction)dbm_has_key, METH_VARARGS, dbm_has_key__doc__},
Georg Brandl96a8c392006-05-29 21:04:52 +0000386 {"firstkey", (PyCFunction)dbm_firstkey,METH_NOARGS, dbm_firstkey__doc__},
Fred Drakee3a41c62000-07-08 05:00:07 +0000387 {"nextkey", (PyCFunction)dbm_nextkey, METH_VARARGS, dbm_nextkey__doc__},
Georg Brandl96a8c392006-05-29 21:04:52 +0000388 {"reorganize",(PyCFunction)dbm_reorganize,METH_NOARGS, dbm_reorganize__doc__},
389 {"sync", (PyCFunction)dbm_sync, METH_NOARGS, dbm_sync__doc__},
Fred Drakee3a41c62000-07-08 05:00:07 +0000390 {NULL, NULL} /* sentinel */
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000391};
392
Roger E. Masseb15bef81996-12-17 19:55:33 +0000393static PyObject *
Fred Drakee3a41c62000-07-08 05:00:07 +0000394dbm_getattr(dbmobject *dp, char *name)
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000395{
Fred Drakee3a41c62000-07-08 05:00:07 +0000396 return Py_FindMethod(dbm_methods, (PyObject *)dp, name);
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000397}
398
Roger E. Masseb15bef81996-12-17 19:55:33 +0000399static PyTypeObject Dbmtype = {
Martin v. Löwis68192102007-07-21 06:55:02 +0000400 PyVarObject_HEAD_INIT(0, 0)
Guido van Rossum14648392001-12-08 18:02:58 +0000401 "gdbm.gdbm",
Fred Drakee3a41c62000-07-08 05:00:07 +0000402 sizeof(dbmobject),
403 0,
404 (destructor)dbm_dealloc, /*tp_dealloc*/
405 0, /*tp_print*/
406 (getattrfunc)dbm_getattr, /*tp_getattr*/
407 0, /*tp_setattr*/
408 0, /*tp_compare*/
409 0, /*tp_repr*/
410 0, /*tp_as_number*/
Facundo Batistadf419892008-02-25 22:33:55 +0000411 &dbm_as_sequence, /*tp_as_sequence*/
Fred Drakee3a41c62000-07-08 05:00:07 +0000412 &dbm_as_mapping, /*tp_as_mapping*/
413 0, /*tp_hash*/
414 0, /*tp_call*/
415 0, /*tp_str*/
416 0, /*tp_getattro*/
417 0, /*tp_setattro*/
418 0, /*tp_as_buffer*/
Facundo Batistadf419892008-02-25 22:33:55 +0000419 Py_TPFLAGS_DEFAULT, /*tp_xxx4*/
Fred Drakee3a41c62000-07-08 05:00:07 +0000420 gdbm_object__doc__, /*tp_doc*/
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000421};
422
423/* ----------------------------------------------------------------- */
424
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000425PyDoc_STRVAR(dbmopen__doc__,
426"open(filename, [flags, [mode]]) -> dbm_object\n\
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000427Open a dbm database and return a dbm object. The filename argument is\n\
428the name of the database file.\n\
429\n\
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000430The optional flags argument can be 'r' (to open an existing database\n\
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000431for reading only -- default), 'w' (to open an existing database for\n\
432reading and writing), 'c' (which creates the database if it doesn't\n\
433exist), or 'n' (which always creates a new empty database).\n\
434\n\
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000435Some versions of gdbm support additional flags which must be\n\
436appended to one of the flags described above. The module constant\n\
437'open_flags' is a string of valid additional flags. The 'f' flag\n\
438opens the database in fast mode; altered data will not automatically\n\
439be written to the disk after every change. This results in faster\n\
440writes to the database, but may result in an inconsistent database\n\
441if the program crashes while the database is still open. Use the\n\
442sync() method to force any unwritten data to be written to the disk.\n\
443The 's' flag causes all database operations to be synchronized to\n\
444disk. The 'u' flag disables locking of the database file.\n\
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000445\n\
446The optional mode argument is the Unix mode of the file, used only\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000447when the database has to be created. It defaults to octal 0666. ");
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000448
Roger E. Masseb15bef81996-12-17 19:55:33 +0000449static PyObject *
Fred Drakee3a41c62000-07-08 05:00:07 +0000450dbmopen(PyObject *self, PyObject *args)
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000451{
Fred Drakee3a41c62000-07-08 05:00:07 +0000452 char *name;
Andrew M. Kuchlingea271f22004-07-07 14:19:09 +0000453 char *flags = "r";
Fred Drakee3a41c62000-07-08 05:00:07 +0000454 int iflags;
455 int mode = 0666;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000456
Fred Drakee3a41c62000-07-08 05:00:07 +0000457 if (!PyArg_ParseTuple(args, "s|si:open", &name, &flags, &mode))
458 return NULL;
459 switch (flags[0]) {
460 case 'r':
461 iflags = GDBM_READER;
462 break;
463 case 'w':
464 iflags = GDBM_WRITER;
465 break;
466 case 'c':
467 iflags = GDBM_WRCREAT;
468 break;
469 case 'n':
470 iflags = GDBM_NEWDB;
471 break;
472 default:
473 PyErr_SetString(DbmError,
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000474 "First flag must be one of 'r', 'w', 'c' or 'n'");
Fred Drakee3a41c62000-07-08 05:00:07 +0000475 return NULL;
476 }
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000477 for (flags++; *flags != '\0'; flags++) {
478 char buf[40];
479 switch (*flags) {
480#ifdef GDBM_FAST
481 case 'f':
482 iflags |= GDBM_FAST;
483 break;
484#endif
485#ifdef GDBM_SYNC
486 case 's':
487 iflags |= GDBM_SYNC;
488 break;
489#endif
490#ifdef GDBM_NOLOCK
491 case 'u':
492 iflags |= GDBM_NOLOCK;
493 break;
494#endif
495 default:
Tim Peters885d4572001-11-28 20:27:42 +0000496 PyOS_snprintf(buf, sizeof(buf), "Flag '%c' is not supported.",
497 *flags);
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000498 PyErr_SetString(DbmError, buf);
499 return NULL;
500 }
501 }
502
Fred Drakee3a41c62000-07-08 05:00:07 +0000503 return newdbmobject(name, iflags, mode);
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000504}
505
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000506static char dbmmodule_open_flags[] = "rwcn"
507#ifdef GDBM_FAST
508 "f"
509#endif
510#ifdef GDBM_SYNC
511 "s"
512#endif
513#ifdef GDBM_NOLOCK
514 "u"
515#endif
516 ;
517
Roger E. Masseb15bef81996-12-17 19:55:33 +0000518static PyMethodDef dbmmodule_methods[] = {
Fred Drakee3a41c62000-07-08 05:00:07 +0000519 { "open", (PyCFunction)dbmopen, METH_VARARGS, dbmopen__doc__},
520 { 0, 0 },
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000521};
522
Mark Hammondfe51c6d2002-08-02 02:27:13 +0000523PyMODINIT_FUNC
Thomas Wouters58d05102000-07-24 14:43:35 +0000524initgdbm(void) {
Martin v. Löwis00ff10c2001-11-11 14:24:05 +0000525 PyObject *m, *d, *s;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000526
Fred Drakee3a41c62000-07-08 05:00:07 +0000527 Dbmtype.ob_type = &PyType_Type;
528 m = Py_InitModule4("gdbm", dbmmodule_methods,
529 gdbmmodule__doc__, (PyObject *)NULL,
530 PYTHON_API_VERSION);
Neal Norwitz1ac754f2006-01-19 06:09:39 +0000531 if (m == NULL)
532 return;
Fred Drakee3a41c62000-07-08 05:00:07 +0000533 d = PyModule_GetDict(m);
534 DbmError = PyErr_NewException("gdbm.error", NULL, NULL);
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000535 if (DbmError != NULL) {
Fred Drakee3a41c62000-07-08 05:00:07 +0000536 PyDict_SetItemString(d, "error", DbmError);
Martin v. Löwis00ff10c2001-11-11 14:24:05 +0000537 s = PyString_FromString(dbmmodule_open_flags);
538 PyDict_SetItemString(d, "open_flags", s);
539 Py_DECREF(s);
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000540 }
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000541}