(root)/
Python-3.11.7/
Modules/
_gdbmmodule.c
       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*
      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 *
      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
     101  gdbm_traverse(gdbmobject *dp, visitproc visit, void *arg)
     102  {
     103      Py_VISIT(Py_TYPE(dp));
     104      return 0;
     105  }
     106  
     107  static void
     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
     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
     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 *
     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 *
     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
     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 *
     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 *
     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 *
     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
     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 *
     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 *
     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 *
     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 *
     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 *
     538  gdbm__enter__(PyObject *self, PyObject *args)
     539  {
     540      Py_INCREF(self);
     541      return self;
     542  }
     543  
     544  static PyObject *
     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 *
     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
     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
     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
     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
     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
     786  PyInit__gdbm(void)
     787  {
     788      return PyModuleDef_Init(&_gdbmmodule);
     789  }