summaryrefslogtreecommitdiffstats
path: root/Modules/mmapmodule.c
diff options
context:
space:
mode:
authorAndrew M. Kuchling <amk@amk.ca>2000-06-18 04:45:14 (GMT)
committerAndrew M. Kuchling <amk@amk.ca>2000-06-18 04:45:14 (GMT)
commit70d2742fce9c971fffc2f0c25c93b7686da84f60 (patch)
tree42be5239910d9e10054107c51301b7af18f1a67d /Modules/mmapmodule.c
parent9bc5f3339ad175e4dedb312fa2c5faecbbb8bfee (diff)
downloadcpython-70d2742fce9c971fffc2f0c25c93b7686da84f60.zip
cpython-70d2742fce9c971fffc2f0c25c93b7686da84f60.tar.gz
cpython-70d2742fce9c971fffc2f0c25c93b7686da84f60.tar.bz2
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.
Diffstat (limited to 'Modules/mmapmodule.c')
-rw-r--r--Modules/mmapmodule.c139
1 files changed, 105 insertions, 34 deletions
diff --git a/Modules/mmapmodule.c b/Modules/mmapmodule.c
index 08ba085..03960fc 100644
--- a/Modules/mmapmodule.c
+++ b/Modules/mmapmodule.c
@@ -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;
}