blob: f15fefdf8222cddf3ec2c983e6d13b6a10cd83a2 [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
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000033 int di_size; /* -1 means recompute */
Fred Drakee3a41c62000-07-08 05:00:07 +000034 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,
Brett Cannon7317c1e2008-11-25 19:19:17 +0000145 "gdbm mappings have bytes or string indices only");
Fred Drakee3a41c62000-07-08 05:00:07 +0000146 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,
Brett Cannon7317c1e2008-11-25 19:19:17 +0000163 "gdbm mappings have byte or 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 = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +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) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000250 PyErr_SetString(DbmError,
251 "GDBM object has already been closed");
252 return -1;
Guido van Rossum0da7e032006-08-19 23:18:48 +0000253 }
Christian Heimes72b710a2008-05-26 13:28:38 +0000254 if (!PyBytes_Check(arg)) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000255 PyErr_Format(PyExc_TypeError,
256 "gdbm key must be bytes, not %.100s",
257 arg->ob_type->tp_name);
258 return -1;
Guido van Rossum0da7e032006-08-19 23:18:48 +0000259 }
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 = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000266 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 */
Guido van Rossum0da7e032006-08-19 23:18:48 +0000276};
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[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +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__},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +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__},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000381 {NULL, NULL} /* sentinel */
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000382};
383
Roger E. Masseb15bef81996-12-17 19:55:33 +0000384static PyTypeObject Dbmtype = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +0000385 PyVarObject_HEAD_INIT(0, 0)
Georg Brandl0a7ac7d2008-05-26 10:29:35 +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*/
Amaury Forgeot d'Arc1f900f12008-07-02 22:38:47 +0000391 0, /*tp_getattr*/
Fred Drakee3a41c62000-07-08 05:00:07 +0000392 0, /*tp_setattr*/
Mark Dickinsone94c6792009-02-02 20:36:42 +0000393 0, /*tp_reserved*/
Fred Drakee3a41c62000-07-08 05:00:07 +0000394 0, /*tp_repr*/
395 0, /*tp_as_number*/
Guido van Rossum0da7e032006-08-19 23:18:48 +0000396 &dbm_as_sequence, /*tp_as_sequence*/
Fred Drakee3a41c62000-07-08 05:00:07 +0000397 &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*/
Christian Heimes836baa52008-02-26 08:18:30 +0000404 Py_TPFLAGS_DEFAULT, /*tp_xxx4*/
Fred Drakee3a41c62000-07-08 05:00:07 +0000405 gdbm_object__doc__, /*tp_doc*/
Amaury Forgeot d'Arc1f900f12008-07-02 22:38:47 +0000406 0, /*tp_traverse*/
407 0, /*tp_clear*/
408 0, /*tp_richcompare*/
409 0, /*tp_weaklistoffset*/
410 0, /*tp_iter*/
411 0, /*tp_iternext*/
412 dbm_methods, /*tp_methods*/
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000413};
414
415/* ----------------------------------------------------------------- */
416
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000417PyDoc_STRVAR(dbmopen__doc__,
418"open(filename, [flags, [mode]]) -> dbm_object\n\
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000419Open a dbm database and return a dbm object. The filename argument is\n\
420the name of the database file.\n\
421\n\
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000422The optional flags argument can be 'r' (to open an existing database\n\
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000423for reading only -- default), 'w' (to open an existing database for\n\
424reading and writing), 'c' (which creates the database if it doesn't\n\
425exist), or 'n' (which always creates a new empty database).\n\
426\n\
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000427Some versions of gdbm support additional flags which must be\n\
428appended to one of the flags described above. The module constant\n\
429'open_flags' is a string of valid additional flags. The 'f' flag\n\
430opens the database in fast mode; altered data will not automatically\n\
431be written to the disk after every change. This results in faster\n\
432writes to the database, but may result in an inconsistent database\n\
433if the program crashes while the database is still open. Use the\n\
434sync() method to force any unwritten data to be written to the disk.\n\
435The 's' flag causes all database operations to be synchronized to\n\
436disk. The 'u' flag disables locking of the database file.\n\
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000437\n\
438The optional mode argument is the Unix mode of the file, used only\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000439when the database has to be created. It defaults to octal 0666. ");
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000440
Roger E. Masseb15bef81996-12-17 19:55:33 +0000441static PyObject *
Fred Drakee3a41c62000-07-08 05:00:07 +0000442dbmopen(PyObject *self, PyObject *args)
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000443{
Fred Drakee3a41c62000-07-08 05:00:07 +0000444 char *name;
Andrew M. Kuchlingea271f22004-07-07 14:19:09 +0000445 char *flags = "r";
Fred Drakee3a41c62000-07-08 05:00:07 +0000446 int iflags;
447 int mode = 0666;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000448
Fred Drakee3a41c62000-07-08 05:00:07 +0000449 if (!PyArg_ParseTuple(args, "s|si:open", &name, &flags, &mode))
450 return NULL;
451 switch (flags[0]) {
452 case 'r':
453 iflags = GDBM_READER;
454 break;
455 case 'w':
456 iflags = GDBM_WRITER;
457 break;
458 case 'c':
459 iflags = GDBM_WRCREAT;
460 break;
461 case 'n':
462 iflags = GDBM_NEWDB;
463 break;
464 default:
465 PyErr_SetString(DbmError,
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000466 "First flag must be one of 'r', 'w', 'c' or 'n'");
Fred Drakee3a41c62000-07-08 05:00:07 +0000467 return NULL;
468 }
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000469 for (flags++; *flags != '\0'; flags++) {
470 char buf[40];
471 switch (*flags) {
472#ifdef GDBM_FAST
473 case 'f':
474 iflags |= GDBM_FAST;
475 break;
476#endif
477#ifdef GDBM_SYNC
478 case 's':
479 iflags |= GDBM_SYNC;
480 break;
481#endif
482#ifdef GDBM_NOLOCK
483 case 'u':
484 iflags |= GDBM_NOLOCK;
485 break;
486#endif
487 default:
Tim Peters885d4572001-11-28 20:27:42 +0000488 PyOS_snprintf(buf, sizeof(buf), "Flag '%c' is not supported.",
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000489 *flags);
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000490 PyErr_SetString(DbmError, buf);
491 return NULL;
492 }
493 }
494
Fred Drakee3a41c62000-07-08 05:00:07 +0000495 return newdbmobject(name, iflags, mode);
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000496}
497
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000498static char dbmmodule_open_flags[] = "rwcn"
499#ifdef GDBM_FAST
500 "f"
501#endif
502#ifdef GDBM_SYNC
503 "s"
504#endif
505#ifdef GDBM_NOLOCK
506 "u"
507#endif
508 ;
509
Roger E. Masseb15bef81996-12-17 19:55:33 +0000510static PyMethodDef dbmmodule_methods[] = {
Fred Drakee3a41c62000-07-08 05:00:07 +0000511 { "open", (PyCFunction)dbmopen, METH_VARARGS, dbmopen__doc__},
512 { 0, 0 },
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000513};
514
Martin v. Löwis1a214512008-06-11 05:26:20 +0000515
516static struct PyModuleDef _gdbmmodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000517 PyModuleDef_HEAD_INIT,
518 "_gdbm",
519 gdbmmodule__doc__,
520 -1,
521 dbmmodule_methods,
522 NULL,
523 NULL,
524 NULL,
525 NULL
Martin v. Löwis1a214512008-06-11 05:26:20 +0000526};
527
Mark Hammondfe51c6d2002-08-02 02:27:13 +0000528PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +0000529PyInit__gdbm(void) {
Martin v. Löwis00ff10c2001-11-11 14:24:05 +0000530 PyObject *m, *d, *s;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000531
Guido van Rossum0da7e032006-08-19 23:18:48 +0000532 if (PyType_Ready(&Dbmtype) < 0)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000533 return NULL;
Martin v. Löwis1a214512008-06-11 05:26:20 +0000534 m = PyModule_Create(&_gdbmmodule);
Neal Norwitz1ac754f2006-01-19 06:09:39 +0000535 if (m == NULL)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000536 return NULL;
Fred Drakee3a41c62000-07-08 05:00:07 +0000537 d = PyModule_GetDict(m);
Georg Brandlb17acad2008-05-28 08:43:17 +0000538 DbmError = PyErr_NewException("_gdbm.error", PyExc_IOError, NULL);
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000539 if (DbmError != NULL) {
Fred Drakee3a41c62000-07-08 05:00:07 +0000540 PyDict_SetItemString(d, "error", DbmError);
Martin v. Löwis7ac97122007-08-11 19:28:53 +0000541 s = PyUnicode_FromString(dbmmodule_open_flags);
Martin v. Löwis00ff10c2001-11-11 14:24:05 +0000542 PyDict_SetItemString(d, "open_flags", s);
543 Py_DECREF(s);
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000544 }
Martin v. Löwis1a214512008-06-11 05:26:20 +0000545 return m;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000546}