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.
This commit is contained in:
Andrew M. Kuchling 2000-06-18 04:45:14 +00:00
parent 9bc5f3339a
commit 70d2742fce
1 changed files with 105 additions and 34 deletions

View File

@ -45,7 +45,7 @@ typedef struct {
#ifdef MS_WIN32
HANDLE map_handle;
HFILE file_handle;
INT_PTR file_handle;
char * tagname;
#endif
@ -123,7 +123,7 @@ mmap_read_byte_method (mmap_object * self,
CHECK_VALID(NULL);
if (!PyArg_ParseTuple(args, ":read_byte"))
return NULL;
if (self->pos >= 0 && self->pos < self->size) {
if (self->pos < self->size) {
where = self->data + self->pos;
value = (char) *(where);
self->pos += 1;
@ -153,7 +153,7 @@ mmap_read_line_method (mmap_object * self,
else
++eol; /* we're interested in the position after the
newline. */
result = PyString_FromStringAndSize(start, (long) (eol - start));
result = PyString_FromStringAndSize(start, (eol - start));
self->pos += (eol - start);
return (result);
}
@ -182,12 +182,12 @@ static PyObject *
mmap_find_method (mmap_object *self,
PyObject *args)
{
long start = self->pos;
int start = self->pos;
char * needle;
int len;
CHECK_VALID(NULL);
if (!PyArg_ParseTuple (args, "s#|l", &needle, &len, &start)) {
if (!PyArg_ParseTuple (args, "s#|i", &needle, &len, &start)) {
return NULL;
} else {
char * p = self->data+self->pos;
@ -200,8 +200,8 @@ mmap_find_method (mmap_object *self,
}
if (!*n) {
return Py_BuildValue (
"l",
(long) (p - (self->data + start)));
"i",
(int) (p - (self->data + start)));
}
p++;
}
@ -255,7 +255,7 @@ mmap_size_method (mmap_object * self,
return NULL;
#ifdef MS_WIN32
if (self->file_handle != (HFILE) 0xFFFFFFFF) {
if (self->file_handle != (INT_PTR) -1) {
return (Py_BuildValue (
"l",
GetFileSize ((HANDLE)self->file_handle, NULL)));
@ -401,39 +401,44 @@ mmap_flush_method (mmap_object * self, PyObject * args)
static PyObject *
mmap_seek_method (mmap_object * self, PyObject * args)
{
/* ptrdiff_t dist; */
long dist;
int dist;
int how=0;
CHECK_VALID(NULL);
if (!PyArg_ParseTuple (args, "l|i", &dist, &how)) {
if (!PyArg_ParseTuple (args, "i|i", &dist, &how)) {
return(NULL);
} else {
unsigned long where;
size_t where;
switch (how) {
case 0:
case 0: /* relative to start */
if (dist < 0)
goto onoutofrange;
where = dist;
break;
case 1:
case 1: /* relative to current position */
if ((int)self->pos + dist < 0)
goto onoutofrange;
where = self->pos + dist;
break;
case 2:
where = self->size - dist;
case 2: /* relative to end */
if ((int)self->size + dist < 0)
goto onoutofrange;
where = self->size + dist;
break;
default:
PyErr_SetString (PyExc_ValueError,
"unknown seek type");
return NULL;
}
if ((where >= 0) && (where < (self->size))) {
self->pos = where;
Py_INCREF (Py_None);
return (Py_None);
} else {
PyErr_SetString (PyExc_ValueError,
"seek out of range");
return NULL;
}
if (where > self->size)
goto onoutofrange;
self->pos = where;
Py_INCREF (Py_None);
return (Py_None);
}
onoutofrange:
PyErr_SetString (PyExc_ValueError, "seek out of range");
return NULL;
}
static PyObject *
@ -704,23 +709,84 @@ static PyTypeObject mmap_object_type = {
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
static PyObject *
new_mmap_object (PyObject * self, PyObject * args, PyObject *kwdict)
{
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;
char * filename;
int namelen;
char *keywords[] = {"file", "size", "flags", "prot", NULL};
if (!PyArg_ParseTupleAndKeywords(args, kwdict,
"il|ii", keywords,
&fd, &map_size, &flags, &prot)
"iO|ii", keywords,
&fd, &map_size_obj, &flags, &prot)
)
return NULL;
map_size = _GetMapSize(map_size_obj);
if (map_size < 0)
return NULL;
m_obj = PyObject_New (mmap_object, &mmap_object_type);
if (m_obj == NULL) {return NULL;}
m_obj->size = (size_t) map_size;
@ -744,24 +810,29 @@ static PyObject *
new_mmap_object (PyObject * self, PyObject * args)
{
mmap_object * m_obj;
unsigned long map_size;
PyObject *map_size_obj = NULL;
int map_size;
char * tagname = "";
DWORD dwErr = 0;
int fileno;
HFILE fh = 0;
INT_PTR fh = 0;
/* Patch the object type */
mmap_object_type.ob_type = &PyType_Type;
if (!PyArg_ParseTuple(args,
"il|z",
"iO|z",
&fileno,
&map_size,
&map_size_obj,
&tagname)
)
return NULL;
map_size = _GetMapSize(map_size_obj);
if (map_size < 0)
return NULL;
/* if an actual filename has been specified */
if (fileno != 0) {
fh = _get_osfhandle(fileno);
@ -784,7 +855,7 @@ new_mmap_object (PyObject * self, PyObject * args)
}
}
else {
m_obj->file_handle = (HFILE) 0xFFFFFFFF;
m_obj->file_handle = (INT_PTR) -1;
m_obj->size = map_size;
}