diff options
author | Victor Stinner <victor.stinner@haypocalc.com> | 2011-05-25 22:16:44 (GMT) |
---|---|---|
committer | Victor Stinner <victor.stinner@haypocalc.com> | 2011-05-25 22:16:44 (GMT) |
commit | e9d44ccb2279a49a69277d38e956731675f1b556 (patch) | |
tree | 1a3c3dd08c14d110ecf700165cfa1d1de8a7bd16 /Modules | |
parent | 5eb555990a5f507d417d0b37d9e4a88a3c161800 (diff) | |
download | cpython-e9d44ccb2279a49a69277d38e956731675f1b556.zip cpython-e9d44ccb2279a49a69277d38e956731675f1b556.tar.gz cpython-e9d44ccb2279a49a69277d38e956731675f1b556.tar.bz2 |
Issue #12175: FileIO.readall() now only reads the file position and size once.
Diffstat (limited to 'Modules')
-rw-r--r-- | Modules/_io/fileio.c | 37 |
1 files changed, 30 insertions, 7 deletions
diff --git a/Modules/_io/fileio.c b/Modules/_io/fileio.c index 141b6de..b3b9e44 100644 --- a/Modules/_io/fileio.c +++ b/Modules/_io/fileio.c @@ -547,14 +547,14 @@ fileio_readinto(fileio *self, PyObject *args) } 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 @@ new_buffersize(fileio *self, size_t currentsize) 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 @@ fileio_readall(fileio *self) 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 @@ fileio_readall(fileio *self) return NULL; } total += n; +#ifdef HAVE_FSTAT + pos += n; +#endif } if (PyBytes_GET_SIZE(result) > total) { |