source: vendor/python/2.5/Modules/fcntlmodule.c

Last change on this file was 3225, checked in by bird, 18 years ago

Python 2.5

File size: 15.3 KB
Line 
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
18static int
19conv_descriptor(PyObject *object, int *target)
20{
21 int fd = PyObject_AsFileDescriptor(object);
22
23 if (fd < 0)
24 return 0;
25 *target = fd;
26 return 1;
27}
28
29
30/* fcntl(fd, opt, [arg]) */
31
32static PyObject *
33fcntl_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 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;
49 }
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;
57 }
58 return PyString_FromStringAndSize(buf, len);
59 }
60
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;
68 }
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;
75 }
76 return PyInt_FromLong((long)ret);
77}
78
79PyDoc_STRVAR(fcntl_doc,
80"fcntl(fd, opt, [arg])\n\
81\n\
82Perform the requested operation on file descriptor fd. The operation\n\
83is defined by op and is operating system dependent. These constants are\n\
84available from the fcntl module. The argument arg is optional, and\n\
85defaults to 0; it may be an int or a string. If arg is given as a string,\n\
86the return value of fcntl is a string of that length, containing the\n\
87resulting value put in the arg buffer by the operating system.The length\n\
88of the arg string is not allowed to exceed 1024 bytes. If the arg given\n\
89is an integer or if none is specified, the result value is an integer\n\
90corresponding to the return value of the fcntl call in the C code.");
91
92
93/* ioctl(fd, opt, [arg]) */
94
95static PyObject *
96fcntl_ioctl(PyObject *self, PyObject *args)
97{
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 */
111
112 if (PyArg_ParseTuple(args, "O&Iw#|i:ioctl",
113 conv_descriptor, &fd, &code,
114 &str, &len, &mutate_arg)) {
115 char *arg;
116
117 if (mutate_arg) {
118 if (len <= IOCTL_BUFSZ) {
119 memcpy(buf, str, len);
120 buf[len] = '\0';
121 arg = buf;
122 }
123 else {
124 arg = str;
125 }
126 }
127 else {
128 if (len > IOCTL_BUFSZ) {
129 PyErr_SetString(PyExc_ValueError,
130 "ioctl string arg too long");
131 return NULL;
132 }
133 else {
134 memcpy(buf, str, len);
135 buf[len] = '\0';
136 arg = buf;
137 }
138 }
139 if (buf == arg) {
140 Py_BEGIN_ALLOW_THREADS /* think array.resize() */
141 ret = ioctl(fd, code, arg);
142 Py_END_ALLOW_THREADS
143 }
144 else {
145 ret = ioctl(fd, code, arg);
146 }
147 if (mutate_arg && (len < IOCTL_BUFSZ)) {
148 memcpy(str, buf, len);
149 }
150 if (ret < 0) {
151 PyErr_SetFromErrno(PyExc_IOError);
152 return NULL;
153 }
154 if (mutate_arg) {
155 return PyInt_FromLong(ret);
156 }
157 else {
158 return PyString_FromStringAndSize(buf, len);
159 }
160 }
161
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;
169 }
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;
178 }
179 return PyString_FromStringAndSize(buf, len);
180 }
181
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;
189 }
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;
200 }
201 return PyInt_FromLong((long)ret);
202#undef IOCTL_BUFSZ
203}
204
205PyDoc_STRVAR(ioctl_doc,
206"ioctl(fd, opt[, arg[, mutate_flag]])\n\
207\n\
208Perform the requested operation on file descriptor fd. The operation is\n\
209defined by opt and is operating system dependent. Typically these codes are\n\
210retrieved from the fcntl or termios library modules.\n\
211\n\
212The argument arg is optional, and defaults to 0; it may be an int or a\n\
213buffer containing character data (most likely a string or an array). \n\
214\n\
215If the argument is a mutable buffer (such as an array) and if the\n\
216mutate_flag argument (which is only allowed in this case) is true then the\n\
217buffer is (in effect) passed to the operating system and changes made by\n\
218the OS will be reflected in the contents of the buffer after the call has\n\
219returned. The return value is the integer returned by the ioctl system\n\
220call.\n\
221\n\
222If the argument is a mutable buffer and the mutable_flag argument is not\n\
223passed or is false, the behavior is as if a string had been passed. This\n\
224behavior will change in future releases of Python.\n\
225\n\
226If the argument is an immutable buffer (most likely a string) then a copy\n\
227of the buffer is passed to the operating system and the return value is a\n\
228string of the same length containing whatever the operating system put in\n\
229the buffer. The length of the arg buffer in this case is not allowed to\n\
230exceed 1024 bytes.\n\
231\n\
232If the arg given is an integer or if none is specified, the result value is\n\
233an integer corresponding to the return value of the ioctl call in the C\n\
234code.");
235
236
237/* flock(fd, operation) */
238
239static PyObject *
240fcntl_flock(PyObject *self, PyObject *args)
241{
242 int fd;
243 int code;
244 int ret;
245
246 if (!PyArg_ParseTuple(args, "O&i:flock",
247 conv_descriptor, &fd, &code))
248 return NULL;
249
250#ifdef HAVE_FLOCK
251 Py_BEGIN_ALLOW_THREADS
252 ret = flock(fd, code);
253 Py_END_ALLOW_THREADS
254#else
255
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
262 {
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;
274 }
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
279 }
280#endif /* HAVE_FLOCK */
281 if (ret < 0) {
282 PyErr_SetFromErrno(PyExc_IOError);
283 return NULL;
284 }
285 Py_INCREF(Py_None);
286 return Py_None;
287}
288
289PyDoc_STRVAR(flock_doc,
290"flock(fd, operation)\n\
291\n\
292Perform the lock operation op on file descriptor fd. See the Unix \n\
293manual page for flock(3) for details. (On some systems, this function is\n\
294emulated using fcntl().)");
295
296
297/* lockf(fd, operation) */
298static PyObject *
299fcntl_lockf(PyObject *self, PyObject *args)
300{
301 int fd, code, ret, whence = 0;
302 PyObject *lenobj = NULL, *startobj = NULL;
303
304 if (!PyArg_ParseTuple(args, "O&i|OOi:lockf",
305 conv_descriptor, &fd, &code,
306 &lenobj, &startobj, &whence))
307 return NULL;
308
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 */
320 {
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;
332 }
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;
344 }
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;
355 }
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
360 }
361 if (ret < 0) {
362 PyErr_SetFromErrno(PyExc_IOError);
363 return NULL;
364 }
365 Py_INCREF(Py_None);
366 return Py_None;
367#endif /* defined(PYOS_OS2) && defined(PYCC_GCC) */
368}
369
370PyDoc_STRVAR(lockf_doc,
371"lockf (fd, operation, length=0, start=0, whence=0)\n\
372\n\
373This is essentially a wrapper around the fcntl() locking calls. fd is the\n\
374file descriptor of the file to lock or unlock, and operation is one of the\n\
375following values:\n\
376\n\
377 LOCK_UN - unlock\n\
378 LOCK_SH - acquire a shared lock\n\
379 LOCK_EX - acquire an exclusive lock\n\
380\n\
381When operation is LOCK_SH or LOCK_EX, it can also be bit-wise OR'd with\n\
382LOCK_NB to avoid blocking on lock acquisition. If LOCK_NB is used and the\n\
383lock cannot be acquired, an IOError will be raised and the exception will\n\
384have an errno attribute set to EACCES or EAGAIN (depending on the operating\n\
385system -- for portability, check for either value).\n\
386\n\
387length is the number of bytes to lock, with the default meaning to lock to\n\
388EOF. start is the byte offset, relative to whence, to that the lock\n\
389starts. whence is as with fileobj.seek(), specifically:\n\
390\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)");
394
395/* List of functions */
396
397static 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 */
403};
404
405
406PyDoc_STRVAR(module_doc,
407"This module performs file control and I/O control on file \n\
408descriptors. It is an interface to the fcntl() and ioctl() Unix\n\
409routines. File descriptors can be obtained with the fileno() method of\n\
410a file or socket object.");
411
412/* Module initialisation */
413
414static int
415ins(PyObject* d, char* symbol, long value)
416{
417 PyObject* v = PyInt_FromLong(value);
418 if (!v || PyDict_SetItemString(d, symbol, v) < 0)
419 return -1;
420
421 Py_DECREF(v);
422 return 0;
423}
424
425#define INS(x) if (ins(d, #x, (long)x)) return -1
426
427static int
428all_ins(PyObject* d)
429{
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
447
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
520
521/* For F_{GET|SET}FL */
522#ifdef FD_CLOEXEC
523 if (ins(d, "FD_CLOEXEC", (long)FD_CLOEXEC)) return -1;
524#endif
525
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
548
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
586
587 return 0;
588}
589
590PyMODINIT_FUNC
591initfcntl(void)
592{
593 PyObject *m, *d;
594
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;
599
600 /* Add some symbolic constants to the module */
601 d = PyModule_GetDict(m);
602 all_ins(d);
603}
Note: See TracBrowser for help on using the repository browser.