mirror of
https://github.com/python/cpython.git
synced 2025-08-03 00:23:06 +00:00
Add largefile support for Linux64 and WIn64. Add test_largefile and some minor
change to regrtest.py to allow optional running of test_largefile ('cause it's slow on Win64). This closes patches: http://sourceforge.net/patch/index.php?func=detailpatch&patch_id=100510&group_id=5470 and http://sourceforge.net/patch/index.php?func=detailpatch&patch_id=100511&group_id=5470
This commit is contained in:
parent
7932ed0ac4
commit
f29f47b38b
4 changed files with 288 additions and 45 deletions
|
@ -42,8 +42,8 @@ redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
|||
#endif
|
||||
|
||||
#ifdef MS_WIN32
|
||||
#define ftruncate _chsize
|
||||
#define fileno _fileno
|
||||
/* can (almost fully) duplicate with _chsize, see file_truncate */
|
||||
#define HAVE_FTRUNCATE
|
||||
#endif
|
||||
|
||||
|
@ -64,6 +64,12 @@ redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
|||
#include <errno.h>
|
||||
#endif
|
||||
|
||||
/* define the appropriate 64-bit capable tell() function */
|
||||
#ifdef MS_WIN64
|
||||
# define TELL64 _telli64
|
||||
#endif
|
||||
|
||||
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
FILE *f_fp;
|
||||
|
@ -239,12 +245,87 @@ file_close(PyFileObject *f, PyObject *args)
|
|||
return Py_None;
|
||||
}
|
||||
|
||||
|
||||
/* a portable fseek() function
|
||||
return 0 on success, non-zero on failure (with errno set) */
|
||||
int
|
||||
_portable_fseek(fp, offset, whence)
|
||||
FILE* fp;
|
||||
#if defined(HAVE_LARGEFILE_SUPPORT) && SIZEOF_OFF_T < 8 && SIZEOF_FPOS_T >= 8
|
||||
fpos_t offset;
|
||||
#else
|
||||
off_t offset;
|
||||
#endif
|
||||
int whence;
|
||||
{
|
||||
#if defined(HAVE_FSEEKO)
|
||||
return fseeko(fp, offset, whence);
|
||||
#elif defined(HAVE_FSEEK64)
|
||||
return fseek64(fp, offset, whence);
|
||||
#elif defined(HAVE_LARGEFILE_SUPPORT) && SIZEOF_FPOS_T >= 8
|
||||
/* lacking a 64-bit capable fseek() (as Win64 does) use a 64-bit capable
|
||||
fsetpos() and tell() to implement fseek()*/
|
||||
fpos_t pos;
|
||||
switch (whence) {
|
||||
case SEEK_CUR:
|
||||
if (fgetpos(fp, &pos) != 0)
|
||||
return -1;
|
||||
offset += pos;
|
||||
break;
|
||||
case SEEK_END:
|
||||
/* do a "no-op" seek first to sync the buffering so that
|
||||
the low-level tell() can be used correctly */
|
||||
if (fseek(fp, 0, SEEK_END) != 0)
|
||||
return -1;
|
||||
if ((pos = TELL64(fileno(fp))) == -1L)
|
||||
return -1;
|
||||
offset += pos;
|
||||
break;
|
||||
/* case SEEK_SET: break; */
|
||||
}
|
||||
return fsetpos(fp, &offset);
|
||||
#else
|
||||
return fseek(fp, offset, whence);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/* a portable ftell() function
|
||||
Return -1 on failure with errno set appropriately, current file
|
||||
position on success */
|
||||
#if defined(HAVE_LARGEFILE_SUPPORT) && SIZEOF_OFF_T < 8 && SIZEOF_FPOS_T >= 8
|
||||
fpos_t
|
||||
#else
|
||||
off_t
|
||||
#endif
|
||||
_portable_ftell(fp)
|
||||
FILE* fp;
|
||||
{
|
||||
#if defined(HAVE_FTELLO) && defined(HAVE_LARGEFILE_SUPPORT)
|
||||
return ftello(fp);
|
||||
#elif defined(HAVE_FTELL64) && defined(HAVE_LARGEFILE_SUPPORT)
|
||||
return ftell64(fp);
|
||||
#elif SIZEOF_FPOS_T >= 8 && defined(HAVE_LARGEFILE_SUPPORT)
|
||||
fpos_t pos;
|
||||
if (fgetpos(fp, &pos) != 0)
|
||||
return -1;
|
||||
return pos;
|
||||
#else
|
||||
return ftell(fp);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static PyObject *
|
||||
file_seek(PyFileObject *f, PyObject *args)
|
||||
{
|
||||
int whence;
|
||||
int ret;
|
||||
#if defined(HAVE_LARGEFILE_SUPPORT) && SIZEOF_OFF_T < 8 && SIZEOF_FPOS_T >= 8
|
||||
fpos_t offset, pos;
|
||||
#else
|
||||
off_t offset;
|
||||
#endif /* !MS_WIN64 */
|
||||
PyObject *offobj;
|
||||
|
||||
if (f->f_fp == NULL)
|
||||
|
@ -260,16 +341,12 @@ file_seek(PyFileObject *f, PyObject *args)
|
|||
#endif
|
||||
if (PyErr_Occurred())
|
||||
return NULL;
|
||||
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
errno = 0;
|
||||
#if defined(HAVE_FSEEKO)
|
||||
ret = fseeko(f->f_fp, offset, whence);
|
||||
#elif defined(HAVE_FSEEK64)
|
||||
ret = fseek64(f->f_fp, offset, whence);
|
||||
#else
|
||||
ret = fseek(f->f_fp, offset, whence);
|
||||
#endif
|
||||
ret = _portable_fseek(f->f_fp, offset, whence);
|
||||
Py_END_ALLOW_THREADS
|
||||
|
||||
if (ret != 0) {
|
||||
PyErr_SetFromErrno(PyExc_IOError);
|
||||
clearerr(f->f_fp);
|
||||
|
@ -279,12 +356,17 @@ file_seek(PyFileObject *f, PyObject *args)
|
|||
return Py_None;
|
||||
}
|
||||
|
||||
|
||||
#ifdef HAVE_FTRUNCATE
|
||||
static PyObject *
|
||||
file_truncate(PyFileObject *f, PyObject *args)
|
||||
{
|
||||
int ret;
|
||||
#if defined(HAVE_LARGEFILE_SUPPORT) && SIZEOF_OFF_T < 8 && SIZEOF_FPOS_T >= 8
|
||||
fpos_t newsize;
|
||||
#else
|
||||
off_t newsize;
|
||||
#endif
|
||||
PyObject *newsizeobj;
|
||||
|
||||
if (f->f_fp == NULL)
|
||||
|
@ -306,13 +388,7 @@ file_truncate(PyFileObject *f, PyObject *args)
|
|||
/* Default to current position*/
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
errno = 0;
|
||||
#if defined(HAVE_FTELLO) && defined(HAVE_LARGEFILE_SUPPORT)
|
||||
newsize = ftello(f->f_fp);
|
||||
#elif defined(HAVE_FTELL64) && defined(HAVE_LARGEFILE_SUPPORT)
|
||||
newsize = ftell64(f->f_fp);
|
||||
#else
|
||||
newsize = ftell(f->f_fp);
|
||||
#endif
|
||||
newsize = _portable_ftell(f->f_fp);
|
||||
Py_END_ALLOW_THREADS
|
||||
if (newsize == -1) {
|
||||
PyErr_SetFromErrno(PyExc_IOError);
|
||||
|
@ -324,49 +400,66 @@ file_truncate(PyFileObject *f, PyObject *args)
|
|||
errno = 0;
|
||||
ret = fflush(f->f_fp);
|
||||
Py_END_ALLOW_THREADS
|
||||
if (ret == 0) {
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
errno = 0;
|
||||
ret = ftruncate(fileno(f->f_fp), newsize);
|
||||
Py_END_ALLOW_THREADS
|
||||
}
|
||||
if (ret != 0) {
|
||||
PyErr_SetFromErrno(PyExc_IOError);
|
||||
clearerr(f->f_fp);
|
||||
if (ret != 0) goto onioerror;
|
||||
|
||||
#ifdef MS_WIN32
|
||||
/* can use _chsize; if, however, the newsize overflows 32-bits then
|
||||
_chsize is *not* adequate; in this case, an OverflowError is raised */
|
||||
if (newsize > LONG_MAX) {
|
||||
PyErr_SetString(PyExc_OverflowError,
|
||||
"the new size is too long for _chsize (it is limited to 32-bit values)");
|
||||
return NULL;
|
||||
} else {
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
errno = 0;
|
||||
ret = _chsize(fileno(f->f_fp), newsize);
|
||||
Py_END_ALLOW_THREADS
|
||||
if (ret != 0) goto onioerror;
|
||||
}
|
||||
#else
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
errno = 0;
|
||||
ret = ftruncate(fileno(f->f_fp), newsize);
|
||||
Py_END_ALLOW_THREADS
|
||||
if (ret != 0) goto onioerror;
|
||||
#endif /* !MS_WIN32 */
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
|
||||
onioerror:
|
||||
PyErr_SetFromErrno(PyExc_IOError);
|
||||
clearerr(f->f_fp);
|
||||
return NULL;
|
||||
}
|
||||
#endif /* HAVE_FTRUNCATE */
|
||||
|
||||
static PyObject *
|
||||
file_tell(PyFileObject *f, PyObject *args)
|
||||
{
|
||||
off_t offset;
|
||||
#if defined(HAVE_LARGEFILE_SUPPORT) && SIZEOF_OFF_T < 8 && SIZEOF_FPOS_T >= 8
|
||||
fpos_t pos;
|
||||
#else
|
||||
off_t pos;
|
||||
#endif
|
||||
|
||||
if (f->f_fp == NULL)
|
||||
return err_closed();
|
||||
if (!PyArg_NoArgs(args))
|
||||
return NULL;
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
errno = 0;
|
||||
#if defined(HAVE_FTELLO) && defined(HAVE_LARGEFILE_SUPPORT)
|
||||
offset = ftello(f->f_fp);
|
||||
#elif defined(HAVE_FTELL64) && defined(HAVE_LARGEFILE_SUPPORT)
|
||||
offset = ftell64(f->f_fp);
|
||||
#else
|
||||
offset = ftell(f->f_fp);
|
||||
#endif
|
||||
pos = _portable_ftell(f->f_fp);
|
||||
Py_END_ALLOW_THREADS
|
||||
if (offset == -1) {
|
||||
if (pos == -1) {
|
||||
PyErr_SetFromErrno(PyExc_IOError);
|
||||
clearerr(f->f_fp);
|
||||
return NULL;
|
||||
}
|
||||
#if !defined(HAVE_LARGEFILE_SUPPORT)
|
||||
return PyInt_FromLong(offset);
|
||||
return PyInt_FromLong(pos);
|
||||
#else
|
||||
return PyLong_FromLongLong(offset);
|
||||
return PyLong_FromLongLong(pos);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -482,6 +575,11 @@ file_read(PyFileObject *f, PyObject *args)
|
|||
buffersize = new_buffersize(f, (size_t)0);
|
||||
else
|
||||
buffersize = bytesrequested;
|
||||
if (buffersize > INT_MAX) {
|
||||
PyErr_SetString(PyExc_OverflowError,
|
||||
"requested number of bytes is more than a Python string can hold");
|
||||
return NULL;
|
||||
}
|
||||
v = PyString_FromStringAndSize((char *)NULL, buffersize);
|
||||
if (v == NULL)
|
||||
return NULL;
|
||||
|
@ -518,7 +616,7 @@ static PyObject *
|
|||
file_readinto(PyFileObject *f, PyObject *args)
|
||||
{
|
||||
char *ptr;
|
||||
int ntodo, ndone, nnow;
|
||||
size_t ntodo, ndone, nnow;
|
||||
|
||||
if (f->f_fp == NULL)
|
||||
return err_closed();
|
||||
|
@ -540,7 +638,7 @@ file_readinto(PyFileObject *f, PyObject *args)
|
|||
ndone += nnow;
|
||||
ntodo -= nnow;
|
||||
}
|
||||
return PyInt_FromLong(ndone);
|
||||
return PyInt_FromLong((long)ndone);
|
||||
}
|
||||
|
||||
|
||||
|
@ -557,7 +655,7 @@ get_line(PyFileObject *f, int n)
|
|||
register FILE *fp;
|
||||
register int c;
|
||||
register char *buf, *end;
|
||||
int n1, n2;
|
||||
size_t n1, n2;
|
||||
PyObject *v;
|
||||
|
||||
fp = f->f_fp;
|
||||
|
@ -596,6 +694,11 @@ get_line(PyFileObject *f, int n)
|
|||
break;
|
||||
n1 = n2;
|
||||
n2 += 1000;
|
||||
if (n2 > INT_MAX) {
|
||||
PyErr_SetString(PyExc_OverflowError,
|
||||
"line is longer than a Python string can hold");
|
||||
return NULL;
|
||||
}
|
||||
Py_BLOCK_THREADS
|
||||
if (_PyString_Resize(&v, n2) < 0)
|
||||
return NULL;
|
||||
|
@ -735,6 +838,11 @@ file_readlines(PyFileObject *f, PyObject *args)
|
|||
/* Need a larger buffer to fit this line */
|
||||
nfilled += nread;
|
||||
buffersize *= 2;
|
||||
if (buffersize > INT_MAX) {
|
||||
PyErr_SetString(PyExc_OverflowError,
|
||||
"line is too long for a Python string");
|
||||
goto error;
|
||||
}
|
||||
if (big_buffer == NULL) {
|
||||
/* Create the big buffer */
|
||||
big_buffer = PyString_FromStringAndSize(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue