blob: b840bf5005aa23d060c042c55a017d0262437833 [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
Serhiy Storchaka9260e772015-04-17 21:05:18 +030019/*[clinic input]
20module _gdbm
21class _gdbm.gdbm "dbmobject *" "&Dbmtype"
22[clinic start generated code]*/
23/*[clinic end generated code: output=da39a3ee5e6b4b0d input=113927c6170729b2]*/
24
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +000025PyDoc_STRVAR(gdbmmodule__doc__,
26"This module provides an interface to the GNU DBM (GDBM) library.\n\
Guido van Rossumbfc49e81998-03-03 22:02:24 +000027\n\
28This module is quite similar to the dbm module, but uses GDBM instead to\n\
Serhiy Storchaka9260e772015-04-17 21:05:18 +030029provide some additional functionality. Please note that the file formats\n\
30created by GDBM and dbm are incompatible.\n\
Guido van Rossumbfc49e81998-03-03 22:02:24 +000031\n\
32GDBM objects behave like mappings (dictionaries), except that keys and\n\
Serhiy Storchaka9260e772015-04-17 21:05:18 +030033values are always immutable bytes-like objects or strings. Printing\n\
34a GDBM object doesn't print the keys and values, and the items() and\n\
35values() methods are not supported.");
Guido van Rossumbfc49e81998-03-03 22:02:24 +000036
Guido van Rossum4b4c6641994-08-08 08:06:37 +000037typedef struct {
Fred Drakee3a41c62000-07-08 05:00:07 +000038 PyObject_HEAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000039 int di_size; /* -1 means recompute */
Fred Drakee3a41c62000-07-08 05:00:07 +000040 GDBM_FILE di_dbm;
Guido van Rossum4b4c6641994-08-08 08:06:37 +000041} dbmobject;
42
Jeremy Hylton938ace62002-07-17 16:30:39 +000043static PyTypeObject Dbmtype;
Guido van Rossum4b4c6641994-08-08 08:06:37 +000044
Serhiy Storchaka9260e772015-04-17 21:05:18 +030045#include "clinic/_gdbmmodule.c.h"
46
Christian Heimes90aa7642007-12-19 02:45:37 +000047#define is_dbmobject(v) (Py_TYPE(v) == &Dbmtype)
Guido van Rossum77eecfa1997-07-17 22:56:01 +000048#define check_dbmobject_open(v) if ((v)->di_dbm == NULL) \
Fred Drakee3a41c62000-07-08 05:00:07 +000049 { PyErr_SetString(DbmError, "GDBM object has already been closed"); \
50 return NULL; }
Guido van Rossum77eecfa1997-07-17 22:56:01 +000051
52
Guido van Rossum4b4c6641994-08-08 08:06:37 +000053
Roger E. Masseb15bef81996-12-17 19:55:33 +000054static PyObject *DbmError;
Guido van Rossum4b4c6641994-08-08 08:06:37 +000055
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +000056PyDoc_STRVAR(gdbm_object__doc__,
57"This object represents a GDBM database.\n\
Guido van Rossumbfc49e81998-03-03 22:02:24 +000058GDBM objects behave like mappings (dictionaries), except that keys and\n\
Serhiy Storchaka9260e772015-04-17 21:05:18 +030059values are always immutable bytes-like objects or strings. Printing\n\
60a GDBM object doesn't print the keys and values, and the items() and\n\
61values() methods are not supported.\n\
Guido van Rossumbfc49e81998-03-03 22:02:24 +000062\n\
63GDBM objects also support additional operations such as firstkey,\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +000064nextkey, reorganize, and sync.");
Guido van Rossumbfc49e81998-03-03 22:02:24 +000065
Roger E. Masseb15bef81996-12-17 19:55:33 +000066static PyObject *
Serhiy Storchaka9260e772015-04-17 21:05:18 +030067newdbmobject(const char *file, int flags, int mode)
Guido van Rossum4b4c6641994-08-08 08:06:37 +000068{
Fred Drakee3a41c62000-07-08 05:00:07 +000069 dbmobject *dp;
Guido van Rossum4b4c6641994-08-08 08:06:37 +000070
Fred Drakee3a41c62000-07-08 05:00:07 +000071 dp = PyObject_New(dbmobject, &Dbmtype);
72 if (dp == NULL)
73 return NULL;
74 dp->di_size = -1;
75 errno = 0;
Serhiy Storchaka9260e772015-04-17 21:05:18 +030076 if ((dp->di_dbm = gdbm_open((char *)file, 0, flags, mode, NULL)) == 0) {
Fred Drakee3a41c62000-07-08 05:00:07 +000077 if (errno != 0)
78 PyErr_SetFromErrno(DbmError);
79 else
80 PyErr_SetString(DbmError, gdbm_strerror(gdbm_errno));
81 Py_DECREF(dp);
82 return NULL;
83 }
84 return (PyObject *)dp;
Guido van Rossum4b4c6641994-08-08 08:06:37 +000085}
86
87/* Methods */
88
89static void
Antoine Pitrou9ed5f272013-08-13 20:18:52 +020090dbm_dealloc(dbmobject *dp)
Guido van Rossum4b4c6641994-08-08 08:06:37 +000091{
Fred Drakee3a41c62000-07-08 05:00:07 +000092 if (dp->di_dbm)
93 gdbm_close(dp->di_dbm);
94 PyObject_Del(dp);
Guido van Rossum4b4c6641994-08-08 08:06:37 +000095}
96
Martin v. Löwis18e16552006-02-15 17:27:45 +000097static Py_ssize_t
Fred Drakee3a41c62000-07-08 05:00:07 +000098dbm_length(dbmobject *dp)
Guido van Rossum4b4c6641994-08-08 08:06:37 +000099{
Fred Drakee3a41c62000-07-08 05:00:07 +0000100 if (dp->di_dbm == NULL) {
Guido van Rossum6252e102007-05-23 20:51:02 +0000101 PyErr_SetString(DbmError, "GDBM object has already been closed");
102 return -1;
Fred Drakee3a41c62000-07-08 05:00:07 +0000103 }
104 if (dp->di_size < 0) {
105 datum key,okey;
106 int size;
107 okey.dsize=0;
Thomas Woutersa5fa2a82006-03-01 22:54:36 +0000108 okey.dptr=NULL;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000109
Fred Drakee3a41c62000-07-08 05:00:07 +0000110 size = 0;
111 for (key=gdbm_firstkey(dp->di_dbm); key.dptr;
112 key = gdbm_nextkey(dp->di_dbm,okey)) {
113 size++;
114 if(okey.dsize) free(okey.dptr);
115 okey=key;
116 }
117 dp->di_size = size;
118 }
119 return dp->di_size;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000120}
121
Roger E. Masseb15bef81996-12-17 19:55:33 +0000122static PyObject *
Antoine Pitrou9ed5f272013-08-13 20:18:52 +0200123dbm_subscript(dbmobject *dp, PyObject *key)
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000124{
Fred Drakee3a41c62000-07-08 05:00:07 +0000125 PyObject *v;
126 datum drec, krec;
Fred Drakeda8d2162000-02-07 17:19:41 +0000127
Fred Drakee3a41c62000-07-08 05:00:07 +0000128 if (!PyArg_Parse(key, "s#", &krec.dptr, &krec.dsize) )
129 return NULL;
130
131 if (dp->di_dbm == NULL) {
132 PyErr_SetString(DbmError,
133 "GDBM object has already been closed");
134 return NULL;
135 }
136 drec = gdbm_fetch(dp->di_dbm, krec);
137 if (drec.dptr == 0) {
Guido van Rossum6252e102007-05-23 20:51:02 +0000138 PyErr_SetObject(PyExc_KeyError, key);
Fred Drakee3a41c62000-07-08 05:00:07 +0000139 return NULL;
140 }
Christian Heimes72b710a2008-05-26 13:28:38 +0000141 v = PyBytes_FromStringAndSize(drec.dptr, drec.dsize);
Fred Drakee3a41c62000-07-08 05:00:07 +0000142 free(drec.dptr);
143 return v;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000144}
145
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300146/*[clinic input]
147_gdbm.gdbm.get
148
149 key: object
150 default: object = None
151 /
152
153Get the value for key, or default if not present.
154[clinic start generated code]*/
Georg Brandld9e833c2010-12-04 09:14:36 +0000155
156static PyObject *
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300157_gdbm_gdbm_get_impl(dbmobject *self, PyObject *key, PyObject *default_value)
158/*[clinic end generated code: output=19b7c585ad4f554a input=a9c20423f34c17b6]*/
Georg Brandld9e833c2010-12-04 09:14:36 +0000159{
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300160 PyObject *res;
Georg Brandld9e833c2010-12-04 09:14:36 +0000161
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300162 res = dbm_subscript(self, key);
Georg Brandld9e833c2010-12-04 09:14:36 +0000163 if (res == NULL && PyErr_ExceptionMatches(PyExc_KeyError)) {
164 PyErr_Clear();
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300165 Py_INCREF(default_value);
166 return default_value;
Georg Brandld9e833c2010-12-04 09:14:36 +0000167 }
168 return res;
169}
170
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000171static int
Fred Drakee3a41c62000-07-08 05:00:07 +0000172dbm_ass_sub(dbmobject *dp, PyObject *v, PyObject *w)
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000173{
Fred Drakee3a41c62000-07-08 05:00:07 +0000174 datum krec, drec;
175
176 if (!PyArg_Parse(v, "s#", &krec.dptr, &krec.dsize) ) {
177 PyErr_SetString(PyExc_TypeError,
Brett Cannon7317c1e2008-11-25 19:19:17 +0000178 "gdbm mappings have bytes or string indices only");
Fred Drakee3a41c62000-07-08 05:00:07 +0000179 return -1;
180 }
181 if (dp->di_dbm == NULL) {
182 PyErr_SetString(DbmError,
Guido van Rossum6252e102007-05-23 20:51:02 +0000183 "GDBM object has already been closed");
184 return -1;
Fred Drakee3a41c62000-07-08 05:00:07 +0000185 }
186 dp->di_size = -1;
187 if (w == NULL) {
188 if (gdbm_delete(dp->di_dbm, krec) < 0) {
Guido van Rossum6252e102007-05-23 20:51:02 +0000189 PyErr_SetObject(PyExc_KeyError, v);
Fred Drakee3a41c62000-07-08 05:00:07 +0000190 return -1;
Guido van Rossum77eecfa1997-07-17 22:56:01 +0000191 }
Fred Drakee3a41c62000-07-08 05:00:07 +0000192 }
193 else {
194 if (!PyArg_Parse(w, "s#", &drec.dptr, &drec.dsize)) {
195 PyErr_SetString(PyExc_TypeError,
Brett Cannon7317c1e2008-11-25 19:19:17 +0000196 "gdbm mappings have byte or string elements only");
Fred Drakee3a41c62000-07-08 05:00:07 +0000197 return -1;
198 }
199 errno = 0;
200 if (gdbm_store(dp->di_dbm, krec, drec, GDBM_REPLACE) < 0) {
201 if (errno != 0)
202 PyErr_SetFromErrno(DbmError);
203 else
204 PyErr_SetString(DbmError,
205 gdbm_strerror(gdbm_errno));
206 return -1;
207 }
208 }
209 return 0;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000210}
211
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300212/*[clinic input]
213_gdbm.gdbm.setdefault
214
215 key: object
216 default: object = None
217 /
218
219Get value for key, or set it to default and return default if not present.
220[clinic start generated code]*/
Georg Brandld9e833c2010-12-04 09:14:36 +0000221
222static PyObject *
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300223_gdbm_gdbm_setdefault_impl(dbmobject *self, PyObject *key,
224 PyObject *default_value)
225/*[clinic end generated code: output=88760ee520329012 input=0db46b69e9680171]*/
Georg Brandld9e833c2010-12-04 09:14:36 +0000226{
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300227 PyObject *res;
Georg Brandld9e833c2010-12-04 09:14:36 +0000228
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300229 res = dbm_subscript(self, key);
Georg Brandld9e833c2010-12-04 09:14:36 +0000230 if (res == NULL && PyErr_ExceptionMatches(PyExc_KeyError)) {
231 PyErr_Clear();
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300232 if (dbm_ass_sub(self, key, default_value) < 0)
Georg Brandld9e833c2010-12-04 09:14:36 +0000233 return NULL;
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300234 return dbm_subscript(self, key);
Georg Brandld9e833c2010-12-04 09:14:36 +0000235 }
236 return res;
237}
238
Roger E. Masseb15bef81996-12-17 19:55:33 +0000239static PyMappingMethods dbm_as_mapping = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000240 (lenfunc)dbm_length, /*mp_length*/
Fred Drakee3a41c62000-07-08 05:00:07 +0000241 (binaryfunc)dbm_subscript, /*mp_subscript*/
242 (objobjargproc)dbm_ass_sub, /*mp_ass_subscript*/
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000243};
244
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300245/*[clinic input]
246_gdbm.gdbm.close
247
248Close the database.
249[clinic start generated code]*/
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000250
Roger E. Masseb15bef81996-12-17 19:55:33 +0000251static PyObject *
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300252_gdbm_gdbm_close_impl(dbmobject *self)
253/*[clinic end generated code: output=23512a594598b563 input=0a203447379b45fd]*/
Guido van Rossum807b7be1995-07-07 22:37:11 +0000254{
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300255 if (self->di_dbm)
256 gdbm_close(self->di_dbm);
257 self->di_dbm = NULL;
Fred Drakee3a41c62000-07-08 05:00:07 +0000258 Py_INCREF(Py_None);
259 return Py_None;
Guido van Rossum807b7be1995-07-07 22:37:11 +0000260}
261
Guido van Rossum6252e102007-05-23 20:51:02 +0000262/* XXX Should return a set or a set view */
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300263/*[clinic input]
264_gdbm.gdbm.keys
265
266Get a list of all keys in the database.
267[clinic start generated code]*/
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000268
Roger E. Masseb15bef81996-12-17 19:55:33 +0000269static PyObject *
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300270_gdbm_gdbm_keys_impl(dbmobject *self)
271/*[clinic end generated code: output=cb4b1776c3645dcc input=1832ee0a3132cfaf]*/
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000272{
Antoine Pitrou9ed5f272013-08-13 20:18:52 +0200273 PyObject *v, *item;
Fred Drakee3a41c62000-07-08 05:00:07 +0000274 datum key, nextkey;
275 int err;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000276
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300277 if (self == NULL || !is_dbmobject(self)) {
Fred Drakee3a41c62000-07-08 05:00:07 +0000278 PyErr_BadInternalCall();
279 return NULL;
280 }
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300281 check_dbmobject_open(self);
Guido van Rossum3be71401996-07-21 02:32:44 +0000282
Fred Drakee3a41c62000-07-08 05:00:07 +0000283 v = PyList_New(0);
284 if (v == NULL)
285 return NULL;
Guido van Rossum77eecfa1997-07-17 22:56:01 +0000286
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300287 key = gdbm_firstkey(self->di_dbm);
Fred Drakee3a41c62000-07-08 05:00:07 +0000288 while (key.dptr) {
Christian Heimes72b710a2008-05-26 13:28:38 +0000289 item = PyBytes_FromStringAndSize(key.dptr, key.dsize);
Fred Drakee3a41c62000-07-08 05:00:07 +0000290 if (item == NULL) {
291 free(key.dptr);
292 Py_DECREF(v);
293 return NULL;
294 }
295 err = PyList_Append(v, item);
296 Py_DECREF(item);
297 if (err != 0) {
298 free(key.dptr);
299 Py_DECREF(v);
300 return NULL;
301 }
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300302 nextkey = gdbm_nextkey(self->di_dbm, key);
Fred Drakee3a41c62000-07-08 05:00:07 +0000303 free(key.dptr);
304 key = nextkey;
305 }
306 return v;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000307}
308
Guido van Rossum0da7e032006-08-19 23:18:48 +0000309static int
310dbm_contains(PyObject *self, PyObject *arg)
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000311{
Guido van Rossum0da7e032006-08-19 23:18:48 +0000312 dbmobject *dp = (dbmobject *)self;
Fred Drakee3a41c62000-07-08 05:00:07 +0000313 datum key;
Serhiy Storchaka7d6392c2013-10-25 00:06:52 +0300314 Py_ssize_t size;
Fred Drakee3a41c62000-07-08 05:00:07 +0000315
Guido van Rossum0da7e032006-08-19 23:18:48 +0000316 if ((dp)->di_dbm == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000317 PyErr_SetString(DbmError,
318 "GDBM object has already been closed");
319 return -1;
Guido van Rossum0da7e032006-08-19 23:18:48 +0000320 }
Serhiy Storchaka7d6392c2013-10-25 00:06:52 +0300321 if (PyUnicode_Check(arg)) {
322 key.dptr = PyUnicode_AsUTF8AndSize(arg, &size);
323 key.dsize = size;
324 if (key.dptr == NULL)
325 return -1;
326 }
327 else if (!PyBytes_Check(arg)) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000328 PyErr_Format(PyExc_TypeError,
Serhiy Storchaka7d6392c2013-10-25 00:06:52 +0300329 "gdbm key must be bytes or string, not %.100s",
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000330 arg->ob_type->tp_name);
331 return -1;
Guido van Rossum0da7e032006-08-19 23:18:48 +0000332 }
Serhiy Storchaka7d6392c2013-10-25 00:06:52 +0300333 else {
334 key.dptr = PyBytes_AS_STRING(arg);
335 key.dsize = PyBytes_GET_SIZE(arg);
336 }
Guido van Rossum0da7e032006-08-19 23:18:48 +0000337 return gdbm_exists(dp->di_dbm, key);
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000338}
339
Guido van Rossum0da7e032006-08-19 23:18:48 +0000340static PySequenceMethods dbm_as_sequence = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000341 0, /* sq_length */
342 0, /* sq_concat */
343 0, /* sq_repeat */
344 0, /* sq_item */
345 0, /* sq_slice */
346 0, /* sq_ass_item */
347 0, /* sq_ass_slice */
348 dbm_contains, /* sq_contains */
349 0, /* sq_inplace_concat */
350 0, /* sq_inplace_repeat */
Guido van Rossum0da7e032006-08-19 23:18:48 +0000351};
352
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300353/*[clinic input]
354_gdbm.gdbm.firstkey
355
356Return the starting key for the traversal.
357
358It's possible to loop over every key in the database using this method
359and the nextkey() method. The traversal is ordered by GDBM's internal
360hash values, and won't be sorted by the key values.
361[clinic start generated code]*/
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000362
Roger E. Masseb15bef81996-12-17 19:55:33 +0000363static PyObject *
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300364_gdbm_gdbm_firstkey_impl(dbmobject *self)
365/*[clinic end generated code: output=9ff85628d84b65d2 input=0dbd6a335d69bba0]*/
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000366{
Antoine Pitrou9ed5f272013-08-13 20:18:52 +0200367 PyObject *v;
Fred Drakee3a41c62000-07-08 05:00:07 +0000368 datum key;
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000369
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300370 check_dbmobject_open(self);
371 key = gdbm_firstkey(self->di_dbm);
Fred Drakee3a41c62000-07-08 05:00:07 +0000372 if (key.dptr) {
Christian Heimes72b710a2008-05-26 13:28:38 +0000373 v = PyBytes_FromStringAndSize(key.dptr, key.dsize);
Fred Drakee3a41c62000-07-08 05:00:07 +0000374 free(key.dptr);
375 return v;
376 }
377 else {
378 Py_INCREF(Py_None);
379 return Py_None;
380 }
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000381}
382
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300383/*[clinic input]
384_gdbm.gdbm.nextkey
385
Larry Hastings38337d12015-05-07 23:30:09 -0700386 key: str(accept={str, robuffer}, zeroes=True)
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300387 /
388
389Returns the key that follows key in the traversal.
390
391The following code prints every key in the database db, without having
392to create a list in memory that contains them all:
393
394 k = db.firstkey()
395 while k != None:
396 print(k)
397 k = db.nextkey(k)
398[clinic start generated code]*/
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000399
Roger E. Masseb15bef81996-12-17 19:55:33 +0000400static PyObject *
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300401_gdbm_gdbm_nextkey_impl(dbmobject *self, const char *key,
402 Py_ssize_clean_t key_length)
Larry Hastings38337d12015-05-07 23:30:09 -0700403/*[clinic end generated code: output=192ab892de6eb2f6 input=1f1606943614e36f]*/
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000404{
Antoine Pitrou9ed5f272013-08-13 20:18:52 +0200405 PyObject *v;
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300406 datum dbm_key, nextkey;
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000407
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300408 dbm_key.dptr = (char *)key;
409 dbm_key.dsize = key_length;
410 check_dbmobject_open(self);
411 nextkey = gdbm_nextkey(self->di_dbm, dbm_key);
Fred Drakee3a41c62000-07-08 05:00:07 +0000412 if (nextkey.dptr) {
Christian Heimes72b710a2008-05-26 13:28:38 +0000413 v = PyBytes_FromStringAndSize(nextkey.dptr, nextkey.dsize);
Fred Drakee3a41c62000-07-08 05:00:07 +0000414 free(nextkey.dptr);
415 return v;
416 }
417 else {
418 Py_INCREF(Py_None);
419 return Py_None;
420 }
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000421}
422
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300423/*[clinic input]
424_gdbm.gdbm.reorganize
425
426Reorganize the database.
427
428If you have carried out a lot of deletions and would like to shrink
429the space used by the GDBM file, this routine will reorganize the
430database. GDBM will not shorten the length of a database file except
431by using this reorganization; otherwise, deleted file space will be
432kept and reused as new (key,value) pairs are added.
433[clinic start generated code]*/
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000434
Roger E. Masseb15bef81996-12-17 19:55:33 +0000435static PyObject *
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300436_gdbm_gdbm_reorganize_impl(dbmobject *self)
437/*[clinic end generated code: output=38d9624df92e961d input=f6bea85bcfd40dd2]*/
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000438{
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300439 check_dbmobject_open(self);
Fred Drakee3a41c62000-07-08 05:00:07 +0000440 errno = 0;
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300441 if (gdbm_reorganize(self->di_dbm) < 0) {
Fred Drakee3a41c62000-07-08 05:00:07 +0000442 if (errno != 0)
443 PyErr_SetFromErrno(DbmError);
444 else
445 PyErr_SetString(DbmError, gdbm_strerror(gdbm_errno));
446 return NULL;
447 }
448 Py_INCREF(Py_None);
449 return Py_None;
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000450}
451
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300452/*[clinic input]
453_gdbm.gdbm.sync
454
455Flush the database to the disk file.
456
457When the database has been opened in fast mode, this method forces
458any unwritten data to be written to the disk.
459[clinic start generated code]*/
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000460
Roger E. Massee5a9c8f1997-03-25 17:39:56 +0000461static PyObject *
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300462_gdbm_gdbm_sync_impl(dbmobject *self)
463/*[clinic end generated code: output=488b15f47028f125 input=2a47d2c9e153ab8a]*/
Roger E. Massee5a9c8f1997-03-25 17:39:56 +0000464{
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300465 check_dbmobject_open(self);
466 gdbm_sync(self->di_dbm);
Fred Drakee3a41c62000-07-08 05:00:07 +0000467 Py_INCREF(Py_None);
468 return Py_None;
Roger E. Massee5a9c8f1997-03-25 17:39:56 +0000469}
470
Nick Coghlanc610aba2013-11-17 15:59:51 +1000471static PyObject *
472dbm__enter__(PyObject *self, PyObject *args)
473{
474 Py_INCREF(self);
475 return self;
476}
477
478static PyObject *
479dbm__exit__(PyObject *self, PyObject *args)
480{
481 _Py_IDENTIFIER(close);
482 return _PyObject_CallMethodId(self, &PyId_close, NULL);
483}
484
Roger E. Masseb15bef81996-12-17 19:55:33 +0000485static PyMethodDef dbm_methods[] = {
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300486 _GDBM_GDBM_CLOSE_METHODDEF
487 _GDBM_GDBM_KEYS_METHODDEF
488 _GDBM_GDBM_FIRSTKEY_METHODDEF
489 _GDBM_GDBM_NEXTKEY_METHODDEF
490 _GDBM_GDBM_REORGANIZE_METHODDEF
491 _GDBM_GDBM_SYNC_METHODDEF
492 _GDBM_GDBM_GET_METHODDEF
493 _GDBM_GDBM_GET_METHODDEF
494 _GDBM_GDBM_SETDEFAULT_METHODDEF
Nick Coghlanc610aba2013-11-17 15:59:51 +1000495 {"__enter__", dbm__enter__, METH_NOARGS, NULL},
496 {"__exit__", dbm__exit__, METH_VARARGS, NULL},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000497 {NULL, NULL} /* sentinel */
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000498};
499
Roger E. Masseb15bef81996-12-17 19:55:33 +0000500static PyTypeObject Dbmtype = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +0000501 PyVarObject_HEAD_INIT(0, 0)
Georg Brandl0a7ac7d2008-05-26 10:29:35 +0000502 "_gdbm.gdbm",
Fred Drakee3a41c62000-07-08 05:00:07 +0000503 sizeof(dbmobject),
504 0,
505 (destructor)dbm_dealloc, /*tp_dealloc*/
506 0, /*tp_print*/
Amaury Forgeot d'Arc1f900f12008-07-02 22:38:47 +0000507 0, /*tp_getattr*/
Fred Drakee3a41c62000-07-08 05:00:07 +0000508 0, /*tp_setattr*/
Mark Dickinsone94c6792009-02-02 20:36:42 +0000509 0, /*tp_reserved*/
Fred Drakee3a41c62000-07-08 05:00:07 +0000510 0, /*tp_repr*/
511 0, /*tp_as_number*/
Guido van Rossum0da7e032006-08-19 23:18:48 +0000512 &dbm_as_sequence, /*tp_as_sequence*/
Fred Drakee3a41c62000-07-08 05:00:07 +0000513 &dbm_as_mapping, /*tp_as_mapping*/
514 0, /*tp_hash*/
515 0, /*tp_call*/
516 0, /*tp_str*/
517 0, /*tp_getattro*/
518 0, /*tp_setattro*/
519 0, /*tp_as_buffer*/
Christian Heimes836baa52008-02-26 08:18:30 +0000520 Py_TPFLAGS_DEFAULT, /*tp_xxx4*/
Fred Drakee3a41c62000-07-08 05:00:07 +0000521 gdbm_object__doc__, /*tp_doc*/
Amaury Forgeot d'Arc1f900f12008-07-02 22:38:47 +0000522 0, /*tp_traverse*/
523 0, /*tp_clear*/
524 0, /*tp_richcompare*/
525 0, /*tp_weaklistoffset*/
526 0, /*tp_iter*/
527 0, /*tp_iternext*/
528 dbm_methods, /*tp_methods*/
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000529};
530
531/* ----------------------------------------------------------------- */
532
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300533/*[clinic input]
534_gdbm.open as dbmopen
535 filename as name: str
536 flags: str="r"
537 mode: int(py_default="0o666") = 0o666
538 /
539
540Open a dbm database and return a dbm object.
541
542The filename argument is the name of the database file.
543
544The optional flags argument can be 'r' (to open an existing database
545for reading only -- default), 'w' (to open an existing database for
546reading and writing), 'c' (which creates the database if it doesn't
547exist), or 'n' (which always creates a new empty database).
548
549Some versions of gdbm support additional flags which must be
550appended to one of the flags described above. The module constant
551'open_flags' is a string of valid additional flags. The 'f' flag
552opens the database in fast mode; altered data will not automatically
553be written to the disk after every change. This results in faster
554writes to the database, but may result in an inconsistent database
555if the program crashes while the database is still open. Use the
556sync() method to force any unwritten data to be written to the disk.
557The 's' flag causes all database operations to be synchronized to
558disk. The 'u' flag disables locking of the database file.
559
560The optional mode argument is the Unix mode of the file, used only
561when the database has to be created. It defaults to octal 0o666.
562[clinic start generated code]*/
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000563
Roger E. Masseb15bef81996-12-17 19:55:33 +0000564static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300565dbmopen_impl(PyObject *module, const char *name, const char *flags, int mode)
566/*[clinic end generated code: output=31aa1bafdf5da688 input=55563cd60e51984a]*/
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000567{
Fred Drakee3a41c62000-07-08 05:00:07 +0000568 int iflags;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000569
Fred Drakee3a41c62000-07-08 05:00:07 +0000570 switch (flags[0]) {
571 case 'r':
572 iflags = GDBM_READER;
573 break;
574 case 'w':
575 iflags = GDBM_WRITER;
576 break;
577 case 'c':
578 iflags = GDBM_WRCREAT;
579 break;
580 case 'n':
581 iflags = GDBM_NEWDB;
582 break;
583 default:
584 PyErr_SetString(DbmError,
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000585 "First flag must be one of 'r', 'w', 'c' or 'n'");
Fred Drakee3a41c62000-07-08 05:00:07 +0000586 return NULL;
587 }
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000588 for (flags++; *flags != '\0'; flags++) {
589 char buf[40];
590 switch (*flags) {
591#ifdef GDBM_FAST
592 case 'f':
593 iflags |= GDBM_FAST;
594 break;
595#endif
596#ifdef GDBM_SYNC
597 case 's':
598 iflags |= GDBM_SYNC;
599 break;
600#endif
601#ifdef GDBM_NOLOCK
602 case 'u':
603 iflags |= GDBM_NOLOCK;
604 break;
605#endif
606 default:
Tim Peters885d4572001-11-28 20:27:42 +0000607 PyOS_snprintf(buf, sizeof(buf), "Flag '%c' is not supported.",
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000608 *flags);
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000609 PyErr_SetString(DbmError, buf);
610 return NULL;
611 }
612 }
613
Fred Drakee3a41c62000-07-08 05:00:07 +0000614 return newdbmobject(name, iflags, mode);
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000615}
616
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000617static char dbmmodule_open_flags[] = "rwcn"
618#ifdef GDBM_FAST
619 "f"
620#endif
621#ifdef GDBM_SYNC
622 "s"
623#endif
624#ifdef GDBM_NOLOCK
625 "u"
626#endif
627 ;
628
Roger E. Masseb15bef81996-12-17 19:55:33 +0000629static PyMethodDef dbmmodule_methods[] = {
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300630 DBMOPEN_METHODDEF
Fred Drakee3a41c62000-07-08 05:00:07 +0000631 { 0, 0 },
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000632};
633
Martin v. Löwis1a214512008-06-11 05:26:20 +0000634
635static struct PyModuleDef _gdbmmodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000636 PyModuleDef_HEAD_INIT,
637 "_gdbm",
638 gdbmmodule__doc__,
639 -1,
640 dbmmodule_methods,
641 NULL,
642 NULL,
643 NULL,
644 NULL
Martin v. Löwis1a214512008-06-11 05:26:20 +0000645};
646
Mark Hammondfe51c6d2002-08-02 02:27:13 +0000647PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +0000648PyInit__gdbm(void) {
Martin v. Löwis00ff10c2001-11-11 14:24:05 +0000649 PyObject *m, *d, *s;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000650
Guido van Rossum0da7e032006-08-19 23:18:48 +0000651 if (PyType_Ready(&Dbmtype) < 0)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000652 return NULL;
Martin v. Löwis1a214512008-06-11 05:26:20 +0000653 m = PyModule_Create(&_gdbmmodule);
Neal Norwitz1ac754f2006-01-19 06:09:39 +0000654 if (m == NULL)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000655 return NULL;
Fred Drakee3a41c62000-07-08 05:00:07 +0000656 d = PyModule_GetDict(m);
Georg Brandlb17acad2008-05-28 08:43:17 +0000657 DbmError = PyErr_NewException("_gdbm.error", PyExc_IOError, NULL);
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000658 if (DbmError != NULL) {
Fred Drakee3a41c62000-07-08 05:00:07 +0000659 PyDict_SetItemString(d, "error", DbmError);
Martin v. Löwis7ac97122007-08-11 19:28:53 +0000660 s = PyUnicode_FromString(dbmmodule_open_flags);
Martin v. Löwis00ff10c2001-11-11 14:24:05 +0000661 PyDict_SetItemString(d, "open_flags", s);
662 Py_DECREF(s);
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000663 }
Martin v. Löwis1a214512008-06-11 05:26:20 +0000664 return m;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000665}