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