blob: 76d54f820b180edd3276cd09021be280a3c4c743 [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 *
Fred Drakee3a41c62000-07-08 05:00:07 +0000192dbm_close(register dbmobject *dp, PyObject *args)
Guido van Rossum807b7be1995-07-07 22:37:11 +0000193{
Fred Drakee3a41c62000-07-08 05:00:07 +0000194 if (!PyArg_ParseTuple(args, ":close"))
195 return NULL;
196 if (dp->di_dbm)
197 gdbm_close(dp->di_dbm);
198 dp->di_dbm = NULL;
199 Py_INCREF(Py_None);
200 return Py_None;
Guido van Rossum807b7be1995-07-07 22:37:11 +0000201}
202
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000203PyDoc_STRVAR(dbm_keys__doc__,
204"keys() -> list_of_keys\n\
205Get a list of all keys in the database.");
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000206
Roger E. Masseb15bef81996-12-17 19:55:33 +0000207static PyObject *
Fred Drakee3a41c62000-07-08 05:00:07 +0000208dbm_keys(register dbmobject *dp, PyObject *args)
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000209{
Fred Drakee3a41c62000-07-08 05:00:07 +0000210 register PyObject *v, *item;
211 datum key, nextkey;
212 int err;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000213
Fred Drakee3a41c62000-07-08 05:00:07 +0000214 if (dp == NULL || !is_dbmobject(dp)) {
215 PyErr_BadInternalCall();
216 return NULL;
217 }
218 if (!PyArg_ParseTuple(args, ":keys"))
219 return NULL;
Guido van Rossum3be71401996-07-21 02:32:44 +0000220
Fred Drakee3a41c62000-07-08 05:00:07 +0000221 check_dbmobject_open(dp);
Guido van Rossum3be71401996-07-21 02:32:44 +0000222
Fred Drakee3a41c62000-07-08 05:00:07 +0000223 v = PyList_New(0);
224 if (v == NULL)
225 return NULL;
Guido van Rossum77eecfa1997-07-17 22:56:01 +0000226
Fred Drakee3a41c62000-07-08 05:00:07 +0000227 key = gdbm_firstkey(dp->di_dbm);
228 while (key.dptr) {
229 item = PyString_FromStringAndSize(key.dptr, key.dsize);
230 if (item == NULL) {
231 free(key.dptr);
232 Py_DECREF(v);
233 return NULL;
234 }
235 err = PyList_Append(v, item);
236 Py_DECREF(item);
237 if (err != 0) {
238 free(key.dptr);
239 Py_DECREF(v);
240 return NULL;
241 }
242 nextkey = gdbm_nextkey(dp->di_dbm, key);
243 free(key.dptr);
244 key = nextkey;
245 }
246 return v;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000247}
248
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000249PyDoc_STRVAR(dbm_has_key__doc__,
250"has_key(key) -> boolean\n\
251Find out whether or not the database contains a given key.");
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000252
Roger E. Masseb15bef81996-12-17 19:55:33 +0000253static PyObject *
Fred Drakee3a41c62000-07-08 05:00:07 +0000254dbm_has_key(register dbmobject *dp, PyObject *args)
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000255{
Fred Drakee3a41c62000-07-08 05:00:07 +0000256 datum key;
257
258 if (!PyArg_ParseTuple(args, "s#:has_key", &key.dptr, &key.dsize))
259 return NULL;
260 check_dbmobject_open(dp);
261 return PyInt_FromLong((long) gdbm_exists(dp->di_dbm, key));
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000262}
263
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000264PyDoc_STRVAR(dbm_firstkey__doc__,
265"firstkey() -> key\n\
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000266It's possible to loop over every key in the database using this method\n\
267and the nextkey() method. The traversal is ordered by GDBM's internal\n\
268hash values, and won't be sorted by the key values. This method\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000269returns the starting key.");
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000270
Roger E. Masseb15bef81996-12-17 19:55:33 +0000271static PyObject *
Fred Drakee3a41c62000-07-08 05:00:07 +0000272dbm_firstkey(register dbmobject *dp, PyObject *args)
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000273{
Fred Drakee3a41c62000-07-08 05:00:07 +0000274 register PyObject *v;
275 datum key;
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000276
Fred Drakee3a41c62000-07-08 05:00:07 +0000277 if (!PyArg_ParseTuple(args, ":firstkey"))
278 return NULL;
279 check_dbmobject_open(dp);
280 key = gdbm_firstkey(dp->di_dbm);
281 if (key.dptr) {
282 v = PyString_FromStringAndSize(key.dptr, key.dsize);
283 free(key.dptr);
284 return v;
285 }
286 else {
287 Py_INCREF(Py_None);
288 return Py_None;
289 }
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000290}
291
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000292PyDoc_STRVAR(dbm_nextkey__doc__,
293"nextkey(key) -> next_key\n\
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000294Returns the key that follows key in the traversal.\n\
295The following code prints every key in the database db, without having\n\
296to create a list in memory that contains them all:\n\
297\n\
298 k = db.firstkey()\n\
299 while k != None:\n\
300 print k\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000301 k = db.nextkey(k)");
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000302
Roger E. Masseb15bef81996-12-17 19:55:33 +0000303static PyObject *
Fred Drakee3a41c62000-07-08 05:00:07 +0000304dbm_nextkey(register dbmobject *dp, PyObject *args)
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000305{
Fred Drakee3a41c62000-07-08 05:00:07 +0000306 register PyObject *v;
307 datum key, nextkey;
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000308
Fred Drakee3a41c62000-07-08 05:00:07 +0000309 if (!PyArg_ParseTuple(args, "s#:nextkey", &key.dptr, &key.dsize))
310 return NULL;
311 check_dbmobject_open(dp);
312 nextkey = gdbm_nextkey(dp->di_dbm, key);
313 if (nextkey.dptr) {
314 v = PyString_FromStringAndSize(nextkey.dptr, nextkey.dsize);
315 free(nextkey.dptr);
316 return v;
317 }
318 else {
319 Py_INCREF(Py_None);
320 return Py_None;
321 }
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000322}
323
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000324PyDoc_STRVAR(dbm_reorganize__doc__,
325"reorganize() -> None\n\
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000326If you have carried out a lot of deletions and would like to shrink\n\
327the space used by the GDBM file, this routine will reorganize the\n\
328database. GDBM will not shorten the length of a database file except\n\
329by using this reorganization; otherwise, deleted file space will be\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000330kept and reused as new (key,value) pairs are added.");
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000331
Roger E. Masseb15bef81996-12-17 19:55:33 +0000332static PyObject *
Fred Drakee3a41c62000-07-08 05:00:07 +0000333dbm_reorganize(register dbmobject *dp, PyObject *args)
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000334{
Fred Drakee3a41c62000-07-08 05:00:07 +0000335 if (!PyArg_ParseTuple(args, ":reorganize"))
336 return NULL;
337 check_dbmobject_open(dp);
338 errno = 0;
339 if (gdbm_reorganize(dp->di_dbm) < 0) {
340 if (errno != 0)
341 PyErr_SetFromErrno(DbmError);
342 else
343 PyErr_SetString(DbmError, gdbm_strerror(gdbm_errno));
344 return NULL;
345 }
346 Py_INCREF(Py_None);
347 return Py_None;
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000348}
349
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000350PyDoc_STRVAR(dbm_sync__doc__,
351"sync() -> None\n\
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000352When the database has been opened in fast mode, this method forces\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000353any unwritten data to be written to the disk.");
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000354
Roger E. Massee5a9c8f1997-03-25 17:39:56 +0000355static PyObject *
Fred Drakee3a41c62000-07-08 05:00:07 +0000356dbm_sync(register dbmobject *dp, PyObject *args)
Roger E. Massee5a9c8f1997-03-25 17:39:56 +0000357{
Fred Drakee3a41c62000-07-08 05:00:07 +0000358 if (!PyArg_ParseTuple(args, ":sync"))
359 return NULL;
360 check_dbmobject_open(dp);
361 gdbm_sync(dp->di_dbm);
362 Py_INCREF(Py_None);
363 return Py_None;
Roger E. Massee5a9c8f1997-03-25 17:39:56 +0000364}
365
Roger E. Masseb15bef81996-12-17 19:55:33 +0000366static PyMethodDef dbm_methods[] = {
Fred Drakee3a41c62000-07-08 05:00:07 +0000367 {"close", (PyCFunction)dbm_close, METH_VARARGS, dbm_close__doc__},
368 {"keys", (PyCFunction)dbm_keys, METH_VARARGS, dbm_keys__doc__},
369 {"has_key", (PyCFunction)dbm_has_key, METH_VARARGS, dbm_has_key__doc__},
370 {"firstkey", (PyCFunction)dbm_firstkey,METH_VARARGS, dbm_firstkey__doc__},
371 {"nextkey", (PyCFunction)dbm_nextkey, METH_VARARGS, dbm_nextkey__doc__},
372 {"reorganize",(PyCFunction)dbm_reorganize,METH_VARARGS, dbm_reorganize__doc__},
373 {"sync", (PyCFunction)dbm_sync, METH_VARARGS, dbm_sync__doc__},
374 {NULL, NULL} /* sentinel */
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000375};
376
Roger E. Masseb15bef81996-12-17 19:55:33 +0000377static PyObject *
Fred Drakee3a41c62000-07-08 05:00:07 +0000378dbm_getattr(dbmobject *dp, char *name)
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000379{
Fred Drakee3a41c62000-07-08 05:00:07 +0000380 return Py_FindMethod(dbm_methods, (PyObject *)dp, name);
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000381}
382
Roger E. Masseb15bef81996-12-17 19:55:33 +0000383static PyTypeObject Dbmtype = {
Fred Drakee3a41c62000-07-08 05:00:07 +0000384 PyObject_HEAD_INIT(0)
385 0,
Guido van Rossum14648392001-12-08 18:02:58 +0000386 "gdbm.gdbm",
Fred Drakee3a41c62000-07-08 05:00:07 +0000387 sizeof(dbmobject),
388 0,
389 (destructor)dbm_dealloc, /*tp_dealloc*/
390 0, /*tp_print*/
391 (getattrfunc)dbm_getattr, /*tp_getattr*/
392 0, /*tp_setattr*/
393 0, /*tp_compare*/
394 0, /*tp_repr*/
395 0, /*tp_as_number*/
396 0, /*tp_as_sequence*/
397 &dbm_as_mapping, /*tp_as_mapping*/
398 0, /*tp_hash*/
399 0, /*tp_call*/
400 0, /*tp_str*/
401 0, /*tp_getattro*/
402 0, /*tp_setattro*/
403 0, /*tp_as_buffer*/
404 0, /*tp_xxx4*/
405 gdbm_object__doc__, /*tp_doc*/
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000406};
407
408/* ----------------------------------------------------------------- */
409
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000410PyDoc_STRVAR(dbmopen__doc__,
411"open(filename, [flags, [mode]]) -> dbm_object\n\
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000412Open a dbm database and return a dbm object. The filename argument is\n\
413the name of the database file.\n\
414\n\
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000415The optional flags argument can be 'r' (to open an existing database\n\
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000416for reading only -- default), 'w' (to open an existing database for\n\
417reading and writing), 'c' (which creates the database if it doesn't\n\
418exist), or 'n' (which always creates a new empty database).\n\
419\n\
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000420Some versions of gdbm support additional flags which must be\n\
421appended to one of the flags described above. The module constant\n\
422'open_flags' is a string of valid additional flags. The 'f' flag\n\
423opens the database in fast mode; altered data will not automatically\n\
424be written to the disk after every change. This results in faster\n\
425writes to the database, but may result in an inconsistent database\n\
426if the program crashes while the database is still open. Use the\n\
427sync() method to force any unwritten data to be written to the disk.\n\
428The 's' flag causes all database operations to be synchronized to\n\
429disk. The 'u' flag disables locking of the database file.\n\
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000430\n\
431The optional mode argument is the Unix mode of the file, used only\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000432when the database has to be created. It defaults to octal 0666. ");
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000433
Roger E. Masseb15bef81996-12-17 19:55:33 +0000434static PyObject *
Fred Drakee3a41c62000-07-08 05:00:07 +0000435dbmopen(PyObject *self, PyObject *args)
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000436{
Fred Drakee3a41c62000-07-08 05:00:07 +0000437 char *name;
Andrew M. Kuchlingea271f22004-07-07 14:19:09 +0000438 char *flags = "r";
Fred Drakee3a41c62000-07-08 05:00:07 +0000439 int iflags;
440 int mode = 0666;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000441
Fred Drakee3a41c62000-07-08 05:00:07 +0000442 if (!PyArg_ParseTuple(args, "s|si:open", &name, &flags, &mode))
443 return NULL;
444 switch (flags[0]) {
445 case 'r':
446 iflags = GDBM_READER;
447 break;
448 case 'w':
449 iflags = GDBM_WRITER;
450 break;
451 case 'c':
452 iflags = GDBM_WRCREAT;
453 break;
454 case 'n':
455 iflags = GDBM_NEWDB;
456 break;
457 default:
458 PyErr_SetString(DbmError,
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000459 "First flag must be one of 'r', 'w', 'c' or 'n'");
Fred Drakee3a41c62000-07-08 05:00:07 +0000460 return NULL;
461 }
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000462 for (flags++; *flags != '\0'; flags++) {
463 char buf[40];
464 switch (*flags) {
465#ifdef GDBM_FAST
466 case 'f':
467 iflags |= GDBM_FAST;
468 break;
469#endif
470#ifdef GDBM_SYNC
471 case 's':
472 iflags |= GDBM_SYNC;
473 break;
474#endif
475#ifdef GDBM_NOLOCK
476 case 'u':
477 iflags |= GDBM_NOLOCK;
478 break;
479#endif
480 default:
Tim Peters885d4572001-11-28 20:27:42 +0000481 PyOS_snprintf(buf, sizeof(buf), "Flag '%c' is not supported.",
482 *flags);
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000483 PyErr_SetString(DbmError, buf);
484 return NULL;
485 }
486 }
487
Fred Drakee3a41c62000-07-08 05:00:07 +0000488 return newdbmobject(name, iflags, mode);
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000489}
490
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000491static char dbmmodule_open_flags[] = "rwcn"
492#ifdef GDBM_FAST
493 "f"
494#endif
495#ifdef GDBM_SYNC
496 "s"
497#endif
498#ifdef GDBM_NOLOCK
499 "u"
500#endif
501 ;
502
Roger E. Masseb15bef81996-12-17 19:55:33 +0000503static PyMethodDef dbmmodule_methods[] = {
Fred Drakee3a41c62000-07-08 05:00:07 +0000504 { "open", (PyCFunction)dbmopen, METH_VARARGS, dbmopen__doc__},
505 { 0, 0 },
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000506};
507
Mark Hammondfe51c6d2002-08-02 02:27:13 +0000508PyMODINIT_FUNC
Thomas Wouters58d05102000-07-24 14:43:35 +0000509initgdbm(void) {
Martin v. Löwis00ff10c2001-11-11 14:24:05 +0000510 PyObject *m, *d, *s;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000511
Fred Drakee3a41c62000-07-08 05:00:07 +0000512 Dbmtype.ob_type = &PyType_Type;
513 m = Py_InitModule4("gdbm", dbmmodule_methods,
514 gdbmmodule__doc__, (PyObject *)NULL,
515 PYTHON_API_VERSION);
Neal Norwitz1ac754f2006-01-19 06:09:39 +0000516 if (m == NULL)
517 return;
Fred Drakee3a41c62000-07-08 05:00:07 +0000518 d = PyModule_GetDict(m);
519 DbmError = PyErr_NewException("gdbm.error", NULL, NULL);
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000520 if (DbmError != NULL) {
Fred Drakee3a41c62000-07-08 05:00:07 +0000521 PyDict_SetItemString(d, "error", DbmError);
Martin v. Löwis00ff10c2001-11-11 14:24:05 +0000522 s = PyString_FromString(dbmmodule_open_flags);
523 PyDict_SetItemString(d, "open_flags", s);
524 Py_DECREF(s);
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000525 }
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000526}