Skip to content

Commit

Permalink
ENH: core: switch to off_t and lseek in Python 3 file seeks
Browse files Browse the repository at this point in the history
This removes dependency on CRT implementation details (whether
fflush/fclose actually seeks the underlying raw file handle or not).

Also, check seek error statuses.
  • Loading branch information
pv committed Jan 9, 2014
1 parent dd05022 commit 41690fc
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 12 deletions.
39 changes: 29 additions & 10 deletions numpy/core/include/numpy/npy_3kcompat.h
Original file line number Diff line number Diff line change
Expand Up @@ -146,11 +146,11 @@ PyUnicode_Concat2(PyObject **left, PyObject *right)
* Get a FILE* handle to the file represented by the Python object
*/
static NPY_INLINE FILE*
npy_PyFile_Dup(PyObject *file, char *mode, Py_ssize_t *orig_pos)
npy_PyFile_Dup(PyObject *file, char *mode, npy_off_t *orig_pos)
{
int fd, fd2;
PyObject *ret, *os;
Py_ssize_t pos;
npy_off_t pos;
FILE *handle;

/* Flush first to ensure things end up in the file in the correct order */
Expand Down Expand Up @@ -191,6 +191,10 @@ npy_PyFile_Dup(PyObject *file, char *mode, Py_ssize_t *orig_pos)

/* Record the original raw file handle position */
*orig_pos = npy_ftell(handle);
if (*orig_pos == -1) {
PyErr_SetString(PyExc_IOError, "obtaining file position failed");
return -1;
}

/* Seek raw handle to the Python-side position */
ret = PyObject_CallMethod(file, "tell", "");
Expand All @@ -204,30 +208,45 @@ npy_PyFile_Dup(PyObject *file, char *mode, Py_ssize_t *orig_pos)
fclose(handle);
return NULL;
}
npy_fseek(handle, pos, SEEK_SET);
if (npy_fseek(handle, pos, SEEK_SET) == -1) {
PyErr_SetString(PyExc_IOError, "seeking file failed");
return -1;
}
return handle;
}

/*
* Close the dup-ed file handle, and seek the Python one to the current position
*/
static NPY_INLINE int
npy_PyFile_DupClose(PyObject *file, FILE* handle, Py_ssize_t orig_pos)
npy_PyFile_DupClose(PyObject *file, FILE* handle, npy_off_t orig_pos)
{
int fd;
PyObject *ret;
Py_ssize_t position;
npy_off_t position;

position = npy_ftell(handle);

/* Close the FILE* handle */
fclose(handle);

/* Restore original file handle position, in order to not confuse
Python-side data structures */
npy_fseek(handle, orig_pos, SEEK_SET);
fd = PyObject_AsFileDescriptor(file);
if (fd == -1) {
return -1;
}
if (npy_lseek(fd, orig_pos, SEEK_SET) == -1) {
PyErr_SetString(PyExc_IOError, "seeking file failed");
return -1;
}

/* Flush before closing to sync the raw file handle position */
fflush(handle);
fclose(handle);
if (position == -1) {
PyErr_SetString(PyExc_IOError, "obtaining file position failed");
return -1;
}

/* Seek Python-side handle to the raw handle position */
/* Seek Python-side handle to the FILE* handle position */
ret = PyObject_CallMethod(file, "seek", NPY_SSIZE_T_PYFMT "i", position, 0);
if (ret == NULL) {
return -1;
Expand Down
5 changes: 5 additions & 0 deletions numpy/core/include/numpy/npy_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,16 @@

/* Enable 64 bit file position support on win-amd64. Ticket #1660 */
#if defined(_MSC_VER) && defined(_WIN64) && (_MSC_VER > 1400)
#include <io.h>
#define npy_fseek _fseeki64
#define npy_ftell _ftelli64
#define npy_lseek _lseeki64
#define npy_off_t npy_int64
#else
#define npy_fseek fseek
#define npy_ftell ftell
#define npy_lseek lseek
#define npy_off_t off_t
#endif

/* enums for detected endianness */
Expand Down
2 changes: 1 addition & 1 deletion numpy/core/src/multiarray/methods.c
Original file line number Diff line number Diff line change
Expand Up @@ -566,7 +566,7 @@ array_tofile(PyArrayObject *self, PyObject *args, PyObject *kwds)
FILE *fd;
char *sep = "";
char *format = "";
Py_ssize_t orig_pos;
npy_off_t orig_pos;
static char *kwlist[] = {"file", "sep", "format", NULL};

if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|ss", kwlist,
Expand Down
2 changes: 1 addition & 1 deletion numpy/core/src/multiarray/multiarraymodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -1972,7 +1972,7 @@ array_fromfile(PyObject *NPY_UNUSED(ignored), PyObject *args, PyObject *keywds)
static char *kwlist[] = {"file", "dtype", "count", "sep", NULL};
PyArray_Descr *type = NULL;
int own;
Py_ssize_t orig_pos;
npy_off_t orig_pos;
FILE *fp;

if (!PyArg_ParseTupleAndKeywords(args, keywds,
Expand Down

0 comments on commit 41690fc

Please sign in to comment.