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 #include "gdbm.h"
9
10 #include <fcntl.h>
11 #include <stdlib.h> // free()
12 #include <sys/stat.h>
13 #include <sys/types.h>
14
15 #if defined(WIN32) && !defined(__CYGWIN__)
16 #include "gdbmerrno.h"
17 extern const char * gdbm_strerror(gdbm_error);
18 #endif
19
20 typedef struct {
21 PyTypeObject *gdbm_type;
22 PyObject *gdbm_error;
23 } _gdbm_state;
24
25 static inline _gdbm_state*
get_gdbm_state(PyObject * module)26 get_gdbm_state(PyObject *module)
27 {
28 void *state = PyModule_GetState(module);
29 assert(state != NULL);
30 return (_gdbm_state *)state;
31 }
32
33 /*[clinic input]
34 module _gdbm
35 class _gdbm.gdbm "gdbmobject *" "&Gdbmtype"
36 [clinic start generated code]*/
37 /*[clinic end generated code: output=da39a3ee5e6b4b0d input=38ae71cedfc7172b]*/
38
39 PyDoc_STRVAR(gdbmmodule__doc__,
40 "This module provides an interface to the GNU DBM (GDBM) library.\n\
41 \n\
42 This module is quite similar to the dbm module, but uses GDBM instead to\n\
43 provide some additional functionality. Please note that the file formats\n\
44 created by GDBM and dbm are incompatible.\n\
45 \n\
46 GDBM objects behave like mappings (dictionaries), except that keys and\n\
47 values are always immutable bytes-like objects or strings. Printing\n\
48 a GDBM object doesn't print the keys and values, and the items() and\n\
49 values() methods are not supported.");
50
51 typedef struct {
52 PyObject_HEAD
53 Py_ssize_t di_size; /* -1 means recompute */
54 GDBM_FILE di_dbm;
55 } gdbmobject;
56
57 #include "clinic/_gdbmmodule.c.h"
58
59 #define check_gdbmobject_open(v, err) \
60 if ((v)->di_dbm == NULL) { \
61 PyErr_SetString(err, "GDBM object has already been closed"); \
62 return NULL; \
63 }
64
65 PyDoc_STRVAR(gdbm_object__doc__,
66 "This object represents a GDBM database.\n\
67 GDBM objects behave like mappings (dictionaries), except that keys and\n\
68 values are always immutable bytes-like objects or strings. Printing\n\
69 a GDBM object doesn't print the keys and values, and the items() and\n\
70 values() methods are not supported.\n\
71 \n\
72 GDBM objects also support additional operations such as firstkey,\n\
73 nextkey, reorganize, and sync.");
74
75 static PyObject *
newgdbmobject(_gdbm_state * state,const char * file,int flags,int mode)76 newgdbmobject(_gdbm_state *state, const char *file, int flags, int mode)
77 {
78 gdbmobject *dp = PyObject_GC_New(gdbmobject, state->gdbm_type);
79 if (dp == NULL) {
80 return NULL;
81 }
82 dp->di_size = -1;
83 errno = 0;
84 PyObject_GC_Track(dp);
85
86 if ((dp->di_dbm = gdbm_open((char *)file, 0, flags, mode, NULL)) == 0) {
87 if (errno != 0) {
88 PyErr_SetFromErrnoWithFilename(state->gdbm_error, file);
89 }
90 else {
91 PyErr_SetString(state->gdbm_error, gdbm_strerror(gdbm_errno));
92 }
93 Py_DECREF(dp);
94 return NULL;
95 }
96 return (PyObject *)dp;
97 }
98
99 /* Methods */
100 static int
gdbm_traverse(gdbmobject * dp,visitproc visit,void * arg)101 gdbm_traverse(gdbmobject *dp, visitproc visit, void *arg)
102 {
103 Py_VISIT(Py_TYPE(dp));
104 return 0;
105 }
106
107 static void
gdbm_dealloc(gdbmobject * dp)108 gdbm_dealloc(gdbmobject *dp)
109 {
110 PyObject_GC_UnTrack(dp);
111 if (dp->di_dbm) {
112 gdbm_close(dp->di_dbm);
113 }
114 PyTypeObject *tp = Py_TYPE(dp);
115 tp->tp_free(dp);
116 Py_DECREF(tp);
117 }
118
119 static Py_ssize_t
gdbm_length(gdbmobject * dp)120 gdbm_length(gdbmobject *dp)
121 {
122 _gdbm_state *state = PyType_GetModuleState(Py_TYPE(dp));
123 if (dp->di_dbm == NULL) {
124 PyErr_SetString(state->gdbm_error, "GDBM object has already been closed");
125 return -1;
126 }
127 if (dp->di_size < 0) {
128 #if GDBM_VERSION_MAJOR >= 1 && GDBM_VERSION_MINOR >= 11
129 errno = 0;
130 gdbm_count_t count;
131 if (gdbm_count(dp->di_dbm, &count) == -1) {
132 if (errno != 0) {
133 PyErr_SetFromErrno(state->gdbm_error);
134 }
135 else {
136 PyErr_SetString(state->gdbm_error, gdbm_strerror(gdbm_errno));
137 }
138 return -1;
139 }
140 if (count > PY_SSIZE_T_MAX) {
141 PyErr_SetString(PyExc_OverflowError, "count exceeds PY_SSIZE_T_MAX");
142 return -1;
143 }
144 dp->di_size = count;
145 #else
146 datum key,okey;
147 okey.dsize=0;
148 okey.dptr=NULL;
149
150 Py_ssize_t size = 0;
151 for (key = gdbm_firstkey(dp->di_dbm); key.dptr;
152 key = gdbm_nextkey(dp->di_dbm,okey)) {
153 size++;
154 if (okey.dsize) {
155 free(okey.dptr);
156 }
157 okey=key;
158 }
159 dp->di_size = size;
160 #endif
161 }
162 return dp->di_size;
163 }
164
165 // Wrapper function for PyArg_Parse(o, "s#", &d.dptr, &d.size).
166 // This function is needed to support PY_SSIZE_T_CLEAN.
167 // Return 1 on success, same to PyArg_Parse().
168 static int
parse_datum(PyObject * o,datum * d,const char * failmsg)169 parse_datum(PyObject *o, datum *d, const char *failmsg)
170 {
171 Py_ssize_t size;
172 if (!PyArg_Parse(o, "s#", &d->dptr, &size)) {
173 if (failmsg != NULL) {
174 PyErr_SetString(PyExc_TypeError, failmsg);
175 }
176 return 0;
177 }
178 if (INT_MAX < size) {
179 PyErr_SetString(PyExc_OverflowError, "size does not fit in an int");
180 return 0;
181 }
182 d->dsize = size;
183 return 1;
184 }
185
186 static PyObject *
gdbm_subscript(gdbmobject * dp,PyObject * key)187 gdbm_subscript(gdbmobject *dp, PyObject *key)
188 {
189 PyObject *v;
190 datum drec, krec;
191 _gdbm_state *state = PyType_GetModuleState(Py_TYPE(dp));
192
193 if (!parse_datum(key, &krec, NULL)) {
194 return NULL;
195 }
196 if (dp->di_dbm == NULL) {
197 PyErr_SetString(state->gdbm_error,
198 "GDBM object has already been closed");
199 return NULL;
200 }
201 drec = gdbm_fetch(dp->di_dbm, krec);
202 if (drec.dptr == 0) {
203 PyErr_SetObject(PyExc_KeyError, key);
204 return NULL;
205 }
206 v = PyBytes_FromStringAndSize(drec.dptr, drec.dsize);
207 free(drec.dptr);
208 return v;
209 }
210
211 /*[clinic input]
212 _gdbm.gdbm.get
213
214 key: object
215 default: object = None
216 /
217
218 Get the value for key, or default if not present.
219 [clinic start generated code]*/
220
221 static PyObject *
_gdbm_gdbm_get_impl(gdbmobject * self,PyObject * key,PyObject * default_value)222 _gdbm_gdbm_get_impl(gdbmobject *self, PyObject *key, PyObject *default_value)
223 /*[clinic end generated code: output=92421838f3a852f4 input=a9c20423f34c17b6]*/
224 {
225 PyObject *res;
226
227 res = gdbm_subscript(self, key);
228 if (res == NULL && PyErr_ExceptionMatches(PyExc_KeyError)) {
229 PyErr_Clear();
230 Py_INCREF(default_value);
231 return default_value;
232 }
233 return res;
234 }
235
236 static int
gdbm_ass_sub(gdbmobject * dp,PyObject * v,PyObject * w)237 gdbm_ass_sub(gdbmobject *dp, PyObject *v, PyObject *w)
238 {
239 datum krec, drec;
240 const char *failmsg = "gdbm mappings have bytes or string indices only";
241 _gdbm_state *state = PyType_GetModuleState(Py_TYPE(dp));
242
243 if (!parse_datum(v, &krec, failmsg)) {
244 return -1;
245 }
246 if (dp->di_dbm == NULL) {
247 PyErr_SetString(state->gdbm_error,
248 "GDBM object has already been closed");
249 return -1;
250 }
251 dp->di_size = -1;
252 if (w == NULL) {
253 if (gdbm_delete(dp->di_dbm, krec) < 0) {
254 if (gdbm_errno == GDBM_ITEM_NOT_FOUND) {
255 PyErr_SetObject(PyExc_KeyError, v);
256 }
257 else {
258 PyErr_SetString(state->gdbm_error, gdbm_strerror(gdbm_errno));
259 }
260 return -1;
261 }
262 }
263 else {
264 if (!parse_datum(w, &drec, failmsg)) {
265 return -1;
266 }
267 errno = 0;
268 if (gdbm_store(dp->di_dbm, krec, drec, GDBM_REPLACE) < 0) {
269 if (errno != 0)
270 PyErr_SetFromErrno(state->gdbm_error);
271 else
272 PyErr_SetString(state->gdbm_error,
273 gdbm_strerror(gdbm_errno));
274 return -1;
275 }
276 }
277 return 0;
278 }
279
280 /*[clinic input]
281 _gdbm.gdbm.setdefault
282
283 key: object
284 default: object = None
285 /
286
287 Get value for key, or set it to default and return default if not present.
288 [clinic start generated code]*/
289
290 static PyObject *
_gdbm_gdbm_setdefault_impl(gdbmobject * self,PyObject * key,PyObject * default_value)291 _gdbm_gdbm_setdefault_impl(gdbmobject *self, PyObject *key,
292 PyObject *default_value)
293 /*[clinic end generated code: output=f3246e880509f142 input=0db46b69e9680171]*/
294 {
295 PyObject *res;
296
297 res = gdbm_subscript(self, key);
298 if (res == NULL && PyErr_ExceptionMatches(PyExc_KeyError)) {
299 PyErr_Clear();
300 if (gdbm_ass_sub(self, key, default_value) < 0)
301 return NULL;
302 return gdbm_subscript(self, key);
303 }
304 return res;
305 }
306
307 /*[clinic input]
308 _gdbm.gdbm.close
309
310 Close the database.
311 [clinic start generated code]*/
312
313 static PyObject *
_gdbm_gdbm_close_impl(gdbmobject * self)314 _gdbm_gdbm_close_impl(gdbmobject *self)
315 /*[clinic end generated code: output=f5abb4d6bb9e52d5 input=0a203447379b45fd]*/
316 {
317 if (self->di_dbm) {
318 gdbm_close(self->di_dbm);
319 }
320 self->di_dbm = NULL;
321 Py_RETURN_NONE;
322 }
323
324 /* XXX Should return a set or a set view */
325 /*[clinic input]
326 _gdbm.gdbm.keys
327
328 cls: defining_class
329
330 Get a list of all keys in the database.
331 [clinic start generated code]*/
332
333 static PyObject *
_gdbm_gdbm_keys_impl(gdbmobject * self,PyTypeObject * cls)334 _gdbm_gdbm_keys_impl(gdbmobject *self, PyTypeObject *cls)
335 /*[clinic end generated code: output=c24b824e81404755 input=1428b7c79703d7d5]*/
336 {
337 PyObject *v, *item;
338 datum key, nextkey;
339 int err;
340
341 _gdbm_state *state = PyType_GetModuleState(cls);
342 assert(state != NULL);
343
344 if (self == NULL || !Py_IS_TYPE(self, state->gdbm_type)) {
345 PyErr_BadInternalCall();
346 return NULL;
347 }
348 check_gdbmobject_open(self, state->gdbm_error);
349
350 v = PyList_New(0);
351 if (v == NULL)
352 return NULL;
353
354 key = gdbm_firstkey(self->di_dbm);
355 while (key.dptr) {
356 item = PyBytes_FromStringAndSize(key.dptr, key.dsize);
357 if (item == NULL) {
358 free(key.dptr);
359 Py_DECREF(v);
360 return NULL;
361 }
362 err = PyList_Append(v, item);
363 Py_DECREF(item);
364 if (err != 0) {
365 free(key.dptr);
366 Py_DECREF(v);
367 return NULL;
368 }
369 nextkey = gdbm_nextkey(self->di_dbm, key);
370 free(key.dptr);
371 key = nextkey;
372 }
373 return v;
374 }
375
376 static int
gdbm_contains(PyObject * self,PyObject * arg)377 gdbm_contains(PyObject *self, PyObject *arg)
378 {
379 gdbmobject *dp = (gdbmobject *)self;
380 datum key;
381 Py_ssize_t size;
382 _gdbm_state *state = PyType_GetModuleState(Py_TYPE(dp));
383
384 if ((dp)->di_dbm == NULL) {
385 PyErr_SetString(state->gdbm_error,
386 "GDBM object has already been closed");
387 return -1;
388 }
389 if (PyUnicode_Check(arg)) {
390 key.dptr = (char *)PyUnicode_AsUTF8AndSize(arg, &size);
391 key.dsize = size;
392 if (key.dptr == NULL)
393 return -1;
394 }
395 else if (!PyBytes_Check(arg)) {
396 PyErr_Format(PyExc_TypeError,
397 "gdbm key must be bytes or string, not %.100s",
398 Py_TYPE(arg)->tp_name);
399 return -1;
400 }
401 else {
402 key.dptr = PyBytes_AS_STRING(arg);
403 key.dsize = PyBytes_GET_SIZE(arg);
404 }
405 return gdbm_exists(dp->di_dbm, key);
406 }
407
408 /*[clinic input]
409 _gdbm.gdbm.firstkey
410
411 cls: defining_class
412
413 Return the starting key for the traversal.
414
415 It's possible to loop over every key in the database using this method
416 and the nextkey() method. The traversal is ordered by GDBM's internal
417 hash values, and won't be sorted by the key values.
418 [clinic start generated code]*/
419
420 static PyObject *
_gdbm_gdbm_firstkey_impl(gdbmobject * self,PyTypeObject * cls)421 _gdbm_gdbm_firstkey_impl(gdbmobject *self, PyTypeObject *cls)
422 /*[clinic end generated code: output=139275e9c8b60827 input=ed8782a029a5d299]*/
423 {
424 PyObject *v;
425 datum key;
426 _gdbm_state *state = PyType_GetModuleState(cls);
427 assert(state != NULL);
428
429 check_gdbmobject_open(self, state->gdbm_error);
430 key = gdbm_firstkey(self->di_dbm);
431 if (key.dptr) {
432 v = PyBytes_FromStringAndSize(key.dptr, key.dsize);
433 free(key.dptr);
434 return v;
435 }
436 else {
437 Py_RETURN_NONE;
438 }
439 }
440
441 /*[clinic input]
442 _gdbm.gdbm.nextkey
443
444 cls: defining_class
445 key: str(accept={str, robuffer}, zeroes=True)
446 /
447
448 Returns the key that follows key in the traversal.
449
450 The following code prints every key in the database db, without having
451 to create a list in memory that contains them all:
452
453 k = db.firstkey()
454 while k is not None:
455 print(k)
456 k = db.nextkey(k)
457 [clinic start generated code]*/
458
459 static PyObject *
_gdbm_gdbm_nextkey_impl(gdbmobject * self,PyTypeObject * cls,const char * key,Py_ssize_t key_length)460 _gdbm_gdbm_nextkey_impl(gdbmobject *self, PyTypeObject *cls, const char *key,
461 Py_ssize_t key_length)
462 /*[clinic end generated code: output=c81a69300ef41766 input=365e297bc0b3db48]*/
463 {
464 PyObject *v;
465 datum dbm_key, nextkey;
466 _gdbm_state *state = PyType_GetModuleState(cls);
467 assert(state != NULL);
468
469 dbm_key.dptr = (char *)key;
470 dbm_key.dsize = key_length;
471 check_gdbmobject_open(self, state->gdbm_error);
472 nextkey = gdbm_nextkey(self->di_dbm, dbm_key);
473 if (nextkey.dptr) {
474 v = PyBytes_FromStringAndSize(nextkey.dptr, nextkey.dsize);
475 free(nextkey.dptr);
476 return v;
477 }
478 else {
479 Py_RETURN_NONE;
480 }
481 }
482
483 /*[clinic input]
484 _gdbm.gdbm.reorganize
485
486 cls: defining_class
487
488 Reorganize the database.
489
490 If you have carried out a lot of deletions and would like to shrink
491 the space used by the GDBM file, this routine will reorganize the
492 database. GDBM will not shorten the length of a database file except
493 by using this reorganization; otherwise, deleted file space will be
494 kept and reused as new (key,value) pairs are added.
495 [clinic start generated code]*/
496
497 static PyObject *
_gdbm_gdbm_reorganize_impl(gdbmobject * self,PyTypeObject * cls)498 _gdbm_gdbm_reorganize_impl(gdbmobject *self, PyTypeObject *cls)
499 /*[clinic end generated code: output=d77c69e8e3dd644a input=e1359faeef844e46]*/
500 {
501 _gdbm_state *state = PyType_GetModuleState(cls);
502 assert(state != NULL);
503 check_gdbmobject_open(self, state->gdbm_error);
504 errno = 0;
505 if (gdbm_reorganize(self->di_dbm) < 0) {
506 if (errno != 0)
507 PyErr_SetFromErrno(state->gdbm_error);
508 else
509 PyErr_SetString(state->gdbm_error, gdbm_strerror(gdbm_errno));
510 return NULL;
511 }
512 Py_RETURN_NONE;
513 }
514
515 /*[clinic input]
516 _gdbm.gdbm.sync
517
518 cls: defining_class
519
520 Flush the database to the disk file.
521
522 When the database has been opened in fast mode, this method forces
523 any unwritten data to be written to the disk.
524 [clinic start generated code]*/
525
526 static PyObject *
_gdbm_gdbm_sync_impl(gdbmobject * self,PyTypeObject * cls)527 _gdbm_gdbm_sync_impl(gdbmobject *self, PyTypeObject *cls)
528 /*[clinic end generated code: output=bb680a2035c3f592 input=3d749235f79b6f2a]*/
529 {
530 _gdbm_state *state = PyType_GetModuleState(cls);
531 assert(state != NULL);
532 check_gdbmobject_open(self, state->gdbm_error);
533 gdbm_sync(self->di_dbm);
534 Py_RETURN_NONE;
535 }
536
537 static PyObject *
gdbm__enter__(PyObject * self,PyObject * args)538 gdbm__enter__(PyObject *self, PyObject *args)
539 {
540 Py_INCREF(self);
541 return self;
542 }
543
544 static PyObject *
gdbm__exit__(PyObject * self,PyObject * args)545 gdbm__exit__(PyObject *self, PyObject *args)
546 {
547 return _gdbm_gdbm_close_impl((gdbmobject *)self);
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: object
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=bca6ec81dc49292c]*/
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;
676 if (!PyUnicode_FSConverter(filename, &filenamebytes)) {
677 return NULL;
678 }
679
680 const char *name = PyBytes_AS_STRING(filenamebytes);
681 if (strlen(name) != (size_t)PyBytes_GET_SIZE(filenamebytes)) {
682 Py_DECREF(filenamebytes);
683 PyErr_SetString(PyExc_ValueError, "embedded null character");
684 return NULL;
685 }
686 PyObject *self = newgdbmobject(state, name, iflags, mode);
687 Py_DECREF(filenamebytes);
688 return self;
689 }
690
691 static const char gdbmmodule_open_flags[] = "rwcn"
692 #ifdef GDBM_FAST
693 "f"
694 #endif
695 #ifdef GDBM_SYNC
696 "s"
697 #endif
698 #ifdef GDBM_NOLOCK
699 "u"
700 #endif
701 ;
702
703 static PyMethodDef _gdbm_module_methods[] = {
704 DBMOPEN_METHODDEF
705 { 0, 0 },
706 };
707
708 static int
_gdbm_exec(PyObject * module)709 _gdbm_exec(PyObject *module)
710 {
711 _gdbm_state *state = get_gdbm_state(module);
712 state->gdbm_type = (PyTypeObject *)PyType_FromModuleAndSpec(module,
713 &gdbmtype_spec, NULL);
714 if (state->gdbm_type == NULL) {
715 return -1;
716 }
717 state->gdbm_error = PyErr_NewException("_gdbm.error", PyExc_OSError, NULL);
718 if (state->gdbm_error == NULL) {
719 return -1;
720 }
721 if (PyModule_AddType(module, (PyTypeObject *)state->gdbm_error) < 0) {
722 return -1;
723 }
724 if (PyModule_AddStringConstant(module, "open_flags",
725 gdbmmodule_open_flags) < 0) {
726 return -1;
727 }
728
729 #if defined(GDBM_VERSION_MAJOR) && defined(GDBM_VERSION_MINOR) && \
730 defined(GDBM_VERSION_PATCH)
731 PyObject *obj = Py_BuildValue("iii", GDBM_VERSION_MAJOR,
732 GDBM_VERSION_MINOR, GDBM_VERSION_PATCH);
733 if (obj == NULL) {
734 return -1;
735 }
736 if (PyModule_AddObject(module, "_GDBM_VERSION", obj) < 0) {
737 Py_DECREF(obj);
738 return -1;
739 }
740 #endif
741 return 0;
742 }
743
744 static int
_gdbm_module_traverse(PyObject * module,visitproc visit,void * arg)745 _gdbm_module_traverse(PyObject *module, visitproc visit, void *arg)
746 {
747 _gdbm_state *state = get_gdbm_state(module);
748 Py_VISIT(state->gdbm_error);
749 Py_VISIT(state->gdbm_type);
750 return 0;
751 }
752
753 static int
_gdbm_module_clear(PyObject * module)754 _gdbm_module_clear(PyObject *module)
755 {
756 _gdbm_state *state = get_gdbm_state(module);
757 Py_CLEAR(state->gdbm_error);
758 Py_CLEAR(state->gdbm_type);
759 return 0;
760 }
761
762 static void
_gdbm_module_free(void * module)763 _gdbm_module_free(void *module)
764 {
765 _gdbm_module_clear((PyObject *)module);
766 }
767
768 static PyModuleDef_Slot _gdbm_module_slots[] = {
769 {Py_mod_exec, _gdbm_exec},
770 {0, NULL}
771 };
772
773 static struct PyModuleDef _gdbmmodule = {
774 PyModuleDef_HEAD_INIT,
775 .m_name = "_gdbm",
776 .m_doc = gdbmmodule__doc__,
777 .m_size = sizeof(_gdbm_state),
778 .m_methods = _gdbm_module_methods,
779 .m_slots = _gdbm_module_slots,
780 .m_traverse = _gdbm_module_traverse,
781 .m_clear = _gdbm_module_clear,
782 .m_free = _gdbm_module_free,
783 };
784
785 PyMODINIT_FUNC
PyInit__gdbm(void)786 PyInit__gdbm(void)
787 {
788 return PyModuleDef_Init(&_gdbmmodule);
789 }
790