blob: 229e16e627db86b10b7570433b6c25ef90d88918 [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
Antoine Pitrou9ed5f272013-08-13 20:18:52 +020082dbm_dealloc(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 *
Antoine Pitrou9ed5f272013-08-13 20:18:52 +0200115dbm_subscript(dbmobject *dp, 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
Georg Brandld9e833c2010-12-04 09:14:36 +0000138PyDoc_STRVAR(dbm_get__doc__,
139"get(key[, default]) -> value\n\
140Get the value for key, or default if not present; if not given,\n\
141default is None.");
142
143static PyObject *
144dbm_get(dbmobject *dp, PyObject *args)
145{
146 PyObject *v, *res;
147 PyObject *def = Py_None;
148
149 if (!PyArg_UnpackTuple(args, "get", 1, 2, &v, &def))
150 return NULL;
151 res = dbm_subscript(dp, v);
152 if (res == NULL && PyErr_ExceptionMatches(PyExc_KeyError)) {
153 PyErr_Clear();
154 Py_INCREF(def);
155 return def;
156 }
157 return res;
158}
159
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000160static int
Fred Drakee3a41c62000-07-08 05:00:07 +0000161dbm_ass_sub(dbmobject *dp, PyObject *v, PyObject *w)
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000162{
Fred Drakee3a41c62000-07-08 05:00:07 +0000163 datum krec, drec;
164
165 if (!PyArg_Parse(v, "s#", &krec.dptr, &krec.dsize) ) {
166 PyErr_SetString(PyExc_TypeError,
Brett Cannon7317c1e2008-11-25 19:19:17 +0000167 "gdbm mappings have bytes or string indices only");
Fred Drakee3a41c62000-07-08 05:00:07 +0000168 return -1;
169 }
170 if (dp->di_dbm == NULL) {
171 PyErr_SetString(DbmError,
Guido van Rossum6252e102007-05-23 20:51:02 +0000172 "GDBM object has already been closed");
173 return -1;
Fred Drakee3a41c62000-07-08 05:00:07 +0000174 }
175 dp->di_size = -1;
176 if (w == NULL) {
177 if (gdbm_delete(dp->di_dbm, krec) < 0) {
Guido van Rossum6252e102007-05-23 20:51:02 +0000178 PyErr_SetObject(PyExc_KeyError, v);
Fred Drakee3a41c62000-07-08 05:00:07 +0000179 return -1;
Guido van Rossum77eecfa1997-07-17 22:56:01 +0000180 }
Fred Drakee3a41c62000-07-08 05:00:07 +0000181 }
182 else {
183 if (!PyArg_Parse(w, "s#", &drec.dptr, &drec.dsize)) {
184 PyErr_SetString(PyExc_TypeError,
Brett Cannon7317c1e2008-11-25 19:19:17 +0000185 "gdbm mappings have byte or string elements only");
Fred Drakee3a41c62000-07-08 05:00:07 +0000186 return -1;
187 }
188 errno = 0;
189 if (gdbm_store(dp->di_dbm, krec, drec, GDBM_REPLACE) < 0) {
190 if (errno != 0)
191 PyErr_SetFromErrno(DbmError);
192 else
193 PyErr_SetString(DbmError,
194 gdbm_strerror(gdbm_errno));
195 return -1;
196 }
197 }
198 return 0;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000199}
200
Georg Brandld9e833c2010-12-04 09:14:36 +0000201PyDoc_STRVAR(dbm_setdefault__doc__,
202"setdefault(key[, default]) -> value\n\
203Get value for key, or set it to default and return default if not present;\n\
204if not given, default is None.");
205
206static PyObject *
207dbm_setdefault(dbmobject *dp, PyObject *args)
208{
209 PyObject *v, *res;
210 PyObject *def = Py_None;
211
212 if (!PyArg_UnpackTuple(args, "setdefault", 1, 2, &v, &def))
213 return NULL;
214 res = dbm_subscript(dp, v);
215 if (res == NULL && PyErr_ExceptionMatches(PyExc_KeyError)) {
216 PyErr_Clear();
217 if (dbm_ass_sub(dp, v, def) < 0)
218 return NULL;
219 return dbm_subscript(dp, v);
220 }
221 return res;
222}
223
Roger E. Masseb15bef81996-12-17 19:55:33 +0000224static PyMappingMethods dbm_as_mapping = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000225 (lenfunc)dbm_length, /*mp_length*/
Fred Drakee3a41c62000-07-08 05:00:07 +0000226 (binaryfunc)dbm_subscript, /*mp_subscript*/
227 (objobjargproc)dbm_ass_sub, /*mp_ass_subscript*/
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000228};
229
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000230PyDoc_STRVAR(dbm_close__doc__,
231"close() -> None\n\
232Closes the database.");
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000233
Roger E. Masseb15bef81996-12-17 19:55:33 +0000234static PyObject *
Antoine Pitrou9ed5f272013-08-13 20:18:52 +0200235dbm_close(dbmobject *dp, PyObject *unused)
Guido van Rossum807b7be1995-07-07 22:37:11 +0000236{
Fred Drakee3a41c62000-07-08 05:00:07 +0000237 if (dp->di_dbm)
238 gdbm_close(dp->di_dbm);
239 dp->di_dbm = NULL;
240 Py_INCREF(Py_None);
241 return Py_None;
Guido van Rossum807b7be1995-07-07 22:37:11 +0000242}
243
Guido van Rossum6252e102007-05-23 20:51:02 +0000244/* XXX Should return a set or a set view */
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000245PyDoc_STRVAR(dbm_keys__doc__,
246"keys() -> list_of_keys\n\
247Get a list of all keys in the database.");
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000248
Roger E. Masseb15bef81996-12-17 19:55:33 +0000249static PyObject *
Antoine Pitrou9ed5f272013-08-13 20:18:52 +0200250dbm_keys(dbmobject *dp, PyObject *unused)
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000251{
Antoine Pitrou9ed5f272013-08-13 20:18:52 +0200252 PyObject *v, *item;
Fred Drakee3a41c62000-07-08 05:00:07 +0000253 datum key, nextkey;
254 int err;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000255
Fred Drakee3a41c62000-07-08 05:00:07 +0000256 if (dp == NULL || !is_dbmobject(dp)) {
257 PyErr_BadInternalCall();
258 return NULL;
259 }
Fred Drakee3a41c62000-07-08 05:00:07 +0000260 check_dbmobject_open(dp);
Guido van Rossum3be71401996-07-21 02:32:44 +0000261
Fred Drakee3a41c62000-07-08 05:00:07 +0000262 v = PyList_New(0);
263 if (v == NULL)
264 return NULL;
Guido van Rossum77eecfa1997-07-17 22:56:01 +0000265
Fred Drakee3a41c62000-07-08 05:00:07 +0000266 key = gdbm_firstkey(dp->di_dbm);
267 while (key.dptr) {
Christian Heimes72b710a2008-05-26 13:28:38 +0000268 item = PyBytes_FromStringAndSize(key.dptr, key.dsize);
Fred Drakee3a41c62000-07-08 05:00:07 +0000269 if (item == NULL) {
270 free(key.dptr);
271 Py_DECREF(v);
272 return NULL;
273 }
274 err = PyList_Append(v, item);
275 Py_DECREF(item);
276 if (err != 0) {
277 free(key.dptr);
278 Py_DECREF(v);
279 return NULL;
280 }
281 nextkey = gdbm_nextkey(dp->di_dbm, key);
282 free(key.dptr);
283 key = nextkey;
284 }
285 return v;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000286}
287
Guido van Rossum0da7e032006-08-19 23:18:48 +0000288static int
289dbm_contains(PyObject *self, PyObject *arg)
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000290{
Guido van Rossum0da7e032006-08-19 23:18:48 +0000291 dbmobject *dp = (dbmobject *)self;
Fred Drakee3a41c62000-07-08 05:00:07 +0000292 datum key;
Serhiy Storchaka7d6392c2013-10-25 00:06:52 +0300293 Py_ssize_t size;
Fred Drakee3a41c62000-07-08 05:00:07 +0000294
Guido van Rossum0da7e032006-08-19 23:18:48 +0000295 if ((dp)->di_dbm == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000296 PyErr_SetString(DbmError,
297 "GDBM object has already been closed");
298 return -1;
Guido van Rossum0da7e032006-08-19 23:18:48 +0000299 }
Serhiy Storchaka7d6392c2013-10-25 00:06:52 +0300300 if (PyUnicode_Check(arg)) {
301 key.dptr = PyUnicode_AsUTF8AndSize(arg, &size);
302 key.dsize = size;
303 if (key.dptr == NULL)
304 return -1;
305 }
306 else if (!PyBytes_Check(arg)) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000307 PyErr_Format(PyExc_TypeError,
Serhiy Storchaka7d6392c2013-10-25 00:06:52 +0300308 "gdbm key must be bytes or string, not %.100s",
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000309 arg->ob_type->tp_name);
310 return -1;
Guido van Rossum0da7e032006-08-19 23:18:48 +0000311 }
Serhiy Storchaka7d6392c2013-10-25 00:06:52 +0300312 else {
313 key.dptr = PyBytes_AS_STRING(arg);
314 key.dsize = PyBytes_GET_SIZE(arg);
315 }
Guido van Rossum0da7e032006-08-19 23:18:48 +0000316 return gdbm_exists(dp->di_dbm, key);
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000317}
318
Guido van Rossum0da7e032006-08-19 23:18:48 +0000319static PySequenceMethods dbm_as_sequence = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000320 0, /* sq_length */
321 0, /* sq_concat */
322 0, /* sq_repeat */
323 0, /* sq_item */
324 0, /* sq_slice */
325 0, /* sq_ass_item */
326 0, /* sq_ass_slice */
327 dbm_contains, /* sq_contains */
328 0, /* sq_inplace_concat */
329 0, /* sq_inplace_repeat */
Guido van Rossum0da7e032006-08-19 23:18:48 +0000330};
331
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000332PyDoc_STRVAR(dbm_firstkey__doc__,
333"firstkey() -> key\n\
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000334It's possible to loop over every key in the database using this method\n\
335and the nextkey() method. The traversal is ordered by GDBM's internal\n\
336hash values, and won't be sorted by the key values. This method\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000337returns the starting key.");
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000338
Roger E. Masseb15bef81996-12-17 19:55:33 +0000339static PyObject *
Antoine Pitrou9ed5f272013-08-13 20:18:52 +0200340dbm_firstkey(dbmobject *dp, PyObject *unused)
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000341{
Antoine Pitrou9ed5f272013-08-13 20:18:52 +0200342 PyObject *v;
Fred Drakee3a41c62000-07-08 05:00:07 +0000343 datum key;
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000344
Fred Drakee3a41c62000-07-08 05:00:07 +0000345 check_dbmobject_open(dp);
346 key = gdbm_firstkey(dp->di_dbm);
347 if (key.dptr) {
Christian Heimes72b710a2008-05-26 13:28:38 +0000348 v = PyBytes_FromStringAndSize(key.dptr, key.dsize);
Fred Drakee3a41c62000-07-08 05:00:07 +0000349 free(key.dptr);
350 return v;
351 }
352 else {
353 Py_INCREF(Py_None);
354 return Py_None;
355 }
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000356}
357
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000358PyDoc_STRVAR(dbm_nextkey__doc__,
359"nextkey(key) -> next_key\n\
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000360Returns the key that follows key in the traversal.\n\
361The following code prints every key in the database db, without having\n\
362to create a list in memory that contains them all:\n\
363\n\
364 k = db.firstkey()\n\
365 while k != None:\n\
366 print k\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000367 k = db.nextkey(k)");
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000368
Roger E. Masseb15bef81996-12-17 19:55:33 +0000369static PyObject *
Antoine Pitrou9ed5f272013-08-13 20:18:52 +0200370dbm_nextkey(dbmobject *dp, PyObject *args)
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000371{
Antoine Pitrou9ed5f272013-08-13 20:18:52 +0200372 PyObject *v;
Fred Drakee3a41c62000-07-08 05:00:07 +0000373 datum key, nextkey;
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000374
Fred Drakee3a41c62000-07-08 05:00:07 +0000375 if (!PyArg_ParseTuple(args, "s#:nextkey", &key.dptr, &key.dsize))
376 return NULL;
377 check_dbmobject_open(dp);
378 nextkey = gdbm_nextkey(dp->di_dbm, key);
379 if (nextkey.dptr) {
Christian Heimes72b710a2008-05-26 13:28:38 +0000380 v = PyBytes_FromStringAndSize(nextkey.dptr, nextkey.dsize);
Fred Drakee3a41c62000-07-08 05:00:07 +0000381 free(nextkey.dptr);
382 return v;
383 }
384 else {
385 Py_INCREF(Py_None);
386 return Py_None;
387 }
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000388}
389
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000390PyDoc_STRVAR(dbm_reorganize__doc__,
391"reorganize() -> None\n\
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000392If you have carried out a lot of deletions and would like to shrink\n\
393the space used by the GDBM file, this routine will reorganize the\n\
394database. GDBM will not shorten the length of a database file except\n\
395by using this reorganization; otherwise, deleted file space will be\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000396kept and reused as new (key,value) pairs are added.");
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000397
Roger E. Masseb15bef81996-12-17 19:55:33 +0000398static PyObject *
Antoine Pitrou9ed5f272013-08-13 20:18:52 +0200399dbm_reorganize(dbmobject *dp, PyObject *unused)
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000400{
Fred Drakee3a41c62000-07-08 05:00:07 +0000401 check_dbmobject_open(dp);
402 errno = 0;
403 if (gdbm_reorganize(dp->di_dbm) < 0) {
404 if (errno != 0)
405 PyErr_SetFromErrno(DbmError);
406 else
407 PyErr_SetString(DbmError, gdbm_strerror(gdbm_errno));
408 return NULL;
409 }
410 Py_INCREF(Py_None);
411 return Py_None;
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000412}
413
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000414PyDoc_STRVAR(dbm_sync__doc__,
415"sync() -> None\n\
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000416When the database has been opened in fast mode, this method forces\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000417any unwritten data to be written to the disk.");
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000418
Roger E. Massee5a9c8f1997-03-25 17:39:56 +0000419static PyObject *
Antoine Pitrou9ed5f272013-08-13 20:18:52 +0200420dbm_sync(dbmobject *dp, PyObject *unused)
Roger E. Massee5a9c8f1997-03-25 17:39:56 +0000421{
Fred Drakee3a41c62000-07-08 05:00:07 +0000422 check_dbmobject_open(dp);
423 gdbm_sync(dp->di_dbm);
424 Py_INCREF(Py_None);
425 return Py_None;
Roger E. Massee5a9c8f1997-03-25 17:39:56 +0000426}
427
Nick Coghlanc610aba2013-11-17 15:59:51 +1000428static PyObject *
429dbm__enter__(PyObject *self, PyObject *args)
430{
431 Py_INCREF(self);
432 return self;
433}
434
435static PyObject *
436dbm__exit__(PyObject *self, PyObject *args)
437{
438 _Py_IDENTIFIER(close);
439 return _PyObject_CallMethodId(self, &PyId_close, NULL);
440}
441
Roger E. Masseb15bef81996-12-17 19:55:33 +0000442static PyMethodDef dbm_methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000443 {"close", (PyCFunction)dbm_close, METH_NOARGS, dbm_close__doc__},
444 {"keys", (PyCFunction)dbm_keys, METH_NOARGS, dbm_keys__doc__},
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000445 {"firstkey", (PyCFunction)dbm_firstkey,METH_NOARGS, dbm_firstkey__doc__},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000446 {"nextkey", (PyCFunction)dbm_nextkey, METH_VARARGS, dbm_nextkey__doc__},
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000447 {"reorganize",(PyCFunction)dbm_reorganize,METH_NOARGS, dbm_reorganize__doc__},
448 {"sync", (PyCFunction)dbm_sync, METH_NOARGS, dbm_sync__doc__},
Georg Brandld9e833c2010-12-04 09:14:36 +0000449 {"get", (PyCFunction)dbm_get, METH_VARARGS, dbm_get__doc__},
450 {"setdefault",(PyCFunction)dbm_setdefault,METH_VARARGS, dbm_setdefault__doc__},
Nick Coghlanc610aba2013-11-17 15:59:51 +1000451 {"__enter__", dbm__enter__, METH_NOARGS, NULL},
452 {"__exit__", dbm__exit__, METH_VARARGS, NULL},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000453 {NULL, NULL} /* sentinel */
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000454};
455
Roger E. Masseb15bef81996-12-17 19:55:33 +0000456static PyTypeObject Dbmtype = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +0000457 PyVarObject_HEAD_INIT(0, 0)
Georg Brandl0a7ac7d2008-05-26 10:29:35 +0000458 "_gdbm.gdbm",
Fred Drakee3a41c62000-07-08 05:00:07 +0000459 sizeof(dbmobject),
460 0,
461 (destructor)dbm_dealloc, /*tp_dealloc*/
462 0, /*tp_print*/
Amaury Forgeot d'Arc1f900f12008-07-02 22:38:47 +0000463 0, /*tp_getattr*/
Fred Drakee3a41c62000-07-08 05:00:07 +0000464 0, /*tp_setattr*/
Mark Dickinsone94c6792009-02-02 20:36:42 +0000465 0, /*tp_reserved*/
Fred Drakee3a41c62000-07-08 05:00:07 +0000466 0, /*tp_repr*/
467 0, /*tp_as_number*/
Guido van Rossum0da7e032006-08-19 23:18:48 +0000468 &dbm_as_sequence, /*tp_as_sequence*/
Fred Drakee3a41c62000-07-08 05:00:07 +0000469 &dbm_as_mapping, /*tp_as_mapping*/
470 0, /*tp_hash*/
471 0, /*tp_call*/
472 0, /*tp_str*/
473 0, /*tp_getattro*/
474 0, /*tp_setattro*/
475 0, /*tp_as_buffer*/
Christian Heimes836baa52008-02-26 08:18:30 +0000476 Py_TPFLAGS_DEFAULT, /*tp_xxx4*/
Fred Drakee3a41c62000-07-08 05:00:07 +0000477 gdbm_object__doc__, /*tp_doc*/
Amaury Forgeot d'Arc1f900f12008-07-02 22:38:47 +0000478 0, /*tp_traverse*/
479 0, /*tp_clear*/
480 0, /*tp_richcompare*/
481 0, /*tp_weaklistoffset*/
482 0, /*tp_iter*/
483 0, /*tp_iternext*/
484 dbm_methods, /*tp_methods*/
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000485};
486
487/* ----------------------------------------------------------------- */
488
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000489PyDoc_STRVAR(dbmopen__doc__,
490"open(filename, [flags, [mode]]) -> dbm_object\n\
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000491Open a dbm database and return a dbm object. The filename argument is\n\
492the name of the database file.\n\
493\n\
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000494The optional flags argument can be 'r' (to open an existing database\n\
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000495for reading only -- default), 'w' (to open an existing database for\n\
496reading and writing), 'c' (which creates the database if it doesn't\n\
497exist), or 'n' (which always creates a new empty database).\n\
498\n\
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000499Some versions of gdbm support additional flags which must be\n\
500appended to one of the flags described above. The module constant\n\
501'open_flags' is a string of valid additional flags. The 'f' flag\n\
502opens the database in fast mode; altered data will not automatically\n\
503be written to the disk after every change. This results in faster\n\
504writes to the database, but may result in an inconsistent database\n\
505if the program crashes while the database is still open. Use the\n\
506sync() method to force any unwritten data to be written to the disk.\n\
507The 's' flag causes all database operations to be synchronized to\n\
508disk. The 'u' flag disables locking of the database file.\n\
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000509\n\
510The optional mode argument is the Unix mode of the file, used only\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000511when the database has to be created. It defaults to octal 0666. ");
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000512
Roger E. Masseb15bef81996-12-17 19:55:33 +0000513static PyObject *
Fred Drakee3a41c62000-07-08 05:00:07 +0000514dbmopen(PyObject *self, PyObject *args)
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000515{
Fred Drakee3a41c62000-07-08 05:00:07 +0000516 char *name;
Andrew M. Kuchlingea271f22004-07-07 14:19:09 +0000517 char *flags = "r";
Fred Drakee3a41c62000-07-08 05:00:07 +0000518 int iflags;
519 int mode = 0666;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000520
Fred Drakee3a41c62000-07-08 05:00:07 +0000521 if (!PyArg_ParseTuple(args, "s|si:open", &name, &flags, &mode))
522 return NULL;
523 switch (flags[0]) {
524 case 'r':
525 iflags = GDBM_READER;
526 break;
527 case 'w':
528 iflags = GDBM_WRITER;
529 break;
530 case 'c':
531 iflags = GDBM_WRCREAT;
532 break;
533 case 'n':
534 iflags = GDBM_NEWDB;
535 break;
536 default:
537 PyErr_SetString(DbmError,
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000538 "First flag must be one of 'r', 'w', 'c' or 'n'");
Fred Drakee3a41c62000-07-08 05:00:07 +0000539 return NULL;
540 }
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000541 for (flags++; *flags != '\0'; flags++) {
542 char buf[40];
543 switch (*flags) {
544#ifdef GDBM_FAST
545 case 'f':
546 iflags |= GDBM_FAST;
547 break;
548#endif
549#ifdef GDBM_SYNC
550 case 's':
551 iflags |= GDBM_SYNC;
552 break;
553#endif
554#ifdef GDBM_NOLOCK
555 case 'u':
556 iflags |= GDBM_NOLOCK;
557 break;
558#endif
559 default:
Tim Peters885d4572001-11-28 20:27:42 +0000560 PyOS_snprintf(buf, sizeof(buf), "Flag '%c' is not supported.",
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000561 *flags);
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000562 PyErr_SetString(DbmError, buf);
563 return NULL;
564 }
565 }
566
Fred Drakee3a41c62000-07-08 05:00:07 +0000567 return newdbmobject(name, iflags, mode);
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000568}
569
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000570static char dbmmodule_open_flags[] = "rwcn"
571#ifdef GDBM_FAST
572 "f"
573#endif
574#ifdef GDBM_SYNC
575 "s"
576#endif
577#ifdef GDBM_NOLOCK
578 "u"
579#endif
580 ;
581
Roger E. Masseb15bef81996-12-17 19:55:33 +0000582static PyMethodDef dbmmodule_methods[] = {
Fred Drakee3a41c62000-07-08 05:00:07 +0000583 { "open", (PyCFunction)dbmopen, METH_VARARGS, dbmopen__doc__},
584 { 0, 0 },
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000585};
586
Martin v. Löwis1a214512008-06-11 05:26:20 +0000587
588static struct PyModuleDef _gdbmmodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000589 PyModuleDef_HEAD_INIT,
590 "_gdbm",
591 gdbmmodule__doc__,
592 -1,
593 dbmmodule_methods,
594 NULL,
595 NULL,
596 NULL,
597 NULL
Martin v. Löwis1a214512008-06-11 05:26:20 +0000598};
599
Mark Hammondfe51c6d2002-08-02 02:27:13 +0000600PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +0000601PyInit__gdbm(void) {
Martin v. Löwis00ff10c2001-11-11 14:24:05 +0000602 PyObject *m, *d, *s;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000603
Guido van Rossum0da7e032006-08-19 23:18:48 +0000604 if (PyType_Ready(&Dbmtype) < 0)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000605 return NULL;
Martin v. Löwis1a214512008-06-11 05:26:20 +0000606 m = PyModule_Create(&_gdbmmodule);
Neal Norwitz1ac754f2006-01-19 06:09:39 +0000607 if (m == NULL)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000608 return NULL;
Fred Drakee3a41c62000-07-08 05:00:07 +0000609 d = PyModule_GetDict(m);
Georg Brandlb17acad2008-05-28 08:43:17 +0000610 DbmError = PyErr_NewException("_gdbm.error", PyExc_IOError, NULL);
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000611 if (DbmError != NULL) {
Fred Drakee3a41c62000-07-08 05:00:07 +0000612 PyDict_SetItemString(d, "error", DbmError);
Martin v. Löwis7ac97122007-08-11 19:28:53 +0000613 s = PyUnicode_FromString(dbmmodule_open_flags);
Martin v. Löwis00ff10c2001-11-11 14:24:05 +0000614 PyDict_SetItemString(d, "open_flags", s);
615 Py_DECREF(s);
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000616 }
Martin v. Löwis1a214512008-06-11 05:26:20 +0000617 return m;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000618}