blob: f3fee4d1244ec1a5f90abf571be0474a40ed1d12 [file] [log] [blame]
Guido van Rossum4b4c6641994-08-08 08:06:37 +00001
2/* DBM module using dictionary interface */
Guido van Rossumbfc49e81998-03-03 22:02:24 +00003/* Author: Anthony Baxter, after dbmmodule.c */
4/* Doc strings: Mitch Chapman */
Guido van Rossum4b4c6641994-08-08 08:06:37 +00005
6
Roger E. Masseb15bef81996-12-17 19:55:33 +00007#include "Python.h"
Guido van Rossum4b4c6641994-08-08 08:06:37 +00008
9#include <sys/types.h>
10#include <sys/stat.h>
11#include <fcntl.h>
12#include "gdbm.h"
13
Tim Peters5687ffe2001-02-28 16:44:18 +000014#if defined(WIN32) && !defined(__CYGWIN__)
Guido van Rossumb6e2a991998-10-03 05:13:27 +000015#include "gdbmerrno.h"
16extern const char * gdbm_strerror(gdbm_error);
17#endif
18
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +000019PyDoc_STRVAR(gdbmmodule__doc__,
20"This module provides an interface to the GNU DBM (GDBM) library.\n\
Guido van Rossumbfc49e81998-03-03 22:02:24 +000021\n\
22This module is quite similar to the dbm module, but uses GDBM instead to\n\
23provide some additional functionality. Please note that the file formats\n\
24created by GDBM and dbm are incompatible. \n\
25\n\
26GDBM objects behave like mappings (dictionaries), except that keys and\n\
27values are always strings. Printing a GDBM object doesn't print the\n\
28keys and values, and the items() and values() methods are not\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +000029supported.");
Guido van Rossumbfc49e81998-03-03 22:02:24 +000030
Guido van Rossum4b4c6641994-08-08 08:06:37 +000031typedef struct {
Fred Drakee3a41c62000-07-08 05:00:07 +000032 PyObject_HEAD
33 int di_size; /* -1 means recompute */
34 GDBM_FILE di_dbm;
Guido van Rossum4b4c6641994-08-08 08:06:37 +000035} dbmobject;
36
Jeremy Hylton938ace62002-07-17 16:30:39 +000037static PyTypeObject Dbmtype;
Guido van Rossum4b4c6641994-08-08 08:06:37 +000038
39#define is_dbmobject(v) ((v)->ob_type == &Dbmtype)
Guido van Rossum77eecfa1997-07-17 22:56:01 +000040#define check_dbmobject_open(v) if ((v)->di_dbm == NULL) \
Fred Drakee3a41c62000-07-08 05:00:07 +000041 { PyErr_SetString(DbmError, "GDBM object has already been closed"); \
42 return NULL; }
Guido van Rossum77eecfa1997-07-17 22:56:01 +000043
44
Guido van Rossum4b4c6641994-08-08 08:06:37 +000045
Roger E. Masseb15bef81996-12-17 19:55:33 +000046static PyObject *DbmError;
Guido van Rossum4b4c6641994-08-08 08:06:37 +000047
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +000048PyDoc_STRVAR(gdbm_object__doc__,
49"This object represents a GDBM database.\n\
Guido van Rossumbfc49e81998-03-03 22:02:24 +000050GDBM objects behave like mappings (dictionaries), except that keys and\n\
51values are always strings. Printing a GDBM object doesn't print the\n\
52keys and values, and the items() and values() methods are not\n\
53supported.\n\
54\n\
55GDBM objects also support additional operations such as firstkey,\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +000056nextkey, reorganize, and sync.");
Guido van Rossumbfc49e81998-03-03 22:02:24 +000057
Roger E. Masseb15bef81996-12-17 19:55:33 +000058static PyObject *
Fred Drakee3a41c62000-07-08 05:00:07 +000059newdbmobject(char *file, int flags, int mode)
Guido van Rossum4b4c6641994-08-08 08:06:37 +000060{
Fred Drakee3a41c62000-07-08 05:00:07 +000061 dbmobject *dp;
Guido van Rossum4b4c6641994-08-08 08:06:37 +000062
Fred Drakee3a41c62000-07-08 05:00:07 +000063 dp = PyObject_New(dbmobject, &Dbmtype);
64 if (dp == NULL)
65 return NULL;
66 dp->di_size = -1;
67 errno = 0;
68 if ((dp->di_dbm = gdbm_open(file, 0, flags, mode, NULL)) == 0) {
69 if (errno != 0)
70 PyErr_SetFromErrno(DbmError);
71 else
72 PyErr_SetString(DbmError, gdbm_strerror(gdbm_errno));
73 Py_DECREF(dp);
74 return NULL;
75 }
76 return (PyObject *)dp;
Guido van Rossum4b4c6641994-08-08 08:06:37 +000077}
78
79/* Methods */
80
81static void
Fred Drakee3a41c62000-07-08 05:00:07 +000082dbm_dealloc(register dbmobject *dp)
Guido van Rossum4b4c6641994-08-08 08:06:37 +000083{
Fred Drakee3a41c62000-07-08 05:00:07 +000084 if (dp->di_dbm)
85 gdbm_close(dp->di_dbm);
86 PyObject_Del(dp);
Guido van Rossum4b4c6641994-08-08 08:06:37 +000087}
88
Martin v. Löwis18e16552006-02-15 17:27:45 +000089static Py_ssize_t
Fred Drakee3a41c62000-07-08 05:00:07 +000090dbm_length(dbmobject *dp)
Guido van Rossum4b4c6641994-08-08 08:06:37 +000091{
Fred Drakee3a41c62000-07-08 05:00:07 +000092 if (dp->di_dbm == NULL) {
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 }
Guido van Rossum6252e102007-05-23 20:51:02 +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) {
223 item = PyString_FromStringAndSize(key.dptr, key.dsize);
224 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 }
Guido van Rossum6252e102007-05-23 20:51:02 +0000254 if (PyUnicode_Check(arg)) {
255 arg = _PyUnicode_AsDefaultEncodedString(arg, NULL);
256 if (arg == NULL)
257 return -1;
258 }
Guido van Rossum0da7e032006-08-19 23:18:48 +0000259 if (!PyString_Check(arg)) {
260 PyErr_Format(PyExc_TypeError,
261 "gdbm key must be string, not %.100s",
262 arg->ob_type->tp_name);
263 return -1;
264 }
265 key.dptr = PyString_AS_STRING(arg);
266 key.dsize = PyString_GET_SIZE(arg);
267 return gdbm_exists(dp->di_dbm, key);
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000268}
269
Guido van Rossum0da7e032006-08-19 23:18:48 +0000270static PySequenceMethods dbm_as_sequence = {
271 0, /* sq_length */
272 0, /* sq_concat */
273 0, /* sq_repeat */
274 0, /* sq_item */
275 0, /* sq_slice */
276 0, /* sq_ass_item */
277 0, /* sq_ass_slice */
278 dbm_contains, /* sq_contains */
279 0, /* sq_inplace_concat */
280 0, /* sq_inplace_repeat */
281};
282
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000283PyDoc_STRVAR(dbm_firstkey__doc__,
284"firstkey() -> key\n\
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000285It's possible to loop over every key in the database using this method\n\
286and the nextkey() method. The traversal is ordered by GDBM's internal\n\
287hash values, and won't be sorted by the key values. This method\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000288returns the starting key.");
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000289
Roger E. Masseb15bef81996-12-17 19:55:33 +0000290static PyObject *
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000291dbm_firstkey(register dbmobject *dp, PyObject *unused)
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000292{
Fred Drakee3a41c62000-07-08 05:00:07 +0000293 register PyObject *v;
294 datum key;
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000295
Fred Drakee3a41c62000-07-08 05:00:07 +0000296 check_dbmobject_open(dp);
297 key = gdbm_firstkey(dp->di_dbm);
298 if (key.dptr) {
299 v = PyString_FromStringAndSize(key.dptr, key.dsize);
300 free(key.dptr);
301 return v;
302 }
303 else {
304 Py_INCREF(Py_None);
305 return Py_None;
306 }
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000307}
308
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000309PyDoc_STRVAR(dbm_nextkey__doc__,
310"nextkey(key) -> next_key\n\
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000311Returns the key that follows key in the traversal.\n\
312The following code prints every key in the database db, without having\n\
313to create a list in memory that contains them all:\n\
314\n\
315 k = db.firstkey()\n\
316 while k != None:\n\
317 print k\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000318 k = db.nextkey(k)");
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000319
Roger E. Masseb15bef81996-12-17 19:55:33 +0000320static PyObject *
Fred Drakee3a41c62000-07-08 05:00:07 +0000321dbm_nextkey(register dbmobject *dp, PyObject *args)
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000322{
Fred Drakee3a41c62000-07-08 05:00:07 +0000323 register PyObject *v;
324 datum key, nextkey;
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000325
Fred Drakee3a41c62000-07-08 05:00:07 +0000326 if (!PyArg_ParseTuple(args, "s#:nextkey", &key.dptr, &key.dsize))
327 return NULL;
328 check_dbmobject_open(dp);
329 nextkey = gdbm_nextkey(dp->di_dbm, key);
330 if (nextkey.dptr) {
331 v = PyString_FromStringAndSize(nextkey.dptr, nextkey.dsize);
332 free(nextkey.dptr);
333 return v;
334 }
335 else {
336 Py_INCREF(Py_None);
337 return Py_None;
338 }
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000339}
340
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000341PyDoc_STRVAR(dbm_reorganize__doc__,
342"reorganize() -> None\n\
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000343If you have carried out a lot of deletions and would like to shrink\n\
344the space used by the GDBM file, this routine will reorganize the\n\
345database. GDBM will not shorten the length of a database file except\n\
346by using this reorganization; otherwise, deleted file space will be\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000347kept and reused as new (key,value) pairs are added.");
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000348
Roger E. Masseb15bef81996-12-17 19:55:33 +0000349static PyObject *
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000350dbm_reorganize(register dbmobject *dp, PyObject *unused)
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000351{
Fred Drakee3a41c62000-07-08 05:00:07 +0000352 check_dbmobject_open(dp);
353 errno = 0;
354 if (gdbm_reorganize(dp->di_dbm) < 0) {
355 if (errno != 0)
356 PyErr_SetFromErrno(DbmError);
357 else
358 PyErr_SetString(DbmError, gdbm_strerror(gdbm_errno));
359 return NULL;
360 }
361 Py_INCREF(Py_None);
362 return Py_None;
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000363}
364
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000365PyDoc_STRVAR(dbm_sync__doc__,
366"sync() -> None\n\
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000367When the database has been opened in fast mode, this method forces\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000368any unwritten data to be written to the disk.");
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000369
Roger E. Massee5a9c8f1997-03-25 17:39:56 +0000370static PyObject *
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000371dbm_sync(register dbmobject *dp, PyObject *unused)
Roger E. Massee5a9c8f1997-03-25 17:39:56 +0000372{
Fred Drakee3a41c62000-07-08 05:00:07 +0000373 check_dbmobject_open(dp);
374 gdbm_sync(dp->di_dbm);
375 Py_INCREF(Py_None);
376 return Py_None;
Roger E. Massee5a9c8f1997-03-25 17:39:56 +0000377}
378
Roger E. Masseb15bef81996-12-17 19:55:33 +0000379static PyMethodDef dbm_methods[] = {
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000380 {"close", (PyCFunction)dbm_close, METH_NOARGS, dbm_close__doc__},
381 {"keys", (PyCFunction)dbm_keys, METH_NOARGS, dbm_keys__doc__},
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000382 {"firstkey", (PyCFunction)dbm_firstkey,METH_NOARGS, dbm_firstkey__doc__},
Fred Drakee3a41c62000-07-08 05:00:07 +0000383 {"nextkey", (PyCFunction)dbm_nextkey, METH_VARARGS, dbm_nextkey__doc__},
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000384 {"reorganize",(PyCFunction)dbm_reorganize,METH_NOARGS, dbm_reorganize__doc__},
385 {"sync", (PyCFunction)dbm_sync, METH_NOARGS, dbm_sync__doc__},
Fred Drakee3a41c62000-07-08 05:00:07 +0000386 {NULL, NULL} /* sentinel */
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000387};
388
Roger E. Masseb15bef81996-12-17 19:55:33 +0000389static PyObject *
Fred Drakee3a41c62000-07-08 05:00:07 +0000390dbm_getattr(dbmobject *dp, char *name)
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000391{
Fred Drakee3a41c62000-07-08 05:00:07 +0000392 return Py_FindMethod(dbm_methods, (PyObject *)dp, name);
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000393}
394
Roger E. Masseb15bef81996-12-17 19:55:33 +0000395static PyTypeObject Dbmtype = {
Fred Drakee3a41c62000-07-08 05:00:07 +0000396 PyObject_HEAD_INIT(0)
397 0,
Guido van Rossum14648392001-12-08 18:02:58 +0000398 "gdbm.gdbm",
Fred Drakee3a41c62000-07-08 05:00:07 +0000399 sizeof(dbmobject),
400 0,
401 (destructor)dbm_dealloc, /*tp_dealloc*/
402 0, /*tp_print*/
403 (getattrfunc)dbm_getattr, /*tp_getattr*/
404 0, /*tp_setattr*/
405 0, /*tp_compare*/
406 0, /*tp_repr*/
407 0, /*tp_as_number*/
Guido van Rossum0da7e032006-08-19 23:18:48 +0000408 &dbm_as_sequence, /*tp_as_sequence*/
Fred Drakee3a41c62000-07-08 05:00:07 +0000409 &dbm_as_mapping, /*tp_as_mapping*/
410 0, /*tp_hash*/
411 0, /*tp_call*/
412 0, /*tp_str*/
413 0, /*tp_getattro*/
414 0, /*tp_setattro*/
415 0, /*tp_as_buffer*/
416 0, /*tp_xxx4*/
417 gdbm_object__doc__, /*tp_doc*/
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000418};
419
420/* ----------------------------------------------------------------- */
421
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000422PyDoc_STRVAR(dbmopen__doc__,
423"open(filename, [flags, [mode]]) -> dbm_object\n\
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000424Open a dbm database and return a dbm object. The filename argument is\n\
425the name of the database file.\n\
426\n\
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000427The optional flags argument can be 'r' (to open an existing database\n\
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000428for reading only -- default), 'w' (to open an existing database for\n\
429reading and writing), 'c' (which creates the database if it doesn't\n\
430exist), or 'n' (which always creates a new empty database).\n\
431\n\
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000432Some versions of gdbm support additional flags which must be\n\
433appended to one of the flags described above. The module constant\n\
434'open_flags' is a string of valid additional flags. The 'f' flag\n\
435opens the database in fast mode; altered data will not automatically\n\
436be written to the disk after every change. This results in faster\n\
437writes to the database, but may result in an inconsistent database\n\
438if the program crashes while the database is still open. Use the\n\
439sync() method to force any unwritten data to be written to the disk.\n\
440The 's' flag causes all database operations to be synchronized to\n\
441disk. The 'u' flag disables locking of the database file.\n\
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000442\n\
443The optional mode argument is the Unix mode of the file, used only\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000444when the database has to be created. It defaults to octal 0666. ");
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000445
Roger E. Masseb15bef81996-12-17 19:55:33 +0000446static PyObject *
Fred Drakee3a41c62000-07-08 05:00:07 +0000447dbmopen(PyObject *self, PyObject *args)
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000448{
Fred Drakee3a41c62000-07-08 05:00:07 +0000449 char *name;
Andrew M. Kuchlingea271f22004-07-07 14:19:09 +0000450 char *flags = "r";
Fred Drakee3a41c62000-07-08 05:00:07 +0000451 int iflags;
452 int mode = 0666;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000453
Fred Drakee3a41c62000-07-08 05:00:07 +0000454 if (!PyArg_ParseTuple(args, "s|si:open", &name, &flags, &mode))
455 return NULL;
456 switch (flags[0]) {
457 case 'r':
458 iflags = GDBM_READER;
459 break;
460 case 'w':
461 iflags = GDBM_WRITER;
462 break;
463 case 'c':
464 iflags = GDBM_WRCREAT;
465 break;
466 case 'n':
467 iflags = GDBM_NEWDB;
468 break;
469 default:
470 PyErr_SetString(DbmError,
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000471 "First flag must be one of 'r', 'w', 'c' or 'n'");
Fred Drakee3a41c62000-07-08 05:00:07 +0000472 return NULL;
473 }
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000474 for (flags++; *flags != '\0'; flags++) {
475 char buf[40];
476 switch (*flags) {
477#ifdef GDBM_FAST
478 case 'f':
479 iflags |= GDBM_FAST;
480 break;
481#endif
482#ifdef GDBM_SYNC
483 case 's':
484 iflags |= GDBM_SYNC;
485 break;
486#endif
487#ifdef GDBM_NOLOCK
488 case 'u':
489 iflags |= GDBM_NOLOCK;
490 break;
491#endif
492 default:
Tim Peters885d4572001-11-28 20:27:42 +0000493 PyOS_snprintf(buf, sizeof(buf), "Flag '%c' is not supported.",
494 *flags);
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000495 PyErr_SetString(DbmError, buf);
496 return NULL;
497 }
498 }
499
Fred Drakee3a41c62000-07-08 05:00:07 +0000500 return newdbmobject(name, iflags, mode);
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000501}
502
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000503static char dbmmodule_open_flags[] = "rwcn"
504#ifdef GDBM_FAST
505 "f"
506#endif
507#ifdef GDBM_SYNC
508 "s"
509#endif
510#ifdef GDBM_NOLOCK
511 "u"
512#endif
513 ;
514
Roger E. Masseb15bef81996-12-17 19:55:33 +0000515static PyMethodDef dbmmodule_methods[] = {
Fred Drakee3a41c62000-07-08 05:00:07 +0000516 { "open", (PyCFunction)dbmopen, METH_VARARGS, dbmopen__doc__},
517 { 0, 0 },
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000518};
519
Mark Hammondfe51c6d2002-08-02 02:27:13 +0000520PyMODINIT_FUNC
Thomas Wouters58d05102000-07-24 14:43:35 +0000521initgdbm(void) {
Martin v. Löwis00ff10c2001-11-11 14:24:05 +0000522 PyObject *m, *d, *s;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000523
Guido van Rossum0da7e032006-08-19 23:18:48 +0000524 if (PyType_Ready(&Dbmtype) < 0)
525 return;
Fred Drakee3a41c62000-07-08 05:00:07 +0000526 m = Py_InitModule4("gdbm", dbmmodule_methods,
527 gdbmmodule__doc__, (PyObject *)NULL,
528 PYTHON_API_VERSION);
Neal Norwitz1ac754f2006-01-19 06:09:39 +0000529 if (m == NULL)
530 return;
Fred Drakee3a41c62000-07-08 05:00:07 +0000531 d = PyModule_GetDict(m);
532 DbmError = PyErr_NewException("gdbm.error", NULL, NULL);
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000533 if (DbmError != NULL) {
Fred Drakee3a41c62000-07-08 05:00:07 +0000534 PyDict_SetItemString(d, "error", DbmError);
Martin v. Löwis00ff10c2001-11-11 14:24:05 +0000535 s = PyString_FromString(dbmmodule_open_flags);
536 PyDict_SetItemString(d, "open_flags", s);
537 Py_DECREF(s);
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000538 }
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000539}