blob: 04b3332bb895e3c6383ab2245a93f67d155dffe7 [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 Heimese93237d2007-12-19 02:37:44 +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) {
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,
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000131 PyString_AS_STRING((PyStringObject *)key));
Fred Drakee3a41c62000-07-08 05:00:07 +0000132 return NULL;
133 }
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000134 v = PyString_FromStringAndSize(drec.dptr, drec.dsize);
Fred Drakee3a41c62000-07-08 05:00:07 +0000135 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,
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000158 PyString_AS_STRING((PyStringObject *)v));
Fred Drakee3a41c62000-07-08 05:00:07 +0000159 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
Facundo Batistadf419892008-02-25 22:33:55 +0000181static int
Christian Heimesaa0ef522008-02-26 08:18:11 +0000182dbm_contains(register dbmobject *dp, PyObject *arg)
Facundo Batistadf419892008-02-25 22:33:55 +0000183{
184 datum key;
185
Christian Heimesaa0ef522008-02-26 08:18:11 +0000186 if ((dp)->di_dbm == NULL) {
187 PyErr_SetString(DbmError,
188 "GDBM object has already been closed");
Facundo Batistadf419892008-02-25 22:33:55 +0000189 return -1;
190 }
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000191 if (!PyString_Check(arg)) {
Christian Heimesaa0ef522008-02-26 08:18:11 +0000192 PyErr_Format(PyExc_TypeError,
193 "gdbm key must be string, not %.100s",
194 arg->ob_type->tp_name);
195 return -1;
196 }
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000197 key.dptr = PyString_AS_STRING(arg);
198 key.dsize = PyString_GET_SIZE(arg);
Facundo Batistadf419892008-02-25 22:33:55 +0000199 return gdbm_exists(dp->di_dbm, key);
200}
201
202static PySequenceMethods dbm_as_sequence = {
203 (lenfunc)dbm_length, /*_length*/
204 0, /*sq_concat*/
205 0, /*sq_repeat*/
206 0, /*sq_item*/
207 0, /*sq_slice*/
208 0, /*sq_ass_item*/
209 0, /*sq_ass_slice*/
210 (objobjproc)dbm_contains, /*sq_contains*/
211 0, /*sq_inplace_concat*/
212 0 /*sq_inplace_repeat*/
213};
214
Roger E. Masseb15bef81996-12-17 19:55:33 +0000215static PyMappingMethods dbm_as_mapping = {
Martin v. Löwis18e16552006-02-15 17:27:45 +0000216 (lenfunc)dbm_length, /*mp_length*/
Fred Drakee3a41c62000-07-08 05:00:07 +0000217 (binaryfunc)dbm_subscript, /*mp_subscript*/
218 (objobjargproc)dbm_ass_sub, /*mp_ass_subscript*/
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000219};
220
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000221PyDoc_STRVAR(dbm_close__doc__,
222"close() -> None\n\
223Closes the database.");
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000224
Roger E. Masseb15bef81996-12-17 19:55:33 +0000225static PyObject *
Georg Brandl96a8c392006-05-29 21:04:52 +0000226dbm_close(register dbmobject *dp, PyObject *unused)
Guido van Rossum807b7be1995-07-07 22:37:11 +0000227{
Fred Drakee3a41c62000-07-08 05:00:07 +0000228 if (dp->di_dbm)
229 gdbm_close(dp->di_dbm);
230 dp->di_dbm = NULL;
231 Py_INCREF(Py_None);
232 return Py_None;
Guido van Rossum807b7be1995-07-07 22:37:11 +0000233}
234
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000235PyDoc_STRVAR(dbm_keys__doc__,
236"keys() -> list_of_keys\n\
237Get a list of all keys in the database.");
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000238
Roger E. Masseb15bef81996-12-17 19:55:33 +0000239static PyObject *
Georg Brandl96a8c392006-05-29 21:04:52 +0000240dbm_keys(register dbmobject *dp, PyObject *unused)
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000241{
Fred Drakee3a41c62000-07-08 05:00:07 +0000242 register PyObject *v, *item;
243 datum key, nextkey;
244 int err;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000245
Fred Drakee3a41c62000-07-08 05:00:07 +0000246 if (dp == NULL || !is_dbmobject(dp)) {
247 PyErr_BadInternalCall();
248 return NULL;
249 }
Fred Drakee3a41c62000-07-08 05:00:07 +0000250 check_dbmobject_open(dp);
Guido van Rossum3be71401996-07-21 02:32:44 +0000251
Fred Drakee3a41c62000-07-08 05:00:07 +0000252 v = PyList_New(0);
253 if (v == NULL)
254 return NULL;
Guido van Rossum77eecfa1997-07-17 22:56:01 +0000255
Fred Drakee3a41c62000-07-08 05:00:07 +0000256 key = gdbm_firstkey(dp->di_dbm);
257 while (key.dptr) {
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000258 item = PyString_FromStringAndSize(key.dptr, key.dsize);
Fred Drakee3a41c62000-07-08 05:00:07 +0000259 if (item == NULL) {
260 free(key.dptr);
261 Py_DECREF(v);
262 return NULL;
263 }
264 err = PyList_Append(v, item);
265 Py_DECREF(item);
266 if (err != 0) {
267 free(key.dptr);
268 Py_DECREF(v);
269 return NULL;
270 }
271 nextkey = gdbm_nextkey(dp->di_dbm, key);
272 free(key.dptr);
273 key = nextkey;
274 }
275 return v;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000276}
277
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000278PyDoc_STRVAR(dbm_has_key__doc__,
279"has_key(key) -> boolean\n\
280Find out whether or not the database contains a given key.");
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000281
Roger E. Masseb15bef81996-12-17 19:55:33 +0000282static PyObject *
Fred Drakee3a41c62000-07-08 05:00:07 +0000283dbm_has_key(register dbmobject *dp, PyObject *args)
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000284{
Fred Drakee3a41c62000-07-08 05:00:07 +0000285 datum key;
286
287 if (!PyArg_ParseTuple(args, "s#:has_key", &key.dptr, &key.dsize))
288 return NULL;
289 check_dbmobject_open(dp);
290 return PyInt_FromLong((long) gdbm_exists(dp->di_dbm, key));
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000291}
292
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000293PyDoc_STRVAR(dbm_firstkey__doc__,
294"firstkey() -> key\n\
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000295It's possible to loop over every key in the database using this method\n\
296and the nextkey() method. The traversal is ordered by GDBM's internal\n\
297hash values, and won't be sorted by the key values. This method\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000298returns the starting key.");
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000299
Roger E. Masseb15bef81996-12-17 19:55:33 +0000300static PyObject *
Georg Brandl96a8c392006-05-29 21:04:52 +0000301dbm_firstkey(register dbmobject *dp, PyObject *unused)
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000302{
Fred Drakee3a41c62000-07-08 05:00:07 +0000303 register PyObject *v;
304 datum key;
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000305
Fred Drakee3a41c62000-07-08 05:00:07 +0000306 check_dbmobject_open(dp);
307 key = gdbm_firstkey(dp->di_dbm);
308 if (key.dptr) {
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000309 v = PyString_FromStringAndSize(key.dptr, key.dsize);
Fred Drakee3a41c62000-07-08 05:00:07 +0000310 free(key.dptr);
311 return v;
312 }
313 else {
314 Py_INCREF(Py_None);
315 return Py_None;
316 }
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000317}
318
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000319PyDoc_STRVAR(dbm_nextkey__doc__,
320"nextkey(key) -> next_key\n\
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000321Returns the key that follows key in the traversal.\n\
322The following code prints every key in the database db, without having\n\
323to create a list in memory that contains them all:\n\
324\n\
325 k = db.firstkey()\n\
326 while k != None:\n\
327 print k\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000328 k = db.nextkey(k)");
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000329
Roger E. Masseb15bef81996-12-17 19:55:33 +0000330static PyObject *
Fred Drakee3a41c62000-07-08 05:00:07 +0000331dbm_nextkey(register dbmobject *dp, PyObject *args)
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000332{
Fred Drakee3a41c62000-07-08 05:00:07 +0000333 register PyObject *v;
334 datum key, nextkey;
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000335
Fred Drakee3a41c62000-07-08 05:00:07 +0000336 if (!PyArg_ParseTuple(args, "s#:nextkey", &key.dptr, &key.dsize))
337 return NULL;
338 check_dbmobject_open(dp);
339 nextkey = gdbm_nextkey(dp->di_dbm, key);
340 if (nextkey.dptr) {
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000341 v = PyString_FromStringAndSize(nextkey.dptr, nextkey.dsize);
Fred Drakee3a41c62000-07-08 05:00:07 +0000342 free(nextkey.dptr);
343 return v;
344 }
345 else {
346 Py_INCREF(Py_None);
347 return Py_None;
348 }
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000349}
350
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000351PyDoc_STRVAR(dbm_reorganize__doc__,
352"reorganize() -> None\n\
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000353If you have carried out a lot of deletions and would like to shrink\n\
354the space used by the GDBM file, this routine will reorganize the\n\
355database. GDBM will not shorten the length of a database file except\n\
356by using this reorganization; otherwise, deleted file space will be\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000357kept and reused as new (key,value) pairs are added.");
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000358
Roger E. Masseb15bef81996-12-17 19:55:33 +0000359static PyObject *
Georg Brandl96a8c392006-05-29 21:04:52 +0000360dbm_reorganize(register dbmobject *dp, PyObject *unused)
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000361{
Fred Drakee3a41c62000-07-08 05:00:07 +0000362 check_dbmobject_open(dp);
363 errno = 0;
364 if (gdbm_reorganize(dp->di_dbm) < 0) {
365 if (errno != 0)
366 PyErr_SetFromErrno(DbmError);
367 else
368 PyErr_SetString(DbmError, gdbm_strerror(gdbm_errno));
369 return NULL;
370 }
371 Py_INCREF(Py_None);
372 return Py_None;
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000373}
374
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000375PyDoc_STRVAR(dbm_sync__doc__,
376"sync() -> None\n\
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000377When the database has been opened in fast mode, this method forces\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000378any unwritten data to be written to the disk.");
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000379
Roger E. Massee5a9c8f1997-03-25 17:39:56 +0000380static PyObject *
Georg Brandl96a8c392006-05-29 21:04:52 +0000381dbm_sync(register dbmobject *dp, PyObject *unused)
Roger E. Massee5a9c8f1997-03-25 17:39:56 +0000382{
Fred Drakee3a41c62000-07-08 05:00:07 +0000383 check_dbmobject_open(dp);
384 gdbm_sync(dp->di_dbm);
385 Py_INCREF(Py_None);
386 return Py_None;
Roger E. Massee5a9c8f1997-03-25 17:39:56 +0000387}
388
Roger E. Masseb15bef81996-12-17 19:55:33 +0000389static PyMethodDef dbm_methods[] = {
Georg Brandl96a8c392006-05-29 21:04:52 +0000390 {"close", (PyCFunction)dbm_close, METH_NOARGS, dbm_close__doc__},
391 {"keys", (PyCFunction)dbm_keys, METH_NOARGS, dbm_keys__doc__},
Fred Drakee3a41c62000-07-08 05:00:07 +0000392 {"has_key", (PyCFunction)dbm_has_key, METH_VARARGS, dbm_has_key__doc__},
Georg Brandl96a8c392006-05-29 21:04:52 +0000393 {"firstkey", (PyCFunction)dbm_firstkey,METH_NOARGS, dbm_firstkey__doc__},
Fred Drakee3a41c62000-07-08 05:00:07 +0000394 {"nextkey", (PyCFunction)dbm_nextkey, METH_VARARGS, dbm_nextkey__doc__},
Georg Brandl96a8c392006-05-29 21:04:52 +0000395 {"reorganize",(PyCFunction)dbm_reorganize,METH_NOARGS, dbm_reorganize__doc__},
396 {"sync", (PyCFunction)dbm_sync, METH_NOARGS, dbm_sync__doc__},
Fred Drakee3a41c62000-07-08 05:00:07 +0000397 {NULL, NULL} /* sentinel */
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000398};
399
Roger E. Masseb15bef81996-12-17 19:55:33 +0000400static PyObject *
Fred Drakee3a41c62000-07-08 05:00:07 +0000401dbm_getattr(dbmobject *dp, char *name)
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000402{
Fred Drakee3a41c62000-07-08 05:00:07 +0000403 return Py_FindMethod(dbm_methods, (PyObject *)dp, name);
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000404}
405
Roger E. Masseb15bef81996-12-17 19:55:33 +0000406static PyTypeObject Dbmtype = {
Martin v. Löwis68192102007-07-21 06:55:02 +0000407 PyVarObject_HEAD_INIT(0, 0)
Guido van Rossum14648392001-12-08 18:02:58 +0000408 "gdbm.gdbm",
Fred Drakee3a41c62000-07-08 05:00:07 +0000409 sizeof(dbmobject),
410 0,
411 (destructor)dbm_dealloc, /*tp_dealloc*/
412 0, /*tp_print*/
413 (getattrfunc)dbm_getattr, /*tp_getattr*/
414 0, /*tp_setattr*/
415 0, /*tp_compare*/
416 0, /*tp_repr*/
417 0, /*tp_as_number*/
Facundo Batistadf419892008-02-25 22:33:55 +0000418 &dbm_as_sequence, /*tp_as_sequence*/
Fred Drakee3a41c62000-07-08 05:00:07 +0000419 &dbm_as_mapping, /*tp_as_mapping*/
420 0, /*tp_hash*/
421 0, /*tp_call*/
422 0, /*tp_str*/
423 0, /*tp_getattro*/
424 0, /*tp_setattro*/
425 0, /*tp_as_buffer*/
Facundo Batistadf419892008-02-25 22:33:55 +0000426 Py_TPFLAGS_DEFAULT, /*tp_xxx4*/
Fred Drakee3a41c62000-07-08 05:00:07 +0000427 gdbm_object__doc__, /*tp_doc*/
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000428};
429
430/* ----------------------------------------------------------------- */
431
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000432PyDoc_STRVAR(dbmopen__doc__,
433"open(filename, [flags, [mode]]) -> dbm_object\n\
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000434Open a dbm database and return a dbm object. The filename argument is\n\
435the name of the database file.\n\
436\n\
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000437The optional flags argument can be 'r' (to open an existing database\n\
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000438for reading only -- default), 'w' (to open an existing database for\n\
439reading and writing), 'c' (which creates the database if it doesn't\n\
440exist), or 'n' (which always creates a new empty database).\n\
441\n\
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000442Some versions of gdbm support additional flags which must be\n\
443appended to one of the flags described above. The module constant\n\
444'open_flags' is a string of valid additional flags. The 'f' flag\n\
445opens the database in fast mode; altered data will not automatically\n\
446be written to the disk after every change. This results in faster\n\
447writes to the database, but may result in an inconsistent database\n\
448if the program crashes while the database is still open. Use the\n\
449sync() method to force any unwritten data to be written to the disk.\n\
450The 's' flag causes all database operations to be synchronized to\n\
451disk. The 'u' flag disables locking of the database file.\n\
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000452\n\
453The optional mode argument is the Unix mode of the file, used only\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000454when the database has to be created. It defaults to octal 0666. ");
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000455
Roger E. Masseb15bef81996-12-17 19:55:33 +0000456static PyObject *
Fred Drakee3a41c62000-07-08 05:00:07 +0000457dbmopen(PyObject *self, PyObject *args)
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000458{
Fred Drakee3a41c62000-07-08 05:00:07 +0000459 char *name;
Andrew M. Kuchlingea271f22004-07-07 14:19:09 +0000460 char *flags = "r";
Fred Drakee3a41c62000-07-08 05:00:07 +0000461 int iflags;
462 int mode = 0666;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000463
Fred Drakee3a41c62000-07-08 05:00:07 +0000464 if (!PyArg_ParseTuple(args, "s|si:open", &name, &flags, &mode))
465 return NULL;
466 switch (flags[0]) {
467 case 'r':
468 iflags = GDBM_READER;
469 break;
470 case 'w':
471 iflags = GDBM_WRITER;
472 break;
473 case 'c':
474 iflags = GDBM_WRCREAT;
475 break;
476 case 'n':
477 iflags = GDBM_NEWDB;
478 break;
479 default:
480 PyErr_SetString(DbmError,
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000481 "First flag must be one of 'r', 'w', 'c' or 'n'");
Fred Drakee3a41c62000-07-08 05:00:07 +0000482 return NULL;
483 }
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000484 for (flags++; *flags != '\0'; flags++) {
485 char buf[40];
486 switch (*flags) {
487#ifdef GDBM_FAST
488 case 'f':
489 iflags |= GDBM_FAST;
490 break;
491#endif
492#ifdef GDBM_SYNC
493 case 's':
494 iflags |= GDBM_SYNC;
495 break;
496#endif
497#ifdef GDBM_NOLOCK
498 case 'u':
499 iflags |= GDBM_NOLOCK;
500 break;
501#endif
502 default:
Tim Peters885d4572001-11-28 20:27:42 +0000503 PyOS_snprintf(buf, sizeof(buf), "Flag '%c' is not supported.",
504 *flags);
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000505 PyErr_SetString(DbmError, buf);
506 return NULL;
507 }
508 }
509
Fred Drakee3a41c62000-07-08 05:00:07 +0000510 return newdbmobject(name, iflags, mode);
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000511}
512
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000513static char dbmmodule_open_flags[] = "rwcn"
514#ifdef GDBM_FAST
515 "f"
516#endif
517#ifdef GDBM_SYNC
518 "s"
519#endif
520#ifdef GDBM_NOLOCK
521 "u"
522#endif
523 ;
524
Roger E. Masseb15bef81996-12-17 19:55:33 +0000525static PyMethodDef dbmmodule_methods[] = {
Fred Drakee3a41c62000-07-08 05:00:07 +0000526 { "open", (PyCFunction)dbmopen, METH_VARARGS, dbmopen__doc__},
527 { 0, 0 },
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000528};
529
Mark Hammondfe51c6d2002-08-02 02:27:13 +0000530PyMODINIT_FUNC
Thomas Wouters58d05102000-07-24 14:43:35 +0000531initgdbm(void) {
Martin v. Löwis00ff10c2001-11-11 14:24:05 +0000532 PyObject *m, *d, *s;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000533
Fred Drakee3a41c62000-07-08 05:00:07 +0000534 Dbmtype.ob_type = &PyType_Type;
535 m = Py_InitModule4("gdbm", dbmmodule_methods,
536 gdbmmodule__doc__, (PyObject *)NULL,
537 PYTHON_API_VERSION);
Neal Norwitz1ac754f2006-01-19 06:09:39 +0000538 if (m == NULL)
539 return;
Fred Drakee3a41c62000-07-08 05:00:07 +0000540 d = PyModule_GetDict(m);
541 DbmError = PyErr_NewException("gdbm.error", NULL, NULL);
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000542 if (DbmError != NULL) {
Fred Drakee3a41c62000-07-08 05:00:07 +0000543 PyDict_SetItemString(d, "error", DbmError);
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000544 s = PyString_FromString(dbmmodule_open_flags);
Martin v. Löwis00ff10c2001-11-11 14:24:05 +0000545 PyDict_SetItemString(d, "open_flags", s);
546 Py_DECREF(s);
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000547 }
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000548}