blob: abc88370911e7ece85eced0c2294f425b3d6a4e7 [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 Heimes90aa7642007-12-19 02:45:37 +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) {
Guido van Rossum6252e102007-05-23 20:51:02 +000093 PyErr_SetString(DbmError, "GDBM object has already been closed");
94 return -1;
Fred Drakee3a41c62000-07-08 05:00:07 +000095 }
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) {
Guido van Rossum6252e102007-05-23 20:51:02 +0000130 PyErr_SetObject(PyExc_KeyError, key);
Fred Drakee3a41c62000-07-08 05:00:07 +0000131 return NULL;
132 }
Christian Heimes72b710a2008-05-26 13:28:38 +0000133 v = PyBytes_FromStringAndSize(drec.dptr, drec.dsize);
Fred Drakee3a41c62000-07-08 05:00:07 +0000134 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,
Guido van Rossum6252e102007-05-23 20:51:02 +0000150 "GDBM object has already been closed");
151 return -1;
Fred Drakee3a41c62000-07-08 05:00:07 +0000152 }
153 dp->di_size = -1;
154 if (w == NULL) {
155 if (gdbm_delete(dp->di_dbm, krec) < 0) {
Guido van Rossum6252e102007-05-23 20:51:02 +0000156 PyErr_SetObject(PyExc_KeyError, v);
Fred Drakee3a41c62000-07-08 05:00:07 +0000157 return -1;
Guido van Rossum77eecfa1997-07-17 22:56:01 +0000158 }
Fred Drakee3a41c62000-07-08 05:00:07 +0000159 }
160 else {
161 if (!PyArg_Parse(w, "s#", &drec.dptr, &drec.dsize)) {
162 PyErr_SetString(PyExc_TypeError,
Guido van Rossum6252e102007-05-23 20:51:02 +0000163 "gdbm mappings have byte string elements only");
Fred Drakee3a41c62000-07-08 05:00:07 +0000164 return -1;
165 }
166 errno = 0;
167 if (gdbm_store(dp->di_dbm, krec, drec, GDBM_REPLACE) < 0) {
168 if (errno != 0)
169 PyErr_SetFromErrno(DbmError);
170 else
171 PyErr_SetString(DbmError,
172 gdbm_strerror(gdbm_errno));
173 return -1;
174 }
175 }
176 return 0;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000177}
178
Roger E. Masseb15bef81996-12-17 19:55:33 +0000179static PyMappingMethods dbm_as_mapping = {
Martin v. Löwis18e16552006-02-15 17:27:45 +0000180 (lenfunc)dbm_length, /*mp_length*/
Fred Drakee3a41c62000-07-08 05:00:07 +0000181 (binaryfunc)dbm_subscript, /*mp_subscript*/
182 (objobjargproc)dbm_ass_sub, /*mp_ass_subscript*/
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000183};
184
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000185PyDoc_STRVAR(dbm_close__doc__,
186"close() -> None\n\
187Closes the database.");
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000188
Roger E. Masseb15bef81996-12-17 19:55:33 +0000189static PyObject *
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000190dbm_close(register dbmobject *dp, PyObject *unused)
Guido van Rossum807b7be1995-07-07 22:37:11 +0000191{
Fred Drakee3a41c62000-07-08 05:00:07 +0000192 if (dp->di_dbm)
193 gdbm_close(dp->di_dbm);
194 dp->di_dbm = NULL;
195 Py_INCREF(Py_None);
196 return Py_None;
Guido van Rossum807b7be1995-07-07 22:37:11 +0000197}
198
Guido van Rossum6252e102007-05-23 20:51:02 +0000199/* XXX Should return a set or a set view */
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000200PyDoc_STRVAR(dbm_keys__doc__,
201"keys() -> list_of_keys\n\
202Get a list of all keys in the database.");
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000203
Roger E. Masseb15bef81996-12-17 19:55:33 +0000204static PyObject *
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000205dbm_keys(register dbmobject *dp, PyObject *unused)
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000206{
Fred Drakee3a41c62000-07-08 05:00:07 +0000207 register PyObject *v, *item;
208 datum key, nextkey;
209 int err;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000210
Fred Drakee3a41c62000-07-08 05:00:07 +0000211 if (dp == NULL || !is_dbmobject(dp)) {
212 PyErr_BadInternalCall();
213 return NULL;
214 }
Fred Drakee3a41c62000-07-08 05:00:07 +0000215 check_dbmobject_open(dp);
Guido van Rossum3be71401996-07-21 02:32:44 +0000216
Fred Drakee3a41c62000-07-08 05:00:07 +0000217 v = PyList_New(0);
218 if (v == NULL)
219 return NULL;
Guido van Rossum77eecfa1997-07-17 22:56:01 +0000220
Fred Drakee3a41c62000-07-08 05:00:07 +0000221 key = gdbm_firstkey(dp->di_dbm);
222 while (key.dptr) {
Christian Heimes72b710a2008-05-26 13:28:38 +0000223 item = PyBytes_FromStringAndSize(key.dptr, key.dsize);
Fred Drakee3a41c62000-07-08 05:00:07 +0000224 if (item == NULL) {
225 free(key.dptr);
226 Py_DECREF(v);
227 return NULL;
228 }
229 err = PyList_Append(v, item);
230 Py_DECREF(item);
231 if (err != 0) {
232 free(key.dptr);
233 Py_DECREF(v);
234 return NULL;
235 }
236 nextkey = gdbm_nextkey(dp->di_dbm, key);
237 free(key.dptr);
238 key = nextkey;
239 }
240 return v;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000241}
242
Guido van Rossum0da7e032006-08-19 23:18:48 +0000243static int
244dbm_contains(PyObject *self, PyObject *arg)
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000245{
Guido van Rossum0da7e032006-08-19 23:18:48 +0000246 dbmobject *dp = (dbmobject *)self;
Fred Drakee3a41c62000-07-08 05:00:07 +0000247 datum key;
248
Guido van Rossum0da7e032006-08-19 23:18:48 +0000249 if ((dp)->di_dbm == NULL) {
250 PyErr_SetString(DbmError,
251 "GDBM object has already been closed");
252 return -1;
253 }
Christian Heimes72b710a2008-05-26 13:28:38 +0000254 if (!PyBytes_Check(arg)) {
Guido van Rossum0da7e032006-08-19 23:18:48 +0000255 PyErr_Format(PyExc_TypeError,
Martin v. Löwis7ac97122007-08-11 19:28:53 +0000256 "gdbm key must be bytes, not %.100s",
Guido van Rossum0da7e032006-08-19 23:18:48 +0000257 arg->ob_type->tp_name);
258 return -1;
259 }
Christian Heimes72b710a2008-05-26 13:28:38 +0000260 key.dptr = PyBytes_AS_STRING(arg);
261 key.dsize = PyBytes_GET_SIZE(arg);
Guido van Rossum0da7e032006-08-19 23:18:48 +0000262 return gdbm_exists(dp->di_dbm, key);
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000263}
264
Guido van Rossum0da7e032006-08-19 23:18:48 +0000265static PySequenceMethods dbm_as_sequence = {
266 0, /* sq_length */
267 0, /* sq_concat */
268 0, /* sq_repeat */
269 0, /* sq_item */
270 0, /* sq_slice */
271 0, /* sq_ass_item */
272 0, /* sq_ass_slice */
273 dbm_contains, /* sq_contains */
274 0, /* sq_inplace_concat */
275 0, /* sq_inplace_repeat */
276};
277
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000278PyDoc_STRVAR(dbm_firstkey__doc__,
279"firstkey() -> key\n\
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000280It's possible to loop over every key in the database using this method\n\
281and the nextkey() method. The traversal is ordered by GDBM's internal\n\
282hash values, and won't be sorted by the key values. This method\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000283returns the starting key.");
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000284
Roger E. Masseb15bef81996-12-17 19:55:33 +0000285static PyObject *
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000286dbm_firstkey(register dbmobject *dp, PyObject *unused)
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000287{
Fred Drakee3a41c62000-07-08 05:00:07 +0000288 register PyObject *v;
289 datum key;
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000290
Fred Drakee3a41c62000-07-08 05:00:07 +0000291 check_dbmobject_open(dp);
292 key = gdbm_firstkey(dp->di_dbm);
293 if (key.dptr) {
Christian Heimes72b710a2008-05-26 13:28:38 +0000294 v = PyBytes_FromStringAndSize(key.dptr, key.dsize);
Fred Drakee3a41c62000-07-08 05:00:07 +0000295 free(key.dptr);
296 return v;
297 }
298 else {
299 Py_INCREF(Py_None);
300 return Py_None;
301 }
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000302}
303
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000304PyDoc_STRVAR(dbm_nextkey__doc__,
305"nextkey(key) -> next_key\n\
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000306Returns the key that follows key in the traversal.\n\
307The following code prints every key in the database db, without having\n\
308to create a list in memory that contains them all:\n\
309\n\
310 k = db.firstkey()\n\
311 while k != None:\n\
312 print k\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000313 k = db.nextkey(k)");
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000314
Roger E. Masseb15bef81996-12-17 19:55:33 +0000315static PyObject *
Fred Drakee3a41c62000-07-08 05:00:07 +0000316dbm_nextkey(register dbmobject *dp, PyObject *args)
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000317{
Fred Drakee3a41c62000-07-08 05:00:07 +0000318 register PyObject *v;
319 datum key, nextkey;
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000320
Fred Drakee3a41c62000-07-08 05:00:07 +0000321 if (!PyArg_ParseTuple(args, "s#:nextkey", &key.dptr, &key.dsize))
322 return NULL;
323 check_dbmobject_open(dp);
324 nextkey = gdbm_nextkey(dp->di_dbm, key);
325 if (nextkey.dptr) {
Christian Heimes72b710a2008-05-26 13:28:38 +0000326 v = PyBytes_FromStringAndSize(nextkey.dptr, nextkey.dsize);
Fred Drakee3a41c62000-07-08 05:00:07 +0000327 free(nextkey.dptr);
328 return v;
329 }
330 else {
331 Py_INCREF(Py_None);
332 return Py_None;
333 }
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000334}
335
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000336PyDoc_STRVAR(dbm_reorganize__doc__,
337"reorganize() -> None\n\
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000338If you have carried out a lot of deletions and would like to shrink\n\
339the space used by the GDBM file, this routine will reorganize the\n\
340database. GDBM will not shorten the length of a database file except\n\
341by using this reorganization; otherwise, deleted file space will be\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000342kept and reused as new (key,value) pairs are added.");
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000343
Roger E. Masseb15bef81996-12-17 19:55:33 +0000344static PyObject *
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000345dbm_reorganize(register dbmobject *dp, PyObject *unused)
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000346{
Fred Drakee3a41c62000-07-08 05:00:07 +0000347 check_dbmobject_open(dp);
348 errno = 0;
349 if (gdbm_reorganize(dp->di_dbm) < 0) {
350 if (errno != 0)
351 PyErr_SetFromErrno(DbmError);
352 else
353 PyErr_SetString(DbmError, gdbm_strerror(gdbm_errno));
354 return NULL;
355 }
356 Py_INCREF(Py_None);
357 return Py_None;
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000358}
359
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000360PyDoc_STRVAR(dbm_sync__doc__,
361"sync() -> None\n\
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000362When the database has been opened in fast mode, this method forces\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000363any unwritten data to be written to the disk.");
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000364
Roger E. Massee5a9c8f1997-03-25 17:39:56 +0000365static PyObject *
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000366dbm_sync(register dbmobject *dp, PyObject *unused)
Roger E. Massee5a9c8f1997-03-25 17:39:56 +0000367{
Fred Drakee3a41c62000-07-08 05:00:07 +0000368 check_dbmobject_open(dp);
369 gdbm_sync(dp->di_dbm);
370 Py_INCREF(Py_None);
371 return Py_None;
Roger E. Massee5a9c8f1997-03-25 17:39:56 +0000372}
373
Roger E. Masseb15bef81996-12-17 19:55:33 +0000374static PyMethodDef dbm_methods[] = {
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000375 {"close", (PyCFunction)dbm_close, METH_NOARGS, dbm_close__doc__},
376 {"keys", (PyCFunction)dbm_keys, METH_NOARGS, dbm_keys__doc__},
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000377 {"firstkey", (PyCFunction)dbm_firstkey,METH_NOARGS, dbm_firstkey__doc__},
Fred Drakee3a41c62000-07-08 05:00:07 +0000378 {"nextkey", (PyCFunction)dbm_nextkey, METH_VARARGS, dbm_nextkey__doc__},
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000379 {"reorganize",(PyCFunction)dbm_reorganize,METH_NOARGS, dbm_reorganize__doc__},
380 {"sync", (PyCFunction)dbm_sync, METH_NOARGS, dbm_sync__doc__},
Fred Drakee3a41c62000-07-08 05:00:07 +0000381 {NULL, NULL} /* sentinel */
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000382};
383
Roger E. Masseb15bef81996-12-17 19:55:33 +0000384static PyObject *
Fred Drakee3a41c62000-07-08 05:00:07 +0000385dbm_getattr(dbmobject *dp, char *name)
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000386{
Fred Drakee3a41c62000-07-08 05:00:07 +0000387 return Py_FindMethod(dbm_methods, (PyObject *)dp, name);
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000388}
389
Roger E. Masseb15bef81996-12-17 19:55:33 +0000390static PyTypeObject Dbmtype = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +0000391 PyVarObject_HEAD_INIT(0, 0)
Georg Brandl0a7ac7d2008-05-26 10:29:35 +0000392 "_gdbm.gdbm",
Fred Drakee3a41c62000-07-08 05:00:07 +0000393 sizeof(dbmobject),
394 0,
395 (destructor)dbm_dealloc, /*tp_dealloc*/
396 0, /*tp_print*/
397 (getattrfunc)dbm_getattr, /*tp_getattr*/
398 0, /*tp_setattr*/
399 0, /*tp_compare*/
400 0, /*tp_repr*/
401 0, /*tp_as_number*/
Guido van Rossum0da7e032006-08-19 23:18:48 +0000402 &dbm_as_sequence, /*tp_as_sequence*/
Fred Drakee3a41c62000-07-08 05:00:07 +0000403 &dbm_as_mapping, /*tp_as_mapping*/
404 0, /*tp_hash*/
405 0, /*tp_call*/
406 0, /*tp_str*/
407 0, /*tp_getattro*/
408 0, /*tp_setattro*/
409 0, /*tp_as_buffer*/
Christian Heimes836baa52008-02-26 08:18:30 +0000410 Py_TPFLAGS_DEFAULT, /*tp_xxx4*/
Fred Drakee3a41c62000-07-08 05:00:07 +0000411 gdbm_object__doc__, /*tp_doc*/
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000412};
413
414/* ----------------------------------------------------------------- */
415
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000416PyDoc_STRVAR(dbmopen__doc__,
417"open(filename, [flags, [mode]]) -> dbm_object\n\
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000418Open a dbm database and return a dbm object. The filename argument is\n\
419the name of the database file.\n\
420\n\
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000421The optional flags argument can be 'r' (to open an existing database\n\
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000422for reading only -- default), 'w' (to open an existing database for\n\
423reading and writing), 'c' (which creates the database if it doesn't\n\
424exist), or 'n' (which always creates a new empty database).\n\
425\n\
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000426Some versions of gdbm support additional flags which must be\n\
427appended to one of the flags described above. The module constant\n\
428'open_flags' is a string of valid additional flags. The 'f' flag\n\
429opens the database in fast mode; altered data will not automatically\n\
430be written to the disk after every change. This results in faster\n\
431writes to the database, but may result in an inconsistent database\n\
432if the program crashes while the database is still open. Use the\n\
433sync() method to force any unwritten data to be written to the disk.\n\
434The 's' flag causes all database operations to be synchronized to\n\
435disk. The 'u' flag disables locking of the database file.\n\
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000436\n\
437The optional mode argument is the Unix mode of the file, used only\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000438when the database has to be created. It defaults to octal 0666. ");
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000439
Roger E. Masseb15bef81996-12-17 19:55:33 +0000440static PyObject *
Fred Drakee3a41c62000-07-08 05:00:07 +0000441dbmopen(PyObject *self, PyObject *args)
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000442{
Fred Drakee3a41c62000-07-08 05:00:07 +0000443 char *name;
Andrew M. Kuchlingea271f22004-07-07 14:19:09 +0000444 char *flags = "r";
Fred Drakee3a41c62000-07-08 05:00:07 +0000445 int iflags;
446 int mode = 0666;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000447
Fred Drakee3a41c62000-07-08 05:00:07 +0000448 if (!PyArg_ParseTuple(args, "s|si:open", &name, &flags, &mode))
449 return NULL;
450 switch (flags[0]) {
451 case 'r':
452 iflags = GDBM_READER;
453 break;
454 case 'w':
455 iflags = GDBM_WRITER;
456 break;
457 case 'c':
458 iflags = GDBM_WRCREAT;
459 break;
460 case 'n':
461 iflags = GDBM_NEWDB;
462 break;
463 default:
464 PyErr_SetString(DbmError,
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000465 "First flag must be one of 'r', 'w', 'c' or 'n'");
Fred Drakee3a41c62000-07-08 05:00:07 +0000466 return NULL;
467 }
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000468 for (flags++; *flags != '\0'; flags++) {
469 char buf[40];
470 switch (*flags) {
471#ifdef GDBM_FAST
472 case 'f':
473 iflags |= GDBM_FAST;
474 break;
475#endif
476#ifdef GDBM_SYNC
477 case 's':
478 iflags |= GDBM_SYNC;
479 break;
480#endif
481#ifdef GDBM_NOLOCK
482 case 'u':
483 iflags |= GDBM_NOLOCK;
484 break;
485#endif
486 default:
Tim Peters885d4572001-11-28 20:27:42 +0000487 PyOS_snprintf(buf, sizeof(buf), "Flag '%c' is not supported.",
488 *flags);
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000489 PyErr_SetString(DbmError, buf);
490 return NULL;
491 }
492 }
493
Fred Drakee3a41c62000-07-08 05:00:07 +0000494 return newdbmobject(name, iflags, mode);
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000495}
496
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000497static char dbmmodule_open_flags[] = "rwcn"
498#ifdef GDBM_FAST
499 "f"
500#endif
501#ifdef GDBM_SYNC
502 "s"
503#endif
504#ifdef GDBM_NOLOCK
505 "u"
506#endif
507 ;
508
Roger E. Masseb15bef81996-12-17 19:55:33 +0000509static PyMethodDef dbmmodule_methods[] = {
Fred Drakee3a41c62000-07-08 05:00:07 +0000510 { "open", (PyCFunction)dbmopen, METH_VARARGS, dbmopen__doc__},
511 { 0, 0 },
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000512};
513
Mark Hammondfe51c6d2002-08-02 02:27:13 +0000514PyMODINIT_FUNC
Georg Brandl0a7ac7d2008-05-26 10:29:35 +0000515init_gdbm(void) {
Martin v. Löwis00ff10c2001-11-11 14:24:05 +0000516 PyObject *m, *d, *s;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000517
Guido van Rossum0da7e032006-08-19 23:18:48 +0000518 if (PyType_Ready(&Dbmtype) < 0)
519 return;
Georg Brandl0a7ac7d2008-05-26 10:29:35 +0000520 m = Py_InitModule4("_gdbm", dbmmodule_methods,
Fred Drakee3a41c62000-07-08 05:00:07 +0000521 gdbmmodule__doc__, (PyObject *)NULL,
522 PYTHON_API_VERSION);
Neal Norwitz1ac754f2006-01-19 06:09:39 +0000523 if (m == NULL)
524 return;
Fred Drakee3a41c62000-07-08 05:00:07 +0000525 d = PyModule_GetDict(m);
Georg Brandlb17acad2008-05-28 08:43:17 +0000526 DbmError = PyErr_NewException("_gdbm.error", PyExc_IOError, NULL);
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000527 if (DbmError != NULL) {
Fred Drakee3a41c62000-07-08 05:00:07 +0000528 PyDict_SetItemString(d, "error", DbmError);
Martin v. Löwis7ac97122007-08-11 19:28:53 +0000529 s = PyUnicode_FromString(dbmmodule_open_flags);
Martin v. Löwis00ff10c2001-11-11 14:24:05 +0000530 PyDict_SetItemString(d, "open_flags", s);
531 Py_DECREF(s);
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000532 }
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000533}