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