Commit e9d44ccb authored by Victor Stinner's avatar Victor Stinner

Issue #12175: FileIO.readall() now only reads the file position and size once.

parent 5eb55599
...@@ -161,7 +161,10 @@ Core and Builtins ...@@ -161,7 +161,10 @@ Core and Builtins
Library 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. threading.
- Issue #12175: RawIOBase.readall() now returns None if read() returns None. - Issue #12175: RawIOBase.readall() now returns None if read() returns None.
......
...@@ -547,14 +547,14 @@ fileio_readinto(fileio *self, PyObject *args) ...@@ -547,14 +547,14 @@ fileio_readinto(fileio *self, PyObject *args)
} }
static size_t 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 #ifdef HAVE_FSTAT
off_t pos, end; if (end != (off_t)-1) {
struct stat st;
if (fstat(self->fd, &st) == 0) {
end = st.st_size;
pos = lseek(self->fd, 0L, SEEK_CUR);
/* Files claiming a size smaller than SMALLCHUNK may /* Files claiming a size smaller than SMALLCHUNK may
actually be streaming pseudo-files. In this case, we actually be streaming pseudo-files. In this case, we
apply the more aggressive algorithm below. apply the more aggressive algorithm below.
...@@ -579,9 +579,14 @@ new_buffersize(fileio *self, size_t currentsize) ...@@ -579,9 +579,14 @@ new_buffersize(fileio *self, size_t currentsize)
static PyObject * static PyObject *
fileio_readall(fileio *self) fileio_readall(fileio *self)
{ {
#ifdef HAVE_FSTAT
struct stat st;
off_t pos, end;
#endif
PyObject *result; PyObject *result;
Py_ssize_t total = 0; Py_ssize_t total = 0;
int n; int n;
size_t newsize;
if (self->fd < 0) if (self->fd < 0)
return err_closed(); return err_closed();
...@@ -592,8 +597,23 @@ fileio_readall(fileio *self) ...@@ -592,8 +597,23 @@ fileio_readall(fileio *self)
if (result == NULL) if (result == NULL)
return 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) { 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) { if (newsize > PY_SSIZE_T_MAX || newsize <= 0) {
PyErr_SetString(PyExc_OverflowError, PyErr_SetString(PyExc_OverflowError,
"unbounded read returned more bytes " "unbounded read returned more bytes "
...@@ -632,6 +652,9 @@ fileio_readall(fileio *self) ...@@ -632,6 +652,9 @@ fileio_readall(fileio *self)
return NULL; return NULL;
} }
total += n; total += n;
#ifdef HAVE_FSTAT
pos += n;
#endif
} }
if (PyBytes_GET_SIZE(result) > total) { if (PyBytes_GET_SIZE(result) > total) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment