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