blob: 6ca3ed6cc36fcc7b99389e02828d9a6043a649e5 [file] [log] [blame]
Guido van Rossum4b4c6641994-08-08 08:06:37 +00001
Dong-hee Nac4862e32020-06-17 01:41:23 +09002/* GDBM 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
Inada Naokic5a216e2019-03-20 19:01:55 +09006#define PY_SSIZE_T_CLEAN
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
Dong-hee Nac4862e32020-06-17 01:41:23 +090019typedef struct {
20 PyTypeObject *gdbm_type;
21 PyObject *gdbm_error;
22} _gdbm_state;
23
24static inline _gdbm_state*
25get_gdbm_state(PyObject *module)
26{
27 void *state = PyModule_GetState(module);
28 assert(state != NULL);
29 return (_gdbm_state *)state;
30}
31
Serhiy Storchaka9260e772015-04-17 21:05:18 +030032/*[clinic input]
33module _gdbm
Dong-hee Nac4862e32020-06-17 01:41:23 +090034class _gdbm.gdbm "gdbmobject *" "&Gdbmtype"
Serhiy Storchaka9260e772015-04-17 21:05:18 +030035[clinic start generated code]*/
Dong-hee Nac4862e32020-06-17 01:41:23 +090036/*[clinic end generated code: output=da39a3ee5e6b4b0d input=38ae71cedfc7172b]*/
Serhiy Storchaka9260e772015-04-17 21:05:18 +030037
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +000038PyDoc_STRVAR(gdbmmodule__doc__,
39"This module provides an interface to the GNU DBM (GDBM) library.\n\
Guido van Rossumbfc49e81998-03-03 22:02:24 +000040\n\
41This module is quite similar to the dbm module, but uses GDBM instead to\n\
Serhiy Storchaka9260e772015-04-17 21:05:18 +030042provide some additional functionality. Please note that the file formats\n\
43created by GDBM and dbm are incompatible.\n\
Guido van Rossumbfc49e81998-03-03 22:02:24 +000044\n\
45GDBM objects behave like mappings (dictionaries), except that keys and\n\
Serhiy Storchaka9260e772015-04-17 21:05:18 +030046values are always immutable bytes-like objects or strings. Printing\n\
47a GDBM object doesn't print the keys and values, and the items() and\n\
48values() methods are not supported.");
Guido van Rossumbfc49e81998-03-03 22:02:24 +000049
Guido van Rossum4b4c6641994-08-08 08:06:37 +000050typedef struct {
Fred Drakee3a41c62000-07-08 05:00:07 +000051 PyObject_HEAD
Dong-hee Na87276642020-05-01 21:15:35 +090052 Py_ssize_t di_size; /* -1 means recompute */
Fred Drakee3a41c62000-07-08 05:00:07 +000053 GDBM_FILE di_dbm;
Dong-hee Nac4862e32020-06-17 01:41:23 +090054} gdbmobject;
Guido van Rossum4b4c6641994-08-08 08:06:37 +000055
Serhiy Storchaka9260e772015-04-17 21:05:18 +030056#include "clinic/_gdbmmodule.c.h"
57
Dong-hee Nac4862e32020-06-17 01:41:23 +090058#define check_gdbmobject_open(v, err) \
59 if ((v)->di_dbm == NULL) { \
60 PyErr_SetString(err, "GDBM object has already been closed"); \
61 return NULL; \
62 }
Guido van Rossum4b4c6641994-08-08 08:06:37 +000063
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +000064PyDoc_STRVAR(gdbm_object__doc__,
65"This object represents a GDBM database.\n\
Guido van Rossumbfc49e81998-03-03 22:02:24 +000066GDBM objects behave like mappings (dictionaries), except that keys and\n\
Serhiy Storchaka9260e772015-04-17 21:05:18 +030067values are always immutable bytes-like objects or strings. Printing\n\
68a GDBM object doesn't print the keys and values, and the items() and\n\
69values() methods are not supported.\n\
Guido van Rossumbfc49e81998-03-03 22:02:24 +000070\n\
71GDBM objects also support additional operations such as firstkey,\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +000072nextkey, reorganize, and sync.");
Guido van Rossumbfc49e81998-03-03 22:02:24 +000073
Roger E. Masseb15bef81996-12-17 19:55:33 +000074static PyObject *
Dong-hee Nac4862e32020-06-17 01:41:23 +090075newgdbmobject(_gdbm_state *state, const char *file, int flags, int mode)
Guido van Rossum4b4c6641994-08-08 08:06:37 +000076{
Miss Islington (bot)0bf05002021-05-27 08:26:15 -070077 gdbmobject *dp = PyObject_GC_New(gdbmobject, state->gdbm_type);
Dong-hee Nac4862e32020-06-17 01:41:23 +090078 if (dp == NULL) {
Fred Drakee3a41c62000-07-08 05:00:07 +000079 return NULL;
Dong-hee Nac4862e32020-06-17 01:41:23 +090080 }
Fred Drakee3a41c62000-07-08 05:00:07 +000081 dp->di_size = -1;
82 errno = 0;
Miss Islington (bot)0bf05002021-05-27 08:26:15 -070083 PyObject_GC_Track(dp);
84
Serhiy Storchaka9260e772015-04-17 21:05:18 +030085 if ((dp->di_dbm = gdbm_open((char *)file, 0, flags, mode, NULL)) == 0) {
Dong-hee Nac4862e32020-06-17 01:41:23 +090086 if (errno != 0) {
87 PyErr_SetFromErrnoWithFilename(state->gdbm_error, file);
88 }
89 else {
90 PyErr_SetString(state->gdbm_error, gdbm_strerror(gdbm_errno));
91 }
Fred Drakee3a41c62000-07-08 05:00:07 +000092 Py_DECREF(dp);
93 return NULL;
94 }
95 return (PyObject *)dp;
Guido van Rossum4b4c6641994-08-08 08:06:37 +000096}
97
98/* Methods */
Miss Islington (bot)0bf05002021-05-27 08:26:15 -070099static int
100gdbm_traverse(gdbmobject *dp, visitproc visit, void *arg)
101{
102 Py_VISIT(Py_TYPE(dp));
103 return 0;
104}
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000105
106static void
Dong-hee Nac4862e32020-06-17 01:41:23 +0900107gdbm_dealloc(gdbmobject *dp)
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000108{
Miss Islington (bot)0bf05002021-05-27 08:26:15 -0700109 PyObject_GC_UnTrack(dp);
Dong-hee Nac4862e32020-06-17 01:41:23 +0900110 if (dp->di_dbm) {
Fred Drakee3a41c62000-07-08 05:00:07 +0000111 gdbm_close(dp->di_dbm);
Dong-hee Nac4862e32020-06-17 01:41:23 +0900112 }
113 PyTypeObject *tp = Py_TYPE(dp);
114 tp->tp_free(dp);
115 Py_DECREF(tp);
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000116}
117
Martin v. Löwis18e16552006-02-15 17:27:45 +0000118static Py_ssize_t
Dong-hee Nac4862e32020-06-17 01:41:23 +0900119gdbm_length(gdbmobject *dp)
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000120{
Dong-hee Nac4862e32020-06-17 01:41:23 +0900121 _gdbm_state *state = PyType_GetModuleState(Py_TYPE(dp));
Fred Drakee3a41c62000-07-08 05:00:07 +0000122 if (dp->di_dbm == NULL) {
Dong-hee Nac4862e32020-06-17 01:41:23 +0900123 PyErr_SetString(state->gdbm_error, "GDBM object has already been closed");
Guido van Rossum6252e102007-05-23 20:51:02 +0000124 return -1;
Fred Drakee3a41c62000-07-08 05:00:07 +0000125 }
126 if (dp->di_size < 0) {
Dong-hee Na87276642020-05-01 21:15:35 +0900127#if GDBM_VERSION_MAJOR >= 1 && GDBM_VERSION_MINOR >= 11
128 errno = 0;
129 gdbm_count_t count;
130 if (gdbm_count(dp->di_dbm, &count) == -1) {
131 if (errno != 0) {
Dong-hee Nac4862e32020-06-17 01:41:23 +0900132 PyErr_SetFromErrno(state->gdbm_error);
Dong-hee Na87276642020-05-01 21:15:35 +0900133 }
134 else {
Dong-hee Nac4862e32020-06-17 01:41:23 +0900135 PyErr_SetString(state->gdbm_error, gdbm_strerror(gdbm_errno));
Dong-hee Na87276642020-05-01 21:15:35 +0900136 }
137 return -1;
138 }
139 if (count > PY_SSIZE_T_MAX) {
140 PyErr_SetString(PyExc_OverflowError, "count exceeds PY_SSIZE_T_MAX");
141 return -1;
142 }
143 dp->di_size = count;
144#else
Fred Drakee3a41c62000-07-08 05:00:07 +0000145 datum key,okey;
Fred Drakee3a41c62000-07-08 05:00:07 +0000146 okey.dsize=0;
Thomas Woutersa5fa2a82006-03-01 22:54:36 +0000147 okey.dptr=NULL;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000148
Dong-hee Na87276642020-05-01 21:15:35 +0900149 Py_ssize_t size = 0;
150 for (key = gdbm_firstkey(dp->di_dbm); key.dptr;
Fred Drakee3a41c62000-07-08 05:00:07 +0000151 key = gdbm_nextkey(dp->di_dbm,okey)) {
152 size++;
Dong-hee Na87276642020-05-01 21:15:35 +0900153 if (okey.dsize) {
154 free(okey.dptr);
155 }
Fred Drakee3a41c62000-07-08 05:00:07 +0000156 okey=key;
157 }
158 dp->di_size = size;
Dong-hee Na87276642020-05-01 21:15:35 +0900159#endif
Fred Drakee3a41c62000-07-08 05:00:07 +0000160 }
161 return dp->di_size;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000162}
163
Inada Naokic5a216e2019-03-20 19:01:55 +0900164// Wrapper function for PyArg_Parse(o, "s#", &d.dptr, &d.size).
165// This function is needed to support PY_SSIZE_T_CLEAN.
166// Return 1 on success, same to PyArg_Parse().
167static int
168parse_datum(PyObject *o, datum *d, const char *failmsg)
169{
170 Py_ssize_t size;
171 if (!PyArg_Parse(o, "s#", &d->dptr, &size)) {
172 if (failmsg != NULL) {
173 PyErr_SetString(PyExc_TypeError, failmsg);
174 }
175 return 0;
176 }
177 if (INT_MAX < size) {
178 PyErr_SetString(PyExc_OverflowError, "size does not fit in an int");
179 return 0;
180 }
181 d->dsize = size;
182 return 1;
183}
184
Roger E. Masseb15bef81996-12-17 19:55:33 +0000185static PyObject *
Dong-hee Nac4862e32020-06-17 01:41:23 +0900186gdbm_subscript(gdbmobject *dp, PyObject *key)
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000187{
Fred Drakee3a41c62000-07-08 05:00:07 +0000188 PyObject *v;
189 datum drec, krec;
Dong-hee Nac4862e32020-06-17 01:41:23 +0900190 _gdbm_state *state = PyType_GetModuleState(Py_TYPE(dp));
Fred Drakeda8d2162000-02-07 17:19:41 +0000191
Inada Naokic5a216e2019-03-20 19:01:55 +0900192 if (!parse_datum(key, &krec, NULL)) {
Fred Drakee3a41c62000-07-08 05:00:07 +0000193 return NULL;
Inada Naokic5a216e2019-03-20 19:01:55 +0900194 }
Fred Drakee3a41c62000-07-08 05:00:07 +0000195 if (dp->di_dbm == NULL) {
Dong-hee Nac4862e32020-06-17 01:41:23 +0900196 PyErr_SetString(state->gdbm_error,
Fred Drakee3a41c62000-07-08 05:00:07 +0000197 "GDBM object has already been closed");
198 return NULL;
199 }
200 drec = gdbm_fetch(dp->di_dbm, krec);
201 if (drec.dptr == 0) {
Guido van Rossum6252e102007-05-23 20:51:02 +0000202 PyErr_SetObject(PyExc_KeyError, key);
Fred Drakee3a41c62000-07-08 05:00:07 +0000203 return NULL;
204 }
Christian Heimes72b710a2008-05-26 13:28:38 +0000205 v = PyBytes_FromStringAndSize(drec.dptr, drec.dsize);
Fred Drakee3a41c62000-07-08 05:00:07 +0000206 free(drec.dptr);
207 return v;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000208}
209
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300210/*[clinic input]
211_gdbm.gdbm.get
212
213 key: object
214 default: object = None
215 /
216
217Get the value for key, or default if not present.
218[clinic start generated code]*/
Georg Brandld9e833c2010-12-04 09:14:36 +0000219
220static PyObject *
Dong-hee Nac4862e32020-06-17 01:41:23 +0900221_gdbm_gdbm_get_impl(gdbmobject *self, PyObject *key, PyObject *default_value)
222/*[clinic end generated code: output=92421838f3a852f4 input=a9c20423f34c17b6]*/
Georg Brandld9e833c2010-12-04 09:14:36 +0000223{
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300224 PyObject *res;
Georg Brandld9e833c2010-12-04 09:14:36 +0000225
Dong-hee Nac4862e32020-06-17 01:41:23 +0900226 res = gdbm_subscript(self, key);
Georg Brandld9e833c2010-12-04 09:14:36 +0000227 if (res == NULL && PyErr_ExceptionMatches(PyExc_KeyError)) {
228 PyErr_Clear();
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300229 Py_INCREF(default_value);
230 return default_value;
Georg Brandld9e833c2010-12-04 09:14:36 +0000231 }
232 return res;
233}
234
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000235static int
Dong-hee Nac4862e32020-06-17 01:41:23 +0900236gdbm_ass_sub(gdbmobject *dp, PyObject *v, PyObject *w)
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000237{
Fred Drakee3a41c62000-07-08 05:00:07 +0000238 datum krec, drec;
Inada Naokic5a216e2019-03-20 19:01:55 +0900239 const char *failmsg = "gdbm mappings have bytes or string indices only";
Dong-hee Nac4862e32020-06-17 01:41:23 +0900240 _gdbm_state *state = PyType_GetModuleState(Py_TYPE(dp));
Fred Drakee3a41c62000-07-08 05:00:07 +0000241
Inada Naokic5a216e2019-03-20 19:01:55 +0900242 if (!parse_datum(v, &krec, failmsg)) {
Fred Drakee3a41c62000-07-08 05:00:07 +0000243 return -1;
244 }
245 if (dp->di_dbm == NULL) {
Dong-hee Nac4862e32020-06-17 01:41:23 +0900246 PyErr_SetString(state->gdbm_error,
Guido van Rossum6252e102007-05-23 20:51:02 +0000247 "GDBM object has already been closed");
248 return -1;
Fred Drakee3a41c62000-07-08 05:00:07 +0000249 }
250 dp->di_size = -1;
251 if (w == NULL) {
252 if (gdbm_delete(dp->di_dbm, krec) < 0) {
Xiang Zhang4fb0b8b2018-12-12 20:46:55 +0800253 if (gdbm_errno == GDBM_ITEM_NOT_FOUND) {
254 PyErr_SetObject(PyExc_KeyError, v);
255 }
256 else {
Dong-hee Nac4862e32020-06-17 01:41:23 +0900257 PyErr_SetString(state->gdbm_error, gdbm_strerror(gdbm_errno));
Xiang Zhang4fb0b8b2018-12-12 20:46:55 +0800258 }
Fred Drakee3a41c62000-07-08 05:00:07 +0000259 return -1;
Guido van Rossum77eecfa1997-07-17 22:56:01 +0000260 }
Fred Drakee3a41c62000-07-08 05:00:07 +0000261 }
262 else {
Inada Naokic5a216e2019-03-20 19:01:55 +0900263 if (!parse_datum(w, &drec, failmsg)) {
Fred Drakee3a41c62000-07-08 05:00:07 +0000264 return -1;
265 }
266 errno = 0;
267 if (gdbm_store(dp->di_dbm, krec, drec, GDBM_REPLACE) < 0) {
268 if (errno != 0)
Dong-hee Nac4862e32020-06-17 01:41:23 +0900269 PyErr_SetFromErrno(state->gdbm_error);
Fred Drakee3a41c62000-07-08 05:00:07 +0000270 else
Dong-hee Nac4862e32020-06-17 01:41:23 +0900271 PyErr_SetString(state->gdbm_error,
Fred Drakee3a41c62000-07-08 05:00:07 +0000272 gdbm_strerror(gdbm_errno));
273 return -1;
274 }
275 }
276 return 0;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000277}
278
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300279/*[clinic input]
280_gdbm.gdbm.setdefault
281
282 key: object
283 default: object = None
284 /
285
286Get value for key, or set it to default and return default if not present.
287[clinic start generated code]*/
Georg Brandld9e833c2010-12-04 09:14:36 +0000288
289static PyObject *
Dong-hee Nac4862e32020-06-17 01:41:23 +0900290_gdbm_gdbm_setdefault_impl(gdbmobject *self, PyObject *key,
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300291 PyObject *default_value)
Dong-hee Nac4862e32020-06-17 01:41:23 +0900292/*[clinic end generated code: output=f3246e880509f142 input=0db46b69e9680171]*/
Georg Brandld9e833c2010-12-04 09:14:36 +0000293{
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300294 PyObject *res;
Georg Brandld9e833c2010-12-04 09:14:36 +0000295
Dong-hee Nac4862e32020-06-17 01:41:23 +0900296 res = gdbm_subscript(self, key);
Georg Brandld9e833c2010-12-04 09:14:36 +0000297 if (res == NULL && PyErr_ExceptionMatches(PyExc_KeyError)) {
298 PyErr_Clear();
Dong-hee Nac4862e32020-06-17 01:41:23 +0900299 if (gdbm_ass_sub(self, key, default_value) < 0)
Georg Brandld9e833c2010-12-04 09:14:36 +0000300 return NULL;
Dong-hee Nac4862e32020-06-17 01:41:23 +0900301 return gdbm_subscript(self, key);
Georg Brandld9e833c2010-12-04 09:14:36 +0000302 }
303 return res;
304}
305
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300306/*[clinic input]
307_gdbm.gdbm.close
308
309Close the database.
310[clinic start generated code]*/
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000311
Roger E. Masseb15bef81996-12-17 19:55:33 +0000312static PyObject *
Dong-hee Nac4862e32020-06-17 01:41:23 +0900313_gdbm_gdbm_close_impl(gdbmobject *self)
314/*[clinic end generated code: output=f5abb4d6bb9e52d5 input=0a203447379b45fd]*/
Guido van Rossum807b7be1995-07-07 22:37:11 +0000315{
Dong-hee Nac4862e32020-06-17 01:41:23 +0900316 if (self->di_dbm) {
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300317 gdbm_close(self->di_dbm);
Dong-hee Nac4862e32020-06-17 01:41:23 +0900318 }
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300319 self->di_dbm = NULL;
Serhiy Storchaka228b12e2017-01-23 09:47:21 +0200320 Py_RETURN_NONE;
Guido van Rossum807b7be1995-07-07 22:37:11 +0000321}
322
Guido van Rossum6252e102007-05-23 20:51:02 +0000323/* XXX Should return a set or a set view */
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300324/*[clinic input]
325_gdbm.gdbm.keys
326
Dong-hee Nac4862e32020-06-17 01:41:23 +0900327 cls: defining_class
328
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300329Get a list of all keys in the database.
330[clinic start generated code]*/
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000331
Roger E. Masseb15bef81996-12-17 19:55:33 +0000332static PyObject *
Dong-hee Nac4862e32020-06-17 01:41:23 +0900333_gdbm_gdbm_keys_impl(gdbmobject *self, PyTypeObject *cls)
334/*[clinic end generated code: output=c24b824e81404755 input=1428b7c79703d7d5]*/
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000335{
Antoine Pitrou9ed5f272013-08-13 20:18:52 +0200336 PyObject *v, *item;
Fred Drakee3a41c62000-07-08 05:00:07 +0000337 datum key, nextkey;
338 int err;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000339
Dong-hee Nac4862e32020-06-17 01:41:23 +0900340 _gdbm_state *state = PyType_GetModuleState(cls);
341 assert(state != NULL);
342
343 if (self == NULL || !Py_IS_TYPE(self, state->gdbm_type)) {
Fred Drakee3a41c62000-07-08 05:00:07 +0000344 PyErr_BadInternalCall();
345 return NULL;
346 }
Dong-hee Nac4862e32020-06-17 01:41:23 +0900347 check_gdbmobject_open(self, state->gdbm_error);
Guido van Rossum3be71401996-07-21 02:32:44 +0000348
Fred Drakee3a41c62000-07-08 05:00:07 +0000349 v = PyList_New(0);
350 if (v == NULL)
351 return NULL;
Guido van Rossum77eecfa1997-07-17 22:56:01 +0000352
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300353 key = gdbm_firstkey(self->di_dbm);
Fred Drakee3a41c62000-07-08 05:00:07 +0000354 while (key.dptr) {
Christian Heimes72b710a2008-05-26 13:28:38 +0000355 item = PyBytes_FromStringAndSize(key.dptr, key.dsize);
Fred Drakee3a41c62000-07-08 05:00:07 +0000356 if (item == NULL) {
357 free(key.dptr);
358 Py_DECREF(v);
359 return NULL;
360 }
361 err = PyList_Append(v, item);
362 Py_DECREF(item);
363 if (err != 0) {
364 free(key.dptr);
365 Py_DECREF(v);
366 return NULL;
367 }
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300368 nextkey = gdbm_nextkey(self->di_dbm, key);
Fred Drakee3a41c62000-07-08 05:00:07 +0000369 free(key.dptr);
370 key = nextkey;
371 }
372 return v;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000373}
374
Guido van Rossum0da7e032006-08-19 23:18:48 +0000375static int
Dong-hee Nac4862e32020-06-17 01:41:23 +0900376gdbm_contains(PyObject *self, PyObject *arg)
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000377{
Dong-hee Nac4862e32020-06-17 01:41:23 +0900378 gdbmobject *dp = (gdbmobject *)self;
Fred Drakee3a41c62000-07-08 05:00:07 +0000379 datum key;
Serhiy Storchaka7d6392c2013-10-25 00:06:52 +0300380 Py_ssize_t size;
Dong-hee Nac4862e32020-06-17 01:41:23 +0900381 _gdbm_state *state = PyType_GetModuleState(Py_TYPE(dp));
Fred Drakee3a41c62000-07-08 05:00:07 +0000382
Guido van Rossum0da7e032006-08-19 23:18:48 +0000383 if ((dp)->di_dbm == NULL) {
Dong-hee Nac4862e32020-06-17 01:41:23 +0900384 PyErr_SetString(state->gdbm_error,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000385 "GDBM object has already been closed");
386 return -1;
Guido van Rossum0da7e032006-08-19 23:18:48 +0000387 }
Serhiy Storchaka7d6392c2013-10-25 00:06:52 +0300388 if (PyUnicode_Check(arg)) {
Serhiy Storchaka2a404b62017-01-22 23:07:07 +0200389 key.dptr = (char *)PyUnicode_AsUTF8AndSize(arg, &size);
Serhiy Storchaka7d6392c2013-10-25 00:06:52 +0300390 key.dsize = size;
391 if (key.dptr == NULL)
392 return -1;
393 }
394 else if (!PyBytes_Check(arg)) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000395 PyErr_Format(PyExc_TypeError,
Serhiy Storchaka7d6392c2013-10-25 00:06:52 +0300396 "gdbm key must be bytes or string, not %.100s",
Victor Stinnerdaa97562020-02-07 03:37:06 +0100397 Py_TYPE(arg)->tp_name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000398 return -1;
Guido van Rossum0da7e032006-08-19 23:18:48 +0000399 }
Serhiy Storchaka7d6392c2013-10-25 00:06:52 +0300400 else {
401 key.dptr = PyBytes_AS_STRING(arg);
402 key.dsize = PyBytes_GET_SIZE(arg);
403 }
Guido van Rossum0da7e032006-08-19 23:18:48 +0000404 return gdbm_exists(dp->di_dbm, key);
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000405}
406
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300407/*[clinic input]
408_gdbm.gdbm.firstkey
409
Dong-hee Nac4862e32020-06-17 01:41:23 +0900410 cls: defining_class
411
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300412Return the starting key for the traversal.
413
414It's possible to loop over every key in the database using this method
415and the nextkey() method. The traversal is ordered by GDBM's internal
416hash values, and won't be sorted by the key values.
417[clinic start generated code]*/
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000418
Roger E. Masseb15bef81996-12-17 19:55:33 +0000419static PyObject *
Dong-hee Nac4862e32020-06-17 01:41:23 +0900420_gdbm_gdbm_firstkey_impl(gdbmobject *self, PyTypeObject *cls)
421/*[clinic end generated code: output=139275e9c8b60827 input=ed8782a029a5d299]*/
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000422{
Antoine Pitrou9ed5f272013-08-13 20:18:52 +0200423 PyObject *v;
Fred Drakee3a41c62000-07-08 05:00:07 +0000424 datum key;
Dong-hee Nac4862e32020-06-17 01:41:23 +0900425 _gdbm_state *state = PyType_GetModuleState(cls);
426 assert(state != NULL);
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000427
Dong-hee Nac4862e32020-06-17 01:41:23 +0900428 check_gdbmobject_open(self, state->gdbm_error);
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300429 key = gdbm_firstkey(self->di_dbm);
Fred Drakee3a41c62000-07-08 05:00:07 +0000430 if (key.dptr) {
Christian Heimes72b710a2008-05-26 13:28:38 +0000431 v = PyBytes_FromStringAndSize(key.dptr, key.dsize);
Fred Drakee3a41c62000-07-08 05:00:07 +0000432 free(key.dptr);
433 return v;
434 }
435 else {
Serhiy Storchaka228b12e2017-01-23 09:47:21 +0200436 Py_RETURN_NONE;
Fred Drakee3a41c62000-07-08 05:00:07 +0000437 }
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000438}
439
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300440/*[clinic input]
441_gdbm.gdbm.nextkey
442
Dong-hee Nac4862e32020-06-17 01:41:23 +0900443 cls: defining_class
Larry Hastings38337d12015-05-07 23:30:09 -0700444 key: str(accept={str, robuffer}, zeroes=True)
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300445 /
446
447Returns the key that follows key in the traversal.
448
449The following code prints every key in the database db, without having
450to create a list in memory that contains them all:
451
452 k = db.firstkey()
453 while k != None:
454 print(k)
455 k = db.nextkey(k)
456[clinic start generated code]*/
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000457
Roger E. Masseb15bef81996-12-17 19:55:33 +0000458static PyObject *
Dong-hee Nac4862e32020-06-17 01:41:23 +0900459_gdbm_gdbm_nextkey_impl(gdbmobject *self, PyTypeObject *cls, const char *key,
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300460 Py_ssize_clean_t key_length)
Dong-hee Nac4862e32020-06-17 01:41:23 +0900461/*[clinic end generated code: output=204964441fdbaf02 input=fcf6a51a96ce0172]*/
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000462{
Antoine Pitrou9ed5f272013-08-13 20:18:52 +0200463 PyObject *v;
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300464 datum dbm_key, nextkey;
Dong-hee Nac4862e32020-06-17 01:41:23 +0900465 _gdbm_state *state = PyType_GetModuleState(cls);
466 assert(state != NULL);
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000467
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300468 dbm_key.dptr = (char *)key;
469 dbm_key.dsize = key_length;
Dong-hee Nac4862e32020-06-17 01:41:23 +0900470 check_gdbmobject_open(self, state->gdbm_error);
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300471 nextkey = gdbm_nextkey(self->di_dbm, dbm_key);
Fred Drakee3a41c62000-07-08 05:00:07 +0000472 if (nextkey.dptr) {
Christian Heimes72b710a2008-05-26 13:28:38 +0000473 v = PyBytes_FromStringAndSize(nextkey.dptr, nextkey.dsize);
Fred Drakee3a41c62000-07-08 05:00:07 +0000474 free(nextkey.dptr);
475 return v;
476 }
477 else {
Serhiy Storchaka228b12e2017-01-23 09:47:21 +0200478 Py_RETURN_NONE;
Fred Drakee3a41c62000-07-08 05:00:07 +0000479 }
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000480}
481
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300482/*[clinic input]
483_gdbm.gdbm.reorganize
484
Dong-hee Nac4862e32020-06-17 01:41:23 +0900485 cls: defining_class
486
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300487Reorganize the database.
488
489If you have carried out a lot of deletions and would like to shrink
490the space used by the GDBM file, this routine will reorganize the
491database. GDBM will not shorten the length of a database file except
492by using this reorganization; otherwise, deleted file space will be
493kept and reused as new (key,value) pairs are added.
494[clinic start generated code]*/
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000495
Roger E. Masseb15bef81996-12-17 19:55:33 +0000496static PyObject *
Dong-hee Nac4862e32020-06-17 01:41:23 +0900497_gdbm_gdbm_reorganize_impl(gdbmobject *self, PyTypeObject *cls)
498/*[clinic end generated code: output=d77c69e8e3dd644a input=e1359faeef844e46]*/
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000499{
Dong-hee Nac4862e32020-06-17 01:41:23 +0900500 _gdbm_state *state = PyType_GetModuleState(cls);
501 assert(state != NULL);
502 check_gdbmobject_open(self, state->gdbm_error);
Fred Drakee3a41c62000-07-08 05:00:07 +0000503 errno = 0;
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300504 if (gdbm_reorganize(self->di_dbm) < 0) {
Fred Drakee3a41c62000-07-08 05:00:07 +0000505 if (errno != 0)
Dong-hee Nac4862e32020-06-17 01:41:23 +0900506 PyErr_SetFromErrno(state->gdbm_error);
Fred Drakee3a41c62000-07-08 05:00:07 +0000507 else
Dong-hee Nac4862e32020-06-17 01:41:23 +0900508 PyErr_SetString(state->gdbm_error, gdbm_strerror(gdbm_errno));
Fred Drakee3a41c62000-07-08 05:00:07 +0000509 return NULL;
510 }
Serhiy Storchaka228b12e2017-01-23 09:47:21 +0200511 Py_RETURN_NONE;
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000512}
513
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300514/*[clinic input]
515_gdbm.gdbm.sync
516
Dong-hee Nac4862e32020-06-17 01:41:23 +0900517 cls: defining_class
518
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300519Flush the database to the disk file.
520
521When the database has been opened in fast mode, this method forces
522any unwritten data to be written to the disk.
523[clinic start generated code]*/
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000524
Roger E. Massee5a9c8f1997-03-25 17:39:56 +0000525static PyObject *
Dong-hee Nac4862e32020-06-17 01:41:23 +0900526_gdbm_gdbm_sync_impl(gdbmobject *self, PyTypeObject *cls)
527/*[clinic end generated code: output=bb680a2035c3f592 input=3d749235f79b6f2a]*/
Roger E. Massee5a9c8f1997-03-25 17:39:56 +0000528{
Dong-hee Nac4862e32020-06-17 01:41:23 +0900529 _gdbm_state *state = PyType_GetModuleState(cls);
530 assert(state != NULL);
531 check_gdbmobject_open(self, state->gdbm_error);
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300532 gdbm_sync(self->di_dbm);
Serhiy Storchaka228b12e2017-01-23 09:47:21 +0200533 Py_RETURN_NONE;
Roger E. Massee5a9c8f1997-03-25 17:39:56 +0000534}
535
Nick Coghlanc610aba2013-11-17 15:59:51 +1000536static PyObject *
Dong-hee Nac4862e32020-06-17 01:41:23 +0900537gdbm__enter__(PyObject *self, PyObject *args)
Nick Coghlanc610aba2013-11-17 15:59:51 +1000538{
539 Py_INCREF(self);
540 return self;
541}
542
543static PyObject *
Dong-hee Nac4862e32020-06-17 01:41:23 +0900544gdbm__exit__(PyObject *self, PyObject *args)
Nick Coghlanc610aba2013-11-17 15:59:51 +1000545{
546 _Py_IDENTIFIER(close);
Jeroen Demeyer762f93f2019-07-08 10:19:25 +0200547 return _PyObject_CallMethodIdNoArgs(self, &PyId_close);
Nick Coghlanc610aba2013-11-17 15:59:51 +1000548}
549
Dong-hee Nac4862e32020-06-17 01:41:23 +0900550static PyMethodDef gdbm_methods[] = {
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300551 _GDBM_GDBM_CLOSE_METHODDEF
552 _GDBM_GDBM_KEYS_METHODDEF
553 _GDBM_GDBM_FIRSTKEY_METHODDEF
554 _GDBM_GDBM_NEXTKEY_METHODDEF
555 _GDBM_GDBM_REORGANIZE_METHODDEF
556 _GDBM_GDBM_SYNC_METHODDEF
557 _GDBM_GDBM_GET_METHODDEF
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300558 _GDBM_GDBM_SETDEFAULT_METHODDEF
Dong-hee Nac4862e32020-06-17 01:41:23 +0900559 {"__enter__", gdbm__enter__, METH_NOARGS, NULL},
560 {"__exit__", gdbm__exit__, METH_VARARGS, NULL},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000561 {NULL, NULL} /* sentinel */
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000562};
563
Dong-hee Nac4862e32020-06-17 01:41:23 +0900564static PyType_Slot gdbmtype_spec_slots[] = {
565 {Py_tp_dealloc, gdbm_dealloc},
Miss Islington (bot)0bf05002021-05-27 08:26:15 -0700566 {Py_tp_traverse, gdbm_traverse},
Dong-hee Nac4862e32020-06-17 01:41:23 +0900567 {Py_tp_methods, gdbm_methods},
568 {Py_sq_contains, gdbm_contains},
569 {Py_mp_length, gdbm_length},
570 {Py_mp_subscript, gdbm_subscript},
571 {Py_mp_ass_subscript, gdbm_ass_sub},
572 {Py_tp_doc, (char*)gdbm_object__doc__},
573 {0, 0}
574};
575
576static PyType_Spec gdbmtype_spec = {
577 .name = "_gdbm.gdbm",
578 .basicsize = sizeof(gdbmobject),
579 // Calling PyType_GetModuleState() on a subclass is not safe.
580 // dbmtype_spec does not have Py_TPFLAGS_BASETYPE flag
581 // which prevents to create a subclass.
582 // So calling PyType_GetModuleState() in this file is always safe.
Miss Islington (bot)0bf05002021-05-27 08:26:15 -0700583 .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION |
Miss Islington (bot)7297d742021-06-17 03:19:44 -0700584 Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_IMMUTABLETYPE),
Dong-hee Nac4862e32020-06-17 01:41:23 +0900585 .slots = gdbmtype_spec_slots,
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000586};
587
588/* ----------------------------------------------------------------- */
589
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300590/*[clinic input]
591_gdbm.open as dbmopen
Dong-hee Nac4862e32020-06-17 01:41:23 +0900592
Serhiy Storchaka6f600ff2018-02-26 16:02:22 +0200593 filename: unicode
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300594 flags: str="r"
595 mode: int(py_default="0o666") = 0o666
596 /
597
598Open a dbm database and return a dbm object.
599
600The filename argument is the name of the database file.
601
602The optional flags argument can be 'r' (to open an existing database
603for reading only -- default), 'w' (to open an existing database for
604reading and writing), 'c' (which creates the database if it doesn't
605exist), or 'n' (which always creates a new empty database).
606
607Some versions of gdbm support additional flags which must be
608appended to one of the flags described above. The module constant
609'open_flags' is a string of valid additional flags. The 'f' flag
610opens the database in fast mode; altered data will not automatically
611be written to the disk after every change. This results in faster
612writes to the database, but may result in an inconsistent database
613if the program crashes while the database is still open. Use the
614sync() method to force any unwritten data to be written to the disk.
615The 's' flag causes all database operations to be synchronized to
616disk. The 'u' flag disables locking of the database file.
617
618The optional mode argument is the Unix mode of the file, used only
619when the database has to be created. It defaults to octal 0o666.
620[clinic start generated code]*/
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000621
Roger E. Masseb15bef81996-12-17 19:55:33 +0000622static PyObject *
Serhiy Storchaka6f600ff2018-02-26 16:02:22 +0200623dbmopen_impl(PyObject *module, PyObject *filename, const char *flags,
624 int mode)
Dong-hee Nac4862e32020-06-17 01:41:23 +0900625/*[clinic end generated code: output=9527750f5df90764 input=812b7d74399ceb0e]*/
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000626{
Fred Drakee3a41c62000-07-08 05:00:07 +0000627 int iflags;
Dong-hee Nac4862e32020-06-17 01:41:23 +0900628 _gdbm_state *state = get_gdbm_state(module);
629 assert(state != NULL);
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000630
Fred Drakee3a41c62000-07-08 05:00:07 +0000631 switch (flags[0]) {
632 case 'r':
633 iflags = GDBM_READER;
634 break;
635 case 'w':
636 iflags = GDBM_WRITER;
637 break;
638 case 'c':
639 iflags = GDBM_WRCREAT;
640 break;
641 case 'n':
642 iflags = GDBM_NEWDB;
643 break;
644 default:
Dong-hee Nac4862e32020-06-17 01:41:23 +0900645 PyErr_SetString(state->gdbm_error,
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000646 "First flag must be one of 'r', 'w', 'c' or 'n'");
Fred Drakee3a41c62000-07-08 05:00:07 +0000647 return NULL;
648 }
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000649 for (flags++; *flags != '\0'; flags++) {
650 char buf[40];
651 switch (*flags) {
652#ifdef GDBM_FAST
653 case 'f':
654 iflags |= GDBM_FAST;
655 break;
656#endif
657#ifdef GDBM_SYNC
658 case 's':
659 iflags |= GDBM_SYNC;
660 break;
661#endif
662#ifdef GDBM_NOLOCK
663 case 'u':
664 iflags |= GDBM_NOLOCK;
665 break;
666#endif
667 default:
Tim Peters885d4572001-11-28 20:27:42 +0000668 PyOS_snprintf(buf, sizeof(buf), "Flag '%c' is not supported.",
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000669 *flags);
Dong-hee Nac4862e32020-06-17 01:41:23 +0900670 PyErr_SetString(state->gdbm_error, buf);
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000671 return NULL;
672 }
673 }
674
Serhiy Storchaka6f600ff2018-02-26 16:02:22 +0200675 PyObject *filenamebytes = PyUnicode_EncodeFSDefault(filename);
676 if (filenamebytes == NULL) {
677 return NULL;
678 }
679 const char *name = PyBytes_AS_STRING(filenamebytes);
680 if (strlen(name) != (size_t)PyBytes_GET_SIZE(filenamebytes)) {
681 Py_DECREF(filenamebytes);
682 PyErr_SetString(PyExc_ValueError, "embedded null character");
683 return NULL;
684 }
Dong-hee Nac4862e32020-06-17 01:41:23 +0900685 PyObject *self = newgdbmobject(state, name, iflags, mode);
Serhiy Storchaka6f600ff2018-02-26 16:02:22 +0200686 Py_DECREF(filenamebytes);
687 return self;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000688}
689
Dong-hee Nac4862e32020-06-17 01:41:23 +0900690static const char gdbmmodule_open_flags[] = "rwcn"
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000691#ifdef GDBM_FAST
692 "f"
693#endif
694#ifdef GDBM_SYNC
695 "s"
696#endif
697#ifdef GDBM_NOLOCK
698 "u"
699#endif
700 ;
701
Dong-hee Nac4862e32020-06-17 01:41:23 +0900702static PyMethodDef _gdbm_module_methods[] = {
Serhiy Storchaka9260e772015-04-17 21:05:18 +0300703 DBMOPEN_METHODDEF
Fred Drakee3a41c62000-07-08 05:00:07 +0000704 { 0, 0 },
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000705};
706
Dong-hee Nac4862e32020-06-17 01:41:23 +0900707static int
708_gdbm_exec(PyObject *module)
709{
710 _gdbm_state *state = get_gdbm_state(module);
711 state->gdbm_type = (PyTypeObject *)PyType_FromModuleAndSpec(module,
712 &gdbmtype_spec, NULL);
713 if (state->gdbm_type == NULL) {
714 return -1;
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000715 }
Dong-hee Nac4862e32020-06-17 01:41:23 +0900716 state->gdbm_error = PyErr_NewException("_gdbm.error", PyExc_OSError, NULL);
717 if (state->gdbm_error == NULL) {
718 return -1;
Victor Stinner00f9edb2018-06-19 23:29:22 +0200719 }
Dong-hee Nac4862e32020-06-17 01:41:23 +0900720 if (PyModule_AddType(module, (PyTypeObject *)state->gdbm_error) < 0) {
721 return -1;
Victor Stinner00f9edb2018-06-19 23:29:22 +0200722 }
Dong-hee Nac4862e32020-06-17 01:41:23 +0900723 if (PyModule_AddStringConstant(module, "open_flags",
724 gdbmmodule_open_flags) < 0) {
725 return -1;
Victor Stinner00f9edb2018-06-19 23:29:22 +0200726 }
727
Xiang Zhangb248e952018-06-20 21:23:30 +0800728#if defined(GDBM_VERSION_MAJOR) && defined(GDBM_VERSION_MINOR) && \
729 defined(GDBM_VERSION_PATCH)
Victor Stinner00f9edb2018-06-19 23:29:22 +0200730 PyObject *obj = Py_BuildValue("iii", GDBM_VERSION_MAJOR,
731 GDBM_VERSION_MINOR, GDBM_VERSION_PATCH);
732 if (obj == NULL) {
Dong-hee Nac4862e32020-06-17 01:41:23 +0900733 return -1;
Victor Stinner00f9edb2018-06-19 23:29:22 +0200734 }
Dong-hee Nac4862e32020-06-17 01:41:23 +0900735 if (PyModule_AddObject(module, "_GDBM_VERSION", obj) < 0) {
Victor Stinner00f9edb2018-06-19 23:29:22 +0200736 Py_DECREF(obj);
Dong-hee Nac4862e32020-06-17 01:41:23 +0900737 return -1;
Victor Stinner00f9edb2018-06-19 23:29:22 +0200738 }
Xiang Zhangb248e952018-06-20 21:23:30 +0800739#endif
Dong-hee Nac4862e32020-06-17 01:41:23 +0900740 return 0;
741}
Victor Stinner00f9edb2018-06-19 23:29:22 +0200742
Dong-hee Nac4862e32020-06-17 01:41:23 +0900743static int
744_gdbm_module_traverse(PyObject *module, visitproc visit, void *arg)
745{
746 _gdbm_state *state = get_gdbm_state(module);
747 Py_VISIT(state->gdbm_error);
748 Py_VISIT(state->gdbm_type);
749 return 0;
750}
Victor Stinner00f9edb2018-06-19 23:29:22 +0200751
Dong-hee Nac4862e32020-06-17 01:41:23 +0900752static int
753_gdbm_module_clear(PyObject *module)
754{
755 _gdbm_state *state = get_gdbm_state(module);
756 Py_CLEAR(state->gdbm_error);
757 Py_CLEAR(state->gdbm_type);
758 return 0;
759}
760
761static void
762_gdbm_module_free(void *module)
763{
764 _gdbm_module_clear((PyObject *)module);
765}
766
767static PyModuleDef_Slot _gdbm_module_slots[] = {
768 {Py_mod_exec, _gdbm_exec},
769 {0, NULL}
770};
771
772static struct PyModuleDef _gdbmmodule = {
773 PyModuleDef_HEAD_INIT,
774 .m_name = "_gdbm",
775 .m_doc = gdbmmodule__doc__,
776 .m_size = sizeof(_gdbm_state),
777 .m_methods = _gdbm_module_methods,
778 .m_slots = _gdbm_module_slots,
779 .m_traverse = _gdbm_module_traverse,
780 .m_clear = _gdbm_module_clear,
781 .m_free = _gdbm_module_free,
782};
783
784PyMODINIT_FUNC
785PyInit__gdbm(void)
786{
787 return PyModuleDef_Init(&_gdbmmodule);
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000788}