blob: accf43894bcf83d6b7f66ff20469652964912588 [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
89static int
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;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000100
Fred Drakee3a41c62000-07-08 05:00:07 +0000101 size = 0;
102 for (key=gdbm_firstkey(dp->di_dbm); key.dptr;
103 key = gdbm_nextkey(dp->di_dbm,okey)) {
104 size++;
105 if(okey.dsize) free(okey.dptr);
106 okey=key;
107 }
108 dp->di_size = size;
109 }
110 return dp->di_size;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000111}
112
Roger E. Masseb15bef81996-12-17 19:55:33 +0000113static PyObject *
Fred Drakee3a41c62000-07-08 05:00:07 +0000114dbm_subscript(dbmobject *dp, register PyObject *key)
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000115{
Fred Drakee3a41c62000-07-08 05:00:07 +0000116 PyObject *v;
117 datum drec, krec;
Fred Drakeda8d2162000-02-07 17:19:41 +0000118
Fred Drakee3a41c62000-07-08 05:00:07 +0000119 if (!PyArg_Parse(key, "s#", &krec.dptr, &krec.dsize) )
120 return NULL;
121
122 if (dp->di_dbm == NULL) {
123 PyErr_SetString(DbmError,
124 "GDBM object has already been closed");
125 return NULL;
126 }
127 drec = gdbm_fetch(dp->di_dbm, krec);
128 if (drec.dptr == 0) {
129 PyErr_SetString(PyExc_KeyError,
130 PyString_AS_STRING((PyStringObject *)key));
131 return NULL;
132 }
133 v = PyString_FromStringAndSize(drec.dptr, drec.dsize);
134 free(drec.dptr);
135 return v;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000136}
137
138static int
Fred Drakee3a41c62000-07-08 05:00:07 +0000139dbm_ass_sub(dbmobject *dp, PyObject *v, PyObject *w)
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000140{
Fred Drakee3a41c62000-07-08 05:00:07 +0000141 datum krec, drec;
142
143 if (!PyArg_Parse(v, "s#", &krec.dptr, &krec.dsize) ) {
144 PyErr_SetString(PyExc_TypeError,
145 "gdbm mappings have string indices only");
146 return -1;
147 }
148 if (dp->di_dbm == NULL) {
149 PyErr_SetString(DbmError,
150 "GDBM object has already been closed");
151 return -1;
152 }
153 dp->di_size = -1;
154 if (w == NULL) {
155 if (gdbm_delete(dp->di_dbm, krec) < 0) {
156 PyErr_SetString(PyExc_KeyError,
157 PyString_AS_STRING((PyStringObject *)v));
158 return -1;
Guido van Rossum77eecfa1997-07-17 22:56:01 +0000159 }
Fred Drakee3a41c62000-07-08 05:00:07 +0000160 }
161 else {
162 if (!PyArg_Parse(w, "s#", &drec.dptr, &drec.dsize)) {
163 PyErr_SetString(PyExc_TypeError,
164 "gdbm mappings have string elements only");
165 return -1;
166 }
167 errno = 0;
168 if (gdbm_store(dp->di_dbm, krec, drec, GDBM_REPLACE) < 0) {
169 if (errno != 0)
170 PyErr_SetFromErrno(DbmError);
171 else
172 PyErr_SetString(DbmError,
173 gdbm_strerror(gdbm_errno));
174 return -1;
175 }
176 }
177 return 0;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000178}
179
Roger E. Masseb15bef81996-12-17 19:55:33 +0000180static PyMappingMethods dbm_as_mapping = {
Fred Drakee3a41c62000-07-08 05:00:07 +0000181 (inquiry)dbm_length, /*mp_length*/
182 (binaryfunc)dbm_subscript, /*mp_subscript*/
183 (objobjargproc)dbm_ass_sub, /*mp_ass_subscript*/
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000184};
185
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000186PyDoc_STRVAR(dbm_close__doc__,
187"close() -> None\n\
188Closes the database.");
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000189
Roger E. Masseb15bef81996-12-17 19:55:33 +0000190static PyObject *
Fred Drakee3a41c62000-07-08 05:00:07 +0000191dbm_close(register dbmobject *dp, PyObject *args)
Guido van Rossum807b7be1995-07-07 22:37:11 +0000192{
Fred Drakee3a41c62000-07-08 05:00:07 +0000193 if (!PyArg_ParseTuple(args, ":close"))
194 return NULL;
195 if (dp->di_dbm)
196 gdbm_close(dp->di_dbm);
197 dp->di_dbm = NULL;
198 Py_INCREF(Py_None);
199 return Py_None;
Guido van Rossum807b7be1995-07-07 22:37:11 +0000200}
201
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000202PyDoc_STRVAR(dbm_keys__doc__,
203"keys() -> list_of_keys\n\
204Get a list of all keys in the database.");
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000205
Roger E. Masseb15bef81996-12-17 19:55:33 +0000206static PyObject *
Fred Drakee3a41c62000-07-08 05:00:07 +0000207dbm_keys(register dbmobject *dp, PyObject *args)
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000208{
Fred Drakee3a41c62000-07-08 05:00:07 +0000209 register PyObject *v, *item;
210 datum key, nextkey;
211 int err;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000212
Fred Drakee3a41c62000-07-08 05:00:07 +0000213 if (dp == NULL || !is_dbmobject(dp)) {
214 PyErr_BadInternalCall();
215 return NULL;
216 }
217 if (!PyArg_ParseTuple(args, ":keys"))
218 return NULL;
Guido van Rossum3be71401996-07-21 02:32:44 +0000219
Fred Drakee3a41c62000-07-08 05:00:07 +0000220 check_dbmobject_open(dp);
Guido van Rossum3be71401996-07-21 02:32:44 +0000221
Fred Drakee3a41c62000-07-08 05:00:07 +0000222 v = PyList_New(0);
223 if (v == NULL)
224 return NULL;
Guido van Rossum77eecfa1997-07-17 22:56:01 +0000225
Fred Drakee3a41c62000-07-08 05:00:07 +0000226 key = gdbm_firstkey(dp->di_dbm);
227 while (key.dptr) {
228 item = PyString_FromStringAndSize(key.dptr, key.dsize);
229 if (item == NULL) {
230 free(key.dptr);
231 Py_DECREF(v);
232 return NULL;
233 }
234 err = PyList_Append(v, item);
235 Py_DECREF(item);
236 if (err != 0) {
237 free(key.dptr);
238 Py_DECREF(v);
239 return NULL;
240 }
241 nextkey = gdbm_nextkey(dp->di_dbm, key);
242 free(key.dptr);
243 key = nextkey;
244 }
245 return v;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000246}
247
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000248PyDoc_STRVAR(dbm_has_key__doc__,
249"has_key(key) -> boolean\n\
250Find out whether or not the database contains a given key.");
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000251
Roger E. Masseb15bef81996-12-17 19:55:33 +0000252static PyObject *
Fred Drakee3a41c62000-07-08 05:00:07 +0000253dbm_has_key(register dbmobject *dp, PyObject *args)
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000254{
Fred Drakee3a41c62000-07-08 05:00:07 +0000255 datum key;
256
257 if (!PyArg_ParseTuple(args, "s#:has_key", &key.dptr, &key.dsize))
258 return NULL;
259 check_dbmobject_open(dp);
260 return PyInt_FromLong((long) gdbm_exists(dp->di_dbm, key));
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000261}
262
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000263PyDoc_STRVAR(dbm_firstkey__doc__,
264"firstkey() -> key\n\
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000265It's possible to loop over every key in the database using this method\n\
266and the nextkey() method. The traversal is ordered by GDBM's internal\n\
267hash values, and won't be sorted by the key values. This method\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000268returns the starting key.");
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000269
Roger E. Masseb15bef81996-12-17 19:55:33 +0000270static PyObject *
Fred Drakee3a41c62000-07-08 05:00:07 +0000271dbm_firstkey(register dbmobject *dp, PyObject *args)
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000272{
Fred Drakee3a41c62000-07-08 05:00:07 +0000273 register PyObject *v;
274 datum key;
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000275
Fred Drakee3a41c62000-07-08 05:00:07 +0000276 if (!PyArg_ParseTuple(args, ":firstkey"))
277 return NULL;
278 check_dbmobject_open(dp);
279 key = gdbm_firstkey(dp->di_dbm);
280 if (key.dptr) {
281 v = PyString_FromStringAndSize(key.dptr, key.dsize);
282 free(key.dptr);
283 return v;
284 }
285 else {
286 Py_INCREF(Py_None);
287 return Py_None;
288 }
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000289}
290
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000291PyDoc_STRVAR(dbm_nextkey__doc__,
292"nextkey(key) -> next_key\n\
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000293Returns the key that follows key in the traversal.\n\
294The following code prints every key in the database db, without having\n\
295to create a list in memory that contains them all:\n\
296\n\
297 k = db.firstkey()\n\
298 while k != None:\n\
299 print k\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000300 k = db.nextkey(k)");
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000301
Roger E. Masseb15bef81996-12-17 19:55:33 +0000302static PyObject *
Fred Drakee3a41c62000-07-08 05:00:07 +0000303dbm_nextkey(register dbmobject *dp, PyObject *args)
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000304{
Fred Drakee3a41c62000-07-08 05:00:07 +0000305 register PyObject *v;
306 datum key, nextkey;
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000307
Fred Drakee3a41c62000-07-08 05:00:07 +0000308 if (!PyArg_ParseTuple(args, "s#:nextkey", &key.dptr, &key.dsize))
309 return NULL;
310 check_dbmobject_open(dp);
311 nextkey = gdbm_nextkey(dp->di_dbm, key);
312 if (nextkey.dptr) {
313 v = PyString_FromStringAndSize(nextkey.dptr, nextkey.dsize);
314 free(nextkey.dptr);
315 return v;
316 }
317 else {
318 Py_INCREF(Py_None);
319 return Py_None;
320 }
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000321}
322
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000323PyDoc_STRVAR(dbm_reorganize__doc__,
324"reorganize() -> None\n\
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000325If you have carried out a lot of deletions and would like to shrink\n\
326the space used by the GDBM file, this routine will reorganize the\n\
327database. GDBM will not shorten the length of a database file except\n\
328by using this reorganization; otherwise, deleted file space will be\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000329kept and reused as new (key,value) pairs are added.");
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000330
Roger E. Masseb15bef81996-12-17 19:55:33 +0000331static PyObject *
Fred Drakee3a41c62000-07-08 05:00:07 +0000332dbm_reorganize(register dbmobject *dp, PyObject *args)
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000333{
Fred Drakee3a41c62000-07-08 05:00:07 +0000334 if (!PyArg_ParseTuple(args, ":reorganize"))
335 return NULL;
336 check_dbmobject_open(dp);
337 errno = 0;
338 if (gdbm_reorganize(dp->di_dbm) < 0) {
339 if (errno != 0)
340 PyErr_SetFromErrno(DbmError);
341 else
342 PyErr_SetString(DbmError, gdbm_strerror(gdbm_errno));
343 return NULL;
344 }
345 Py_INCREF(Py_None);
346 return Py_None;
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000347}
348
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000349PyDoc_STRVAR(dbm_sync__doc__,
350"sync() -> None\n\
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000351When the database has been opened in fast mode, this method forces\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000352any unwritten data to be written to the disk.");
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000353
Roger E. Massee5a9c8f1997-03-25 17:39:56 +0000354static PyObject *
Fred Drakee3a41c62000-07-08 05:00:07 +0000355dbm_sync(register dbmobject *dp, PyObject *args)
Roger E. Massee5a9c8f1997-03-25 17:39:56 +0000356{
Fred Drakee3a41c62000-07-08 05:00:07 +0000357 if (!PyArg_ParseTuple(args, ":sync"))
358 return NULL;
359 check_dbmobject_open(dp);
360 gdbm_sync(dp->di_dbm);
361 Py_INCREF(Py_None);
362 return Py_None;
Roger E. Massee5a9c8f1997-03-25 17:39:56 +0000363}
364
Roger E. Masseb15bef81996-12-17 19:55:33 +0000365static PyMethodDef dbm_methods[] = {
Fred Drakee3a41c62000-07-08 05:00:07 +0000366 {"close", (PyCFunction)dbm_close, METH_VARARGS, dbm_close__doc__},
367 {"keys", (PyCFunction)dbm_keys, METH_VARARGS, dbm_keys__doc__},
368 {"has_key", (PyCFunction)dbm_has_key, METH_VARARGS, dbm_has_key__doc__},
369 {"firstkey", (PyCFunction)dbm_firstkey,METH_VARARGS, dbm_firstkey__doc__},
370 {"nextkey", (PyCFunction)dbm_nextkey, METH_VARARGS, dbm_nextkey__doc__},
371 {"reorganize",(PyCFunction)dbm_reorganize,METH_VARARGS, dbm_reorganize__doc__},
372 {"sync", (PyCFunction)dbm_sync, METH_VARARGS, dbm_sync__doc__},
373 {NULL, NULL} /* sentinel */
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000374};
375
Roger E. Masseb15bef81996-12-17 19:55:33 +0000376static PyObject *
Fred Drakee3a41c62000-07-08 05:00:07 +0000377dbm_getattr(dbmobject *dp, char *name)
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000378{
Fred Drakee3a41c62000-07-08 05:00:07 +0000379 return Py_FindMethod(dbm_methods, (PyObject *)dp, name);
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000380}
381
Roger E. Masseb15bef81996-12-17 19:55:33 +0000382static PyTypeObject Dbmtype = {
Fred Drakee3a41c62000-07-08 05:00:07 +0000383 PyObject_HEAD_INIT(0)
384 0,
Guido van Rossum14648392001-12-08 18:02:58 +0000385 "gdbm.gdbm",
Fred Drakee3a41c62000-07-08 05:00:07 +0000386 sizeof(dbmobject),
387 0,
388 (destructor)dbm_dealloc, /*tp_dealloc*/
389 0, /*tp_print*/
390 (getattrfunc)dbm_getattr, /*tp_getattr*/
391 0, /*tp_setattr*/
392 0, /*tp_compare*/
393 0, /*tp_repr*/
394 0, /*tp_as_number*/
395 0, /*tp_as_sequence*/
396 &dbm_as_mapping, /*tp_as_mapping*/
397 0, /*tp_hash*/
398 0, /*tp_call*/
399 0, /*tp_str*/
400 0, /*tp_getattro*/
401 0, /*tp_setattro*/
402 0, /*tp_as_buffer*/
403 0, /*tp_xxx4*/
404 gdbm_object__doc__, /*tp_doc*/
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000405};
406
407/* ----------------------------------------------------------------- */
408
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000409PyDoc_STRVAR(dbmopen__doc__,
410"open(filename, [flags, [mode]]) -> dbm_object\n\
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000411Open a dbm database and return a dbm object. The filename argument is\n\
412the name of the database file.\n\
413\n\
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000414The optional flags argument can be 'r' (to open an existing database\n\
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000415for reading only -- default), 'w' (to open an existing database for\n\
416reading and writing), 'c' (which creates the database if it doesn't\n\
417exist), or 'n' (which always creates a new empty database).\n\
418\n\
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000419Some versions of gdbm support additional flags which must be\n\
420appended to one of the flags described above. The module constant\n\
421'open_flags' is a string of valid additional flags. The 'f' flag\n\
422opens the database in fast mode; altered data will not automatically\n\
423be written to the disk after every change. This results in faster\n\
424writes to the database, but may result in an inconsistent database\n\
425if the program crashes while the database is still open. Use the\n\
426sync() method to force any unwritten data to be written to the disk.\n\
427The 's' flag causes all database operations to be synchronized to\n\
428disk. The 'u' flag disables locking of the database file.\n\
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000429\n\
430The optional mode argument is the Unix mode of the file, used only\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000431when the database has to be created. It defaults to octal 0666. ");
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000432
Roger E. Masseb15bef81996-12-17 19:55:33 +0000433static PyObject *
Fred Drakee3a41c62000-07-08 05:00:07 +0000434dbmopen(PyObject *self, PyObject *args)
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000435{
Fred Drakee3a41c62000-07-08 05:00:07 +0000436 char *name;
437 char *flags = "r ";
438 int iflags;
439 int mode = 0666;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000440
Fred Drakee3a41c62000-07-08 05:00:07 +0000441 if (!PyArg_ParseTuple(args, "s|si:open", &name, &flags, &mode))
442 return NULL;
443 switch (flags[0]) {
444 case 'r':
445 iflags = GDBM_READER;
446 break;
447 case 'w':
448 iflags = GDBM_WRITER;
449 break;
450 case 'c':
451 iflags = GDBM_WRCREAT;
452 break;
453 case 'n':
454 iflags = GDBM_NEWDB;
455 break;
456 default:
457 PyErr_SetString(DbmError,
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000458 "First flag must be one of 'r', 'w', 'c' or 'n'");
Fred Drakee3a41c62000-07-08 05:00:07 +0000459 return NULL;
460 }
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000461 for (flags++; *flags != '\0'; flags++) {
462 char buf[40];
463 switch (*flags) {
464#ifdef GDBM_FAST
465 case 'f':
466 iflags |= GDBM_FAST;
467 break;
468#endif
469#ifdef GDBM_SYNC
470 case 's':
471 iflags |= GDBM_SYNC;
472 break;
473#endif
474#ifdef GDBM_NOLOCK
475 case 'u':
476 iflags |= GDBM_NOLOCK;
477 break;
478#endif
479 default:
Tim Peters885d4572001-11-28 20:27:42 +0000480 PyOS_snprintf(buf, sizeof(buf), "Flag '%c' is not supported.",
481 *flags);
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000482 PyErr_SetString(DbmError, buf);
483 return NULL;
484 }
485 }
486
Fred Drakee3a41c62000-07-08 05:00:07 +0000487 return newdbmobject(name, iflags, mode);
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000488}
489
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000490static char dbmmodule_open_flags[] = "rwcn"
491#ifdef GDBM_FAST
492 "f"
493#endif
494#ifdef GDBM_SYNC
495 "s"
496#endif
497#ifdef GDBM_NOLOCK
498 "u"
499#endif
500 ;
501
Roger E. Masseb15bef81996-12-17 19:55:33 +0000502static PyMethodDef dbmmodule_methods[] = {
Fred Drakee3a41c62000-07-08 05:00:07 +0000503 { "open", (PyCFunction)dbmopen, METH_VARARGS, dbmopen__doc__},
504 { 0, 0 },
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000505};
506
Mark Hammondfe51c6d2002-08-02 02:27:13 +0000507PyMODINIT_FUNC
Thomas Wouters58d05102000-07-24 14:43:35 +0000508initgdbm(void) {
Martin v. Löwis00ff10c2001-11-11 14:24:05 +0000509 PyObject *m, *d, *s;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000510
Fred Drakee3a41c62000-07-08 05:00:07 +0000511 Dbmtype.ob_type = &PyType_Type;
512 m = Py_InitModule4("gdbm", dbmmodule_methods,
513 gdbmmodule__doc__, (PyObject *)NULL,
514 PYTHON_API_VERSION);
515 d = PyModule_GetDict(m);
516 DbmError = PyErr_NewException("gdbm.error", NULL, NULL);
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000517 if (DbmError != NULL) {
Fred Drakee3a41c62000-07-08 05:00:07 +0000518 PyDict_SetItemString(d, "error", DbmError);
Martin v. Löwis00ff10c2001-11-11 14:24:05 +0000519 s = PyString_FromString(dbmmodule_open_flags);
520 PyDict_SetItemString(d, "open_flags", s);
521 Py_DECREF(s);
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000522 }
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000523}