changeset: 70390:72c89daace57 user: Victor Stinner date: Thu May 26 00:16:44 2011 +0200 files: Misc/NEWS Modules/_io/fileio.c description: Issue #12175: FileIO.readall() now only reads the file position and size once. diff -r 8aa1ae77cfe1 -r 72c89daace57 Misc/NEWS --- a/Misc/NEWS Wed May 25 23:46:09 2011 +0200 +++ b/Misc/NEWS Thu May 26 00:16:44 2011 +0200 @@ -161,7 +161,10 @@ Library ------- -- Issue #12180: Fixed a few remaining errors in test_packaging when no +- Issue #12175: FileIO.readall() now only reads the file position and size + once. + +- Issue #12180: Fixed a few remaining errors in test_packaging when no threading. - Issue #12175: RawIOBase.readall() now returns None if read() returns None. diff -r 8aa1ae77cfe1 -r 72c89daace57 Modules/_io/fileio.c --- a/Modules/_io/fileio.c Wed May 25 23:46:09 2011 +0200 +++ b/Modules/_io/fileio.c Thu May 26 00:16:44 2011 +0200 @@ -547,14 +547,14 @@ } static size_t -new_buffersize(fileio *self, size_t currentsize) +new_buffersize(fileio *self, size_t currentsize +#ifdef HAVE_FSTAT + , off_t pos, off_t end +#endif + ) { #ifdef HAVE_FSTAT - off_t pos, end; - struct stat st; - if (fstat(self->fd, &st) == 0) { - end = st.st_size; - pos = lseek(self->fd, 0L, SEEK_CUR); + if (end != (off_t)-1) { /* Files claiming a size smaller than SMALLCHUNK may actually be streaming pseudo-files. In this case, we apply the more aggressive algorithm below. @@ -579,9 +579,14 @@ static PyObject * fileio_readall(fileio *self) { +#ifdef HAVE_FSTAT + struct stat st; + off_t pos, end; +#endif PyObject *result; Py_ssize_t total = 0; int n; + size_t newsize; if (self->fd < 0) return err_closed(); @@ -592,8 +597,23 @@ if (result == NULL) return NULL; +#ifdef HAVE_FSTAT +#if defined(MS_WIN64) || defined(MS_WINDOWS) + pos = _lseeki64(self->fd, 0L, SEEK_CUR); +#else + pos = lseek(self->fd, 0L, SEEK_CUR); +#endif + if (fstat(self->fd, &st) == 0) + end = st.st_size; + else + end = (off_t)-1; +#endif while (1) { - size_t newsize = new_buffersize(self, total); +#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 " @@ -632,6 +652,9 @@ return NULL; } total += n; +#ifdef HAVE_FSTAT + pos += n; +#endif } if (PyBytes_GET_SIZE(result) > total) {