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