+++ /dev/null
-\r
-/* fcntl module */\r
-\r
-#define PY_SSIZE_T_CLEAN\r
-\r
-#include "Python.h"\r
-\r
-#ifdef HAVE_SYS_FILE_H\r
-#include <sys/file.h>\r
-#endif\r
-\r
-#include <sys/ioctl.h>\r
-#include <fcntl.h>\r
-#ifdef HAVE_STROPTS_H\r
-#include <stropts.h>\r
-#endif\r
-\r
-static int\r
-conv_descriptor(PyObject *object, int *target)\r
-{\r
- int fd = PyObject_AsFileDescriptor(object);\r
-\r
- if (fd < 0)\r
- return 0;\r
- *target = fd;\r
- return 1;\r
-}\r
-\r
-\r
-/* fcntl(fd, opt, [arg]) */\r
-\r
-static PyObject *\r
-fcntl_fcntl(PyObject *self, PyObject *args)\r
-{\r
- int fd;\r
- int code;\r
- long arg;\r
- int ret;\r
- char *str;\r
- Py_ssize_t len;\r
- char buf[1024];\r
-\r
- if (PyArg_ParseTuple(args, "O&is#:fcntl",\r
- conv_descriptor, &fd, &code, &str, &len)) {\r
- if (len > sizeof buf) {\r
- PyErr_SetString(PyExc_ValueError,\r
- "fcntl string arg too long");\r
- return NULL;\r
- }\r
- memcpy(buf, str, len);\r
- Py_BEGIN_ALLOW_THREADS\r
- ret = fcntl(fd, code, buf);\r
- Py_END_ALLOW_THREADS\r
- if (ret < 0) {\r
- PyErr_SetFromErrno(PyExc_IOError);\r
- return NULL;\r
- }\r
- return PyString_FromStringAndSize(buf, len);\r
- }\r
-\r
- PyErr_Clear();\r
- arg = 0;\r
- if (!PyArg_ParseTuple(args,\r
- "O&i|l;fcntl requires a file or file descriptor,"\r
- " an integer and optionally a third integer or a string",\r
- conv_descriptor, &fd, &code, &arg)) {\r
- return NULL;\r
- }\r
- Py_BEGIN_ALLOW_THREADS\r
- ret = fcntl(fd, code, arg);\r
- Py_END_ALLOW_THREADS\r
- if (ret < 0) {\r
- PyErr_SetFromErrno(PyExc_IOError);\r
- return NULL;\r
- }\r
- return PyInt_FromLong((long)ret);\r
-}\r
-\r
-PyDoc_STRVAR(fcntl_doc,\r
-"fcntl(fd, opt, [arg])\n\\r
-\n\\r
-Perform the requested operation on file descriptor fd. The operation\n\\r
-is defined by op and is operating system dependent. These constants are\n\\r
-available from the fcntl module. The argument arg is optional, and\n\\r
-defaults to 0; it may be an int or a string. If arg is given as a string,\n\\r
-the return value of fcntl is a string of that length, containing the\n\\r
-resulting value put in the arg buffer by the operating system. The length\n\\r
-of the arg string is not allowed to exceed 1024 bytes. If the arg given\n\\r
-is an integer or if none is specified, the result value is an integer\n\\r
-corresponding to the return value of the fcntl call in the C code.");\r
-\r
-\r
-/* ioctl(fd, opt, [arg]) */\r
-\r
-static PyObject *\r
-fcntl_ioctl(PyObject *self, PyObject *args)\r
-{\r
-#define IOCTL_BUFSZ 1024\r
- int fd;\r
- /* In PyArg_ParseTuple below, we use the unsigned non-checked 'I'\r
- format for the 'code' parameter because Python turns 0x8000000\r
- into either a large positive number (PyLong or PyInt on 64-bit\r
- platforms) or a negative number on others (32-bit PyInt)\r
- whereas the system expects it to be a 32bit bit field value\r
- regardless of it being passed as an int or unsigned long on\r
- various platforms. See the termios.TIOCSWINSZ constant across\r
- platforms for an example of thise.\r
-\r
- If any of the 64bit platforms ever decide to use more than 32bits\r
- in their unsigned long ioctl codes this will break and need\r
- special casing based on the platform being built on.\r
- */\r
- unsigned int code;\r
- int arg;\r
- int ret;\r
- char *str;\r
- Py_ssize_t len;\r
- int mutate_arg = 1;\r
- char buf[IOCTL_BUFSZ+1]; /* argument plus NUL byte */\r
-\r
- if (PyArg_ParseTuple(args, "O&Iw#|i:ioctl",\r
- conv_descriptor, &fd, &code,\r
- &str, &len, &mutate_arg)) {\r
- char *arg;\r
-\r
- if (mutate_arg) {\r
- if (len <= IOCTL_BUFSZ) {\r
- memcpy(buf, str, len);\r
- buf[len] = '\0';\r
- arg = buf;\r
- }\r
- else {\r
- arg = str;\r
- }\r
- }\r
- else {\r
- if (len > IOCTL_BUFSZ) {\r
- PyErr_SetString(PyExc_ValueError,\r
- "ioctl string arg too long");\r
- return NULL;\r
- }\r
- else {\r
- memcpy(buf, str, len);\r
- buf[len] = '\0';\r
- arg = buf;\r
- }\r
- }\r
- if (buf == arg) {\r
- Py_BEGIN_ALLOW_THREADS /* think array.resize() */\r
- ret = ioctl(fd, code, arg);\r
- Py_END_ALLOW_THREADS\r
- }\r
- else {\r
- ret = ioctl(fd, code, arg);\r
- }\r
- if (mutate_arg && (len <= IOCTL_BUFSZ)) {\r
- memcpy(str, buf, len);\r
- }\r
- if (ret < 0) {\r
- PyErr_SetFromErrno(PyExc_IOError);\r
- return NULL;\r
- }\r
- if (mutate_arg) {\r
- return PyInt_FromLong(ret);\r
- }\r
- else {\r
- return PyString_FromStringAndSize(buf, len);\r
- }\r
- }\r
-\r
- PyErr_Clear();\r
- if (PyArg_ParseTuple(args, "O&Is#:ioctl",\r
- conv_descriptor, &fd, &code, &str, &len)) {\r
- if (len > IOCTL_BUFSZ) {\r
- PyErr_SetString(PyExc_ValueError,\r
- "ioctl string arg too long");\r
- return NULL;\r
- }\r
- memcpy(buf, str, len);\r
- buf[len] = '\0';\r
- Py_BEGIN_ALLOW_THREADS\r
- ret = ioctl(fd, code, buf);\r
- Py_END_ALLOW_THREADS\r
- if (ret < 0) {\r
- PyErr_SetFromErrno(PyExc_IOError);\r
- return NULL;\r
- }\r
- return PyString_FromStringAndSize(buf, len);\r
- }\r
-\r
- PyErr_Clear();\r
- arg = 0;\r
- if (!PyArg_ParseTuple(args,\r
- "O&I|i;ioctl requires a file or file descriptor,"\r
- " an integer and optionally an integer or buffer argument",\r
- conv_descriptor, &fd, &code, &arg)) {\r
- return NULL;\r
- }\r
- Py_BEGIN_ALLOW_THREADS\r
-#ifdef __VMS\r
- ret = ioctl(fd, code, (void *)arg);\r
-#else\r
- ret = ioctl(fd, code, arg);\r
-#endif\r
- Py_END_ALLOW_THREADS\r
- if (ret < 0) {\r
- PyErr_SetFromErrno(PyExc_IOError);\r
- return NULL;\r
- }\r
- return PyInt_FromLong((long)ret);\r
-#undef IOCTL_BUFSZ\r
-}\r
-\r
-PyDoc_STRVAR(ioctl_doc,\r
-"ioctl(fd, opt[, arg[, mutate_flag]])\n\\r
-\n\\r
-Perform the requested operation on file descriptor fd. The operation is\n\\r
-defined by opt and is operating system dependent. Typically these codes are\n\\r
-retrieved from the fcntl or termios library modules.\n\\r
-\n\\r
-The argument arg is optional, and defaults to 0; it may be an int or a\n\\r
-buffer containing character data (most likely a string or an array). \n\\r
-\n\\r
-If the argument is a mutable buffer (such as an array) and if the\n\\r
-mutate_flag argument (which is only allowed in this case) is true then the\n\\r
-buffer is (in effect) passed to the operating system and changes made by\n\\r
-the OS will be reflected in the contents of the buffer after the call has\n\\r
-returned. The return value is the integer returned by the ioctl system\n\\r
-call.\n\\r
-\n\\r
-If the argument is a mutable buffer and the mutable_flag argument is not\n\\r
-passed or is false, the behavior is as if a string had been passed. This\n\\r
-behavior will change in future releases of Python.\n\\r
-\n\\r
-If the argument is an immutable buffer (most likely a string) then a copy\n\\r
-of the buffer is passed to the operating system and the return value is a\n\\r
-string of the same length containing whatever the operating system put in\n\\r
-the buffer. The length of the arg buffer in this case is not allowed to\n\\r
-exceed 1024 bytes.\n\\r
-\n\\r
-If the arg given is an integer or if none is specified, the result value is\n\\r
-an integer corresponding to the return value of the ioctl call in the C\n\\r
-code.");\r
-\r
-\r
-/* flock(fd, operation) */\r
-\r
-static PyObject *\r
-fcntl_flock(PyObject *self, PyObject *args)\r
-{\r
- int fd;\r
- int code;\r
- int ret;\r
-\r
- if (!PyArg_ParseTuple(args, "O&i:flock",\r
- conv_descriptor, &fd, &code))\r
- return NULL;\r
-\r
-#ifdef HAVE_FLOCK\r
- Py_BEGIN_ALLOW_THREADS\r
- ret = flock(fd, code);\r
- Py_END_ALLOW_THREADS\r
-#else\r
-\r
-#ifndef LOCK_SH\r
-#define LOCK_SH 1 /* shared lock */\r
-#define LOCK_EX 2 /* exclusive lock */\r
-#define LOCK_NB 4 /* don't block when locking */\r
-#define LOCK_UN 8 /* unlock */\r
-#endif\r
- {\r
- struct flock l;\r
- if (code == LOCK_UN)\r
- l.l_type = F_UNLCK;\r
- else if (code & LOCK_SH)\r
- l.l_type = F_RDLCK;\r
- else if (code & LOCK_EX)\r
- l.l_type = F_WRLCK;\r
- else {\r
- PyErr_SetString(PyExc_ValueError,\r
- "unrecognized flock argument");\r
- return NULL;\r
- }\r
- l.l_whence = l.l_start = l.l_len = 0;\r
- Py_BEGIN_ALLOW_THREADS\r
- ret = fcntl(fd, (code & LOCK_NB) ? F_SETLK : F_SETLKW, &l);\r
- Py_END_ALLOW_THREADS\r
- }\r
-#endif /* HAVE_FLOCK */\r
- if (ret < 0) {\r
- PyErr_SetFromErrno(PyExc_IOError);\r
- return NULL;\r
- }\r
- Py_INCREF(Py_None);\r
- return Py_None;\r
-}\r
-\r
-PyDoc_STRVAR(flock_doc,\r
-"flock(fd, operation)\n\\r
-\n\\r
-Perform the lock operation op on file descriptor fd. See the Unix \n\\r
-manual page for flock(3) for details. (On some systems, this function is\n\\r
-emulated using fcntl().)");\r
-\r
-\r
-/* lockf(fd, operation) */\r
-static PyObject *\r
-fcntl_lockf(PyObject *self, PyObject *args)\r
-{\r
- int fd, code, ret, whence = 0;\r
- PyObject *lenobj = NULL, *startobj = NULL;\r
-\r
- if (!PyArg_ParseTuple(args, "O&i|OOi:lockf",\r
- conv_descriptor, &fd, &code,\r
- &lenobj, &startobj, &whence))\r
- return NULL;\r
-\r
-#if defined(PYOS_OS2) && defined(PYCC_GCC)\r
- PyErr_SetString(PyExc_NotImplementedError,\r
- "lockf not supported on OS/2 (EMX)");\r
- return NULL;\r
-#else\r
-#ifndef LOCK_SH\r
-#define LOCK_SH 1 /* shared lock */\r
-#define LOCK_EX 2 /* exclusive lock */\r
-#define LOCK_NB 4 /* don't block when locking */\r
-#define LOCK_UN 8 /* unlock */\r
-#endif /* LOCK_SH */\r
- {\r
- struct flock l;\r
- if (code == LOCK_UN)\r
- l.l_type = F_UNLCK;\r
- else if (code & LOCK_SH)\r
- l.l_type = F_RDLCK;\r
- else if (code & LOCK_EX)\r
- l.l_type = F_WRLCK;\r
- else {\r
- PyErr_SetString(PyExc_ValueError,\r
- "unrecognized lockf argument");\r
- return NULL;\r
- }\r
- l.l_start = l.l_len = 0;\r
- if (startobj != NULL) {\r
-#if !defined(HAVE_LARGEFILE_SUPPORT)\r
- l.l_start = PyInt_AsLong(startobj);\r
-#else\r
- l.l_start = PyLong_Check(startobj) ?\r
- PyLong_AsLongLong(startobj) :\r
- PyInt_AsLong(startobj);\r
-#endif\r
- if (PyErr_Occurred())\r
- return NULL;\r
- }\r
- if (lenobj != NULL) {\r
-#if !defined(HAVE_LARGEFILE_SUPPORT)\r
- l.l_len = PyInt_AsLong(lenobj);\r
-#else\r
- l.l_len = PyLong_Check(lenobj) ?\r
- PyLong_AsLongLong(lenobj) :\r
- PyInt_AsLong(lenobj);\r
-#endif\r
- if (PyErr_Occurred())\r
- return NULL;\r
- }\r
- l.l_whence = whence;\r
- Py_BEGIN_ALLOW_THREADS\r
- ret = fcntl(fd, (code & LOCK_NB) ? F_SETLK : F_SETLKW, &l);\r
- Py_END_ALLOW_THREADS\r
- }\r
- if (ret < 0) {\r
- PyErr_SetFromErrno(PyExc_IOError);\r
- return NULL;\r
- }\r
- Py_INCREF(Py_None);\r
- return Py_None;\r
-#endif /* defined(PYOS_OS2) && defined(PYCC_GCC) */\r
-}\r
-\r
-PyDoc_STRVAR(lockf_doc,\r
-"lockf (fd, operation, length=0, start=0, whence=0)\n\\r
-\n\\r
-This is essentially a wrapper around the fcntl() locking calls. fd is the\n\\r
-file descriptor of the file to lock or unlock, and operation is one of the\n\\r
-following values:\n\\r
-\n\\r
- LOCK_UN - unlock\n\\r
- LOCK_SH - acquire a shared lock\n\\r
- LOCK_EX - acquire an exclusive lock\n\\r
-\n\\r
-When operation is LOCK_SH or LOCK_EX, it can also be bitwise ORed with\n\\r
-LOCK_NB to avoid blocking on lock acquisition. If LOCK_NB is used and the\n\\r
-lock cannot be acquired, an IOError will be raised and the exception will\n\\r
-have an errno attribute set to EACCES or EAGAIN (depending on the operating\n\\r
-system -- for portability, check for either value).\n\\r
-\n\\r
-length is the number of bytes to lock, with the default meaning to lock to\n\\r
-EOF. start is the byte offset, relative to whence, to that the lock\n\\r
-starts. whence is as with fileobj.seek(), specifically:\n\\r
-\n\\r
- 0 - relative to the start of the file (SEEK_SET)\n\\r
- 1 - relative to the current buffer position (SEEK_CUR)\n\\r
- 2 - relative to the end of the file (SEEK_END)");\r
-\r
-/* List of functions */\r
-\r
-static PyMethodDef fcntl_methods[] = {\r
- {"fcntl", fcntl_fcntl, METH_VARARGS, fcntl_doc},\r
- {"ioctl", fcntl_ioctl, METH_VARARGS, ioctl_doc},\r
- {"flock", fcntl_flock, METH_VARARGS, flock_doc},\r
- {"lockf", fcntl_lockf, METH_VARARGS, lockf_doc},\r
- {NULL, NULL} /* sentinel */\r
-};\r
-\r
-\r
-PyDoc_STRVAR(module_doc,\r
-"This module performs file control and I/O control on file \n\\r
-descriptors. It is an interface to the fcntl() and ioctl() Unix\n\\r
-routines. File descriptors can be obtained with the fileno() method of\n\\r
-a file or socket object.");\r
-\r
-/* Module initialisation */\r
-\r
-static int\r
-ins(PyObject* d, char* symbol, long value)\r
-{\r
- PyObject* v = PyInt_FromLong(value);\r
- if (!v || PyDict_SetItemString(d, symbol, v) < 0)\r
- return -1;\r
-\r
- Py_DECREF(v);\r
- return 0;\r
-}\r
-\r
-#define INS(x) if (ins(d, #x, (long)x)) return -1\r
-\r
-static int\r
-all_ins(PyObject* d)\r
-{\r
- if (ins(d, "LOCK_SH", (long)LOCK_SH)) return -1;\r
- if (ins(d, "LOCK_EX", (long)LOCK_EX)) return -1;\r
- if (ins(d, "LOCK_NB", (long)LOCK_NB)) return -1;\r
- if (ins(d, "LOCK_UN", (long)LOCK_UN)) return -1;\r
-/* GNU extensions, as of glibc 2.2.4 */\r
-#ifdef LOCK_MAND\r
- if (ins(d, "LOCK_MAND", (long)LOCK_MAND)) return -1;\r
-#endif\r
-#ifdef LOCK_READ\r
- if (ins(d, "LOCK_READ", (long)LOCK_READ)) return -1;\r
-#endif\r
-#ifdef LOCK_WRITE\r
- if (ins(d, "LOCK_WRITE", (long)LOCK_WRITE)) return -1;\r
-#endif\r
-#ifdef LOCK_RW\r
- if (ins(d, "LOCK_RW", (long)LOCK_RW)) return -1;\r
-#endif\r
-\r
-#ifdef F_DUPFD\r
- if (ins(d, "F_DUPFD", (long)F_DUPFD)) return -1;\r
-#endif\r
-#ifdef F_GETFD\r
- if (ins(d, "F_GETFD", (long)F_GETFD)) return -1;\r
-#endif\r
-#ifdef F_SETFD\r
- if (ins(d, "F_SETFD", (long)F_SETFD)) return -1;\r
-#endif\r
-#ifdef F_GETFL\r
- if (ins(d, "F_GETFL", (long)F_GETFL)) return -1;\r
-#endif\r
-#ifdef F_SETFL\r
- if (ins(d, "F_SETFL", (long)F_SETFL)) return -1;\r
-#endif\r
-#ifdef F_GETLK\r
- if (ins(d, "F_GETLK", (long)F_GETLK)) return -1;\r
-#endif\r
-#ifdef F_SETLK\r
- if (ins(d, "F_SETLK", (long)F_SETLK)) return -1;\r
-#endif\r
-#ifdef F_SETLKW\r
- if (ins(d, "F_SETLKW", (long)F_SETLKW)) return -1;\r
-#endif\r
-#ifdef F_GETOWN\r
- if (ins(d, "F_GETOWN", (long)F_GETOWN)) return -1;\r
-#endif\r
-#ifdef F_SETOWN\r
- if (ins(d, "F_SETOWN", (long)F_SETOWN)) return -1;\r
-#endif\r
-#ifdef F_GETSIG\r
- if (ins(d, "F_GETSIG", (long)F_GETSIG)) return -1;\r
-#endif\r
-#ifdef F_SETSIG\r
- if (ins(d, "F_SETSIG", (long)F_SETSIG)) return -1;\r
-#endif\r
-#ifdef F_RDLCK\r
- if (ins(d, "F_RDLCK", (long)F_RDLCK)) return -1;\r
-#endif\r
-#ifdef F_WRLCK\r
- if (ins(d, "F_WRLCK", (long)F_WRLCK)) return -1;\r
-#endif\r
-#ifdef F_UNLCK\r
- if (ins(d, "F_UNLCK", (long)F_UNLCK)) return -1;\r
-#endif\r
-/* LFS constants */\r
-#ifdef F_GETLK64\r
- if (ins(d, "F_GETLK64", (long)F_GETLK64)) return -1;\r
-#endif\r
-#ifdef F_SETLK64\r
- if (ins(d, "F_SETLK64", (long)F_SETLK64)) return -1;\r
-#endif\r
-#ifdef F_SETLKW64\r
- if (ins(d, "F_SETLKW64", (long)F_SETLKW64)) return -1;\r
-#endif\r
-/* GNU extensions, as of glibc 2.2.4. */\r
-#ifdef FASYNC\r
- if (ins(d, "FASYNC", (long)FASYNC)) return -1;\r
-#endif\r
-#ifdef F_SETLEASE\r
- if (ins(d, "F_SETLEASE", (long)F_SETLEASE)) return -1;\r
-#endif\r
-#ifdef F_GETLEASE\r
- if (ins(d, "F_GETLEASE", (long)F_GETLEASE)) return -1;\r
-#endif\r
-#ifdef F_NOTIFY\r
- if (ins(d, "F_NOTIFY", (long)F_NOTIFY)) return -1;\r
-#endif\r
-/* Old BSD flock(). */\r
-#ifdef F_EXLCK\r
- if (ins(d, "F_EXLCK", (long)F_EXLCK)) return -1;\r
-#endif\r
-#ifdef F_SHLCK\r
- if (ins(d, "F_SHLCK", (long)F_SHLCK)) return -1;\r
-#endif\r
-\r
-/* OS X (and maybe others) let you tell the storage device to flush to physical media */\r
-#ifdef F_FULLFSYNC\r
- if (ins(d, "F_FULLFSYNC", (long)F_FULLFSYNC)) return -1;\r
-#endif\r
-\r
-/* For F_{GET|SET}FL */\r
-#ifdef FD_CLOEXEC\r
- if (ins(d, "FD_CLOEXEC", (long)FD_CLOEXEC)) return -1;\r
-#endif\r
-\r
-/* For F_NOTIFY */\r
-#ifdef DN_ACCESS\r
- if (ins(d, "DN_ACCESS", (long)DN_ACCESS)) return -1;\r
-#endif\r
-#ifdef DN_MODIFY\r
- if (ins(d, "DN_MODIFY", (long)DN_MODIFY)) return -1;\r
-#endif\r
-#ifdef DN_CREATE\r
- if (ins(d, "DN_CREATE", (long)DN_CREATE)) return -1;\r
-#endif\r
-#ifdef DN_DELETE\r
- if (ins(d, "DN_DELETE", (long)DN_DELETE)) return -1;\r
-#endif\r
-#ifdef DN_RENAME\r
- if (ins(d, "DN_RENAME", (long)DN_RENAME)) return -1;\r
-#endif\r
-#ifdef DN_ATTRIB\r
- if (ins(d, "DN_ATTRIB", (long)DN_ATTRIB)) return -1;\r
-#endif\r
-#ifdef DN_MULTISHOT\r
- if (ins(d, "DN_MULTISHOT", (long)DN_MULTISHOT)) return -1;\r
-#endif\r
-\r
-#ifdef HAVE_STROPTS_H\r
- /* Unix 98 guarantees that these are in stropts.h. */\r
- INS(I_PUSH);\r
- INS(I_POP);\r
- INS(I_LOOK);\r
- INS(I_FLUSH);\r
- INS(I_FLUSHBAND);\r
- INS(I_SETSIG);\r
- INS(I_GETSIG);\r
- INS(I_FIND);\r
- INS(I_PEEK);\r
- INS(I_SRDOPT);\r
- INS(I_GRDOPT);\r
- INS(I_NREAD);\r
- INS(I_FDINSERT);\r
- INS(I_STR);\r
- INS(I_SWROPT);\r
-#ifdef I_GWROPT\r
- /* despite the comment above, old-ish glibcs miss a couple... */\r
- INS(I_GWROPT);\r
-#endif\r
- INS(I_SENDFD);\r
- INS(I_RECVFD);\r
- INS(I_LIST);\r
- INS(I_ATMARK);\r
- INS(I_CKBAND);\r
- INS(I_GETBAND);\r
- INS(I_CANPUT);\r
- INS(I_SETCLTIME);\r
-#ifdef I_GETCLTIME\r
- INS(I_GETCLTIME);\r
-#endif\r
- INS(I_LINK);\r
- INS(I_UNLINK);\r
- INS(I_PLINK);\r
- INS(I_PUNLINK);\r
-#endif\r
-\r
- return 0;\r
-}\r
-\r
-PyMODINIT_FUNC\r
-initfcntl(void)\r
-{\r
- PyObject *m, *d;\r
-\r
- /* Create the module and add the functions and documentation */\r
- m = Py_InitModule3("fcntl", fcntl_methods, module_doc);\r
- if (m == NULL)\r
- return;\r
-\r
- /* Add some symbolic constants to the module */\r
- d = PyModule_GetDict(m);\r
- all_ins(d);\r
-}\r