blob: cc94e60745c89df00f965e10b0fce660b28d1716 [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)
Zsolt Cserna9df346b2018-09-27 21:54:34 +020078 PyErr_SetFromErrnoWithFilename(DbmError, file);
Fred Drakee3a41c62000-07-08 05:00:07 +000079 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) {
Xiang Zhang4fb0b8b2018-12-12 20:46:55 +0800189 if (gdbm_errno == GDBM_ITEM_NOT_FOUND) {
190 PyErr_SetObject(PyExc_KeyError, v);
191 }
192 else {
193 PyErr_SetString(DbmError, gdbm_strerror(gdbm_errno));
194 }
Fred Drakee3a41c62000-07-08 05:00:07 +0000195 return -1;
Guido van Rossum77eecfa1997-07-17 22:56:01 +0000196 }
Fred Drakee3a41c62000-07-08 05:00:07 +0000197 }
198 else {
199 if (!PyArg_Parse(w, "s#", &drec.dptr, &drec.dsize)) {
200 PyErr_SetString(PyExc_TypeError,
Xiang Zhang4fb0b8b2018-12-12 20:46:55 +0800201 "gdbm mappings have bytes or string elements only");
Fred Drakee3a41c62000-07-08 05:00:07 +0000202 return -1;
203 }
204 errno = 0;
205 if (gdbm_store(dp->di_dbm, krec, drec, GDBM_REPLACE) < 0) {
206 if (errno != 0)
207 PyErr_SetFromErrno(DbmError);
208 else
209 PyErr_SetString(DbmError,
210 gdbm_strerror(gdbm_errno));
211 return -1;
212 }
213 }
214 return 0;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000215}
216
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300217/*[clinic input]
218_gdbm.gdbm.setdefault
219
220 key: object
221 default: object = None
222 /
223
224Get value for key, or set it to default and return default if not present.
225[clinic start generated code]*/
Georg Brandld9e833c2010-12-04 09:14:36 +0000226
227static PyObject *
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300228_gdbm_gdbm_setdefault_impl(dbmobject *self, PyObject *key,
229 PyObject *default_value)
230/*[clinic end generated code: output=88760ee520329012 input=0db46b69e9680171]*/
Georg Brandld9e833c2010-12-04 09:14:36 +0000231{
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300232 PyObject *res;
Georg Brandld9e833c2010-12-04 09:14:36 +0000233
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300234 res = dbm_subscript(self, key);
Georg Brandld9e833c2010-12-04 09:14:36 +0000235 if (res == NULL && PyErr_ExceptionMatches(PyExc_KeyError)) {
236 PyErr_Clear();
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300237 if (dbm_ass_sub(self, key, default_value) < 0)
Georg Brandld9e833c2010-12-04 09:14:36 +0000238 return NULL;
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300239 return dbm_subscript(self, key);
Georg Brandld9e833c2010-12-04 09:14:36 +0000240 }
241 return res;
242}
243
Roger E. Masseb15bef81996-12-17 19:55:33 +0000244static PyMappingMethods dbm_as_mapping = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000245 (lenfunc)dbm_length, /*mp_length*/
Fred Drakee3a41c62000-07-08 05:00:07 +0000246 (binaryfunc)dbm_subscript, /*mp_subscript*/
247 (objobjargproc)dbm_ass_sub, /*mp_ass_subscript*/
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000248};
249
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300250/*[clinic input]
251_gdbm.gdbm.close
252
253Close the database.
254[clinic start generated code]*/
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000255
Roger E. Masseb15bef81996-12-17 19:55:33 +0000256static PyObject *
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300257_gdbm_gdbm_close_impl(dbmobject *self)
258/*[clinic end generated code: output=23512a594598b563 input=0a203447379b45fd]*/
Guido van Rossum807b7be1995-07-07 22:37:11 +0000259{
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300260 if (self->di_dbm)
261 gdbm_close(self->di_dbm);
262 self->di_dbm = NULL;
Serhiy Storchaka228b12e2017-01-23 09:47:21 +0200263 Py_RETURN_NONE;
Guido van Rossum807b7be1995-07-07 22:37:11 +0000264}
265
Guido van Rossum6252e102007-05-23 20:51:02 +0000266/* XXX Should return a set or a set view */
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300267/*[clinic input]
268_gdbm.gdbm.keys
269
270Get a list of all keys in the database.
271[clinic start generated code]*/
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000272
Roger E. Masseb15bef81996-12-17 19:55:33 +0000273static PyObject *
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300274_gdbm_gdbm_keys_impl(dbmobject *self)
275/*[clinic end generated code: output=cb4b1776c3645dcc input=1832ee0a3132cfaf]*/
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000276{
Antoine Pitrou9ed5f272013-08-13 20:18:52 +0200277 PyObject *v, *item;
Fred Drakee3a41c62000-07-08 05:00:07 +0000278 datum key, nextkey;
279 int err;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000280
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300281 if (self == NULL || !is_dbmobject(self)) {
Fred Drakee3a41c62000-07-08 05:00:07 +0000282 PyErr_BadInternalCall();
283 return NULL;
284 }
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300285 check_dbmobject_open(self);
Guido van Rossum3be71401996-07-21 02:32:44 +0000286
Fred Drakee3a41c62000-07-08 05:00:07 +0000287 v = PyList_New(0);
288 if (v == NULL)
289 return NULL;
Guido van Rossum77eecfa1997-07-17 22:56:01 +0000290
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300291 key = gdbm_firstkey(self->di_dbm);
Fred Drakee3a41c62000-07-08 05:00:07 +0000292 while (key.dptr) {
Christian Heimes72b710a2008-05-26 13:28:38 +0000293 item = PyBytes_FromStringAndSize(key.dptr, key.dsize);
Fred Drakee3a41c62000-07-08 05:00:07 +0000294 if (item == NULL) {
295 free(key.dptr);
296 Py_DECREF(v);
297 return NULL;
298 }
299 err = PyList_Append(v, item);
300 Py_DECREF(item);
301 if (err != 0) {
302 free(key.dptr);
303 Py_DECREF(v);
304 return NULL;
305 }
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300306 nextkey = gdbm_nextkey(self->di_dbm, key);
Fred Drakee3a41c62000-07-08 05:00:07 +0000307 free(key.dptr);
308 key = nextkey;
309 }
310 return v;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000311}
312
Guido van Rossum0da7e032006-08-19 23:18:48 +0000313static int
314dbm_contains(PyObject *self, PyObject *arg)
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000315{
Guido van Rossum0da7e032006-08-19 23:18:48 +0000316 dbmobject *dp = (dbmobject *)self;
Fred Drakee3a41c62000-07-08 05:00:07 +0000317 datum key;
Serhiy Storchaka7d6392c2013-10-25 00:06:52 +0300318 Py_ssize_t size;
Fred Drakee3a41c62000-07-08 05:00:07 +0000319
Guido van Rossum0da7e032006-08-19 23:18:48 +0000320 if ((dp)->di_dbm == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000321 PyErr_SetString(DbmError,
322 "GDBM object has already been closed");
323 return -1;
Guido van Rossum0da7e032006-08-19 23:18:48 +0000324 }
Serhiy Storchaka7d6392c2013-10-25 00:06:52 +0300325 if (PyUnicode_Check(arg)) {
Serhiy Storchaka2a404b62017-01-22 23:07:07 +0200326 key.dptr = (char *)PyUnicode_AsUTF8AndSize(arg, &size);
Serhiy Storchaka7d6392c2013-10-25 00:06:52 +0300327 key.dsize = size;
328 if (key.dptr == NULL)
329 return -1;
330 }
331 else if (!PyBytes_Check(arg)) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000332 PyErr_Format(PyExc_TypeError,
Serhiy Storchaka7d6392c2013-10-25 00:06:52 +0300333 "gdbm key must be bytes or string, not %.100s",
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000334 arg->ob_type->tp_name);
335 return -1;
Guido van Rossum0da7e032006-08-19 23:18:48 +0000336 }
Serhiy Storchaka7d6392c2013-10-25 00:06:52 +0300337 else {
338 key.dptr = PyBytes_AS_STRING(arg);
339 key.dsize = PyBytes_GET_SIZE(arg);
340 }
Guido van Rossum0da7e032006-08-19 23:18:48 +0000341 return gdbm_exists(dp->di_dbm, key);
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000342}
343
Guido van Rossum0da7e032006-08-19 23:18:48 +0000344static PySequenceMethods dbm_as_sequence = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000345 0, /* sq_length */
346 0, /* sq_concat */
347 0, /* sq_repeat */
348 0, /* sq_item */
349 0, /* sq_slice */
350 0, /* sq_ass_item */
351 0, /* sq_ass_slice */
352 dbm_contains, /* sq_contains */
353 0, /* sq_inplace_concat */
354 0, /* sq_inplace_repeat */
Guido van Rossum0da7e032006-08-19 23:18:48 +0000355};
356
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300357/*[clinic input]
358_gdbm.gdbm.firstkey
359
360Return the starting key for the traversal.
361
362It's possible to loop over every key in the database using this method
363and the nextkey() method. The traversal is ordered by GDBM's internal
364hash values, and won't be sorted by the key values.
365[clinic start generated code]*/
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000366
Roger E. Masseb15bef81996-12-17 19:55:33 +0000367static PyObject *
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300368_gdbm_gdbm_firstkey_impl(dbmobject *self)
369/*[clinic end generated code: output=9ff85628d84b65d2 input=0dbd6a335d69bba0]*/
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000370{
Antoine Pitrou9ed5f272013-08-13 20:18:52 +0200371 PyObject *v;
Fred Drakee3a41c62000-07-08 05:00:07 +0000372 datum key;
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000373
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300374 check_dbmobject_open(self);
375 key = gdbm_firstkey(self->di_dbm);
Fred Drakee3a41c62000-07-08 05:00:07 +0000376 if (key.dptr) {
Christian Heimes72b710a2008-05-26 13:28:38 +0000377 v = PyBytes_FromStringAndSize(key.dptr, key.dsize);
Fred Drakee3a41c62000-07-08 05:00:07 +0000378 free(key.dptr);
379 return v;
380 }
381 else {
Serhiy Storchaka228b12e2017-01-23 09:47:21 +0200382 Py_RETURN_NONE;
Fred Drakee3a41c62000-07-08 05:00:07 +0000383 }
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000384}
385
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300386/*[clinic input]
387_gdbm.gdbm.nextkey
388
Larry Hastings38337d12015-05-07 23:30:09 -0700389 key: str(accept={str, robuffer}, zeroes=True)
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300390 /
391
392Returns the key that follows key in the traversal.
393
394The following code prints every key in the database db, without having
395to create a list in memory that contains them all:
396
397 k = db.firstkey()
398 while k != None:
399 print(k)
400 k = db.nextkey(k)
401[clinic start generated code]*/
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000402
Roger E. Masseb15bef81996-12-17 19:55:33 +0000403static PyObject *
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300404_gdbm_gdbm_nextkey_impl(dbmobject *self, const char *key,
405 Py_ssize_clean_t key_length)
Larry Hastings38337d12015-05-07 23:30:09 -0700406/*[clinic end generated code: output=192ab892de6eb2f6 input=1f1606943614e36f]*/
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000407{
Antoine Pitrou9ed5f272013-08-13 20:18:52 +0200408 PyObject *v;
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300409 datum dbm_key, nextkey;
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000410
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300411 dbm_key.dptr = (char *)key;
412 dbm_key.dsize = key_length;
413 check_dbmobject_open(self);
414 nextkey = gdbm_nextkey(self->di_dbm, dbm_key);
Fred Drakee3a41c62000-07-08 05:00:07 +0000415 if (nextkey.dptr) {
Christian Heimes72b710a2008-05-26 13:28:38 +0000416 v = PyBytes_FromStringAndSize(nextkey.dptr, nextkey.dsize);
Fred Drakee3a41c62000-07-08 05:00:07 +0000417 free(nextkey.dptr);
418 return v;
419 }
420 else {
Serhiy Storchaka228b12e2017-01-23 09:47:21 +0200421 Py_RETURN_NONE;
Fred Drakee3a41c62000-07-08 05:00:07 +0000422 }
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000423}
424
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300425/*[clinic input]
426_gdbm.gdbm.reorganize
427
428Reorganize the database.
429
430If you have carried out a lot of deletions and would like to shrink
431the space used by the GDBM file, this routine will reorganize the
432database. GDBM will not shorten the length of a database file except
433by using this reorganization; otherwise, deleted file space will be
434kept and reused as new (key,value) pairs are added.
435[clinic start generated code]*/
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000436
Roger E. Masseb15bef81996-12-17 19:55:33 +0000437static PyObject *
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300438_gdbm_gdbm_reorganize_impl(dbmobject *self)
439/*[clinic end generated code: output=38d9624df92e961d input=f6bea85bcfd40dd2]*/
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000440{
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300441 check_dbmobject_open(self);
Fred Drakee3a41c62000-07-08 05:00:07 +0000442 errno = 0;
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300443 if (gdbm_reorganize(self->di_dbm) < 0) {
Fred Drakee3a41c62000-07-08 05:00:07 +0000444 if (errno != 0)
445 PyErr_SetFromErrno(DbmError);
446 else
447 PyErr_SetString(DbmError, gdbm_strerror(gdbm_errno));
448 return NULL;
449 }
Serhiy Storchaka228b12e2017-01-23 09:47:21 +0200450 Py_RETURN_NONE;
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000451}
452
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300453/*[clinic input]
454_gdbm.gdbm.sync
455
456Flush the database to the disk file.
457
458When the database has been opened in fast mode, this method forces
459any unwritten data to be written to the disk.
460[clinic start generated code]*/
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000461
Roger E. Massee5a9c8f1997-03-25 17:39:56 +0000462static PyObject *
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300463_gdbm_gdbm_sync_impl(dbmobject *self)
464/*[clinic end generated code: output=488b15f47028f125 input=2a47d2c9e153ab8a]*/
Roger E. Massee5a9c8f1997-03-25 17:39:56 +0000465{
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300466 check_dbmobject_open(self);
467 gdbm_sync(self->di_dbm);
Serhiy Storchaka228b12e2017-01-23 09:47:21 +0200468 Py_RETURN_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
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300493 _GDBM_GDBM_SETDEFAULT_METHODDEF
Nick Coghlanc610aba2013-11-17 15:59:51 +1000494 {"__enter__", dbm__enter__, METH_NOARGS, NULL},
495 {"__exit__", dbm__exit__, METH_VARARGS, NULL},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000496 {NULL, NULL} /* sentinel */
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000497};
498
Roger E. Masseb15bef81996-12-17 19:55:33 +0000499static PyTypeObject Dbmtype = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +0000500 PyVarObject_HEAD_INIT(0, 0)
Georg Brandl0a7ac7d2008-05-26 10:29:35 +0000501 "_gdbm.gdbm",
Fred Drakee3a41c62000-07-08 05:00:07 +0000502 sizeof(dbmobject),
503 0,
504 (destructor)dbm_dealloc, /*tp_dealloc*/
505 0, /*tp_print*/
Amaury Forgeot d'Arc1f900f12008-07-02 22:38:47 +0000506 0, /*tp_getattr*/
Fred Drakee3a41c62000-07-08 05:00:07 +0000507 0, /*tp_setattr*/
Mark Dickinsone94c6792009-02-02 20:36:42 +0000508 0, /*tp_reserved*/
Fred Drakee3a41c62000-07-08 05:00:07 +0000509 0, /*tp_repr*/
510 0, /*tp_as_number*/
Guido van Rossum0da7e032006-08-19 23:18:48 +0000511 &dbm_as_sequence, /*tp_as_sequence*/
Fred Drakee3a41c62000-07-08 05:00:07 +0000512 &dbm_as_mapping, /*tp_as_mapping*/
513 0, /*tp_hash*/
514 0, /*tp_call*/
515 0, /*tp_str*/
516 0, /*tp_getattro*/
517 0, /*tp_setattro*/
518 0, /*tp_as_buffer*/
Christian Heimes836baa52008-02-26 08:18:30 +0000519 Py_TPFLAGS_DEFAULT, /*tp_xxx4*/
Fred Drakee3a41c62000-07-08 05:00:07 +0000520 gdbm_object__doc__, /*tp_doc*/
Amaury Forgeot d'Arc1f900f12008-07-02 22:38:47 +0000521 0, /*tp_traverse*/
522 0, /*tp_clear*/
523 0, /*tp_richcompare*/
524 0, /*tp_weaklistoffset*/
525 0, /*tp_iter*/
526 0, /*tp_iternext*/
527 dbm_methods, /*tp_methods*/
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000528};
529
530/* ----------------------------------------------------------------- */
531
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300532/*[clinic input]
533_gdbm.open as dbmopen
Serhiy Storchaka6f600ff2018-02-26 16:02:22 +0200534 filename: unicode
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300535 flags: str="r"
536 mode: int(py_default="0o666") = 0o666
537 /
538
539Open a dbm database and return a dbm object.
540
541The filename argument is the name of the database file.
542
543The optional flags argument can be 'r' (to open an existing database
544for reading only -- default), 'w' (to open an existing database for
545reading and writing), 'c' (which creates the database if it doesn't
546exist), or 'n' (which always creates a new empty database).
547
548Some versions of gdbm support additional flags which must be
549appended to one of the flags described above. The module constant
550'open_flags' is a string of valid additional flags. The 'f' flag
551opens the database in fast mode; altered data will not automatically
552be written to the disk after every change. This results in faster
553writes to the database, but may result in an inconsistent database
554if the program crashes while the database is still open. Use the
555sync() method to force any unwritten data to be written to the disk.
556The 's' flag causes all database operations to be synchronized to
557disk. The 'u' flag disables locking of the database file.
558
559The optional mode argument is the Unix mode of the file, used only
560when the database has to be created. It defaults to octal 0o666.
561[clinic start generated code]*/
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000562
Roger E. Masseb15bef81996-12-17 19:55:33 +0000563static PyObject *
Serhiy Storchaka6f600ff2018-02-26 16:02:22 +0200564dbmopen_impl(PyObject *module, PyObject *filename, const char *flags,
565 int mode)
566/*[clinic end generated code: output=9527750f5df90764 input=3be0b0875974b928]*/
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
Serhiy Storchaka6f600ff2018-02-26 16:02:22 +0200614 PyObject *filenamebytes = PyUnicode_EncodeFSDefault(filename);
615 if (filenamebytes == NULL) {
616 return NULL;
617 }
618 const char *name = PyBytes_AS_STRING(filenamebytes);
619 if (strlen(name) != (size_t)PyBytes_GET_SIZE(filenamebytes)) {
620 Py_DECREF(filenamebytes);
621 PyErr_SetString(PyExc_ValueError, "embedded null character");
622 return NULL;
623 }
624 PyObject *self = newdbmobject(name, iflags, mode);
625 Py_DECREF(filenamebytes);
626 return self;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000627}
628
Serhiy Storchaka2d06e842015-12-25 19:53:18 +0200629static const char dbmmodule_open_flags[] = "rwcn"
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000630#ifdef GDBM_FAST
631 "f"
632#endif
633#ifdef GDBM_SYNC
634 "s"
635#endif
636#ifdef GDBM_NOLOCK
637 "u"
638#endif
639 ;
640
Roger E. Masseb15bef81996-12-17 19:55:33 +0000641static PyMethodDef dbmmodule_methods[] = {
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300642 DBMOPEN_METHODDEF
Fred Drakee3a41c62000-07-08 05:00:07 +0000643 { 0, 0 },
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000644};
645
Martin v. Löwis1a214512008-06-11 05:26:20 +0000646
647static struct PyModuleDef _gdbmmodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000648 PyModuleDef_HEAD_INIT,
649 "_gdbm",
650 gdbmmodule__doc__,
651 -1,
652 dbmmodule_methods,
653 NULL,
654 NULL,
655 NULL,
656 NULL
Martin v. Löwis1a214512008-06-11 05:26:20 +0000657};
658
Mark Hammondfe51c6d2002-08-02 02:27:13 +0000659PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +0000660PyInit__gdbm(void) {
Victor Stinner00f9edb2018-06-19 23:29:22 +0200661 PyObject *m;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000662
Guido van Rossum0da7e032006-08-19 23:18:48 +0000663 if (PyType_Ready(&Dbmtype) < 0)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000664 return NULL;
Martin v. Löwis1a214512008-06-11 05:26:20 +0000665 m = PyModule_Create(&_gdbmmodule);
Victor Stinner00f9edb2018-06-19 23:29:22 +0200666 if (m == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000667 return NULL;
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000668 }
Victor Stinner00f9edb2018-06-19 23:29:22 +0200669
670 DbmError = PyErr_NewException("_gdbm.error", PyExc_OSError, NULL);
671 if (DbmError == NULL) {
672 goto error;
673 }
674 Py_INCREF(DbmError);
675 if (PyModule_AddObject(m, "error", DbmError) < 0) {
676 Py_DECREF(DbmError);
677 goto error;
678 }
679
680 if (PyModule_AddStringConstant(m, "open_flags",
681 dbmmodule_open_flags) < 0) {
682 goto error;
683 }
684
Xiang Zhangb248e952018-06-20 21:23:30 +0800685#if defined(GDBM_VERSION_MAJOR) && defined(GDBM_VERSION_MINOR) && \
686 defined(GDBM_VERSION_PATCH)
Victor Stinner00f9edb2018-06-19 23:29:22 +0200687 PyObject *obj = Py_BuildValue("iii", GDBM_VERSION_MAJOR,
688 GDBM_VERSION_MINOR, GDBM_VERSION_PATCH);
689 if (obj == NULL) {
690 goto error;
691 }
692 if (PyModule_AddObject(m, "_GDBM_VERSION", obj) < 0) {
693 Py_DECREF(obj);
694 goto error;
695 }
Xiang Zhangb248e952018-06-20 21:23:30 +0800696#endif
Victor Stinner00f9edb2018-06-19 23:29:22 +0200697
Martin v. Löwis1a214512008-06-11 05:26:20 +0000698 return m;
Victor Stinner00f9edb2018-06-19 23:29:22 +0200699
700error:
701 Py_DECREF(m);
702 return NULL;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000703}