Line data Source code
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 : static int
19 0 : conv_descriptor(PyObject *object, int *target)
20 : {
21 0 : int fd = PyObject_AsFileDescriptor(object);
22 :
23 0 : if (fd < 0)
24 0 : return 0;
25 0 : *target = fd;
26 0 : return 1;
27 : }
28 :
29 :
30 : /* fcntl(fd, op, [arg]) */
31 :
32 : static PyObject *
33 0 : fcntl_fcntl(PyObject *self, PyObject *args)
34 : {
35 : int fd;
36 : int code;
37 : int arg;
38 : int ret;
39 : char *str;
40 : Py_ssize_t len;
41 : char buf[1024];
42 :
43 0 : if (PyArg_ParseTuple(args, "O&is#:fcntl",
44 : conv_descriptor, &fd, &code, &str, &len)) {
45 0 : if (len > sizeof buf) {
46 0 : PyErr_SetString(PyExc_ValueError,
47 : "fcntl string arg too long");
48 0 : return NULL;
49 : }
50 0 : memcpy(buf, str, len);
51 : Py_BEGIN_ALLOW_THREADS
52 0 : ret = fcntl(fd, code, buf);
53 : Py_END_ALLOW_THREADS
54 0 : if (ret < 0) {
55 0 : PyErr_SetFromErrno(PyExc_IOError);
56 0 : return NULL;
57 : }
58 0 : return PyString_FromStringAndSize(buf, len);
59 : }
60 :
61 0 : PyErr_Clear();
62 0 : arg = 0;
63 0 : if (!PyArg_ParseTuple(args,
64 : "O&i|I;fcntl requires a file or file descriptor,"
65 : " an integer and optionally a third integer or a string",
66 : conv_descriptor, &fd, &code, &arg)) {
67 0 : return NULL;
68 : }
69 : Py_BEGIN_ALLOW_THREADS
70 0 : ret = fcntl(fd, code, arg);
71 : Py_END_ALLOW_THREADS
72 0 : if (ret < 0) {
73 0 : PyErr_SetFromErrno(PyExc_IOError);
74 0 : return NULL;
75 : }
76 0 : return PyInt_FromLong((long)ret);
77 : }
78 :
79 : PyDoc_STRVAR(fcntl_doc,
80 : "fcntl(fd, op, [arg])\n\
81 : \n\
82 : Perform the operation op on file descriptor fd. The values used\n\
83 : for op are operating system dependent, and are available\n\
84 : as constants in the fcntl module, using the same names as used in\n\
85 : the relevant C header files. The argument arg is optional, and\n\
86 : defaults to 0; it may be an int or a string. If arg is given as a string,\n\
87 : the return value of fcntl is a string of that length, containing the\n\
88 : resulting value put in the arg buffer by the operating system. The length\n\
89 : of the arg string is not allowed to exceed 1024 bytes. If the arg given\n\
90 : is an integer or if none is specified, the result value is an integer\n\
91 : corresponding to the return value of the fcntl call in the C code.");
92 :
93 :
94 : /* ioctl(fd, op, [arg]) */
95 :
96 : static PyObject *
97 0 : fcntl_ioctl(PyObject *self, PyObject *args)
98 : {
99 : #define IOCTL_BUFSZ 1024
100 : int fd;
101 : /* In PyArg_ParseTuple below, we use the unsigned non-checked 'I'
102 : format for the 'code' parameter because Python turns 0x8000000
103 : into either a large positive number (PyLong or PyInt on 64-bit
104 : platforms) or a negative number on others (32-bit PyInt)
105 : whereas the system expects it to be a 32bit bit field value
106 : regardless of it being passed as an int or unsigned long on
107 : various platforms. See the termios.TIOCSWINSZ constant across
108 : platforms for an example of this.
109 :
110 : If any of the 64bit platforms ever decide to use more than 32bits
111 : in their unsigned long ioctl codes this will break and need
112 : special casing based on the platform being built on.
113 : */
114 : unsigned int code;
115 : int arg;
116 : int ret;
117 : char *str;
118 : Py_ssize_t len;
119 0 : int mutate_arg = 1;
120 : char buf[IOCTL_BUFSZ+1]; /* argument plus NUL byte */
121 :
122 0 : if (PyArg_ParseTuple(args, "O&Iw#|i:ioctl",
123 : conv_descriptor, &fd, &code,
124 : &str, &len, &mutate_arg)) {
125 : char *arg;
126 :
127 0 : if (mutate_arg) {
128 0 : if (len <= IOCTL_BUFSZ) {
129 0 : memcpy(buf, str, len);
130 0 : buf[len] = '\0';
131 0 : arg = buf;
132 : }
133 : else {
134 0 : arg = str;
135 : }
136 : }
137 : else {
138 0 : if (len > IOCTL_BUFSZ) {
139 0 : PyErr_SetString(PyExc_ValueError,
140 : "ioctl string arg too long");
141 0 : return NULL;
142 : }
143 : else {
144 0 : memcpy(buf, str, len);
145 0 : buf[len] = '\0';
146 0 : arg = buf;
147 : }
148 : }
149 0 : if (buf == arg) {
150 : Py_BEGIN_ALLOW_THREADS /* think array.resize() */
151 0 : ret = ioctl(fd, code, arg);
152 : Py_END_ALLOW_THREADS
153 : }
154 : else {
155 0 : ret = ioctl(fd, code, arg);
156 : }
157 0 : if (mutate_arg && (len <= IOCTL_BUFSZ)) {
158 0 : memcpy(str, buf, len);
159 : }
160 0 : if (ret < 0) {
161 0 : PyErr_SetFromErrno(PyExc_IOError);
162 0 : return NULL;
163 : }
164 0 : if (mutate_arg) {
165 0 : return PyInt_FromLong(ret);
166 : }
167 : else {
168 0 : return PyString_FromStringAndSize(buf, len);
169 : }
170 : }
171 :
172 0 : PyErr_Clear();
173 0 : if (PyArg_ParseTuple(args, "O&Is#:ioctl",
174 : conv_descriptor, &fd, &code, &str, &len)) {
175 0 : if (len > IOCTL_BUFSZ) {
176 0 : PyErr_SetString(PyExc_ValueError,
177 : "ioctl string arg too long");
178 0 : return NULL;
179 : }
180 0 : memcpy(buf, str, len);
181 0 : buf[len] = '\0';
182 : Py_BEGIN_ALLOW_THREADS
183 0 : ret = ioctl(fd, code, buf);
184 : Py_END_ALLOW_THREADS
185 0 : if (ret < 0) {
186 0 : PyErr_SetFromErrno(PyExc_IOError);
187 0 : return NULL;
188 : }
189 0 : return PyString_FromStringAndSize(buf, len);
190 : }
191 :
192 0 : PyErr_Clear();
193 0 : arg = 0;
194 0 : if (!PyArg_ParseTuple(args,
195 : "O&I|i;ioctl requires a file or file descriptor,"
196 : " an integer and optionally an integer or buffer argument",
197 : conv_descriptor, &fd, &code, &arg)) {
198 0 : return NULL;
199 : }
200 : Py_BEGIN_ALLOW_THREADS
201 : #ifdef __VMS
202 : ret = ioctl(fd, code, (void *)arg);
203 : #else
204 0 : ret = ioctl(fd, code, arg);
205 : #endif
206 : Py_END_ALLOW_THREADS
207 0 : if (ret < 0) {
208 0 : PyErr_SetFromErrno(PyExc_IOError);
209 0 : return NULL;
210 : }
211 0 : return PyInt_FromLong((long)ret);
212 : #undef IOCTL_BUFSZ
213 : }
214 :
215 : PyDoc_STRVAR(ioctl_doc,
216 : "ioctl(fd, op[, arg[, mutate_flag]])\n\
217 : \n\
218 : Perform the operation op on file descriptor fd. The values used for op\n\
219 : are operating system dependent, and are available as constants in the\n\
220 : fcntl or termios library modules, using the same names as used in the\n\
221 : relevant C header files.\n\
222 : \n\
223 : The argument arg is optional, and defaults to 0; it may be an int or a\n\
224 : buffer containing character data (most likely a string or an array). \n\
225 : \n\
226 : If the argument is a mutable buffer (such as an array) and if the\n\
227 : mutate_flag argument (which is only allowed in this case) is true then the\n\
228 : buffer is (in effect) passed to the operating system and changes made by\n\
229 : the OS will be reflected in the contents of the buffer after the call has\n\
230 : returned. The return value is the integer returned by the ioctl system\n\
231 : call.\n\
232 : \n\
233 : If the argument is a mutable buffer and the mutable_flag argument is not\n\
234 : passed or is false, the behavior is as if a string had been passed. This\n\
235 : behavior will change in future releases of Python.\n\
236 : \n\
237 : If the argument is an immutable buffer (most likely a string) then a copy\n\
238 : of the buffer is passed to the operating system and the return value is a\n\
239 : string of the same length containing whatever the operating system put in\n\
240 : the buffer. The length of the arg buffer in this case is not allowed to\n\
241 : exceed 1024 bytes.\n\
242 : \n\
243 : If the arg given is an integer or if none is specified, the result value is\n\
244 : an integer corresponding to the return value of the ioctl call in the C\n\
245 : code.");
246 :
247 :
248 : /* flock(fd, operation) */
249 :
250 : static PyObject *
251 0 : fcntl_flock(PyObject *self, PyObject *args)
252 : {
253 : int fd;
254 : int code;
255 : int ret;
256 :
257 0 : if (!PyArg_ParseTuple(args, "O&i:flock",
258 : conv_descriptor, &fd, &code))
259 0 : return NULL;
260 :
261 : #ifdef HAVE_FLOCK
262 : Py_BEGIN_ALLOW_THREADS
263 0 : ret = flock(fd, code);
264 : Py_END_ALLOW_THREADS
265 : #else
266 :
267 : #ifndef LOCK_SH
268 : #define LOCK_SH 1 /* shared lock */
269 : #define LOCK_EX 2 /* exclusive lock */
270 : #define LOCK_NB 4 /* don't block when locking */
271 : #define LOCK_UN 8 /* unlock */
272 : #endif
273 : {
274 : struct flock l;
275 : if (code == LOCK_UN)
276 : l.l_type = F_UNLCK;
277 : else if (code & LOCK_SH)
278 : l.l_type = F_RDLCK;
279 : else if (code & LOCK_EX)
280 : l.l_type = F_WRLCK;
281 : else {
282 : PyErr_SetString(PyExc_ValueError,
283 : "unrecognized flock argument");
284 : return NULL;
285 : }
286 : l.l_whence = l.l_start = l.l_len = 0;
287 : Py_BEGIN_ALLOW_THREADS
288 : ret = fcntl(fd, (code & LOCK_NB) ? F_SETLK : F_SETLKW, &l);
289 : Py_END_ALLOW_THREADS
290 : }
291 : #endif /* HAVE_FLOCK */
292 0 : if (ret < 0) {
293 0 : PyErr_SetFromErrno(PyExc_IOError);
294 0 : return NULL;
295 : }
296 0 : Py_INCREF(Py_None);
297 0 : return Py_None;
298 : }
299 :
300 : PyDoc_STRVAR(flock_doc,
301 : "flock(fd, operation)\n\
302 : \n\
303 : Perform the lock operation op on file descriptor fd. See the Unix \n\
304 : manual page for flock(2) for details. (On some systems, this function is\n\
305 : emulated using fcntl().)");
306 :
307 :
308 : /* lockf(fd, operation) */
309 : static PyObject *
310 0 : fcntl_lockf(PyObject *self, PyObject *args)
311 : {
312 0 : int fd, code, ret, whence = 0;
313 0 : PyObject *lenobj = NULL, *startobj = NULL;
314 :
315 0 : if (!PyArg_ParseTuple(args, "O&i|OOi:lockf",
316 : conv_descriptor, &fd, &code,
317 : &lenobj, &startobj, &whence))
318 0 : return NULL;
319 :
320 : #if defined(PYOS_OS2) && defined(PYCC_GCC)
321 : PyErr_SetString(PyExc_NotImplementedError,
322 : "lockf not supported on OS/2 (EMX)");
323 : return NULL;
324 : #else
325 : #ifndef LOCK_SH
326 : #define LOCK_SH 1 /* shared lock */
327 : #define LOCK_EX 2 /* exclusive lock */
328 : #define LOCK_NB 4 /* don't block when locking */
329 : #define LOCK_UN 8 /* unlock */
330 : #endif /* LOCK_SH */
331 : {
332 : struct flock l;
333 0 : if (code == LOCK_UN)
334 0 : l.l_type = F_UNLCK;
335 0 : else if (code & LOCK_SH)
336 0 : l.l_type = F_RDLCK;
337 0 : else if (code & LOCK_EX)
338 0 : l.l_type = F_WRLCK;
339 : else {
340 0 : PyErr_SetString(PyExc_ValueError,
341 : "unrecognized lockf argument");
342 0 : return NULL;
343 : }
344 0 : l.l_start = l.l_len = 0;
345 0 : if (startobj != NULL) {
346 : #if !defined(HAVE_LARGEFILE_SUPPORT)
347 0 : l.l_start = PyInt_AsLong(startobj);
348 : #else
349 : l.l_start = PyLong_Check(startobj) ?
350 : PyLong_AsLongLong(startobj) :
351 : PyInt_AsLong(startobj);
352 : #endif
353 0 : if (PyErr_Occurred())
354 0 : return NULL;
355 : }
356 0 : if (lenobj != NULL) {
357 : #if !defined(HAVE_LARGEFILE_SUPPORT)
358 0 : l.l_len = PyInt_AsLong(lenobj);
359 : #else
360 : l.l_len = PyLong_Check(lenobj) ?
361 : PyLong_AsLongLong(lenobj) :
362 : PyInt_AsLong(lenobj);
363 : #endif
364 0 : if (PyErr_Occurred())
365 0 : return NULL;
366 : }
367 0 : l.l_whence = whence;
368 : Py_BEGIN_ALLOW_THREADS
369 0 : ret = fcntl(fd, (code & LOCK_NB) ? F_SETLK : F_SETLKW, &l);
370 : Py_END_ALLOW_THREADS
371 : }
372 0 : if (ret < 0) {
373 0 : PyErr_SetFromErrno(PyExc_IOError);
374 0 : return NULL;
375 : }
376 0 : Py_INCREF(Py_None);
377 0 : return Py_None;
378 : #endif /* defined(PYOS_OS2) && defined(PYCC_GCC) */
379 : }
380 :
381 : PyDoc_STRVAR(lockf_doc,
382 : "lockf (fd, operation, length=0, start=0, whence=0)\n\
383 : \n\
384 : This is essentially a wrapper around the fcntl() locking calls. fd is the\n\
385 : file descriptor of the file to lock or unlock, and operation is one of the\n\
386 : following values:\n\
387 : \n\
388 : LOCK_UN - unlock\n\
389 : LOCK_SH - acquire a shared lock\n\
390 : LOCK_EX - acquire an exclusive lock\n\
391 : \n\
392 : When operation is LOCK_SH or LOCK_EX, it can also be bitwise ORed with\n\
393 : LOCK_NB to avoid blocking on lock acquisition. If LOCK_NB is used and the\n\
394 : lock cannot be acquired, an IOError will be raised and the exception will\n\
395 : have an errno attribute set to EACCES or EAGAIN (depending on the operating\n\
396 : system -- for portability, check for either value).\n\
397 : \n\
398 : length is the number of bytes to lock, with the default meaning to lock to\n\
399 : EOF. start is the byte offset, relative to whence, to that the lock\n\
400 : starts. whence is as with fileobj.seek(), specifically:\n\
401 : \n\
402 : 0 - relative to the start of the file (SEEK_SET)\n\
403 : 1 - relative to the current buffer position (SEEK_CUR)\n\
404 : 2 - relative to the end of the file (SEEK_END)");
405 :
406 : /* List of functions */
407 :
408 : static PyMethodDef fcntl_methods[] = {
409 : {"fcntl", fcntl_fcntl, METH_VARARGS, fcntl_doc},
410 : {"ioctl", fcntl_ioctl, METH_VARARGS, ioctl_doc},
411 : {"flock", fcntl_flock, METH_VARARGS, flock_doc},
412 : {"lockf", fcntl_lockf, METH_VARARGS, lockf_doc},
413 : {NULL, NULL} /* sentinel */
414 : };
415 :
416 :
417 : PyDoc_STRVAR(module_doc,
418 : "This module performs file control and I/O control on file \n\
419 : descriptors. It is an interface to the fcntl() and ioctl() Unix\n\
420 : routines. File descriptors can be obtained with the fileno() method of\n\
421 : a file or socket object.");
422 :
423 : /* Module initialisation */
424 :
425 : static int
426 207 : ins(PyObject* d, char* symbol, long value)
427 : {
428 207 : PyObject* v = PyInt_FromLong(value);
429 207 : if (!v || PyDict_SetItemString(d, symbol, v) < 0)
430 0 : return -1;
431 :
432 207 : Py_DECREF(v);
433 207 : return 0;
434 : }
435 :
436 : #define INS(x) if (ins(d, #x, (long)x)) return -1
437 :
438 : static int
439 3 : all_ins(PyObject* d)
440 : {
441 3 : if (ins(d, "LOCK_SH", (long)LOCK_SH)) return -1;
442 3 : if (ins(d, "LOCK_EX", (long)LOCK_EX)) return -1;
443 3 : if (ins(d, "LOCK_NB", (long)LOCK_NB)) return -1;
444 3 : if (ins(d, "LOCK_UN", (long)LOCK_UN)) return -1;
445 : /* GNU extensions, as of glibc 2.2.4 */
446 : #ifdef LOCK_MAND
447 3 : if (ins(d, "LOCK_MAND", (long)LOCK_MAND)) return -1;
448 : #endif
449 : #ifdef LOCK_READ
450 3 : if (ins(d, "LOCK_READ", (long)LOCK_READ)) return -1;
451 : #endif
452 : #ifdef LOCK_WRITE
453 3 : if (ins(d, "LOCK_WRITE", (long)LOCK_WRITE)) return -1;
454 : #endif
455 : #ifdef LOCK_RW
456 3 : if (ins(d, "LOCK_RW", (long)LOCK_RW)) return -1;
457 : #endif
458 :
459 : #ifdef F_DUPFD
460 3 : if (ins(d, "F_DUPFD", (long)F_DUPFD)) return -1;
461 : #endif
462 : #ifdef F_GETFD
463 3 : if (ins(d, "F_GETFD", (long)F_GETFD)) return -1;
464 : #endif
465 : #ifdef F_SETFD
466 3 : if (ins(d, "F_SETFD", (long)F_SETFD)) return -1;
467 : #endif
468 : #ifdef F_GETFL
469 3 : if (ins(d, "F_GETFL", (long)F_GETFL)) return -1;
470 : #endif
471 : #ifdef F_SETFL
472 3 : if (ins(d, "F_SETFL", (long)F_SETFL)) return -1;
473 : #endif
474 : #ifdef F_GETLK
475 3 : if (ins(d, "F_GETLK", (long)F_GETLK)) return -1;
476 : #endif
477 : #ifdef F_SETLK
478 3 : if (ins(d, "F_SETLK", (long)F_SETLK)) return -1;
479 : #endif
480 : #ifdef F_SETLKW
481 3 : if (ins(d, "F_SETLKW", (long)F_SETLKW)) return -1;
482 : #endif
483 : #ifdef F_GETOWN
484 3 : if (ins(d, "F_GETOWN", (long)F_GETOWN)) return -1;
485 : #endif
486 : #ifdef F_SETOWN
487 3 : if (ins(d, "F_SETOWN", (long)F_SETOWN)) return -1;
488 : #endif
489 : #ifdef F_GETSIG
490 3 : if (ins(d, "F_GETSIG", (long)F_GETSIG)) return -1;
491 : #endif
492 : #ifdef F_SETSIG
493 3 : if (ins(d, "F_SETSIG", (long)F_SETSIG)) return -1;
494 : #endif
495 : #ifdef F_RDLCK
496 3 : if (ins(d, "F_RDLCK", (long)F_RDLCK)) return -1;
497 : #endif
498 : #ifdef F_WRLCK
499 3 : if (ins(d, "F_WRLCK", (long)F_WRLCK)) return -1;
500 : #endif
501 : #ifdef F_UNLCK
502 3 : if (ins(d, "F_UNLCK", (long)F_UNLCK)) return -1;
503 : #endif
504 : /* LFS constants */
505 : #ifdef F_GETLK64
506 3 : if (ins(d, "F_GETLK64", (long)F_GETLK64)) return -1;
507 : #endif
508 : #ifdef F_SETLK64
509 3 : if (ins(d, "F_SETLK64", (long)F_SETLK64)) return -1;
510 : #endif
511 : #ifdef F_SETLKW64
512 3 : if (ins(d, "F_SETLKW64", (long)F_SETLKW64)) return -1;
513 : #endif
514 : /* GNU extensions, as of glibc 2.2.4. */
515 : #ifdef FASYNC
516 3 : if (ins(d, "FASYNC", (long)FASYNC)) return -1;
517 : #endif
518 : #ifdef F_SETLEASE
519 3 : if (ins(d, "F_SETLEASE", (long)F_SETLEASE)) return -1;
520 : #endif
521 : #ifdef F_GETLEASE
522 3 : if (ins(d, "F_GETLEASE", (long)F_GETLEASE)) return -1;
523 : #endif
524 : #ifdef F_NOTIFY
525 3 : if (ins(d, "F_NOTIFY", (long)F_NOTIFY)) return -1;
526 : #endif
527 : /* Old BSD flock(). */
528 : #ifdef F_EXLCK
529 3 : if (ins(d, "F_EXLCK", (long)F_EXLCK)) return -1;
530 : #endif
531 : #ifdef F_SHLCK
532 3 : if (ins(d, "F_SHLCK", (long)F_SHLCK)) return -1;
533 : #endif
534 :
535 : /* OS X (and maybe others) let you tell the storage device to flush to physical media */
536 : #ifdef F_FULLFSYNC
537 : if (ins(d, "F_FULLFSYNC", (long)F_FULLFSYNC)) return -1;
538 : #endif
539 :
540 : /* For F_{GET|SET}FL */
541 : #ifdef FD_CLOEXEC
542 3 : if (ins(d, "FD_CLOEXEC", (long)FD_CLOEXEC)) return -1;
543 : #endif
544 :
545 : /* For F_NOTIFY */
546 : #ifdef DN_ACCESS
547 3 : if (ins(d, "DN_ACCESS", (long)DN_ACCESS)) return -1;
548 : #endif
549 : #ifdef DN_MODIFY
550 3 : if (ins(d, "DN_MODIFY", (long)DN_MODIFY)) return -1;
551 : #endif
552 : #ifdef DN_CREATE
553 3 : if (ins(d, "DN_CREATE", (long)DN_CREATE)) return -1;
554 : #endif
555 : #ifdef DN_DELETE
556 3 : if (ins(d, "DN_DELETE", (long)DN_DELETE)) return -1;
557 : #endif
558 : #ifdef DN_RENAME
559 3 : if (ins(d, "DN_RENAME", (long)DN_RENAME)) return -1;
560 : #endif
561 : #ifdef DN_ATTRIB
562 3 : if (ins(d, "DN_ATTRIB", (long)DN_ATTRIB)) return -1;
563 : #endif
564 : #ifdef DN_MULTISHOT
565 3 : if (ins(d, "DN_MULTISHOT", (long)DN_MULTISHOT)) return -1;
566 : #endif
567 :
568 : #ifdef HAVE_STROPTS_H
569 : /* Unix 98 guarantees that these are in stropts.h. */
570 3 : INS(I_PUSH);
571 3 : INS(I_POP);
572 3 : INS(I_LOOK);
573 3 : INS(I_FLUSH);
574 3 : INS(I_FLUSHBAND);
575 3 : INS(I_SETSIG);
576 3 : INS(I_GETSIG);
577 3 : INS(I_FIND);
578 3 : INS(I_PEEK);
579 3 : INS(I_SRDOPT);
580 3 : INS(I_GRDOPT);
581 3 : INS(I_NREAD);
582 3 : INS(I_FDINSERT);
583 3 : INS(I_STR);
584 3 : INS(I_SWROPT);
585 : #ifdef I_GWROPT
586 : /* despite the comment above, old-ish glibcs miss a couple... */
587 3 : INS(I_GWROPT);
588 : #endif
589 3 : INS(I_SENDFD);
590 3 : INS(I_RECVFD);
591 3 : INS(I_LIST);
592 3 : INS(I_ATMARK);
593 3 : INS(I_CKBAND);
594 3 : INS(I_GETBAND);
595 3 : INS(I_CANPUT);
596 3 : INS(I_SETCLTIME);
597 : #ifdef I_GETCLTIME
598 3 : INS(I_GETCLTIME);
599 : #endif
600 3 : INS(I_LINK);
601 3 : INS(I_UNLINK);
602 3 : INS(I_PLINK);
603 3 : INS(I_PUNLINK);
604 : #endif
605 :
606 3 : return 0;
607 : }
608 :
609 : PyMODINIT_FUNC
610 3 : initfcntl(void)
611 : {
612 : PyObject *m, *d;
613 :
614 : /* Create the module and add the functions and documentation */
615 3 : m = Py_InitModule3("fcntl", fcntl_methods, module_doc);
616 3 : if (m == NULL)
617 3 : return;
618 :
619 : /* Add some symbolic constants to the module */
620 3 : d = PyModule_GetDict(m);
621 3 : all_ins(d);
622 : }
|