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
conv_descriptor(PyObject * object,int * target)19 conv_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, op, [arg]) */
31
32 static PyObject *
fcntl_fcntl(PyObject * self,PyObject * args)33 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 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
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 *
fcntl_ioctl(PyObject * self,PyObject * args)97 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 int mutate_arg = 1;
120 char buf[IOCTL_BUFSZ+1]; /* argument plus NUL byte */
121
122 if (PyArg_ParseTuple(args, "O&Iw#|i:ioctl",
123 conv_descriptor, &fd, &code,
124 &str, &len, &mutate_arg)) {
125 char *arg;
126
127 if (mutate_arg) {
128 if (len <= IOCTL_BUFSZ) {
129 memcpy(buf, str, len);
130 buf[len] = '\0';
131 arg = buf;
132 }
133 else {
134 arg = str;
135 }
136 }
137 else {
138 if (len > IOCTL_BUFSZ) {
139 PyErr_SetString(PyExc_ValueError,
140 "ioctl string arg too long");
141 return NULL;
142 }
143 else {
144 memcpy(buf, str, len);
145 buf[len] = '\0';
146 arg = buf;
147 }
148 }
149 if (buf == arg) {
150 Py_BEGIN_ALLOW_THREADS /* think array.resize() */
151 ret = ioctl(fd, code, arg);
152 Py_END_ALLOW_THREADS
153 }
154 else {
155 ret = ioctl(fd, code, arg);
156 }
157 if (mutate_arg && (len <= IOCTL_BUFSZ)) {
158 memcpy(str, buf, len);
159 }
160 if (ret < 0) {
161 PyErr_SetFromErrno(PyExc_IOError);
162 return NULL;
163 }
164 if (mutate_arg) {
165 return PyInt_FromLong(ret);
166 }
167 else {
168 return PyString_FromStringAndSize(buf, len);
169 }
170 }
171
172 PyErr_Clear();
173 if (PyArg_ParseTuple(args, "O&Is#:ioctl",
174 conv_descriptor, &fd, &code, &str, &len)) {
175 if (len > IOCTL_BUFSZ) {
176 PyErr_SetString(PyExc_ValueError,
177 "ioctl string arg too long");
178 return NULL;
179 }
180 memcpy(buf, str, len);
181 buf[len] = '\0';
182 Py_BEGIN_ALLOW_THREADS
183 ret = ioctl(fd, code, buf);
184 Py_END_ALLOW_THREADS
185 if (ret < 0) {
186 PyErr_SetFromErrno(PyExc_IOError);
187 return NULL;
188 }
189 return PyString_FromStringAndSize(buf, len);
190 }
191
192 PyErr_Clear();
193 arg = 0;
194 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 return NULL;
199 }
200 Py_BEGIN_ALLOW_THREADS
201 #ifdef __VMS
202 ret = ioctl(fd, code, (void *)arg);
203 #else
204 ret = ioctl(fd, code, arg);
205 #endif
206 Py_END_ALLOW_THREADS
207 if (ret < 0) {
208 PyErr_SetFromErrno(PyExc_IOError);
209 return NULL;
210 }
211 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 *
fcntl_flock(PyObject * self,PyObject * args)251 fcntl_flock(PyObject *self, PyObject *args)
252 {
253 int fd;
254 int code;
255 int ret;
256
257 if (!PyArg_ParseTuple(args, "O&i:flock",
258 conv_descriptor, &fd, &code))
259 return NULL;
260
261 #ifdef HAVE_FLOCK
262 Py_BEGIN_ALLOW_THREADS
263 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 if (ret < 0) {
293 PyErr_SetFromErrno(PyExc_IOError);
294 return NULL;
295 }
296 Py_INCREF(Py_None);
297 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 *
fcntl_lockf(PyObject * self,PyObject * args)310 fcntl_lockf(PyObject *self, PyObject *args)
311 {
312 int fd, code, ret, whence = 0;
313 PyObject *lenobj = NULL, *startobj = NULL;
314
315 if (!PyArg_ParseTuple(args, "O&i|OOi:lockf",
316 conv_descriptor, &fd, &code,
317 &lenobj, &startobj, &whence))
318 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 if (code == LOCK_UN)
334 l.l_type = F_UNLCK;
335 else if (code & LOCK_SH)
336 l.l_type = F_RDLCK;
337 else if (code & LOCK_EX)
338 l.l_type = F_WRLCK;
339 else {
340 PyErr_SetString(PyExc_ValueError,
341 "unrecognized lockf argument");
342 return NULL;
343 }
344 l.l_start = l.l_len = 0;
345 if (startobj != NULL) {
346 #if !defined(HAVE_LARGEFILE_SUPPORT)
347 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 if (PyErr_Occurred())
354 return NULL;
355 }
356 if (lenobj != NULL) {
357 #if !defined(HAVE_LARGEFILE_SUPPORT)
358 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 if (PyErr_Occurred())
365 return NULL;
366 }
367 l.l_whence = whence;
368 Py_BEGIN_ALLOW_THREADS
369 ret = fcntl(fd, (code & LOCK_NB) ? F_SETLK : F_SETLKW, &l);
370 Py_END_ALLOW_THREADS
371 }
372 if (ret < 0) {
373 PyErr_SetFromErrno(PyExc_IOError);
374 return NULL;
375 }
376 Py_INCREF(Py_None);
377 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
ins(PyObject * d,char * symbol,long value)426 ins(PyObject* d, char* symbol, long value)
427 {
428 PyObject* v = PyInt_FromLong(value);
429 if (!v || PyDict_SetItemString(d, symbol, v) < 0)
430 return -1;
431
432 Py_DECREF(v);
433 return 0;
434 }
435
436 #define INS(x) if (ins(d, #x, (long)x)) return -1
437
438 static int
all_ins(PyObject * d)439 all_ins(PyObject* d)
440 {
441 if (ins(d, "LOCK_SH", (long)LOCK_SH)) return -1;
442 if (ins(d, "LOCK_EX", (long)LOCK_EX)) return -1;
443 if (ins(d, "LOCK_NB", (long)LOCK_NB)) return -1;
444 if (ins(d, "LOCK_UN", (long)LOCK_UN)) return -1;
445 /* GNU extensions, as of glibc 2.2.4 */
446 #ifdef LOCK_MAND
447 if (ins(d, "LOCK_MAND", (long)LOCK_MAND)) return -1;
448 #endif
449 #ifdef LOCK_READ
450 if (ins(d, "LOCK_READ", (long)LOCK_READ)) return -1;
451 #endif
452 #ifdef LOCK_WRITE
453 if (ins(d, "LOCK_WRITE", (long)LOCK_WRITE)) return -1;
454 #endif
455 #ifdef LOCK_RW
456 if (ins(d, "LOCK_RW", (long)LOCK_RW)) return -1;
457 #endif
458
459 #ifdef F_DUPFD
460 if (ins(d, "F_DUPFD", (long)F_DUPFD)) return -1;
461 #endif
462 #ifdef F_GETFD
463 if (ins(d, "F_GETFD", (long)F_GETFD)) return -1;
464 #endif
465 #ifdef F_SETFD
466 if (ins(d, "F_SETFD", (long)F_SETFD)) return -1;
467 #endif
468 #ifdef F_GETFL
469 if (ins(d, "F_GETFL", (long)F_GETFL)) return -1;
470 #endif
471 #ifdef F_SETFL
472 if (ins(d, "F_SETFL", (long)F_SETFL)) return -1;
473 #endif
474 #ifdef F_GETLK
475 if (ins(d, "F_GETLK", (long)F_GETLK)) return -1;
476 #endif
477 #ifdef F_SETLK
478 if (ins(d, "F_SETLK", (long)F_SETLK)) return -1;
479 #endif
480 #ifdef F_SETLKW
481 if (ins(d, "F_SETLKW", (long)F_SETLKW)) return -1;
482 #endif
483 #ifdef F_GETOWN
484 if (ins(d, "F_GETOWN", (long)F_GETOWN)) return -1;
485 #endif
486 #ifdef F_SETOWN
487 if (ins(d, "F_SETOWN", (long)F_SETOWN)) return -1;
488 #endif
489 #ifdef F_GETSIG
490 if (ins(d, "F_GETSIG", (long)F_GETSIG)) return -1;
491 #endif
492 #ifdef F_SETSIG
493 if (ins(d, "F_SETSIG", (long)F_SETSIG)) return -1;
494 #endif
495 #ifdef F_RDLCK
496 if (ins(d, "F_RDLCK", (long)F_RDLCK)) return -1;
497 #endif
498 #ifdef F_WRLCK
499 if (ins(d, "F_WRLCK", (long)F_WRLCK)) return -1;
500 #endif
501 #ifdef F_UNLCK
502 if (ins(d, "F_UNLCK", (long)F_UNLCK)) return -1;
503 #endif
504 /* LFS constants */
505 #ifdef F_GETLK64
506 if (ins(d, "F_GETLK64", (long)F_GETLK64)) return -1;
507 #endif
508 #ifdef F_SETLK64
509 if (ins(d, "F_SETLK64", (long)F_SETLK64)) return -1;
510 #endif
511 #ifdef F_SETLKW64
512 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 if (ins(d, "FASYNC", (long)FASYNC)) return -1;
517 #endif
518 #ifdef F_SETLEASE
519 if (ins(d, "F_SETLEASE", (long)F_SETLEASE)) return -1;
520 #endif
521 #ifdef F_GETLEASE
522 if (ins(d, "F_GETLEASE", (long)F_GETLEASE)) return -1;
523 #endif
524 #ifdef F_NOTIFY
525 if (ins(d, "F_NOTIFY", (long)F_NOTIFY)) return -1;
526 #endif
527 /* Old BSD flock(). */
528 #ifdef F_EXLCK
529 if (ins(d, "F_EXLCK", (long)F_EXLCK)) return -1;
530 #endif
531 #ifdef F_SHLCK
532 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 if (ins(d, "FD_CLOEXEC", (long)FD_CLOEXEC)) return -1;
543 #endif
544
545 /* For F_NOTIFY */
546 #ifdef DN_ACCESS
547 if (ins(d, "DN_ACCESS", (long)DN_ACCESS)) return -1;
548 #endif
549 #ifdef DN_MODIFY
550 if (ins(d, "DN_MODIFY", (long)DN_MODIFY)) return -1;
551 #endif
552 #ifdef DN_CREATE
553 if (ins(d, "DN_CREATE", (long)DN_CREATE)) return -1;
554 #endif
555 #ifdef DN_DELETE
556 if (ins(d, "DN_DELETE", (long)DN_DELETE)) return -1;
557 #endif
558 #ifdef DN_RENAME
559 if (ins(d, "DN_RENAME", (long)DN_RENAME)) return -1;
560 #endif
561 #ifdef DN_ATTRIB
562 if (ins(d, "DN_ATTRIB", (long)DN_ATTRIB)) return -1;
563 #endif
564 #ifdef DN_MULTISHOT
565 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 INS(I_PUSH);
571 INS(I_POP);
572 INS(I_LOOK);
573 INS(I_FLUSH);
574 INS(I_FLUSHBAND);
575 INS(I_SETSIG);
576 INS(I_GETSIG);
577 INS(I_FIND);
578 INS(I_PEEK);
579 INS(I_SRDOPT);
580 INS(I_GRDOPT);
581 INS(I_NREAD);
582 INS(I_FDINSERT);
583 INS(I_STR);
584 INS(I_SWROPT);
585 #ifdef I_GWROPT
586 /* despite the comment above, old-ish glibcs miss a couple... */
587 INS(I_GWROPT);
588 #endif
589 INS(I_SENDFD);
590 INS(I_RECVFD);
591 INS(I_LIST);
592 INS(I_ATMARK);
593 INS(I_CKBAND);
594 INS(I_GETBAND);
595 INS(I_CANPUT);
596 INS(I_SETCLTIME);
597 #ifdef I_GETCLTIME
598 INS(I_GETCLTIME);
599 #endif
600 INS(I_LINK);
601 INS(I_UNLINK);
602 INS(I_PLINK);
603 INS(I_PUNLINK);
604 #endif
605
606 return 0;
607 }
608
609 PyMODINIT_FUNC
initfcntl(void)610 initfcntl(void)
611 {
612 PyObject *m, *d;
613
614 /* Create the module and add the functions and documentation */
615 m = Py_InitModule3("fcntl", fcntl_methods, module_doc);
616 if (m == NULL)
617 return;
618
619 /* Add some symbolic constants to the module */
620 d = PyModule_GetDict(m);
621 all_ins(d);
622 }
623