blob: cfc6abc37f5f885eb6441e59648cb683473e22ef [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
39#define is_dbmobject(v) ((v)->ob_type == &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
Roger E. Masseb15bef81996-12-17 19:55:33 +0000181static PyMappingMethods dbm_as_mapping = {
Martin v. Löwis18e16552006-02-15 17:27:45 +0000182 (lenfunc)dbm_length, /*mp_length*/
Fred Drakee3a41c62000-07-08 05:00:07 +0000183 (binaryfunc)dbm_subscript, /*mp_subscript*/
184 (objobjargproc)dbm_ass_sub, /*mp_ass_subscript*/
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000185};
186
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000187PyDoc_STRVAR(dbm_close__doc__,
188"close() -> None\n\
189Closes the database.");
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000190
Roger E. Masseb15bef81996-12-17 19:55:33 +0000191static PyObject *
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000192dbm_close(register dbmobject *dp, PyObject *unused)
Guido van Rossum807b7be1995-07-07 22:37:11 +0000193{
Fred Drakee3a41c62000-07-08 05:00:07 +0000194 if (dp->di_dbm)
195 gdbm_close(dp->di_dbm);
196 dp->di_dbm = NULL;
197 Py_INCREF(Py_None);
198 return Py_None;
Guido van Rossum807b7be1995-07-07 22:37:11 +0000199}
200
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000201PyDoc_STRVAR(dbm_keys__doc__,
202"keys() -> list_of_keys\n\
203Get a list of all keys in the database.");
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000204
Roger E. Masseb15bef81996-12-17 19:55:33 +0000205static PyObject *
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000206dbm_keys(register dbmobject *dp, PyObject *unused)
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000207{
Fred Drakee3a41c62000-07-08 05:00:07 +0000208 register PyObject *v, *item;
209 datum key, nextkey;
210 int err;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000211
Fred Drakee3a41c62000-07-08 05:00:07 +0000212 if (dp == NULL || !is_dbmobject(dp)) {
213 PyErr_BadInternalCall();
214 return NULL;
215 }
Fred Drakee3a41c62000-07-08 05:00:07 +0000216 check_dbmobject_open(dp);
Guido van Rossum3be71401996-07-21 02:32:44 +0000217
Fred Drakee3a41c62000-07-08 05:00:07 +0000218 v = PyList_New(0);
219 if (v == NULL)
220 return NULL;
Guido van Rossum77eecfa1997-07-17 22:56:01 +0000221
Fred Drakee3a41c62000-07-08 05:00:07 +0000222 key = gdbm_firstkey(dp->di_dbm);
223 while (key.dptr) {
224 item = PyString_FromStringAndSize(key.dptr, key.dsize);
225 if (item == NULL) {
226 free(key.dptr);
227 Py_DECREF(v);
228 return NULL;
229 }
230 err = PyList_Append(v, item);
231 Py_DECREF(item);
232 if (err != 0) {
233 free(key.dptr);
234 Py_DECREF(v);
235 return NULL;
236 }
237 nextkey = gdbm_nextkey(dp->di_dbm, key);
238 free(key.dptr);
239 key = nextkey;
240 }
241 return v;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000242}
243
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000244PyDoc_STRVAR(dbm_has_key__doc__,
245"has_key(key) -> boolean\n\
246Find out whether or not the database contains a given key.");
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000247
Roger E. Masseb15bef81996-12-17 19:55:33 +0000248static PyObject *
Fred Drakee3a41c62000-07-08 05:00:07 +0000249dbm_has_key(register dbmobject *dp, PyObject *args)
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000250{
Fred Drakee3a41c62000-07-08 05:00:07 +0000251 datum key;
252
253 if (!PyArg_ParseTuple(args, "s#:has_key", &key.dptr, &key.dsize))
254 return NULL;
255 check_dbmobject_open(dp);
256 return PyInt_FromLong((long) gdbm_exists(dp->di_dbm, key));
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000257}
258
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000259PyDoc_STRVAR(dbm_firstkey__doc__,
260"firstkey() -> key\n\
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000261It's possible to loop over every key in the database using this method\n\
262and the nextkey() method. The traversal is ordered by GDBM's internal\n\
263hash values, and won't be sorted by the key values. This method\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000264returns the starting key.");
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000265
Roger E. Masseb15bef81996-12-17 19:55:33 +0000266static PyObject *
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000267dbm_firstkey(register dbmobject *dp, PyObject *unused)
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000268{
Fred Drakee3a41c62000-07-08 05:00:07 +0000269 register PyObject *v;
270 datum key;
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000271
Fred Drakee3a41c62000-07-08 05:00:07 +0000272 check_dbmobject_open(dp);
273 key = gdbm_firstkey(dp->di_dbm);
274 if (key.dptr) {
275 v = PyString_FromStringAndSize(key.dptr, key.dsize);
276 free(key.dptr);
277 return v;
278 }
279 else {
280 Py_INCREF(Py_None);
281 return Py_None;
282 }
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000283}
284
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000285PyDoc_STRVAR(dbm_nextkey__doc__,
286"nextkey(key) -> next_key\n\
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000287Returns the key that follows key in the traversal.\n\
288The following code prints every key in the database db, without having\n\
289to create a list in memory that contains them all:\n\
290\n\
291 k = db.firstkey()\n\
292 while k != None:\n\
293 print k\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000294 k = db.nextkey(k)");
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000295
Roger E. Masseb15bef81996-12-17 19:55:33 +0000296static PyObject *
Fred Drakee3a41c62000-07-08 05:00:07 +0000297dbm_nextkey(register dbmobject *dp, PyObject *args)
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000298{
Fred Drakee3a41c62000-07-08 05:00:07 +0000299 register PyObject *v;
300 datum key, nextkey;
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000301
Fred Drakee3a41c62000-07-08 05:00:07 +0000302 if (!PyArg_ParseTuple(args, "s#:nextkey", &key.dptr, &key.dsize))
303 return NULL;
304 check_dbmobject_open(dp);
305 nextkey = gdbm_nextkey(dp->di_dbm, key);
306 if (nextkey.dptr) {
307 v = PyString_FromStringAndSize(nextkey.dptr, nextkey.dsize);
308 free(nextkey.dptr);
309 return v;
310 }
311 else {
312 Py_INCREF(Py_None);
313 return Py_None;
314 }
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000315}
316
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000317PyDoc_STRVAR(dbm_reorganize__doc__,
318"reorganize() -> None\n\
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000319If you have carried out a lot of deletions and would like to shrink\n\
320the space used by the GDBM file, this routine will reorganize the\n\
321database. GDBM will not shorten the length of a database file except\n\
322by using this reorganization; otherwise, deleted file space will be\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000323kept and reused as new (key,value) pairs are added.");
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000324
Roger E. Masseb15bef81996-12-17 19:55:33 +0000325static PyObject *
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000326dbm_reorganize(register dbmobject *dp, PyObject *unused)
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000327{
Fred Drakee3a41c62000-07-08 05:00:07 +0000328 check_dbmobject_open(dp);
329 errno = 0;
330 if (gdbm_reorganize(dp->di_dbm) < 0) {
331 if (errno != 0)
332 PyErr_SetFromErrno(DbmError);
333 else
334 PyErr_SetString(DbmError, gdbm_strerror(gdbm_errno));
335 return NULL;
336 }
337 Py_INCREF(Py_None);
338 return Py_None;
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000339}
340
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000341PyDoc_STRVAR(dbm_sync__doc__,
342"sync() -> None\n\
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000343When the database has been opened in fast mode, this method forces\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000344any unwritten data to be written to the disk.");
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000345
Roger E. Massee5a9c8f1997-03-25 17:39:56 +0000346static PyObject *
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000347dbm_sync(register dbmobject *dp, PyObject *unused)
Roger E. Massee5a9c8f1997-03-25 17:39:56 +0000348{
Fred Drakee3a41c62000-07-08 05:00:07 +0000349 check_dbmobject_open(dp);
350 gdbm_sync(dp->di_dbm);
351 Py_INCREF(Py_None);
352 return Py_None;
Roger E. Massee5a9c8f1997-03-25 17:39:56 +0000353}
354
Roger E. Masseb15bef81996-12-17 19:55:33 +0000355static PyMethodDef dbm_methods[] = {
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000356 {"close", (PyCFunction)dbm_close, METH_NOARGS, dbm_close__doc__},
357 {"keys", (PyCFunction)dbm_keys, METH_NOARGS, dbm_keys__doc__},
Fred Drakee3a41c62000-07-08 05:00:07 +0000358 {"has_key", (PyCFunction)dbm_has_key, METH_VARARGS, dbm_has_key__doc__},
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000359 {"firstkey", (PyCFunction)dbm_firstkey,METH_NOARGS, dbm_firstkey__doc__},
Fred Drakee3a41c62000-07-08 05:00:07 +0000360 {"nextkey", (PyCFunction)dbm_nextkey, METH_VARARGS, dbm_nextkey__doc__},
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000361 {"reorganize",(PyCFunction)dbm_reorganize,METH_NOARGS, dbm_reorganize__doc__},
362 {"sync", (PyCFunction)dbm_sync, METH_NOARGS, dbm_sync__doc__},
Fred Drakee3a41c62000-07-08 05:00:07 +0000363 {NULL, NULL} /* sentinel */
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000364};
365
Roger E. Masseb15bef81996-12-17 19:55:33 +0000366static PyObject *
Fred Drakee3a41c62000-07-08 05:00:07 +0000367dbm_getattr(dbmobject *dp, char *name)
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000368{
Fred Drakee3a41c62000-07-08 05:00:07 +0000369 return Py_FindMethod(dbm_methods, (PyObject *)dp, name);
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000370}
371
Roger E. Masseb15bef81996-12-17 19:55:33 +0000372static PyTypeObject Dbmtype = {
Fred Drakee3a41c62000-07-08 05:00:07 +0000373 PyObject_HEAD_INIT(0)
374 0,
Guido van Rossum14648392001-12-08 18:02:58 +0000375 "gdbm.gdbm",
Fred Drakee3a41c62000-07-08 05:00:07 +0000376 sizeof(dbmobject),
377 0,
378 (destructor)dbm_dealloc, /*tp_dealloc*/
379 0, /*tp_print*/
380 (getattrfunc)dbm_getattr, /*tp_getattr*/
381 0, /*tp_setattr*/
382 0, /*tp_compare*/
383 0, /*tp_repr*/
384 0, /*tp_as_number*/
385 0, /*tp_as_sequence*/
386 &dbm_as_mapping, /*tp_as_mapping*/
387 0, /*tp_hash*/
388 0, /*tp_call*/
389 0, /*tp_str*/
390 0, /*tp_getattro*/
391 0, /*tp_setattro*/
392 0, /*tp_as_buffer*/
393 0, /*tp_xxx4*/
394 gdbm_object__doc__, /*tp_doc*/
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000395};
396
397/* ----------------------------------------------------------------- */
398
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000399PyDoc_STRVAR(dbmopen__doc__,
400"open(filename, [flags, [mode]]) -> dbm_object\n\
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000401Open a dbm database and return a dbm object. The filename argument is\n\
402the name of the database file.\n\
403\n\
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000404The optional flags argument can be 'r' (to open an existing database\n\
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000405for reading only -- default), 'w' (to open an existing database for\n\
406reading and writing), 'c' (which creates the database if it doesn't\n\
407exist), or 'n' (which always creates a new empty database).\n\
408\n\
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000409Some versions of gdbm support additional flags which must be\n\
410appended to one of the flags described above. The module constant\n\
411'open_flags' is a string of valid additional flags. The 'f' flag\n\
412opens the database in fast mode; altered data will not automatically\n\
413be written to the disk after every change. This results in faster\n\
414writes to the database, but may result in an inconsistent database\n\
415if the program crashes while the database is still open. Use the\n\
416sync() method to force any unwritten data to be written to the disk.\n\
417The 's' flag causes all database operations to be synchronized to\n\
418disk. The 'u' flag disables locking of the database file.\n\
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000419\n\
420The optional mode argument is the Unix mode of the file, used only\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000421when the database has to be created. It defaults to octal 0666. ");
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000422
Roger E. Masseb15bef81996-12-17 19:55:33 +0000423static PyObject *
Fred Drakee3a41c62000-07-08 05:00:07 +0000424dbmopen(PyObject *self, PyObject *args)
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000425{
Fred Drakee3a41c62000-07-08 05:00:07 +0000426 char *name;
Andrew M. Kuchlingea271f22004-07-07 14:19:09 +0000427 char *flags = "r";
Fred Drakee3a41c62000-07-08 05:00:07 +0000428 int iflags;
429 int mode = 0666;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000430
Fred Drakee3a41c62000-07-08 05:00:07 +0000431 if (!PyArg_ParseTuple(args, "s|si:open", &name, &flags, &mode))
432 return NULL;
433 switch (flags[0]) {
434 case 'r':
435 iflags = GDBM_READER;
436 break;
437 case 'w':
438 iflags = GDBM_WRITER;
439 break;
440 case 'c':
441 iflags = GDBM_WRCREAT;
442 break;
443 case 'n':
444 iflags = GDBM_NEWDB;
445 break;
446 default:
447 PyErr_SetString(DbmError,
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000448 "First flag must be one of 'r', 'w', 'c' or 'n'");
Fred Drakee3a41c62000-07-08 05:00:07 +0000449 return NULL;
450 }
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000451 for (flags++; *flags != '\0'; flags++) {
452 char buf[40];
453 switch (*flags) {
454#ifdef GDBM_FAST
455 case 'f':
456 iflags |= GDBM_FAST;
457 break;
458#endif
459#ifdef GDBM_SYNC
460 case 's':
461 iflags |= GDBM_SYNC;
462 break;
463#endif
464#ifdef GDBM_NOLOCK
465 case 'u':
466 iflags |= GDBM_NOLOCK;
467 break;
468#endif
469 default:
Tim Peters885d4572001-11-28 20:27:42 +0000470 PyOS_snprintf(buf, sizeof(buf), "Flag '%c' is not supported.",
471 *flags);
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000472 PyErr_SetString(DbmError, buf);
473 return NULL;
474 }
475 }
476
Fred Drakee3a41c62000-07-08 05:00:07 +0000477 return newdbmobject(name, iflags, mode);
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000478}
479
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000480static char dbmmodule_open_flags[] = "rwcn"
481#ifdef GDBM_FAST
482 "f"
483#endif
484#ifdef GDBM_SYNC
485 "s"
486#endif
487#ifdef GDBM_NOLOCK
488 "u"
489#endif
490 ;
491
Roger E. Masseb15bef81996-12-17 19:55:33 +0000492static PyMethodDef dbmmodule_methods[] = {
Fred Drakee3a41c62000-07-08 05:00:07 +0000493 { "open", (PyCFunction)dbmopen, METH_VARARGS, dbmopen__doc__},
494 { 0, 0 },
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000495};
496
Mark Hammondfe51c6d2002-08-02 02:27:13 +0000497PyMODINIT_FUNC
Thomas Wouters58d05102000-07-24 14:43:35 +0000498initgdbm(void) {
Martin v. Löwis00ff10c2001-11-11 14:24:05 +0000499 PyObject *m, *d, *s;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000500
Fred Drakee3a41c62000-07-08 05:00:07 +0000501 Dbmtype.ob_type = &PyType_Type;
502 m = Py_InitModule4("gdbm", dbmmodule_methods,
503 gdbmmodule__doc__, (PyObject *)NULL,
504 PYTHON_API_VERSION);
Neal Norwitz1ac754f2006-01-19 06:09:39 +0000505 if (m == NULL)
506 return;
Fred Drakee3a41c62000-07-08 05:00:07 +0000507 d = PyModule_GetDict(m);
508 DbmError = PyErr_NewException("gdbm.error", NULL, NULL);
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000509 if (DbmError != NULL) {
Fred Drakee3a41c62000-07-08 05:00:07 +0000510 PyDict_SetItemString(d, "error", DbmError);
Martin v. Löwis00ff10c2001-11-11 14:24:05 +0000511 s = PyString_FromString(dbmmodule_open_flags);
512 PyDict_SetItemString(d, "open_flags", s);
513 Py_DECREF(s);
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000514 }
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000515}