mirror of
https://github.com/python/cpython.git
synced 2025-10-28 17:13:08 +00:00
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:
parent
9bc5f3339a
commit
70d2742fce
1 changed files with 105 additions and 34 deletions
|
|
@ -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,
|
||||||
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,
|
||||||
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 *
|
||||||
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,
|
||||||
}
|
}
|
||||||
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,
|
||||||
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,40 +401,45 @@ 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");
|
onoutofrange:
|
||||||
|
PyErr_SetString (PyExc_ValueError, "seek out of range");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
mmap_move_method (mmap_object * self, PyObject * args)
|
mmap_move_method (mmap_object * self, PyObject * args)
|
||||||
|
|
@ -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 *
|
||||||
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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue