Issue #23152: Implement _Py_fstat() to support files larger than 2 GB on Windows.

fstat() may fail with EOVERFLOW on files larger than 2 GB because the file size type is an signed 32-bit integer.
This commit is contained in:
Steve Dower 2015-02-21 08:44:05 -08:00
parent 18d1924987
commit f2f373f593
12 changed files with 242 additions and 180 deletions

View file

@ -180,9 +180,9 @@ fileio_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
static int
check_fd(int fd)
{
#if defined(HAVE_FSTAT)
struct stat buf;
if (!_PyVerify_fd(fd) || (fstat(fd, &buf) < 0 && errno == EBADF)) {
#if defined(HAVE_FSTAT) || defined(MS_WINDOWS)
struct _Py_stat_struct buf;
if (!_PyVerify_fd(fd) || (_Py_fstat(fd, &buf) < 0 && errno == EBADF)) {
PyObject *exc;
char *msg = strerror(EBADF);
exc = PyObject_CallFunction(PyExc_OSError, "(is)",
@ -222,8 +222,8 @@ fileio_init(PyObject *oself, PyObject *args, PyObject *kwds)
#elif !defined(MS_WINDOWS)
int *atomic_flag_works = NULL;
#endif
#ifdef HAVE_FSTAT
struct stat fdfstat;
#if defined(HAVE_FSTAT) || defined(MS_WINDOWS)
struct _Py_stat_struct fdfstat;
#endif
int async_err = 0;
@ -420,9 +420,11 @@ fileio_init(PyObject *oself, PyObject *args, PyObject *kwds)
}
self->blksize = DEFAULT_BUFFER_SIZE;
#ifdef HAVE_FSTAT
if (fstat(self->fd, &fdfstat) < 0)
#if defined(HAVE_FSTAT) || defined(MS_WINDOWS)
if (_Py_fstat(self->fd, &fdfstat) < 0) {
PyErr_SetFromErrno(PyExc_OSError);
goto error;
}
#if defined(S_ISDIR) && defined(EISDIR)
/* On Unix, open will succeed for directories.
In Python, there should be no file objects referring to
@ -437,7 +439,7 @@ fileio_init(PyObject *oself, PyObject *args, PyObject *kwds)
if (fdfstat.st_blksize > 1)
self->blksize = fdfstat.st_blksize;
#endif /* HAVE_STRUCT_STAT_ST_BLKSIZE */
#endif /* HAVE_FSTAT */
#endif /* HAVE_FSTAT || MS_WINDOWS */
#if defined(MS_WINDOWS) || defined(__CYGWIN__)
/* don't translate newlines (\r\n <=> \n) */
@ -603,17 +605,7 @@ fileio_readinto(fileio *self, PyObject *args)
return PyLong_FromSsize_t(n);
}
#ifndef HAVE_FSTAT
static PyObject *
fileio_readall(fileio *self)
{
_Py_IDENTIFIER(readall);
return _PyObject_CallMethodId((PyObject*)&PyRawIOBase_Type,
&PyId_readall, "O", self);
}
#else
#if defined(HAVE_FSTAT) || defined(MS_WINDOWS)
static size_t
new_buffersize(fileio *self, size_t currentsize)
@ -637,7 +629,7 @@ new_buffersize(fileio *self, size_t currentsize)
static PyObject *
fileio_readall(fileio *self)
{
struct stat st;
struct _Py_stat_struct st;
Py_off_t pos, end;
PyObject *result;
Py_ssize_t bytes_read = 0;
@ -655,7 +647,7 @@ fileio_readall(fileio *self)
#else
pos = lseek(self->fd, 0L, SEEK_CUR);
#endif
if (fstat(self->fd, &st) == 0)
if (_Py_fstat(self->fd, &st) == 0)
end = st.st_size;
else
end = (Py_off_t)-1;
@ -729,7 +721,17 @@ fileio_readall(fileio *self)
return result;
}
#endif /* HAVE_FSTAT */
#else
static PyObject *
fileio_readall(fileio *self)
{
_Py_IDENTIFIER(readall);
return _PyObject_CallMethodId((PyObject*)&PyRawIOBase_Type,
&PyId_readall, "O", self);
}
#endif /* HAVE_FSTAT || MS_WINDOWS */
static PyObject *
fileio_read(fileio *self, PyObject *args)