summaryrefslogtreecommitdiffstats
path: root/Modules
diff options
context:
space:
mode:
authorMichael W. Hudson <mwh@python.net>2003-03-03 12:29:42 (GMT)
committerMichael W. Hudson <mwh@python.net>2003-03-03 12:29:42 (GMT)
commitf00899866888408106fea4147a9d2cdc2f1e8dbc (patch)
tree32aae5a6d01192bc79456886bd8d299ad84ecdeb /Modules
parent122152451e1bc7aaff69d28b8950afa7848c6de6 (diff)
downloadcpython-f00899866888408106fea4147a9d2cdc2f1e8dbc.zip
cpython-f00899866888408106fea4147a9d2cdc2f1e8dbc.tar.gz
cpython-f00899866888408106fea4147a9d2cdc2f1e8dbc.tar.bz2
Fix bug
[ 555817 ] Flawed fcntl.ioctl implementation. with my patch that allows for an array to be mutated when passed as the buffer argument to ioctl() (details complicated by backwards compatibility considerations -- read the docs!).
Diffstat (limited to 'Modules')
-rw-r--r--Modules/fcntlmodule.c94
1 files changed, 83 insertions, 11 deletions
diff --git a/Modules/fcntlmodule.c b/Modules/fcntlmodule.c
index c5d9b4d..c495a77 100644
--- a/Modules/fcntlmodule.c
+++ b/Modules/fcntlmodule.c
@@ -99,8 +99,62 @@ fcntl_ioctl(PyObject *self, PyObject *args)
int ret;
char *str;
int len;
+ int mutate_arg = 0;
char buf[1024];
+ if (PyArg_ParseTuple(args, "O&iw#|i:ioctl",
+ conv_descriptor, &fd, &code,
+ &str, &len, &mutate_arg)) {
+ char *arg;
+
+ if (PyTuple_Size(args) == 3) {
+ /* warning goes here in 2.4 */
+ mutate_arg = 0;
+ }
+ if (mutate_arg) {
+ if (len <= sizeof buf) {
+ memcpy(buf, str, len);
+ arg = buf;
+ }
+ else {
+ arg = str;
+ }
+ }
+ else {
+ if (len > sizeof buf) {
+ PyErr_SetString(PyExc_ValueError,
+ "ioctl string arg too long");
+ return NULL;
+ }
+ else {
+ memcpy(buf, str, len);
+ arg = buf;
+ }
+ }
+ if (buf == arg) {
+ Py_BEGIN_ALLOW_THREADS /* think array.resize() */
+ ret = ioctl(fd, code, arg);
+ Py_END_ALLOW_THREADS
+ }
+ else {
+ ret = ioctl(fd, code, arg);
+ }
+ if (mutate_arg && (len < sizeof buf)) {
+ memcpy(str, buf, len);
+ }
+ if (ret < 0) {
+ PyErr_SetFromErrno(PyExc_IOError);
+ return NULL;
+ }
+ if (mutate_arg) {
+ return PyInt_FromLong(ret);
+ }
+ else {
+ return PyString_FromStringAndSize(buf, len);
+ }
+ }
+
+ PyErr_Clear();
if (PyArg_ParseTuple(args, "O&is#:ioctl",
conv_descriptor, &fd, &code, &str, &len)) {
if (len > sizeof buf) {
@@ -123,7 +177,7 @@ fcntl_ioctl(PyObject *self, PyObject *args)
arg = 0;
if (!PyArg_ParseTuple(args,
"O&i|i;ioctl requires a file or file descriptor,"
- " an integer and optionally a third integer or a string",
+ " an integer and optionally a integer or buffer argument",
conv_descriptor, &fd, &code, &arg)) {
return NULL;
}
@@ -138,17 +192,35 @@ fcntl_ioctl(PyObject *self, PyObject *args)
}
PyDoc_STRVAR(ioctl_doc,
-"ioctl(fd, opt, [arg])\n\
+"ioctl(fd, opt[, arg[, mutate_flag]])\n\
\n\
-Perform the requested operation on file descriptor fd. The operation\n\
-is defined by op and is operating system dependent. Typically these\n\
-codes can be retrieved from the library module IOCTL. The argument arg\n\
-is optional, and defaults to 0; it may be an int or a string. If arg is\n\
-given as a string, the return value of ioctl is a string of that length,\n\
-containing the resulting value put in the arg buffer by the operating system.\n\
-The length of the arg string is not allowed to exceed 1024 bytes. If the arg\n\
-given is an integer or if none is specified, the result value is an integer\n\
-corresponding to the return value of the ioctl call in the C code.");
+Perform the requested operation on file descriptor fd. The operation is\n\
+defined by op and is operating system dependent. Typically these codes are\n\
+retrieved from the fcntl or termios library modules.\n\
+\n\
+The argument arg is optional, and defaults to 0; it may be an int or a\n\
+buffer containing character data (most likely a string or an array). \n\
+\n\
+If the argument is a mutable buffer (such as an array) and if the\n\
+mutate_flag argument (which is only allowed in this case) is true then the\n\
+buffer is (in effect) passed to the operating system and changes made by\n\
+the OS will be reflected in the contents of the buffer after the call has\n\
+returned. The return value is the integer returned by the ioctl system\n\
+call.\n\
+\n\
+If the argument is a mutable buffer and the mutable_flag argument is not\n\
+passed or is false, the behavior is as if a string had been passed. This\n\
+behavior will change in future releases of Python.\n\
+\n\
+If the argument is an immutable buffer (most likely a string) then a copy\n\
+of the buffer is passed to the operating system and the return value is a\n\
+string of the same length containing whatever the operating system put in\n\
+the buffer. The length of the arg buffer in this case is not allowed to\n\
+exceed 1024 bytes.\n\
+\n\
+If the arg given is an integer or if none is specified, the result value is\n\
+an integer corresponding to the return value of the ioctl call in the C\n\
+code.");
/* flock(fd, operation) */