blob: 0ffb4b4f16919d22bc0d60dfb1816df7819e3d97 [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
Guido van Rossum0da7e032006-08-19 23:18:48 +0000244static int
245dbm_contains(PyObject *self, PyObject *arg)
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000246{
Guido van Rossum0da7e032006-08-19 23:18:48 +0000247 dbmobject *dp = (dbmobject *)self;
Fred Drakee3a41c62000-07-08 05:00:07 +0000248 datum key;
249
Guido van Rossum0da7e032006-08-19 23:18:48 +0000250 if ((dp)->di_dbm == NULL) {
251 PyErr_SetString(DbmError,
252 "GDBM object has already been closed");
253 return -1;
254 }
255 if (!PyString_Check(arg)) {
256 PyErr_Format(PyExc_TypeError,
257 "gdbm key must be string, not %.100s",
258 arg->ob_type->tp_name);
259 return -1;
260 }
261 key.dptr = PyString_AS_STRING(arg);
262 key.dsize = PyString_GET_SIZE(arg);
263 return gdbm_exists(dp->di_dbm, key);
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000264}
265
Guido van Rossum0da7e032006-08-19 23:18:48 +0000266static PySequenceMethods dbm_as_sequence = {
267 0, /* sq_length */
268 0, /* sq_concat */
269 0, /* sq_repeat */
270 0, /* sq_item */
271 0, /* sq_slice */
272 0, /* sq_ass_item */
273 0, /* sq_ass_slice */
274 dbm_contains, /* sq_contains */
275 0, /* sq_inplace_concat */
276 0, /* sq_inplace_repeat */
277};
278
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000279PyDoc_STRVAR(dbm_firstkey__doc__,
280"firstkey() -> key\n\
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000281It's possible to loop over every key in the database using this method\n\
282and the nextkey() method. The traversal is ordered by GDBM's internal\n\
283hash values, and won't be sorted by the key values. This method\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000284returns the starting key.");
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000285
Roger E. Masseb15bef81996-12-17 19:55:33 +0000286static PyObject *
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000287dbm_firstkey(register dbmobject *dp, PyObject *unused)
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000288{
Fred Drakee3a41c62000-07-08 05:00:07 +0000289 register PyObject *v;
290 datum key;
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000291
Fred Drakee3a41c62000-07-08 05:00:07 +0000292 check_dbmobject_open(dp);
293 key = gdbm_firstkey(dp->di_dbm);
294 if (key.dptr) {
295 v = PyString_FromStringAndSize(key.dptr, key.dsize);
296 free(key.dptr);
297 return v;
298 }
299 else {
300 Py_INCREF(Py_None);
301 return Py_None;
302 }
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000303}
304
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000305PyDoc_STRVAR(dbm_nextkey__doc__,
306"nextkey(key) -> next_key\n\
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000307Returns the key that follows key in the traversal.\n\
308The following code prints every key in the database db, without having\n\
309to create a list in memory that contains them all:\n\
310\n\
311 k = db.firstkey()\n\
312 while k != None:\n\
313 print k\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000314 k = db.nextkey(k)");
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000315
Roger E. Masseb15bef81996-12-17 19:55:33 +0000316static PyObject *
Fred Drakee3a41c62000-07-08 05:00:07 +0000317dbm_nextkey(register dbmobject *dp, PyObject *args)
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000318{
Fred Drakee3a41c62000-07-08 05:00:07 +0000319 register PyObject *v;
320 datum key, nextkey;
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000321
Fred Drakee3a41c62000-07-08 05:00:07 +0000322 if (!PyArg_ParseTuple(args, "s#:nextkey", &key.dptr, &key.dsize))
323 return NULL;
324 check_dbmobject_open(dp);
325 nextkey = gdbm_nextkey(dp->di_dbm, key);
326 if (nextkey.dptr) {
327 v = PyString_FromStringAndSize(nextkey.dptr, nextkey.dsize);
328 free(nextkey.dptr);
329 return v;
330 }
331 else {
332 Py_INCREF(Py_None);
333 return Py_None;
334 }
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000335}
336
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000337PyDoc_STRVAR(dbm_reorganize__doc__,
338"reorganize() -> None\n\
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000339If you have carried out a lot of deletions and would like to shrink\n\
340the space used by the GDBM file, this routine will reorganize the\n\
341database. GDBM will not shorten the length of a database file except\n\
342by using this reorganization; otherwise, deleted file space will be\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000343kept and reused as new (key,value) pairs are added.");
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000344
Roger E. Masseb15bef81996-12-17 19:55:33 +0000345static PyObject *
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000346dbm_reorganize(register dbmobject *dp, PyObject *unused)
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000347{
Fred Drakee3a41c62000-07-08 05:00:07 +0000348 check_dbmobject_open(dp);
349 errno = 0;
350 if (gdbm_reorganize(dp->di_dbm) < 0) {
351 if (errno != 0)
352 PyErr_SetFromErrno(DbmError);
353 else
354 PyErr_SetString(DbmError, gdbm_strerror(gdbm_errno));
355 return NULL;
356 }
357 Py_INCREF(Py_None);
358 return Py_None;
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000359}
360
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000361PyDoc_STRVAR(dbm_sync__doc__,
362"sync() -> None\n\
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000363When the database has been opened in fast mode, this method forces\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000364any unwritten data to be written to the disk.");
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000365
Roger E. Massee5a9c8f1997-03-25 17:39:56 +0000366static PyObject *
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000367dbm_sync(register dbmobject *dp, PyObject *unused)
Roger E. Massee5a9c8f1997-03-25 17:39:56 +0000368{
Fred Drakee3a41c62000-07-08 05:00:07 +0000369 check_dbmobject_open(dp);
370 gdbm_sync(dp->di_dbm);
371 Py_INCREF(Py_None);
372 return Py_None;
Roger E. Massee5a9c8f1997-03-25 17:39:56 +0000373}
374
Roger E. Masseb15bef81996-12-17 19:55:33 +0000375static PyMethodDef dbm_methods[] = {
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000376 {"close", (PyCFunction)dbm_close, METH_NOARGS, dbm_close__doc__},
377 {"keys", (PyCFunction)dbm_keys, METH_NOARGS, dbm_keys__doc__},
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000378 {"firstkey", (PyCFunction)dbm_firstkey,METH_NOARGS, dbm_firstkey__doc__},
Fred Drakee3a41c62000-07-08 05:00:07 +0000379 {"nextkey", (PyCFunction)dbm_nextkey, METH_VARARGS, dbm_nextkey__doc__},
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000380 {"reorganize",(PyCFunction)dbm_reorganize,METH_NOARGS, dbm_reorganize__doc__},
381 {"sync", (PyCFunction)dbm_sync, METH_NOARGS, dbm_sync__doc__},
Fred Drakee3a41c62000-07-08 05:00:07 +0000382 {NULL, NULL} /* sentinel */
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000383};
384
Roger E. Masseb15bef81996-12-17 19:55:33 +0000385static PyObject *
Fred Drakee3a41c62000-07-08 05:00:07 +0000386dbm_getattr(dbmobject *dp, char *name)
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000387{
Fred Drakee3a41c62000-07-08 05:00:07 +0000388 return Py_FindMethod(dbm_methods, (PyObject *)dp, name);
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000389}
390
Roger E. Masseb15bef81996-12-17 19:55:33 +0000391static PyTypeObject Dbmtype = {
Fred Drakee3a41c62000-07-08 05:00:07 +0000392 PyObject_HEAD_INIT(0)
393 0,
Guido van Rossum14648392001-12-08 18:02:58 +0000394 "gdbm.gdbm",
Fred Drakee3a41c62000-07-08 05:00:07 +0000395 sizeof(dbmobject),
396 0,
397 (destructor)dbm_dealloc, /*tp_dealloc*/
398 0, /*tp_print*/
399 (getattrfunc)dbm_getattr, /*tp_getattr*/
400 0, /*tp_setattr*/
401 0, /*tp_compare*/
402 0, /*tp_repr*/
403 0, /*tp_as_number*/
Guido van Rossum0da7e032006-08-19 23:18:48 +0000404 &dbm_as_sequence, /*tp_as_sequence*/
Fred Drakee3a41c62000-07-08 05:00:07 +0000405 &dbm_as_mapping, /*tp_as_mapping*/
406 0, /*tp_hash*/
407 0, /*tp_call*/
408 0, /*tp_str*/
409 0, /*tp_getattro*/
410 0, /*tp_setattro*/
411 0, /*tp_as_buffer*/
412 0, /*tp_xxx4*/
413 gdbm_object__doc__, /*tp_doc*/
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000414};
415
416/* ----------------------------------------------------------------- */
417
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000418PyDoc_STRVAR(dbmopen__doc__,
419"open(filename, [flags, [mode]]) -> dbm_object\n\
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000420Open a dbm database and return a dbm object. The filename argument is\n\
421the name of the database file.\n\
422\n\
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000423The optional flags argument can be 'r' (to open an existing database\n\
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000424for reading only -- default), 'w' (to open an existing database for\n\
425reading and writing), 'c' (which creates the database if it doesn't\n\
426exist), or 'n' (which always creates a new empty database).\n\
427\n\
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000428Some versions of gdbm support additional flags which must be\n\
429appended to one of the flags described above. The module constant\n\
430'open_flags' is a string of valid additional flags. The 'f' flag\n\
431opens the database in fast mode; altered data will not automatically\n\
432be written to the disk after every change. This results in faster\n\
433writes to the database, but may result in an inconsistent database\n\
434if the program crashes while the database is still open. Use the\n\
435sync() method to force any unwritten data to be written to the disk.\n\
436The 's' flag causes all database operations to be synchronized to\n\
437disk. The 'u' flag disables locking of the database file.\n\
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000438\n\
439The optional mode argument is the Unix mode of the file, used only\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000440when the database has to be created. It defaults to octal 0666. ");
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000441
Roger E. Masseb15bef81996-12-17 19:55:33 +0000442static PyObject *
Fred Drakee3a41c62000-07-08 05:00:07 +0000443dbmopen(PyObject *self, PyObject *args)
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000444{
Fred Drakee3a41c62000-07-08 05:00:07 +0000445 char *name;
Andrew M. Kuchlingea271f22004-07-07 14:19:09 +0000446 char *flags = "r";
Fred Drakee3a41c62000-07-08 05:00:07 +0000447 int iflags;
448 int mode = 0666;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000449
Fred Drakee3a41c62000-07-08 05:00:07 +0000450 if (!PyArg_ParseTuple(args, "s|si:open", &name, &flags, &mode))
451 return NULL;
452 switch (flags[0]) {
453 case 'r':
454 iflags = GDBM_READER;
455 break;
456 case 'w':
457 iflags = GDBM_WRITER;
458 break;
459 case 'c':
460 iflags = GDBM_WRCREAT;
461 break;
462 case 'n':
463 iflags = GDBM_NEWDB;
464 break;
465 default:
466 PyErr_SetString(DbmError,
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000467 "First flag must be one of 'r', 'w', 'c' or 'n'");
Fred Drakee3a41c62000-07-08 05:00:07 +0000468 return NULL;
469 }
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000470 for (flags++; *flags != '\0'; flags++) {
471 char buf[40];
472 switch (*flags) {
473#ifdef GDBM_FAST
474 case 'f':
475 iflags |= GDBM_FAST;
476 break;
477#endif
478#ifdef GDBM_SYNC
479 case 's':
480 iflags |= GDBM_SYNC;
481 break;
482#endif
483#ifdef GDBM_NOLOCK
484 case 'u':
485 iflags |= GDBM_NOLOCK;
486 break;
487#endif
488 default:
Tim Peters885d4572001-11-28 20:27:42 +0000489 PyOS_snprintf(buf, sizeof(buf), "Flag '%c' is not supported.",
490 *flags);
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000491 PyErr_SetString(DbmError, buf);
492 return NULL;
493 }
494 }
495
Fred Drakee3a41c62000-07-08 05:00:07 +0000496 return newdbmobject(name, iflags, mode);
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000497}
498
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000499static char dbmmodule_open_flags[] = "rwcn"
500#ifdef GDBM_FAST
501 "f"
502#endif
503#ifdef GDBM_SYNC
504 "s"
505#endif
506#ifdef GDBM_NOLOCK
507 "u"
508#endif
509 ;
510
Roger E. Masseb15bef81996-12-17 19:55:33 +0000511static PyMethodDef dbmmodule_methods[] = {
Fred Drakee3a41c62000-07-08 05:00:07 +0000512 { "open", (PyCFunction)dbmopen, METH_VARARGS, dbmopen__doc__},
513 { 0, 0 },
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000514};
515
Mark Hammondfe51c6d2002-08-02 02:27:13 +0000516PyMODINIT_FUNC
Thomas Wouters58d05102000-07-24 14:43:35 +0000517initgdbm(void) {
Martin v. Löwis00ff10c2001-11-11 14:24:05 +0000518 PyObject *m, *d, *s;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000519
Guido van Rossum0da7e032006-08-19 23:18:48 +0000520 if (PyType_Ready(&Dbmtype) < 0)
521 return;
Fred Drakee3a41c62000-07-08 05:00:07 +0000522 m = Py_InitModule4("gdbm", dbmmodule_methods,
523 gdbmmodule__doc__, (PyObject *)NULL,
524 PYTHON_API_VERSION);
Neal Norwitz1ac754f2006-01-19 06:09:39 +0000525 if (m == NULL)
526 return;
Fred Drakee3a41c62000-07-08 05:00:07 +0000527 d = PyModule_GetDict(m);
528 DbmError = PyErr_NewException("gdbm.error", NULL, NULL);
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000529 if (DbmError != NULL) {
Fred Drakee3a41c62000-07-08 05:00:07 +0000530 PyDict_SetItemString(d, "error", DbmError);
Martin v. Löwis00ff10c2001-11-11 14:24:05 +0000531 s = PyString_FromString(dbmmodule_open_flags);
532 PyDict_SetItemString(d, "open_flags", s);
533 Py_DECREF(s);
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000534 }
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000535}