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