Commit 70d2742f authored by Andrew M. Kuchling's avatar Andrew M. Kuchling

Patch from Trent Mick:

	The seek() method is broken for any 'whence' value (seek from
	start, current, orend) other than the default. I have a patch
	that fixes that as well as gets mmap'd files working on
	Linux64 and Win64.
parent 9bc5f333
...@@ -45,7 +45,7 @@ typedef struct { ...@@ -45,7 +45,7 @@ typedef struct {
#ifdef MS_WIN32 #ifdef MS_WIN32
HANDLE map_handle; HANDLE map_handle;
HFILE file_handle; INT_PTR file_handle;
char * tagname; char * tagname;
#endif #endif
...@@ -123,7 +123,7 @@ mmap_read_byte_method (mmap_object * self, ...@@ -123,7 +123,7 @@ mmap_read_byte_method (mmap_object * self,
CHECK_VALID(NULL); CHECK_VALID(NULL);
if (!PyArg_ParseTuple(args, ":read_byte")) if (!PyArg_ParseTuple(args, ":read_byte"))
return NULL; return NULL;
if (self->pos >= 0 && self->pos < self->size) { if (self->pos < self->size) {
where = self->data + self->pos; where = self->data + self->pos;
value = (char) *(where); value = (char) *(where);
self->pos += 1; self->pos += 1;
...@@ -153,7 +153,7 @@ mmap_read_line_method (mmap_object * self, ...@@ -153,7 +153,7 @@ mmap_read_line_method (mmap_object * self,
else else
++eol; /* we're interested in the position after the ++eol; /* we're interested in the position after the
newline. */ newline. */
result = PyString_FromStringAndSize(start, (long) (eol - start)); result = PyString_FromStringAndSize(start, (eol - start));
self->pos += (eol - start); self->pos += (eol - start);
return (result); return (result);
} }
...@@ -182,12 +182,12 @@ static PyObject * ...@@ -182,12 +182,12 @@ static PyObject *
mmap_find_method (mmap_object *self, mmap_find_method (mmap_object *self,
PyObject *args) PyObject *args)
{ {
long start = self->pos; int start = self->pos;
char * needle; char * needle;
int len; int len;
CHECK_VALID(NULL); CHECK_VALID(NULL);
if (!PyArg_ParseTuple (args, "s#|l", &needle, &len, &start)) { if (!PyArg_ParseTuple (args, "s#|i", &needle, &len, &start)) {
return NULL; return NULL;
} else { } else {
char * p = self->data+self->pos; char * p = self->data+self->pos;
...@@ -200,8 +200,8 @@ mmap_find_method (mmap_object *self, ...@@ -200,8 +200,8 @@ mmap_find_method (mmap_object *self,
} }
if (!*n) { if (!*n) {
return Py_BuildValue ( return Py_BuildValue (
"l", "i",
(long) (p - (self->data + start))); (int) (p - (self->data + start)));
} }
p++; p++;
} }
...@@ -255,7 +255,7 @@ mmap_size_method (mmap_object * self, ...@@ -255,7 +255,7 @@ mmap_size_method (mmap_object * self,
return NULL; return NULL;
#ifdef MS_WIN32 #ifdef MS_WIN32
if (self->file_handle != (HFILE) 0xFFFFFFFF) { if (self->file_handle != (INT_PTR) -1) {
return (Py_BuildValue ( return (Py_BuildValue (
"l", "l",
GetFileSize ((HANDLE)self->file_handle, NULL))); GetFileSize ((HANDLE)self->file_handle, NULL)));
...@@ -401,39 +401,44 @@ mmap_flush_method (mmap_object * self, PyObject * args) ...@@ -401,39 +401,44 @@ mmap_flush_method (mmap_object * self, PyObject * args)
static PyObject * static PyObject *
mmap_seek_method (mmap_object * self, PyObject * args) mmap_seek_method (mmap_object * self, PyObject * args)
{ {
/* ptrdiff_t dist; */ int dist;
long dist;
int how=0; int how=0;
CHECK_VALID(NULL); CHECK_VALID(NULL);
if (!PyArg_ParseTuple (args, "l|i", &dist, &how)) { if (!PyArg_ParseTuple (args, "i|i", &dist, &how)) {
return(NULL); return(NULL);
} else { } else {
unsigned long where; size_t where;
switch (how) { switch (how) {
case 0: case 0: /* relative to start */
if (dist < 0)
goto onoutofrange;
where = dist; where = dist;
break; break;
case 1: case 1: /* relative to current position */
if ((int)self->pos + dist < 0)
goto onoutofrange;
where = self->pos + dist; where = self->pos + dist;
break; break;
case 2: case 2: /* relative to end */
where = self->size - dist; if ((int)self->size + dist < 0)
goto onoutofrange;
where = self->size + dist;
break; break;
default: default:
PyErr_SetString (PyExc_ValueError, PyErr_SetString (PyExc_ValueError,
"unknown seek type"); "unknown seek type");
return NULL; return NULL;
} }
if ((where >= 0) && (where < (self->size))) { if (where > self->size)
goto onoutofrange;
self->pos = where; self->pos = where;
Py_INCREF (Py_None); Py_INCREF (Py_None);
return (Py_None); return (Py_None);
} else {
PyErr_SetString (PyExc_ValueError,
"seek out of range");
return NULL;
}
} }
onoutofrange:
PyErr_SetString (PyExc_ValueError, "seek out of range");
return NULL;
} }
static PyObject * static PyObject *
...@@ -704,22 +709,83 @@ static PyTypeObject mmap_object_type = { ...@@ -704,22 +709,83 @@ static PyTypeObject mmap_object_type = {
0, /*tp_doc*/ 0, /*tp_doc*/
}; };
/* extract the map size from the given PyObject
The map size is restricted to [0, INT_MAX] because this is the current
Python limitation on object sizes. Although the mmap object *could* handle
a larger map size, there is no point because all the useful operations
(len(), slicing(), sequence indexing) are limited by a C int.
Returns -1 on error, with an apprpriate Python exception raised. On
success, the map size is returned. */
static int
_GetMapSize(o)
PyObject *o;
{
if (PyInt_Check(o)) {
long i = PyInt_AsLong(o);
if (PyErr_Occurred())
return -1;
if (i < 0)
goto onnegoverflow;
if (i > INT_MAX)
goto onposoverflow;
return (int)i;
}
else if (PyLong_Check(o)) {
long i = PyLong_AsLong(o);
if (PyErr_Occurred()) {
/* yes negative overflow is mistaken for positive overflow
but not worth the trouble to check sign of 'i' */
if (PyErr_ExceptionMatches(PyExc_OverflowError))
goto onposoverflow;
else
return -1;
}
if (i < 0)
goto onnegoverflow;
if (i > INT_MAX)
goto onposoverflow;
return (int)i;
}
else {
PyErr_SetString(PyExc_TypeError,
"map size must be an integral value");
return -1;
}
onnegoverflow:
PyErr_SetString(PyExc_OverflowError,
"memory mapped size must be positive");
return -1;
onposoverflow:
PyErr_SetString(PyExc_OverflowError,
"memory mapped size is too large (limited by C int)");
return -1;
}
#ifdef UNIX #ifdef UNIX
static PyObject * static PyObject *
new_mmap_object (PyObject * self, PyObject * args, PyObject *kwdict) new_mmap_object (PyObject * self, PyObject * args, PyObject *kwdict)
{ {
mmap_object * m_obj; mmap_object * m_obj;
unsigned long map_size; PyObject *map_size_obj = NULL;
int map_size;
int fd, flags = MAP_SHARED, prot = PROT_WRITE | PROT_READ; int fd, flags = MAP_SHARED, prot = PROT_WRITE | PROT_READ;
char * filename; char * filename;
int namelen; int namelen;
char *keywords[] = {"file", "size", "flags", "prot", NULL}; char *keywords[] = {"file", "size", "flags", "prot", NULL};
if (!PyArg_ParseTupleAndKeywords(args, kwdict, if (!PyArg_ParseTupleAndKeywords(args, kwdict,
"il|ii", keywords, "iO|ii", keywords,
&fd, &map_size, &flags, &prot) &fd, &map_size_obj, &flags, &prot)
) )
return NULL; return NULL;
map_size = _GetMapSize(map_size_obj);
if (map_size < 0)
return NULL;
m_obj = PyObject_New (mmap_object, &mmap_object_type); m_obj = PyObject_New (mmap_object, &mmap_object_type);
if (m_obj == NULL) {return NULL;} if (m_obj == NULL) {return NULL;}
...@@ -744,24 +810,29 @@ static PyObject * ...@@ -744,24 +810,29 @@ static PyObject *
new_mmap_object (PyObject * self, PyObject * args) new_mmap_object (PyObject * self, PyObject * args)
{ {
mmap_object * m_obj; mmap_object * m_obj;
unsigned long map_size; PyObject *map_size_obj = NULL;
int map_size;
char * tagname = ""; char * tagname = "";
DWORD dwErr = 0; DWORD dwErr = 0;
int fileno; int fileno;
HFILE fh = 0; INT_PTR fh = 0;
/* Patch the object type */ /* Patch the object type */
mmap_object_type.ob_type = &PyType_Type; mmap_object_type.ob_type = &PyType_Type;
if (!PyArg_ParseTuple(args, if (!PyArg_ParseTuple(args,
"il|z", "iO|z",
&fileno, &fileno,
&map_size, &map_size_obj,
&tagname) &tagname)
) )
return NULL; return NULL;
map_size = _GetMapSize(map_size_obj);
if (map_size < 0)
return NULL;
/* if an actual filename has been specified */ /* if an actual filename has been specified */
if (fileno != 0) { if (fileno != 0) {
fh = _get_osfhandle(fileno); fh = _get_osfhandle(fileno);
...@@ -784,7 +855,7 @@ new_mmap_object (PyObject * self, PyObject * args) ...@@ -784,7 +855,7 @@ new_mmap_object (PyObject * self, PyObject * args)
} }
} }
else { else {
m_obj->file_handle = (HFILE) 0xFFFFFFFF; m_obj->file_handle = (INT_PTR) -1;
m_obj->size = map_size; m_obj->size = map_size;
} }
......
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