# HG changeset patch # Parent ca54c27a9045c655ef1ad9ce248f02eb00137476 diff -r ca54c27a9045 Modules/_io/fileio.c --- a/Modules/_io/fileio.c Tue Aug 21 14:54:22 2012 +0100 +++ b/Modules/_io/fileio.c Wed Aug 22 13:36:00 2012 +0100 @@ -604,22 +604,16 @@ #ifdef HAVE_FSTAT struct stat st; Py_off_t pos, end; -#endif PyObject *result; Py_ssize_t total = 0; int n; - size_t newsize; + size_t size; if (self->fd < 0) return err_closed(); if (!_PyVerify_fd(self->fd)) return PyErr_SetFromErrno(PyExc_IOError); - result = PyBytes_FromStringAndSize(NULL, SMALLCHUNK); - if (result == NULL) - return NULL; - -#ifdef HAVE_FSTAT #if defined(MS_WIN64) || defined(MS_WINDOWS) pos = _lseeki64(self->fd, 0L, SEEK_CUR); #else @@ -629,36 +623,49 @@ end = st.st_size; else end = (Py_off_t)-1; -#endif + if (pos < 0 || end <= 0) +#endif /* HAVE_FSTAT */ + { + /* We can't calculate the buffer size needed, so fall back to + reading in chunks. */ + _Py_IDENTIFIER(readall); + return _PyObject_CallMethodId((PyObject*)&PyRawIOBase_Type, + &PyId_readall, "O", self); + } + +#ifdef HAVE_FSTAT + size = new_buffersize(self, total, pos, end); + result = PyBytes_FromStringAndSize(NULL, size); + if (result == NULL) + return NULL; + while (1) { -#ifdef HAVE_FSTAT - newsize = new_buffersize(self, total, pos, end); -#else - newsize = new_buffersize(self, total); -#endif - if (newsize > PY_SSIZE_T_MAX || newsize <= 0) { - PyErr_SetString(PyExc_OverflowError, - "unbounded read returned more bytes " - "than a Python string can hold "); - Py_DECREF(result); - return NULL; - } + if (total >= (Py_ssize_t)size) { + size = new_buffersize(self, total, pos, end); + if (size > PY_SSIZE_T_MAX || size <= 0) { + PyErr_SetString(PyExc_OverflowError, + "unbounded read returned more bytes " + "than a Python string can hold "); + Py_DECREF(result); + return NULL; + } - if (PyBytes_GET_SIZE(result) < (Py_ssize_t)newsize) { - if (_PyBytes_Resize(&result, newsize) < 0) { - if (total == 0) { - Py_DECREF(result); - return NULL; + if (PyBytes_GET_SIZE(result) < (Py_ssize_t)size) { + if (_PyBytes_Resize(&result, size) < 0) { + if (total == 0) { + Py_DECREF(result); + return NULL; + } + PyErr_Clear(); + break; } - PyErr_Clear(); - break; } } Py_BEGIN_ALLOW_THREADS errno = 0; n = read(self->fd, PyBytes_AS_STRING(result) + total, - newsize - total); + size - total); Py_END_ALLOW_THREADS if (n == 0) break; @@ -681,9 +688,7 @@ return NULL; } total += n; -#ifdef HAVE_FSTAT pos += n; -#endif } if (PyBytes_GET_SIZE(result) > total) { @@ -694,6 +699,7 @@ } } return result; +#endif /* HAVE_FSTAT */ } static PyObject *