1
2 /* GDBM module using dictionary interface */
3 /* Author: Anthony Baxter, after dbmmodule.c */
4 /* Doc strings: Mitch Chapman */
5
6 #define PY_SSIZE_T_CLEAN
7 #include "Python.h"
8
9 #include <sys/types.h>
10 #include <sys/stat.h>
11 #include <fcntl.h>
12 #include "gdbm.h"
13
14 #if defined(WIN32) && !defined(__CYGWIN__)
15 #include "gdbmerrno.h"
16 extern const char * gdbm_strerror(gdbm_error);
17 #endif
18
19 typedef struct {
20 PyTypeObject *gdbm_type;
21 PyObject *gdbm_error;
22 } _gdbm_state;
23
24 static inline _gdbm_state*
get_gdbm_state(PyObject * module)25 get_gdbm_state(PyObject *module)
26 {
27 void *state = PyModule_GetState(module);
28 assert(state != NULL);
29 return (_gdbm_state *)state;
30 }
31
32 /*[clinic input]
33 module _gdbm
34 class _gdbm.gdbm "gdbmobject *" "&Gdbmtype"
35 [clinic start generated code]*/
36 /*[clinic end generated code: output=da39a3ee5e6b4b0d input=38ae71cedfc7172b]*/
37
38 PyDoc_STRVAR(gdbmmodule__doc__,
39 "This module provides an interface to the GNU DBM (GDBM) library.\n\
40 \n\
41 This module is quite similar to the dbm module, but uses GDBM instead to\n\
42 provide some additional functionality. Please note that the file formats\n\
43 created by GDBM and dbm are incompatible.\n\
44 \n\
45 GDBM objects behave like mappings (dictionaries), except that keys and\n\
46 values are always immutable bytes-like objects or strings. Printing\n\
47 a GDBM object doesn't print the keys and values, and the items() and\n\
48 values() methods are not supported.");
49
50 typedef struct {
51 PyObject_HEAD
52 Py_ssize_t di_size; /* -1 means recompute */
53 GDBM_FILE di_dbm;
54 } gdbmobject;
55
56 #include "clinic/_gdbmmodule.c.h"
57
58 #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 }
63
64 PyDoc_STRVAR(gdbm_object__doc__,
65 "This object represents a GDBM database.\n\
66 GDBM objects behave like mappings (dictionaries), except that keys and\n\
67 values are always immutable bytes-like objects or strings. Printing\n\
68 a GDBM object doesn't print the keys and values, and the items() and\n\
69 values() methods are not supported.\n\
70 \n\
71 GDBM objects also support additional operations such as firstkey,\n\
72 nextkey, reorganize, and sync.");
73
74 static PyObject *
newgdbmobject(_gdbm_state * state,const char * file,int flags,int mode)75 newgdbmobject(_gdbm_state *state, const char *file, int flags, int mode)
76 {
77 gdbmobject *dp = PyObject_GC_New(gdbmobject, state->gdbm_type);
78 if (dp == NULL) {
79 return NULL;
80 }
81 dp->di_size = -1;
82 errno = 0;
83 PyObject_GC_Track(dp);
84
85 if ((dp->di_dbm = gdbm_open((char *)file, 0, flags, mode, NULL)) == 0) {
86 if (errno != 0) {
87 PyErr_SetFromErrnoWithFilename(state->gdbm_error, file);
88 }
89 else {
90 PyErr_SetString(state->gdbm_error, gdbm_strerror(gdbm_errno));
91 }
92 Py_DECREF(dp);
93 return NULL;
94 }
95 return (PyObject *)dp;
96 }
97
98 /* Methods */
99 static int
gdbm_traverse(gdbmobject * dp,visitproc visit,void * arg)100 gdbm_traverse(gdbmobject *dp, visitproc visit, void *arg)
101 {
102 Py_VISIT(Py_TYPE(dp));
103 return 0;
104 }
105
106 static void
gdbm_dealloc(gdbmobject * dp)107 gdbm_dealloc(gdbmobject *dp)
108 {
109 PyObject_GC_UnTrack(dp);
110 if (dp->di_dbm) {
111 gdbm_close(dp->di_dbm);
112 }
113 PyTypeObject *tp = Py_TYPE(dp);
114 tp->tp_free(dp);
115 Py_DECREF(tp);
116 }
117
118 static Py_ssize_t
gdbm_length(gdbmobject * dp)119 gdbm_length(gdbmobject *dp)
120 {
121 _gdbm_state *state = PyType_GetModuleState(Py_TYPE(dp));
122 if (dp->di_dbm == NULL) {
123 PyErr_SetString(state->gdbm_error, "GDBM object has already been closed");
124 return -1;
125 }
126 if (dp->di_size < 0) {
127 #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) {
132 PyErr_SetFromErrno(state->gdbm_error);
133 }
134 else {
135 PyErr_SetString(state->gdbm_error, gdbm_strerror(gdbm_errno));
136 }
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
145 datum key,okey;
146 okey.dsize=0;
147 okey.dptr=NULL;
148
149 Py_ssize_t size = 0;
150 for (key = gdbm_firstkey(dp->di_dbm); key.dptr;
151 key = gdbm_nextkey(dp->di_dbm,okey)) {
152 size++;
153 if (okey.dsize) {
154 free(okey.dptr);
155 }
156 okey=key;
157 }
158 dp->di_size = size;
159 #endif
160 }
161 return dp->di_size;
162 }
163
164 // 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().
167 static int
parse_datum(PyObject * o,datum * d,const char * failmsg)168 parse_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
185 static PyObject *
gdbm_subscript(gdbmobject * dp,PyObject * key)186 gdbm_subscript(gdbmobject *dp, PyObject *key)
187 {
188 PyObject *v;
189 datum drec, krec;
190 _gdbm_state *state = PyType_GetModuleState(Py_TYPE(dp));
191
192 if (!parse_datum(key, &krec, NULL)) {
193 return NULL;
194 }
195 if (dp->di_dbm == NULL) {
196 PyErr_SetString(state->gdbm_error,
197 "GDBM object has already been closed");
198 return NULL;
199 }
200 drec = gdbm_fetch(dp->di_dbm, krec);
201 if (drec.dptr == 0) {
202 PyErr_SetObject(PyExc_KeyError, key);
203 return NULL;
204 }
205 v = PyBytes_FromStringAndSize(drec.dptr, drec.dsize);
206 free(drec.dptr);
207 return v;
208 }
209
210 /*[clinic input]
211 _gdbm.gdbm.get
212
213 key: object
214 default: object = None
215 /
216
217 Get the value for key, or default if not present.
218 [clinic start generated code]*/
219
220 static PyObject *
_gdbm_gdbm_get_impl(gdbmobject * self,PyObject * key,PyObject * default_value)221 _gdbm_gdbm_get_impl(gdbmobject *self, PyObject *key, PyObject *default_value)
222 /*[clinic end generated code: output=92421838f3a852f4 input=a9c20423f34c17b6]*/
223 {
224 PyObject *res;
225
226 res = gdbm_subscript(self, key);
227 if (res == NULL && PyErr_ExceptionMatches(PyExc_KeyError)) {
228 PyErr_Clear();
229 Py_INCREF(default_value);
230 return default_value;
231 }
232 return res;
233 }
234
235 static int
gdbm_ass_sub(gdbmobject * dp,PyObject * v,PyObject * w)236 gdbm_ass_sub(gdbmobject *dp, PyObject *v, PyObject *w)
237 {
238 datum krec, drec;
239 const char *failmsg = "gdbm mappings have bytes or string indices only";
240 _gdbm_state *state = PyType_GetModuleState(Py_TYPE(dp));
241
242 if (!parse_datum(v, &krec, failmsg)) {
243 return -1;
244 }
245 if (dp->di_dbm == NULL) {
246 PyErr_SetString(state->gdbm_error,
247 "GDBM object has already been closed");
248 return -1;
249 }
250 dp->di_size = -1;
251 if (w == NULL) {
252 if (gdbm_delete(dp->di_dbm, krec) < 0) {
253 if (gdbm_errno == GDBM_ITEM_NOT_FOUND) {
254 PyErr_SetObject(PyExc_KeyError, v);
255 }
256 else {
257 PyErr_SetString(state->gdbm_error, gdbm_strerror(gdbm_errno));
258 }
259 return -1;
260 }
261 }
262 else {
263 if (!parse_datum(w, &drec, failmsg)) {
264 return -1;
265 }
266 errno = 0;
267 if (gdbm_store(dp->di_dbm, krec, drec, GDBM_REPLACE) < 0) {
268 if (errno != 0)
269 PyErr_SetFromErrno(state->gdbm_error);
270 else
271 PyErr_SetString(state->gdbm_error,
272 gdbm_strerror(gdbm_errno));
273 return -1;
274 }
275 }
276 return 0;
277 }
278
279 /*[clinic input]
280 _gdbm.gdbm.setdefault
281
282 key: object
283 default: object = None
284 /
285
286 Get value for key, or set it to default and return default if not present.
287 [clinic start generated code]*/
288
289 static PyObject *
_gdbm_gdbm_setdefault_impl(gdbmobject * self,PyObject * key,PyObject * default_value)290 _gdbm_gdbm_setdefault_impl(gdbmobject *self, PyObject *key,
291 PyObject *default_value)
292 /*[clinic end generated code: output=f3246e880509f142 input=0db46b69e9680171]*/
293 {
294 PyObject *res;
295
296 res = gdbm_subscript(self, key);
297 if (res == NULL && PyErr_ExceptionMatches(PyExc_KeyError)) {
298 PyErr_Clear();
299 if (gdbm_ass_sub(self, key, default_value) < 0)
300 return NULL;
301 return gdbm_subscript(self, key);
302 }
303 return res;
304 }
305
306 /*[clinic input]
307 _gdbm.gdbm.close
308
309 Close the database.
310 [clinic start generated code]*/
311
312 static PyObject *
_gdbm_gdbm_close_impl(gdbmobject * self)313 _gdbm_gdbm_close_impl(gdbmobject *self)
314 /*[clinic end generated code: output=f5abb4d6bb9e52d5 input=0a203447379b45fd]*/
315 {
316 if (self->di_dbm) {
317 gdbm_close(self->di_dbm);
318 }
319 self->di_dbm = NULL;
320 Py_RETURN_NONE;
321 }
322
323 /* XXX Should return a set or a set view */
324 /*[clinic input]
325 _gdbm.gdbm.keys
326
327 cls: defining_class
328
329 Get a list of all keys in the database.
330 [clinic start generated code]*/
331
332 static PyObject *
_gdbm_gdbm_keys_impl(gdbmobject * self,PyTypeObject * cls)333 _gdbm_gdbm_keys_impl(gdbmobject *self, PyTypeObject *cls)
334 /*[clinic end generated code: output=c24b824e81404755 input=1428b7c79703d7d5]*/
335 {
336 PyObject *v, *item;
337 datum key, nextkey;
338 int err;
339
340 _gdbm_state *state = PyType_GetModuleState(cls);
341 assert(state != NULL);
342
343 if (self == NULL || !Py_IS_TYPE(self, state->gdbm_type)) {
344 PyErr_BadInternalCall();
345 return NULL;
346 }
347 check_gdbmobject_open(self, state->gdbm_error);
348
349 v = PyList_New(0);
350 if (v == NULL)
351 return NULL;
352
353 key = gdbm_firstkey(self->di_dbm);
354 while (key.dptr) {
355 item = PyBytes_FromStringAndSize(key.dptr, key.dsize);
356 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 }
368 nextkey = gdbm_nextkey(self->di_dbm, key);
369 free(key.dptr);
370 key = nextkey;
371 }
372 return v;
373 }
374
375 static int
gdbm_contains(PyObject * self,PyObject * arg)376 gdbm_contains(PyObject *self, PyObject *arg)
377 {
378 gdbmobject *dp = (gdbmobject *)self;
379 datum key;
380 Py_ssize_t size;
381 _gdbm_state *state = PyType_GetModuleState(Py_TYPE(dp));
382
383 if ((dp)->di_dbm == NULL) {
384 PyErr_SetString(state->gdbm_error,
385 "GDBM object has already been closed");
386 return -1;
387 }
388 if (PyUnicode_Check(arg)) {
389 key.dptr = (char *)PyUnicode_AsUTF8AndSize(arg, &size);
390 key.dsize = size;
391 if (key.dptr == NULL)
392 return -1;
393 }
394 else if (!PyBytes_Check(arg)) {
395 PyErr_Format(PyExc_TypeError,
396 "gdbm key must be bytes or string, not %.100s",
397 Py_TYPE(arg)->tp_name);
398 return -1;
399 }
400 else {
401 key.dptr = PyBytes_AS_STRING(arg);
402 key.dsize = PyBytes_GET_SIZE(arg);
403 }
404 return gdbm_exists(dp->di_dbm, key);
405 }
406
407 /*[clinic input]
408 _gdbm.gdbm.firstkey
409
410 cls: defining_class
411
412 Return the starting key for the traversal.
413
414 It's possible to loop over every key in the database using this method
415 and the nextkey() method. The traversal is ordered by GDBM's internal
416 hash values, and won't be sorted by the key values.
417 [clinic start generated code]*/
418
419 static PyObject *
_gdbm_gdbm_firstkey_impl(gdbmobject * self,PyTypeObject * cls)420 _gdbm_gdbm_firstkey_impl(gdbmobject *self, PyTypeObject *cls)
421 /*[clinic end generated code: output=139275e9c8b60827 input=ed8782a029a5d299]*/
422 {
423 PyObject *v;
424 datum key;
425 _gdbm_state *state = PyType_GetModuleState(cls);
426 assert(state != NULL);
427
428 check_gdbmobject_open(self, state->gdbm_error);
429 key = gdbm_firstkey(self->di_dbm);
430 if (key.dptr) {
431 v = PyBytes_FromStringAndSize(key.dptr, key.dsize);
432 free(key.dptr);
433 return v;
434 }
435 else {
436 Py_RETURN_NONE;
437 }
438 }
439
440 /*[clinic input]
441 _gdbm.gdbm.nextkey
442
443 cls: defining_class
444 key: str(accept={str, robuffer}, zeroes=True)
445 /
446
447 Returns the key that follows key in the traversal.
448
449 The following code prints every key in the database db, without having
450 to create a list in memory that contains them all:
451
452 k = db.firstkey()
453 while k is not None:
454 print(k)
455 k = db.nextkey(k)
456 [clinic start generated code]*/
457
458 static PyObject *
_gdbm_gdbm_nextkey_impl(gdbmobject * self,PyTypeObject * cls,const char * key,Py_ssize_clean_t key_length)459 _gdbm_gdbm_nextkey_impl(gdbmobject *self, PyTypeObject *cls, const char *key,
460 Py_ssize_clean_t key_length)
461 /*[clinic end generated code: output=204964441fdbaf02 input=365e297bc0b3db48]*/
462 {
463 PyObject *v;
464 datum dbm_key, nextkey;
465 _gdbm_state *state = PyType_GetModuleState(cls);
466 assert(state != NULL);
467
468 dbm_key.dptr = (char *)key;
469 dbm_key.dsize = key_length;
470 check_gdbmobject_open(self, state->gdbm_error);
471 nextkey = gdbm_nextkey(self->di_dbm, dbm_key);
472 if (nextkey.dptr) {
473 v = PyBytes_FromStringAndSize(nextkey.dptr, nextkey.dsize);
474 free(nextkey.dptr);
475 return v;
476 }
477 else {
478 Py_RETURN_NONE;
479 }
480 }
481
482 /*[clinic input]
483 _gdbm.gdbm.reorganize
484
485 cls: defining_class
486
487 Reorganize the database.
488
489 If you have carried out a lot of deletions and would like to shrink
490 the space used by the GDBM file, this routine will reorganize the
491 database. GDBM will not shorten the length of a database file except
492 by using this reorganization; otherwise, deleted file space will be
493 kept and reused as new (key,value) pairs are added.
494 [clinic start generated code]*/
495
496 static PyObject *
_gdbm_gdbm_reorganize_impl(gdbmobject * self,PyTypeObject * cls)497 _gdbm_gdbm_reorganize_impl(gdbmobject *self, PyTypeObject *cls)
498 /*[clinic end generated code: output=d77c69e8e3dd644a input=e1359faeef844e46]*/
499 {
500 _gdbm_state *state = PyType_GetModuleState(cls);
501 assert(state != NULL);
502 check_gdbmobject_open(self, state->gdbm_error);
503 errno = 0;
504 if (gdbm_reorganize(self->di_dbm) < 0) {
505 if (errno != 0)
506 PyErr_SetFromErrno(state->gdbm_error);
507 else
508 PyErr_SetString(state->gdbm_error, gdbm_strerror(gdbm_errno));
509 return NULL;
510 }
511 Py_RETURN_NONE;
512 }
513
514 /*[clinic input]
515 _gdbm.gdbm.sync
516
517 cls: defining_class
518
519 Flush the database to the disk file.
520
521 When the database has been opened in fast mode, this method forces
522 any unwritten data to be written to the disk.
523 [clinic start generated code]*/
524
525 static PyObject *
_gdbm_gdbm_sync_impl(gdbmobject * self,PyTypeObject * cls)526 _gdbm_gdbm_sync_impl(gdbmobject *self, PyTypeObject *cls)
527 /*[clinic end generated code: output=bb680a2035c3f592 input=3d749235f79b6f2a]*/
528 {
529 _gdbm_state *state = PyType_GetModuleState(cls);
530 assert(state != NULL);
531 check_gdbmobject_open(self, state->gdbm_error);
532 gdbm_sync(self->di_dbm);
533 Py_RETURN_NONE;
534 }
535
536 static PyObject *
gdbm__enter__(PyObject * self,PyObject * args)537 gdbm__enter__(PyObject *self, PyObject *args)
538 {
539 Py_INCREF(self);
540 return self;
541 }
542
543 static PyObject *
gdbm__exit__(PyObject * self,PyObject * args)544 gdbm__exit__(PyObject *self, PyObject *args)
545 {
546 _Py_IDENTIFIER(close);
547 return _PyObject_CallMethodIdNoArgs(self, &PyId_close);
548 }
549
550 static PyMethodDef gdbm_methods[] = {
551 _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
558 _GDBM_GDBM_SETDEFAULT_METHODDEF
559 {"__enter__", gdbm__enter__, METH_NOARGS, NULL},
560 {"__exit__", gdbm__exit__, METH_VARARGS, NULL},
561 {NULL, NULL} /* sentinel */
562 };
563
564 static PyType_Slot gdbmtype_spec_slots[] = {
565 {Py_tp_dealloc, gdbm_dealloc},
566 {Py_tp_traverse, gdbm_traverse},
567 {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
576 static 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.
583 .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION |
584 Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_IMMUTABLETYPE),
585 .slots = gdbmtype_spec_slots,
586 };
587
588 /* ----------------------------------------------------------------- */
589
590 /*[clinic input]
591 _gdbm.open as dbmopen
592
593 filename: unicode
594 flags: str="r"
595 mode: int(py_default="0o666") = 0o666
596 /
597
598 Open a dbm database and return a dbm object.
599
600 The filename argument is the name of the database file.
601
602 The optional flags argument can be 'r' (to open an existing database
603 for reading only -- default), 'w' (to open an existing database for
604 reading and writing), 'c' (which creates the database if it doesn't
605 exist), or 'n' (which always creates a new empty database).
606
607 Some versions of gdbm support additional flags which must be
608 appended to one of the flags described above. The module constant
609 'open_flags' is a string of valid additional flags. The 'f' flag
610 opens the database in fast mode; altered data will not automatically
611 be written to the disk after every change. This results in faster
612 writes to the database, but may result in an inconsistent database
613 if the program crashes while the database is still open. Use the
614 sync() method to force any unwritten data to be written to the disk.
615 The 's' flag causes all database operations to be synchronized to
616 disk. The 'u' flag disables locking of the database file.
617
618 The optional mode argument is the Unix mode of the file, used only
619 when the database has to be created. It defaults to octal 0o666.
620 [clinic start generated code]*/
621
622 static PyObject *
dbmopen_impl(PyObject * module,PyObject * filename,const char * flags,int mode)623 dbmopen_impl(PyObject *module, PyObject *filename, const char *flags,
624 int mode)
625 /*[clinic end generated code: output=9527750f5df90764 input=812b7d74399ceb0e]*/
626 {
627 int iflags;
628 _gdbm_state *state = get_gdbm_state(module);
629 assert(state != NULL);
630
631 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:
645 PyErr_SetString(state->gdbm_error,
646 "First flag must be one of 'r', 'w', 'c' or 'n'");
647 return NULL;
648 }
649 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:
668 PyOS_snprintf(buf, sizeof(buf), "Flag '%c' is not supported.",
669 *flags);
670 PyErr_SetString(state->gdbm_error, buf);
671 return NULL;
672 }
673 }
674
675 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 }
685 PyObject *self = newgdbmobject(state, name, iflags, mode);
686 Py_DECREF(filenamebytes);
687 return self;
688 }
689
690 static const char gdbmmodule_open_flags[] = "rwcn"
691 #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
702 static PyMethodDef _gdbm_module_methods[] = {
703 DBMOPEN_METHODDEF
704 { 0, 0 },
705 };
706
707 static int
_gdbm_exec(PyObject * module)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;
715 }
716 state->gdbm_error = PyErr_NewException("_gdbm.error", PyExc_OSError, NULL);
717 if (state->gdbm_error == NULL) {
718 return -1;
719 }
720 if (PyModule_AddType(module, (PyTypeObject *)state->gdbm_error) < 0) {
721 return -1;
722 }
723 if (PyModule_AddStringConstant(module, "open_flags",
724 gdbmmodule_open_flags) < 0) {
725 return -1;
726 }
727
728 #if defined(GDBM_VERSION_MAJOR) && defined(GDBM_VERSION_MINOR) && \
729 defined(GDBM_VERSION_PATCH)
730 PyObject *obj = Py_BuildValue("iii", GDBM_VERSION_MAJOR,
731 GDBM_VERSION_MINOR, GDBM_VERSION_PATCH);
732 if (obj == NULL) {
733 return -1;
734 }
735 if (PyModule_AddObject(module, "_GDBM_VERSION", obj) < 0) {
736 Py_DECREF(obj);
737 return -1;
738 }
739 #endif
740 return 0;
741 }
742
743 static int
_gdbm_module_traverse(PyObject * module,visitproc visit,void * arg)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 }
751
752 static int
_gdbm_module_clear(PyObject * module)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
761 static void
_gdbm_module_free(void * module)762 _gdbm_module_free(void *module)
763 {
764 _gdbm_module_clear((PyObject *)module);
765 }
766
767 static PyModuleDef_Slot _gdbm_module_slots[] = {
768 {Py_mod_exec, _gdbm_exec},
769 {0, NULL}
770 };
771
772 static 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
784 PyMODINIT_FUNC
PyInit__gdbm(void)785 PyInit__gdbm(void)
786 {
787 return PyModuleDef_Init(&_gdbmmodule);
788 }
789