(root)/
Python-3.11.7/
Modules/
fcntlmodule.c
       1  
       2  /* fcntl module */
       3  
       4  #define PY_SSIZE_T_CLEAN
       5  
       6  #include "Python.h"
       7  
       8  #ifdef HAVE_SYS_FILE_H
       9  #include <sys/file.h>
      10  #endif
      11  
      12  #include <sys/ioctl.h>
      13  #include <fcntl.h>
      14  #ifdef HAVE_STROPTS_H
      15  #include <stropts.h>
      16  #endif
      17  
      18  /*[clinic input]
      19  module fcntl
      20  [clinic start generated code]*/
      21  /*[clinic end generated code: output=da39a3ee5e6b4b0d input=124b58387c158179]*/
      22  
      23  #include "clinic/fcntlmodule.c.h"
      24  
      25  /*[clinic input]
      26  fcntl.fcntl
      27  
      28      fd: fildes
      29      cmd as code: int
      30      arg: object(c_default='NULL') = 0
      31      /
      32  
      33  Perform the operation `cmd` on file descriptor fd.
      34  
      35  The values used for `cmd` are operating system dependent, and are available
      36  as constants in the fcntl module, using the same names as used in
      37  the relevant C header files.  The argument arg is optional, and
      38  defaults to 0; it may be an int or a string.  If arg is given as a string,
      39  the return value of fcntl is a string of that length, containing the
      40  resulting value put in the arg buffer by the operating system.  The length
      41  of the arg string is not allowed to exceed 1024 bytes.  If the arg given
      42  is an integer or if none is specified, the result value is an integer
      43  corresponding to the return value of the fcntl call in the C code.
      44  [clinic start generated code]*/
      45  
      46  static PyObject *
      47  fcntl_fcntl_impl(PyObject *module, int fd, int code, PyObject *arg)
      48  /*[clinic end generated code: output=888fc93b51c295bd input=7955340198e5f334]*/
      49  {
      50      unsigned int int_arg = 0;
      51      int ret;
      52      char *str;
      53      Py_ssize_t len;
      54      char buf[1024];
      55      int async_err = 0;
      56  
      57      if (PySys_Audit("fcntl.fcntl", "iiO", fd, code, arg ? arg : Py_None) < 0) {
      58          return NULL;
      59      }
      60  
      61      if (arg != NULL) {
      62          int parse_result;
      63  
      64          if (PyArg_Parse(arg, "s#", &str, &len)) {
      65              if ((size_t)len > sizeof buf) {
      66                  PyErr_SetString(PyExc_ValueError,
      67                                  "fcntl string arg too long");
      68                  return NULL;
      69              }
      70              memcpy(buf, str, len);
      71              do {
      72                  Py_BEGIN_ALLOW_THREADS
      73                  ret = fcntl(fd, code, buf);
      74                  Py_END_ALLOW_THREADS
      75              } while (ret == -1 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
      76              if (ret < 0) {
      77                  return !async_err ? PyErr_SetFromErrno(PyExc_OSError) : NULL;
      78              }
      79              return PyBytes_FromStringAndSize(buf, len);
      80          }
      81  
      82          PyErr_Clear();
      83          parse_result = PyArg_Parse(arg,
      84              "I;fcntl requires a file or file descriptor,"
      85              " an integer and optionally a third integer or a string",
      86              &int_arg);
      87          if (!parse_result) {
      88            return NULL;
      89          }
      90      }
      91  
      92      do {
      93          Py_BEGIN_ALLOW_THREADS
      94          ret = fcntl(fd, code, (int)int_arg);
      95          Py_END_ALLOW_THREADS
      96      } while (ret == -1 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
      97      if (ret < 0) {
      98          return !async_err ? PyErr_SetFromErrno(PyExc_OSError) : NULL;
      99      }
     100      return PyLong_FromLong((long)ret);
     101  }
     102  
     103  
     104  /*[clinic input]
     105  fcntl.ioctl
     106  
     107      fd: fildes
     108      request as code: unsigned_int(bitwise=True)
     109      arg as ob_arg: object(c_default='NULL') = 0
     110      mutate_flag as mutate_arg: bool = True
     111      /
     112  
     113  Perform the operation `request` on file descriptor `fd`.
     114  
     115  The values used for `request` are operating system dependent, and are available
     116  as constants in the fcntl or termios library modules, using the same names as
     117  used in the relevant C header files.
     118  
     119  The argument `arg` is optional, and defaults to 0; it may be an int or a
     120  buffer containing character data (most likely a string or an array).
     121  
     122  If the argument is a mutable buffer (such as an array) and if the
     123  mutate_flag argument (which is only allowed in this case) is true then the
     124  buffer is (in effect) passed to the operating system and changes made by
     125  the OS will be reflected in the contents of the buffer after the call has
     126  returned.  The return value is the integer returned by the ioctl system
     127  call.
     128  
     129  If the argument is a mutable buffer and the mutable_flag argument is false,
     130  the behavior is as if a string had been passed.
     131  
     132  If the argument is an immutable buffer (most likely a string) then a copy
     133  of the buffer is passed to the operating system and the return value is a
     134  string of the same length containing whatever the operating system put in
     135  the buffer.  The length of the arg buffer in this case is not allowed to
     136  exceed 1024 bytes.
     137  
     138  If the arg given is an integer or if none is specified, the result value is
     139  an integer corresponding to the return value of the ioctl call in the C
     140  code.
     141  [clinic start generated code]*/
     142  
     143  static PyObject *
     144  fcntl_ioctl_impl(PyObject *module, int fd, unsigned int code,
     145                   PyObject *ob_arg, int mutate_arg)
     146  /*[clinic end generated code: output=7f7f5840c65991be input=967b4a4cbeceb0a8]*/
     147  {
     148  #define IOCTL_BUFSZ 1024
     149      /* We use the unsigned non-checked 'I' format for the 'code' parameter
     150         because the system expects it to be a 32bit bit field value
     151         regardless of it being passed as an int or unsigned long on
     152         various platforms.  See the termios.TIOCSWINSZ constant across
     153         platforms for an example of this.
     154  
     155         If any of the 64bit platforms ever decide to use more than 32bits
     156         in their unsigned long ioctl codes this will break and need
     157         special casing based on the platform being built on.
     158       */
     159      int arg = 0;
     160      int ret;
     161      Py_buffer pstr;
     162      char *str;
     163      Py_ssize_t len;
     164      char buf[IOCTL_BUFSZ+1];  /* argument plus NUL byte */
     165  
     166      if (PySys_Audit("fcntl.ioctl", "iIO", fd, code,
     167                      ob_arg ? ob_arg : Py_None) < 0) {
     168          return NULL;
     169      }
     170  
     171      if (ob_arg != NULL) {
     172          if (PyArg_Parse(ob_arg, "w*:ioctl", &pstr)) {
     173              char *arg;
     174              str = pstr.buf;
     175              len = pstr.len;
     176  
     177              if (mutate_arg) {
     178                  if (len <= IOCTL_BUFSZ) {
     179                      memcpy(buf, str, len);
     180                      buf[len] = '\0';
     181                      arg = buf;
     182                  }
     183                  else {
     184                      arg = str;
     185                  }
     186              }
     187              else {
     188                  if (len > IOCTL_BUFSZ) {
     189                      PyBuffer_Release(&pstr);
     190                      PyErr_SetString(PyExc_ValueError,
     191                          "ioctl string arg too long");
     192                      return NULL;
     193                  }
     194                  else {
     195                      memcpy(buf, str, len);
     196                      buf[len] = '\0';
     197                      arg = buf;
     198                  }
     199              }
     200              if (buf == arg) {
     201                  Py_BEGIN_ALLOW_THREADS /* think array.resize() */
     202                  ret = ioctl(fd, code, arg);
     203                  Py_END_ALLOW_THREADS
     204              }
     205              else {
     206                  ret = ioctl(fd, code, arg);
     207              }
     208              if (mutate_arg && (len <= IOCTL_BUFSZ)) {
     209                  memcpy(str, buf, len);
     210              }
     211              if (ret < 0) {
     212                  PyErr_SetFromErrno(PyExc_OSError);
     213                  PyBuffer_Release(&pstr);
     214                  return NULL;
     215              }
     216              PyBuffer_Release(&pstr);
     217              if (mutate_arg) {
     218                  return PyLong_FromLong(ret);
     219              }
     220              else {
     221                  return PyBytes_FromStringAndSize(buf, len);
     222              }
     223          }
     224  
     225          PyErr_Clear();
     226          if (PyArg_Parse(ob_arg, "s*:ioctl", &pstr)) {
     227              str = pstr.buf;
     228              len = pstr.len;
     229              if (len > IOCTL_BUFSZ) {
     230                  PyBuffer_Release(&pstr);
     231                  PyErr_SetString(PyExc_ValueError,
     232                                  "ioctl string arg too long");
     233                  return NULL;
     234              }
     235              memcpy(buf, str, len);
     236              buf[len] = '\0';
     237              Py_BEGIN_ALLOW_THREADS
     238              ret = ioctl(fd, code, buf);
     239              Py_END_ALLOW_THREADS
     240              if (ret < 0) {
     241                  PyErr_SetFromErrno(PyExc_OSError);
     242                  PyBuffer_Release(&pstr);
     243                  return NULL;
     244              }
     245              PyBuffer_Release(&pstr);
     246              return PyBytes_FromStringAndSize(buf, len);
     247          }
     248  
     249          PyErr_Clear();
     250          if (!PyArg_Parse(ob_arg,
     251               "i;ioctl requires a file or file descriptor,"
     252               " an integer and optionally an integer or buffer argument",
     253               &arg)) {
     254            return NULL;
     255          }
     256          // Fall-through to outside the 'if' statement.
     257      }
     258      Py_BEGIN_ALLOW_THREADS
     259      ret = ioctl(fd, code, arg);
     260      Py_END_ALLOW_THREADS
     261      if (ret < 0) {
     262          PyErr_SetFromErrno(PyExc_OSError);
     263          return NULL;
     264      }
     265      return PyLong_FromLong((long)ret);
     266  #undef IOCTL_BUFSZ
     267  }
     268  
     269  /*[clinic input]
     270  fcntl.flock
     271  
     272      fd: fildes
     273      operation as code: int
     274      /
     275  
     276  Perform the lock operation `operation` on file descriptor `fd`.
     277  
     278  See the Unix manual page for flock(2) for details (On some systems, this
     279  function is emulated using fcntl()).
     280  [clinic start generated code]*/
     281  
     282  static PyObject *
     283  fcntl_flock_impl(PyObject *module, int fd, int code)
     284  /*[clinic end generated code: output=84059e2b37d2fc64 input=0bfc00f795953452]*/
     285  {
     286      int ret;
     287      int async_err = 0;
     288  
     289      if (PySys_Audit("fcntl.flock", "ii", fd, code) < 0) {
     290          return NULL;
     291      }
     292  
     293  #ifdef HAVE_FLOCK
     294      do {
     295          Py_BEGIN_ALLOW_THREADS
     296          ret = flock(fd, code);
     297          Py_END_ALLOW_THREADS
     298      } while (ret == -1 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
     299  #else
     300  
     301  #ifndef LOCK_SH
     302  #define LOCK_SH         1       /* shared lock */
     303  #define LOCK_EX         2       /* exclusive lock */
     304  #define LOCK_NB         4       /* don't block when locking */
     305  #define LOCK_UN         8       /* unlock */
     306  #endif
     307      {
     308          struct flock l;
     309          if (code == LOCK_UN)
     310              l.l_type = F_UNLCK;
     311          else if (code & LOCK_SH)
     312              l.l_type = F_RDLCK;
     313          else if (code & LOCK_EX)
     314              l.l_type = F_WRLCK;
     315          else {
     316              PyErr_SetString(PyExc_ValueError,
     317                              "unrecognized flock argument");
     318              return NULL;
     319          }
     320          l.l_whence = l.l_start = l.l_len = 0;
     321          do {
     322              Py_BEGIN_ALLOW_THREADS
     323              ret = fcntl(fd, (code & LOCK_NB) ? F_SETLK : F_SETLKW, &l);
     324              Py_END_ALLOW_THREADS
     325          } while (ret == -1 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
     326      }
     327  #endif /* HAVE_FLOCK */
     328      if (ret < 0) {
     329          return !async_err ? PyErr_SetFromErrno(PyExc_OSError) : NULL;
     330      }
     331      Py_RETURN_NONE;
     332  }
     333  
     334  
     335  /*[clinic input]
     336  fcntl.lockf
     337  
     338      fd: fildes
     339      cmd as code: int
     340      len as lenobj: object(c_default='NULL') = 0
     341      start as startobj: object(c_default='NULL') = 0
     342      whence: int = 0
     343      /
     344  
     345  A wrapper around the fcntl() locking calls.
     346  
     347  `fd` is the file descriptor of the file to lock or unlock, and operation is one
     348  of the following values:
     349  
     350      LOCK_UN - unlock
     351      LOCK_SH - acquire a shared lock
     352      LOCK_EX - acquire an exclusive lock
     353  
     354  When operation is LOCK_SH or LOCK_EX, it can also be bitwise ORed with
     355  LOCK_NB to avoid blocking on lock acquisition.  If LOCK_NB is used and the
     356  lock cannot be acquired, an OSError will be raised and the exception will
     357  have an errno attribute set to EACCES or EAGAIN (depending on the operating
     358  system -- for portability, check for either value).
     359  
     360  `len` is the number of bytes to lock, with the default meaning to lock to
     361  EOF.  `start` is the byte offset, relative to `whence`, to that the lock
     362  starts.  `whence` is as with fileobj.seek(), specifically:
     363  
     364      0 - relative to the start of the file (SEEK_SET)
     365      1 - relative to the current buffer position (SEEK_CUR)
     366      2 - relative to the end of the file (SEEK_END)
     367  [clinic start generated code]*/
     368  
     369  static PyObject *
     370  fcntl_lockf_impl(PyObject *module, int fd, int code, PyObject *lenobj,
     371                   PyObject *startobj, int whence)
     372  /*[clinic end generated code: output=4985e7a172e7461a input=5480479fc63a04b8]*/
     373  {
     374      int ret;
     375      int async_err = 0;
     376  
     377      if (PySys_Audit("fcntl.lockf", "iiOOi", fd, code, lenobj ? lenobj : Py_None,
     378                      startobj ? startobj : Py_None, whence) < 0) {
     379          return NULL;
     380      }
     381  
     382  #ifndef LOCK_SH
     383  #define LOCK_SH         1       /* shared lock */
     384  #define LOCK_EX         2       /* exclusive lock */
     385  #define LOCK_NB         4       /* don't block when locking */
     386  #define LOCK_UN         8       /* unlock */
     387  #endif  /* LOCK_SH */
     388      {
     389          struct flock l;
     390          if (code == LOCK_UN)
     391              l.l_type = F_UNLCK;
     392          else if (code & LOCK_SH)
     393              l.l_type = F_RDLCK;
     394          else if (code & LOCK_EX)
     395              l.l_type = F_WRLCK;
     396          else {
     397              PyErr_SetString(PyExc_ValueError,
     398                              "unrecognized lockf argument");
     399              return NULL;
     400          }
     401          l.l_start = l.l_len = 0;
     402          if (startobj != NULL) {
     403  #if !defined(HAVE_LARGEFILE_SUPPORT)
     404              l.l_start = PyLong_AsLong(startobj);
     405  #else
     406              l.l_start = PyLong_Check(startobj) ?
     407                              PyLong_AsLongLong(startobj) :
     408                      PyLong_AsLong(startobj);
     409  #endif
     410              if (PyErr_Occurred())
     411                  return NULL;
     412          }
     413          if (lenobj != NULL) {
     414  #if !defined(HAVE_LARGEFILE_SUPPORT)
     415              l.l_len = PyLong_AsLong(lenobj);
     416  #else
     417              l.l_len = PyLong_Check(lenobj) ?
     418                              PyLong_AsLongLong(lenobj) :
     419                      PyLong_AsLong(lenobj);
     420  #endif
     421              if (PyErr_Occurred())
     422                  return NULL;
     423          }
     424          l.l_whence = whence;
     425          do {
     426              Py_BEGIN_ALLOW_THREADS
     427              ret = fcntl(fd, (code & LOCK_NB) ? F_SETLK : F_SETLKW, &l);
     428              Py_END_ALLOW_THREADS
     429          } while (ret == -1 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
     430      }
     431      if (ret < 0) {
     432          return !async_err ? PyErr_SetFromErrno(PyExc_OSError) : NULL;
     433      }
     434      Py_RETURN_NONE;
     435  }
     436  
     437  /* List of functions */
     438  
     439  static PyMethodDef fcntl_methods[] = {
     440      FCNTL_FCNTL_METHODDEF
     441      FCNTL_IOCTL_METHODDEF
     442      FCNTL_FLOCK_METHODDEF
     443      FCNTL_LOCKF_METHODDEF
     444      {NULL, NULL}  /* sentinel */
     445  };
     446  
     447  
     448  PyDoc_STRVAR(module_doc,
     449  "This module performs file control and I/O control on file\n\
     450  descriptors.  It is an interface to the fcntl() and ioctl() Unix\n\
     451  routines.  File descriptors can be obtained with the fileno() method of\n\
     452  a file or socket object.");
     453  
     454  /* Module initialisation */
     455  
     456  
     457  static int
     458  all_ins(PyObject* m)
     459  {
     460      if (PyModule_AddIntMacro(m, LOCK_SH)) return -1;
     461      if (PyModule_AddIntMacro(m, LOCK_EX)) return -1;
     462      if (PyModule_AddIntMacro(m, LOCK_NB)) return -1;
     463      if (PyModule_AddIntMacro(m, LOCK_UN)) return -1;
     464  /* GNU extensions, as of glibc 2.2.4 */
     465  #ifdef LOCK_MAND
     466      if (PyModule_AddIntMacro(m, LOCK_MAND)) return -1;
     467  #endif
     468  #ifdef LOCK_READ
     469      if (PyModule_AddIntMacro(m, LOCK_READ)) return -1;
     470  #endif
     471  #ifdef LOCK_WRITE
     472      if (PyModule_AddIntMacro(m, LOCK_WRITE)) return -1;
     473  #endif
     474  #ifdef LOCK_RW
     475      if (PyModule_AddIntMacro(m, LOCK_RW)) return -1;
     476  #endif
     477  
     478  #ifdef F_DUPFD
     479      if (PyModule_AddIntMacro(m, F_DUPFD)) return -1;
     480  #endif
     481  #ifdef F_DUPFD_CLOEXEC
     482      if (PyModule_AddIntMacro(m, F_DUPFD_CLOEXEC)) return -1;
     483  #endif
     484  #ifdef F_GETFD
     485      if (PyModule_AddIntMacro(m, F_GETFD)) return -1;
     486  #endif
     487  #ifdef F_SETFD
     488      if (PyModule_AddIntMacro(m, F_SETFD)) return -1;
     489  #endif
     490  #ifdef F_GETFL
     491      if (PyModule_AddIntMacro(m, F_GETFL)) return -1;
     492  #endif
     493  #ifdef F_SETFL
     494      if (PyModule_AddIntMacro(m, F_SETFL)) return -1;
     495  #endif
     496  #ifdef F_GETLK
     497      if (PyModule_AddIntMacro(m, F_GETLK)) return -1;
     498  #endif
     499  #ifdef F_SETLK
     500      if (PyModule_AddIntMacro(m, F_SETLK)) return -1;
     501  #endif
     502  #ifdef F_SETLKW
     503      if (PyModule_AddIntMacro(m, F_SETLKW)) return -1;
     504  #endif
     505  #ifdef F_OFD_GETLK
     506      if (PyModule_AddIntMacro(m, F_OFD_GETLK)) return -1;
     507  #endif
     508  #ifdef F_OFD_SETLK
     509      if (PyModule_AddIntMacro(m, F_OFD_SETLK)) return -1;
     510  #endif
     511  #ifdef F_OFD_SETLKW
     512      if (PyModule_AddIntMacro(m, F_OFD_SETLKW)) return -1;
     513  #endif
     514  #ifdef F_GETOWN
     515      if (PyModule_AddIntMacro(m, F_GETOWN)) return -1;
     516  #endif
     517  #ifdef F_SETOWN
     518      if (PyModule_AddIntMacro(m, F_SETOWN)) return -1;
     519  #endif
     520  #ifdef F_GETPATH
     521      if (PyModule_AddIntMacro(m, F_GETPATH)) return -1;
     522  #endif
     523  #ifdef F_GETSIG
     524      if (PyModule_AddIntMacro(m, F_GETSIG)) return -1;
     525  #endif
     526  #ifdef F_SETSIG
     527      if (PyModule_AddIntMacro(m, F_SETSIG)) return -1;
     528  #endif
     529  #ifdef F_RDLCK
     530      if (PyModule_AddIntMacro(m, F_RDLCK)) return -1;
     531  #endif
     532  #ifdef F_WRLCK
     533      if (PyModule_AddIntMacro(m, F_WRLCK)) return -1;
     534  #endif
     535  #ifdef F_UNLCK
     536      if (PyModule_AddIntMacro(m, F_UNLCK)) return -1;
     537  #endif
     538  /* LFS constants */
     539  #ifdef F_GETLK64
     540      if (PyModule_AddIntMacro(m, F_GETLK64)) return -1;
     541  #endif
     542  #ifdef F_SETLK64
     543      if (PyModule_AddIntMacro(m, F_SETLK64)) return -1;
     544  #endif
     545  #ifdef F_SETLKW64
     546      if (PyModule_AddIntMacro(m, F_SETLKW64)) return -1;
     547  #endif
     548  /* GNU extensions, as of glibc 2.2.4. */
     549  #ifdef FASYNC
     550      if (PyModule_AddIntMacro(m, FASYNC)) return -1;
     551  #endif
     552  #ifdef F_SETLEASE
     553      if (PyModule_AddIntMacro(m, F_SETLEASE)) return -1;
     554  #endif
     555  #ifdef F_GETLEASE
     556      if (PyModule_AddIntMacro(m, F_GETLEASE)) return -1;
     557  #endif
     558  #ifdef F_NOTIFY
     559      if (PyModule_AddIntMacro(m, F_NOTIFY)) return -1;
     560  #endif
     561  /* Old BSD flock(). */
     562  #ifdef F_EXLCK
     563      if (PyModule_AddIntMacro(m, F_EXLCK)) return -1;
     564  #endif
     565  #ifdef F_SHLCK
     566      if (PyModule_AddIntMacro(m, F_SHLCK)) return -1;
     567  #endif
     568  
     569  /* Linux specifics */
     570  #ifdef F_SETPIPE_SZ
     571      if (PyModule_AddIntMacro(m, F_SETPIPE_SZ)) return -1;
     572  #endif
     573  #ifdef F_GETPIPE_SZ
     574      if (PyModule_AddIntMacro(m, F_GETPIPE_SZ)) return -1;
     575  #endif
     576  
     577  /* OS X specifics */
     578  #ifdef F_FULLFSYNC
     579      if (PyModule_AddIntMacro(m, F_FULLFSYNC)) return -1;
     580  #endif
     581  #ifdef F_NOCACHE
     582      if (PyModule_AddIntMacro(m, F_NOCACHE)) return -1;
     583  #endif
     584  
     585  /* FreeBSD specifics */
     586  #ifdef F_DUP2FD
     587      if (PyModule_AddIntMacro(m, F_DUP2FD)) return -1;
     588  #endif
     589  #ifdef F_DUP2FD_CLOEXEC
     590      if (PyModule_AddIntMacro(m, F_DUP2FD_CLOEXEC)) return -1;
     591  #endif
     592  
     593  /* For F_{GET|SET}FL */
     594  #ifdef FD_CLOEXEC
     595      if (PyModule_AddIntMacro(m, FD_CLOEXEC)) return -1;
     596  #endif
     597  
     598  /* For F_NOTIFY */
     599  #ifdef DN_ACCESS
     600      if (PyModule_AddIntMacro(m, DN_ACCESS)) return -1;
     601  #endif
     602  #ifdef DN_MODIFY
     603      if (PyModule_AddIntMacro(m, DN_MODIFY)) return -1;
     604  #endif
     605  #ifdef DN_CREATE
     606      if (PyModule_AddIntMacro(m, DN_CREATE)) return -1;
     607  #endif
     608  #ifdef DN_DELETE
     609      if (PyModule_AddIntMacro(m, DN_DELETE)) return -1;
     610  #endif
     611  #ifdef DN_RENAME
     612      if (PyModule_AddIntMacro(m, DN_RENAME)) return -1;
     613  #endif
     614  #ifdef DN_ATTRIB
     615      if (PyModule_AddIntMacro(m, DN_ATTRIB)) return -1;
     616  #endif
     617  #ifdef DN_MULTISHOT
     618      if (PyModule_AddIntMacro(m, DN_MULTISHOT)) return -1;
     619  #endif
     620  
     621  #ifdef HAVE_STROPTS_H
     622      /* Unix 98 guarantees that these are in stropts.h. */
     623      if (PyModule_AddIntMacro(m, I_PUSH)) return -1;
     624      if (PyModule_AddIntMacro(m, I_POP)) return -1;
     625      if (PyModule_AddIntMacro(m, I_LOOK)) return -1;
     626      if (PyModule_AddIntMacro(m, I_FLUSH)) return -1;
     627      if (PyModule_AddIntMacro(m, I_FLUSHBAND)) return -1;
     628      if (PyModule_AddIntMacro(m, I_SETSIG)) return -1;
     629      if (PyModule_AddIntMacro(m, I_GETSIG)) return -1;
     630      if (PyModule_AddIntMacro(m, I_FIND)) return -1;
     631      if (PyModule_AddIntMacro(m, I_PEEK)) return -1;
     632      if (PyModule_AddIntMacro(m, I_SRDOPT)) return -1;
     633      if (PyModule_AddIntMacro(m, I_GRDOPT)) return -1;
     634      if (PyModule_AddIntMacro(m, I_NREAD)) return -1;
     635      if (PyModule_AddIntMacro(m, I_FDINSERT)) return -1;
     636      if (PyModule_AddIntMacro(m, I_STR)) return -1;
     637      if (PyModule_AddIntMacro(m, I_SWROPT)) return -1;
     638  #ifdef I_GWROPT
     639      /* despite the comment above, old-ish glibcs miss a couple... */
     640      if (PyModule_AddIntMacro(m, I_GWROPT)) return -1;
     641  #endif
     642      if (PyModule_AddIntMacro(m, I_SENDFD)) return -1;
     643      if (PyModule_AddIntMacro(m, I_RECVFD)) return -1;
     644      if (PyModule_AddIntMacro(m, I_LIST)) return -1;
     645      if (PyModule_AddIntMacro(m, I_ATMARK)) return -1;
     646      if (PyModule_AddIntMacro(m, I_CKBAND)) return -1;
     647      if (PyModule_AddIntMacro(m, I_GETBAND)) return -1;
     648      if (PyModule_AddIntMacro(m, I_CANPUT)) return -1;
     649      if (PyModule_AddIntMacro(m, I_SETCLTIME)) return -1;
     650  #ifdef I_GETCLTIME
     651      if (PyModule_AddIntMacro(m, I_GETCLTIME)) return -1;
     652  #endif
     653      if (PyModule_AddIntMacro(m, I_LINK)) return -1;
     654      if (PyModule_AddIntMacro(m, I_UNLINK)) return -1;
     655      if (PyModule_AddIntMacro(m, I_PLINK)) return -1;
     656      if (PyModule_AddIntMacro(m, I_PUNLINK)) return -1;
     657  #endif
     658  #ifdef F_ADD_SEALS
     659      /* Linux: file sealing for memfd_create() */
     660      if (PyModule_AddIntMacro(m, F_ADD_SEALS)) return -1;
     661      if (PyModule_AddIntMacro(m, F_GET_SEALS)) return -1;
     662      if (PyModule_AddIntMacro(m, F_SEAL_SEAL)) return -1;
     663      if (PyModule_AddIntMacro(m, F_SEAL_SHRINK)) return -1;
     664      if (PyModule_AddIntMacro(m, F_SEAL_GROW)) return -1;
     665      if (PyModule_AddIntMacro(m, F_SEAL_WRITE)) return -1;
     666  #endif
     667      return 0;
     668  }
     669  
     670  static int
     671  fcntl_exec(PyObject *module)
     672  {
     673      if (all_ins(module) < 0) {
     674          return -1;
     675      }
     676      return 0;
     677  }
     678  
     679  static PyModuleDef_Slot fcntl_slots[] = {
     680      {Py_mod_exec, fcntl_exec},
     681      {0, NULL}
     682  };
     683  
     684  static struct PyModuleDef fcntlmodule = {
     685      PyModuleDef_HEAD_INIT,
     686      .m_name = "fcntl",
     687      .m_doc = module_doc,
     688      .m_size = 0,
     689      .m_methods = fcntl_methods,
     690      .m_slots = fcntl_slots,
     691  };
     692  
     693  PyMODINIT_FUNC
     694  PyInit_fcntl(void)
     695  {
     696      return PyModuleDef_Init(&fcntlmodule);
     697  }