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