blob: 12d973b5cee3f2f92672e4c296e17f16a87f2dc9 [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;
Serhiy Storchaka228b12e2017-01-23 09:47:21 +0200258 Py_RETURN_NONE;
Guido van Rossum807b7be1995-07-07 22:37:11 +0000259}
260
Guido van Rossum6252e102007-05-23 20:51:02 +0000261/* XXX Should return a set or a set view */
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300262/*[clinic input]
263_gdbm.gdbm.keys
264
265Get a list of all keys in the database.
266[clinic start generated code]*/
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000267
Roger E. Masseb15bef81996-12-17 19:55:33 +0000268static PyObject *
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300269_gdbm_gdbm_keys_impl(dbmobject *self)
270/*[clinic end generated code: output=cb4b1776c3645dcc input=1832ee0a3132cfaf]*/
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000271{
Antoine Pitrou9ed5f272013-08-13 20:18:52 +0200272 PyObject *v, *item;
Fred Drakee3a41c62000-07-08 05:00:07 +0000273 datum key, nextkey;
274 int err;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000275
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300276 if (self == NULL || !is_dbmobject(self)) {
Fred Drakee3a41c62000-07-08 05:00:07 +0000277 PyErr_BadInternalCall();
278 return NULL;
279 }
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300280 check_dbmobject_open(self);
Guido van Rossum3be71401996-07-21 02:32:44 +0000281
Fred Drakee3a41c62000-07-08 05:00:07 +0000282 v = PyList_New(0);
283 if (v == NULL)
284 return NULL;
Guido van Rossum77eecfa1997-07-17 22:56:01 +0000285
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300286 key = gdbm_firstkey(self->di_dbm);
Fred Drakee3a41c62000-07-08 05:00:07 +0000287 while (key.dptr) {
Christian Heimes72b710a2008-05-26 13:28:38 +0000288 item = PyBytes_FromStringAndSize(key.dptr, key.dsize);
Fred Drakee3a41c62000-07-08 05:00:07 +0000289 if (item == NULL) {
290 free(key.dptr);
291 Py_DECREF(v);
292 return NULL;
293 }
294 err = PyList_Append(v, item);
295 Py_DECREF(item);
296 if (err != 0) {
297 free(key.dptr);
298 Py_DECREF(v);
299 return NULL;
300 }
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300301 nextkey = gdbm_nextkey(self->di_dbm, key);
Fred Drakee3a41c62000-07-08 05:00:07 +0000302 free(key.dptr);
303 key = nextkey;
304 }
305 return v;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000306}
307
Guido van Rossum0da7e032006-08-19 23:18:48 +0000308static int
309dbm_contains(PyObject *self, PyObject *arg)
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000310{
Guido van Rossum0da7e032006-08-19 23:18:48 +0000311 dbmobject *dp = (dbmobject *)self;
Fred Drakee3a41c62000-07-08 05:00:07 +0000312 datum key;
Serhiy Storchaka7d6392c2013-10-25 00:06:52 +0300313 Py_ssize_t size;
Fred Drakee3a41c62000-07-08 05:00:07 +0000314
Guido van Rossum0da7e032006-08-19 23:18:48 +0000315 if ((dp)->di_dbm == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000316 PyErr_SetString(DbmError,
317 "GDBM object has already been closed");
318 return -1;
Guido van Rossum0da7e032006-08-19 23:18:48 +0000319 }
Serhiy Storchaka7d6392c2013-10-25 00:06:52 +0300320 if (PyUnicode_Check(arg)) {
Serhiy Storchaka2a404b62017-01-22 23:07:07 +0200321 key.dptr = (char *)PyUnicode_AsUTF8AndSize(arg, &size);
Serhiy Storchaka7d6392c2013-10-25 00:06:52 +0300322 key.dsize = size;
323 if (key.dptr == NULL)
324 return -1;
325 }
326 else if (!PyBytes_Check(arg)) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000327 PyErr_Format(PyExc_TypeError,
Serhiy Storchaka7d6392c2013-10-25 00:06:52 +0300328 "gdbm key must be bytes or string, not %.100s",
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000329 arg->ob_type->tp_name);
330 return -1;
Guido van Rossum0da7e032006-08-19 23:18:48 +0000331 }
Serhiy Storchaka7d6392c2013-10-25 00:06:52 +0300332 else {
333 key.dptr = PyBytes_AS_STRING(arg);
334 key.dsize = PyBytes_GET_SIZE(arg);
335 }
Guido van Rossum0da7e032006-08-19 23:18:48 +0000336 return gdbm_exists(dp->di_dbm, key);
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000337}
338
Guido van Rossum0da7e032006-08-19 23:18:48 +0000339static PySequenceMethods dbm_as_sequence = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000340 0, /* sq_length */
341 0, /* sq_concat */
342 0, /* sq_repeat */
343 0, /* sq_item */
344 0, /* sq_slice */
345 0, /* sq_ass_item */
346 0, /* sq_ass_slice */
347 dbm_contains, /* sq_contains */
348 0, /* sq_inplace_concat */
349 0, /* sq_inplace_repeat */
Guido van Rossum0da7e032006-08-19 23:18:48 +0000350};
351
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300352/*[clinic input]
353_gdbm.gdbm.firstkey
354
355Return the starting key for the traversal.
356
357It's possible to loop over every key in the database using this method
358and the nextkey() method. The traversal is ordered by GDBM's internal
359hash values, and won't be sorted by the key values.
360[clinic start generated code]*/
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000361
Roger E. Masseb15bef81996-12-17 19:55:33 +0000362static PyObject *
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300363_gdbm_gdbm_firstkey_impl(dbmobject *self)
364/*[clinic end generated code: output=9ff85628d84b65d2 input=0dbd6a335d69bba0]*/
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000365{
Antoine Pitrou9ed5f272013-08-13 20:18:52 +0200366 PyObject *v;
Fred Drakee3a41c62000-07-08 05:00:07 +0000367 datum key;
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000368
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300369 check_dbmobject_open(self);
370 key = gdbm_firstkey(self->di_dbm);
Fred Drakee3a41c62000-07-08 05:00:07 +0000371 if (key.dptr) {
Christian Heimes72b710a2008-05-26 13:28:38 +0000372 v = PyBytes_FromStringAndSize(key.dptr, key.dsize);
Fred Drakee3a41c62000-07-08 05:00:07 +0000373 free(key.dptr);
374 return v;
375 }
376 else {
Serhiy Storchaka228b12e2017-01-23 09:47:21 +0200377 Py_RETURN_NONE;
Fred Drakee3a41c62000-07-08 05:00:07 +0000378 }
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000379}
380
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300381/*[clinic input]
382_gdbm.gdbm.nextkey
383
Larry Hastings38337d12015-05-07 23:30:09 -0700384 key: str(accept={str, robuffer}, zeroes=True)
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300385 /
386
387Returns the key that follows key in the traversal.
388
389The following code prints every key in the database db, without having
390to create a list in memory that contains them all:
391
392 k = db.firstkey()
393 while k != None:
394 print(k)
395 k = db.nextkey(k)
396[clinic start generated code]*/
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000397
Roger E. Masseb15bef81996-12-17 19:55:33 +0000398static PyObject *
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300399_gdbm_gdbm_nextkey_impl(dbmobject *self, const char *key,
400 Py_ssize_clean_t key_length)
Larry Hastings38337d12015-05-07 23:30:09 -0700401/*[clinic end generated code: output=192ab892de6eb2f6 input=1f1606943614e36f]*/
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000402{
Antoine Pitrou9ed5f272013-08-13 20:18:52 +0200403 PyObject *v;
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300404 datum dbm_key, nextkey;
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000405
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300406 dbm_key.dptr = (char *)key;
407 dbm_key.dsize = key_length;
408 check_dbmobject_open(self);
409 nextkey = gdbm_nextkey(self->di_dbm, dbm_key);
Fred Drakee3a41c62000-07-08 05:00:07 +0000410 if (nextkey.dptr) {
Christian Heimes72b710a2008-05-26 13:28:38 +0000411 v = PyBytes_FromStringAndSize(nextkey.dptr, nextkey.dsize);
Fred Drakee3a41c62000-07-08 05:00:07 +0000412 free(nextkey.dptr);
413 return v;
414 }
415 else {
Serhiy Storchaka228b12e2017-01-23 09:47:21 +0200416 Py_RETURN_NONE;
Fred Drakee3a41c62000-07-08 05:00:07 +0000417 }
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000418}
419
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300420/*[clinic input]
421_gdbm.gdbm.reorganize
422
423Reorganize the database.
424
425If you have carried out a lot of deletions and would like to shrink
426the space used by the GDBM file, this routine will reorganize the
427database. GDBM will not shorten the length of a database file except
428by using this reorganization; otherwise, deleted file space will be
429kept and reused as new (key,value) pairs are added.
430[clinic start generated code]*/
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000431
Roger E. Masseb15bef81996-12-17 19:55:33 +0000432static PyObject *
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300433_gdbm_gdbm_reorganize_impl(dbmobject *self)
434/*[clinic end generated code: output=38d9624df92e961d input=f6bea85bcfd40dd2]*/
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000435{
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300436 check_dbmobject_open(self);
Fred Drakee3a41c62000-07-08 05:00:07 +0000437 errno = 0;
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300438 if (gdbm_reorganize(self->di_dbm) < 0) {
Fred Drakee3a41c62000-07-08 05:00:07 +0000439 if (errno != 0)
440 PyErr_SetFromErrno(DbmError);
441 else
442 PyErr_SetString(DbmError, gdbm_strerror(gdbm_errno));
443 return NULL;
444 }
Serhiy Storchaka228b12e2017-01-23 09:47:21 +0200445 Py_RETURN_NONE;
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000446}
447
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300448/*[clinic input]
449_gdbm.gdbm.sync
450
451Flush the database to the disk file.
452
453When the database has been opened in fast mode, this method forces
454any unwritten data to be written to the disk.
455[clinic start generated code]*/
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000456
Roger E. Massee5a9c8f1997-03-25 17:39:56 +0000457static PyObject *
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300458_gdbm_gdbm_sync_impl(dbmobject *self)
459/*[clinic end generated code: output=488b15f47028f125 input=2a47d2c9e153ab8a]*/
Roger E. Massee5a9c8f1997-03-25 17:39:56 +0000460{
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300461 check_dbmobject_open(self);
462 gdbm_sync(self->di_dbm);
Serhiy Storchaka228b12e2017-01-23 09:47:21 +0200463 Py_RETURN_NONE;
Roger E. Massee5a9c8f1997-03-25 17:39:56 +0000464}
465
Nick Coghlanc610aba2013-11-17 15:59:51 +1000466static PyObject *
467dbm__enter__(PyObject *self, PyObject *args)
468{
469 Py_INCREF(self);
470 return self;
471}
472
473static PyObject *
474dbm__exit__(PyObject *self, PyObject *args)
475{
476 _Py_IDENTIFIER(close);
477 return _PyObject_CallMethodId(self, &PyId_close, NULL);
478}
479
Roger E. Masseb15bef81996-12-17 19:55:33 +0000480static PyMethodDef dbm_methods[] = {
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300481 _GDBM_GDBM_CLOSE_METHODDEF
482 _GDBM_GDBM_KEYS_METHODDEF
483 _GDBM_GDBM_FIRSTKEY_METHODDEF
484 _GDBM_GDBM_NEXTKEY_METHODDEF
485 _GDBM_GDBM_REORGANIZE_METHODDEF
486 _GDBM_GDBM_SYNC_METHODDEF
487 _GDBM_GDBM_GET_METHODDEF
488 _GDBM_GDBM_GET_METHODDEF
489 _GDBM_GDBM_SETDEFAULT_METHODDEF
Nick Coghlanc610aba2013-11-17 15:59:51 +1000490 {"__enter__", dbm__enter__, METH_NOARGS, NULL},
491 {"__exit__", dbm__exit__, METH_VARARGS, NULL},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000492 {NULL, NULL} /* sentinel */
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000493};
494
Roger E. Masseb15bef81996-12-17 19:55:33 +0000495static PyTypeObject Dbmtype = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +0000496 PyVarObject_HEAD_INIT(0, 0)
Georg Brandl0a7ac7d2008-05-26 10:29:35 +0000497 "_gdbm.gdbm",
Fred Drakee3a41c62000-07-08 05:00:07 +0000498 sizeof(dbmobject),
499 0,
500 (destructor)dbm_dealloc, /*tp_dealloc*/
501 0, /*tp_print*/
Amaury Forgeot d'Arc1f900f12008-07-02 22:38:47 +0000502 0, /*tp_getattr*/
Fred Drakee3a41c62000-07-08 05:00:07 +0000503 0, /*tp_setattr*/
Mark Dickinsone94c6792009-02-02 20:36:42 +0000504 0, /*tp_reserved*/
Fred Drakee3a41c62000-07-08 05:00:07 +0000505 0, /*tp_repr*/
506 0, /*tp_as_number*/
Guido van Rossum0da7e032006-08-19 23:18:48 +0000507 &dbm_as_sequence, /*tp_as_sequence*/
Fred Drakee3a41c62000-07-08 05:00:07 +0000508 &dbm_as_mapping, /*tp_as_mapping*/
509 0, /*tp_hash*/
510 0, /*tp_call*/
511 0, /*tp_str*/
512 0, /*tp_getattro*/
513 0, /*tp_setattro*/
514 0, /*tp_as_buffer*/
Christian Heimes836baa52008-02-26 08:18:30 +0000515 Py_TPFLAGS_DEFAULT, /*tp_xxx4*/
Fred Drakee3a41c62000-07-08 05:00:07 +0000516 gdbm_object__doc__, /*tp_doc*/
Amaury Forgeot d'Arc1f900f12008-07-02 22:38:47 +0000517 0, /*tp_traverse*/
518 0, /*tp_clear*/
519 0, /*tp_richcompare*/
520 0, /*tp_weaklistoffset*/
521 0, /*tp_iter*/
522 0, /*tp_iternext*/
523 dbm_methods, /*tp_methods*/
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000524};
525
526/* ----------------------------------------------------------------- */
527
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300528/*[clinic input]
529_gdbm.open as dbmopen
530 filename as name: str
531 flags: str="r"
532 mode: int(py_default="0o666") = 0o666
533 /
534
535Open a dbm database and return a dbm object.
536
537The filename argument is the name of the database file.
538
539The optional flags argument can be 'r' (to open an existing database
540for reading only -- default), 'w' (to open an existing database for
541reading and writing), 'c' (which creates the database if it doesn't
542exist), or 'n' (which always creates a new empty database).
543
544Some versions of gdbm support additional flags which must be
545appended to one of the flags described above. The module constant
546'open_flags' is a string of valid additional flags. The 'f' flag
547opens the database in fast mode; altered data will not automatically
548be written to the disk after every change. This results in faster
549writes to the database, but may result in an inconsistent database
550if the program crashes while the database is still open. Use the
551sync() method to force any unwritten data to be written to the disk.
552The 's' flag causes all database operations to be synchronized to
553disk. The 'u' flag disables locking of the database file.
554
555The optional mode argument is the Unix mode of the file, used only
556when the database has to be created. It defaults to octal 0o666.
557[clinic start generated code]*/
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000558
Roger E. Masseb15bef81996-12-17 19:55:33 +0000559static PyObject *
Serhiy Storchaka1a2b24f2016-07-07 17:35:15 +0300560dbmopen_impl(PyObject *module, const char *name, const char *flags, int mode)
561/*[clinic end generated code: output=31aa1bafdf5da688 input=55563cd60e51984a]*/
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000562{
Fred Drakee3a41c62000-07-08 05:00:07 +0000563 int iflags;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000564
Fred Drakee3a41c62000-07-08 05:00:07 +0000565 switch (flags[0]) {
566 case 'r':
567 iflags = GDBM_READER;
568 break;
569 case 'w':
570 iflags = GDBM_WRITER;
571 break;
572 case 'c':
573 iflags = GDBM_WRCREAT;
574 break;
575 case 'n':
576 iflags = GDBM_NEWDB;
577 break;
578 default:
579 PyErr_SetString(DbmError,
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000580 "First flag must be one of 'r', 'w', 'c' or 'n'");
Fred Drakee3a41c62000-07-08 05:00:07 +0000581 return NULL;
582 }
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000583 for (flags++; *flags != '\0'; flags++) {
584 char buf[40];
585 switch (*flags) {
586#ifdef GDBM_FAST
587 case 'f':
588 iflags |= GDBM_FAST;
589 break;
590#endif
591#ifdef GDBM_SYNC
592 case 's':
593 iflags |= GDBM_SYNC;
594 break;
595#endif
596#ifdef GDBM_NOLOCK
597 case 'u':
598 iflags |= GDBM_NOLOCK;
599 break;
600#endif
601 default:
Tim Peters885d4572001-11-28 20:27:42 +0000602 PyOS_snprintf(buf, sizeof(buf), "Flag '%c' is not supported.",
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000603 *flags);
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000604 PyErr_SetString(DbmError, buf);
605 return NULL;
606 }
607 }
608
Fred Drakee3a41c62000-07-08 05:00:07 +0000609 return newdbmobject(name, iflags, mode);
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000610}
611
Serhiy Storchaka2d06e842015-12-25 19:53:18 +0200612static const char dbmmodule_open_flags[] = "rwcn"
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000613#ifdef GDBM_FAST
614 "f"
615#endif
616#ifdef GDBM_SYNC
617 "s"
618#endif
619#ifdef GDBM_NOLOCK
620 "u"
621#endif
622 ;
623
Roger E. Masseb15bef81996-12-17 19:55:33 +0000624static PyMethodDef dbmmodule_methods[] = {
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300625 DBMOPEN_METHODDEF
Fred Drakee3a41c62000-07-08 05:00:07 +0000626 { 0, 0 },
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000627};
628
Martin v. Löwis1a214512008-06-11 05:26:20 +0000629
630static struct PyModuleDef _gdbmmodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000631 PyModuleDef_HEAD_INIT,
632 "_gdbm",
633 gdbmmodule__doc__,
634 -1,
635 dbmmodule_methods,
636 NULL,
637 NULL,
638 NULL,
639 NULL
Martin v. Löwis1a214512008-06-11 05:26:20 +0000640};
641
Mark Hammondfe51c6d2002-08-02 02:27:13 +0000642PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +0000643PyInit__gdbm(void) {
Martin v. Löwis00ff10c2001-11-11 14:24:05 +0000644 PyObject *m, *d, *s;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000645
Guido van Rossum0da7e032006-08-19 23:18:48 +0000646 if (PyType_Ready(&Dbmtype) < 0)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000647 return NULL;
Martin v. Löwis1a214512008-06-11 05:26:20 +0000648 m = PyModule_Create(&_gdbmmodule);
Neal Norwitz1ac754f2006-01-19 06:09:39 +0000649 if (m == NULL)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000650 return NULL;
Fred Drakee3a41c62000-07-08 05:00:07 +0000651 d = PyModule_GetDict(m);
Serhiy Storchaka55fe1ae2017-04-16 10:46:38 +0300652 DbmError = PyErr_NewException("_gdbm.error", PyExc_OSError, NULL);
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000653 if (DbmError != NULL) {
Fred Drakee3a41c62000-07-08 05:00:07 +0000654 PyDict_SetItemString(d, "error", DbmError);
Martin v. Löwis7ac97122007-08-11 19:28:53 +0000655 s = PyUnicode_FromString(dbmmodule_open_flags);
Martin v. Löwis00ff10c2001-11-11 14:24:05 +0000656 PyDict_SetItemString(d, "open_flags", s);
657 Py_DECREF(s);
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000658 }
Martin v. Löwis1a214512008-06-11 05:26:20 +0000659 return m;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000660}