summaryrefslogtreecommitdiffstats
path: root/Modules/mmapmodule.c
diff options
context:
space:
mode:
Diffstat (limited to 'Modules/mmapmodule.c')
-rw-r--r--Modules/mmapmodule.c325
1 files changed, 147 insertions, 178 deletions
diff --git a/Modules/mmapmodule.c b/Modules/mmapmodule.c
index 03685ce..33c143e 100644
--- a/Modules/mmapmodule.c
+++ b/Modules/mmapmodule.c
@@ -98,6 +98,7 @@ typedef struct {
#else
off_t offset;
#endif
+ int exports;
#ifdef MS_WINDOWS
HANDLE map_handle;
@@ -131,8 +132,6 @@ mmap_object_dealloc(mmap_object *m_obj)
if (m_obj->fd >= 0)
(void) close(m_obj->fd);
if (m_obj->data!=NULL) {
- if (m_obj->access != ACCESS_READ && m_obj->access != ACCESS_COPY)
- msync(m_obj->data, m_obj->size, MS_SYNC);
munmap(m_obj->data, m_obj->size);
}
#endif /* UNIX */
@@ -143,6 +142,11 @@ mmap_object_dealloc(mmap_object *m_obj)
static PyObject *
mmap_close_method(mmap_object *self, PyObject *unused)
{
+ if (self->exports > 0) {
+ PyErr_SetString(PyExc_BufferError, "cannot close "\
+ "exported pointers exist");
+ return NULL;
+ }
#ifdef MS_WINDOWS
/* For each resource we maintain, we need to check
the value is valid, and if so, free the resource
@@ -207,7 +211,7 @@ mmap_read_byte_method(mmap_object *self,
if (self->pos < self->size) {
char value = self->data[self->pos];
self->pos += 1;
- return Py_BuildValue("c", value);
+ return Py_BuildValue("B", (unsigned char)value);
} else {
PyErr_SetString(PyExc_ValueError, "read byte out of range");
return NULL;
@@ -231,7 +235,7 @@ mmap_read_line_method(mmap_object *self,
else
++eol; /* we're interested in the position after the
newline. */
- result = PyString_FromStringAndSize(start, (eol - start));
+ result = PyBytes_FromStringAndSize(start, (eol - start));
self->pos += (eol - start);
return result;
}
@@ -261,7 +265,7 @@ mmap_read_method(mmap_object *self,
if (num_bytes < 0 || num_bytes > n) {
num_bytes = n;
}
- result = Py_BuildValue("s#", self->data+self->pos, num_bytes);
+ result = PyBytes_FromStringAndSize(self->data+self->pos, num_bytes);
self->pos += num_bytes;
return result;
}
@@ -277,7 +281,7 @@ mmap_gfind(mmap_object *self,
Py_ssize_t len;
CHECK_VALID(NULL);
- if (!PyArg_ParseTuple(args, reverse ? "s#|nn:rfind" : "s#|nn:find",
+ if (!PyArg_ParseTuple(args, reverse ? "y#|nn:rfind" : "y#|nn:find",
&needle, &len, &start, &end)) {
return NULL;
} else {
@@ -307,10 +311,10 @@ mmap_gfind(mmap_object *self,
for (i = 0; i < len && needle[i] == p[i]; ++i)
/* nothing */;
if (i == len) {
- return PyInt_FromSsize_t(p - self->data);
+ return PyLong_FromSsize_t(p - self->data);
}
}
- return PyInt_FromLong(-1);
+ return PyLong_FromLong(-1);
}
}
@@ -329,7 +333,7 @@ mmap_rfind_method(mmap_object *self,
}
static int
-is_writeable(mmap_object *self)
+is_writable(mmap_object *self)
{
if (self->access != ACCESS_READ)
return 1;
@@ -340,6 +344,11 @@ is_writeable(mmap_object *self)
static int
is_resizeable(mmap_object *self)
{
+ if (self->exports > 0) {
+ PyErr_SetString(PyExc_BufferError,
+ "mmap can't resize with extant buffers exported.");
+ return 0;
+ }
if ((self->access == ACCESS_WRITE) || (self->access == ACCESS_DEFAULT))
return 1;
PyErr_Format(PyExc_TypeError,
@@ -356,10 +365,10 @@ mmap_write_method(mmap_object *self,
char *data;
CHECK_VALID(NULL);
- if (!PyArg_ParseTuple(args, "s#:write", &data, &length))
+ if (!PyArg_ParseTuple(args, "y#:write", &data, &length))
return(NULL);
- if (!is_writeable(self))
+ if (!is_writable(self))
return NULL;
if ((self->pos + length) > self->size) {
@@ -379,10 +388,10 @@ mmap_write_byte_method(mmap_object *self,
char value;
CHECK_VALID(NULL);
- if (!PyArg_ParseTuple(args, "c:write_byte", &value))
+ if (!PyArg_ParseTuple(args, "b:write_byte", &value))
return(NULL);
- if (!is_writeable(self))
+ if (!is_writable(self))
return NULL;
if (self->pos < self->size) {
@@ -416,11 +425,11 @@ mmap_size_method(mmap_object *self,
return PyErr_SetFromWindowsErr(error);
}
if (!high && low < LONG_MAX)
- return PyInt_FromLong((long)low);
+ return PyLong_FromLong((long)low);
size = (((PY_LONG_LONG)high)<<32) + low;
return PyLong_FromLongLong(size);
} else {
- return PyInt_FromSsize_t(self->size);
+ return PyLong_FromSsize_t(self->size);
}
#endif /* MS_WINDOWS */
@@ -434,7 +443,7 @@ mmap_size_method(mmap_object *self,
#ifdef HAVE_LARGEFILE_SUPPORT
return PyLong_FromLongLong(buf.st_size);
#else
- return PyInt_FromLong(buf.st_size);
+ return PyLong_FromLong(buf.st_size);
#endif
}
#endif /* UNIX */
@@ -549,7 +558,7 @@ static PyObject *
mmap_tell_method(mmap_object *self, PyObject *unused)
{
CHECK_VALID(NULL);
- return PyInt_FromSize_t(self->pos);
+ return PyLong_FromSize_t(self->pos);
}
static PyObject *
@@ -569,7 +578,7 @@ mmap_flush_method(mmap_object *self, PyObject *args)
return PyLong_FromLong(0);
#ifdef MS_WINDOWS
- return PyInt_FromLong((long) FlushViewOfFile(self->data+offset, size));
+ return PyLong_FromLong((long) FlushViewOfFile(self->data+offset, size));
#elif defined(UNIX)
/* XXX semantics of return value? */
/* XXX flags for msync? */
@@ -577,7 +586,7 @@ mmap_flush_method(mmap_object *self, PyObject *args)
PyErr_SetFromErrno(mmap_module_error);
return NULL;
}
- return PyInt_FromLong(0);
+ return PyLong_FromLong(0);
#else
PyErr_SetString(PyExc_ValueError, "flush not supported on this system");
return NULL;
@@ -632,7 +641,7 @@ mmap_move_method(mmap_object *self, PyObject *args)
unsigned long dest, src, cnt;
CHECK_VALID(NULL);
if (!PyArg_ParseTuple(args, "kkk:move", &dest, &src, &cnt) ||
- !is_writeable(self)) {
+ !is_writable(self)) {
return NULL;
} else {
/* bounds check the values */
@@ -649,6 +658,31 @@ mmap_move_method(mmap_object *self, PyObject *args)
}
}
+static PyObject *
+mmap_closed_get(mmap_object *self)
+{
+#ifdef MS_WINDOWS
+ return PyBool_FromLong(self->map_handle == NULL ? 1 : 0);
+#elif defined(UNIX)
+ return PyBool_FromLong(self->data == NULL ? 1 : 0);
+#endif
+}
+
+static PyObject *
+mmap__enter__method(mmap_object *self, PyObject *args)
+{
+ CHECK_VALID(NULL);
+
+ Py_INCREF(self);
+ return (PyObject *)self;
+}
+
+static PyObject *
+mmap__exit__method(PyObject *self, PyObject *args)
+{
+ return PyObject_CallMethod(self, "close", NULL);
+}
+
static struct PyMethodDef mmap_object_methods[] = {
{"close", (PyCFunction) mmap_close_method, METH_NOARGS},
{"find", (PyCFunction) mmap_find_method, METH_VARARGS},
@@ -664,58 +698,34 @@ static struct PyMethodDef mmap_object_methods[] = {
{"tell", (PyCFunction) mmap_tell_method, METH_NOARGS},
{"write", (PyCFunction) mmap_write_method, METH_VARARGS},
{"write_byte", (PyCFunction) mmap_write_byte_method, METH_VARARGS},
+ {"__enter__", (PyCFunction) mmap__enter__method, METH_NOARGS},
+ {"__exit__", (PyCFunction) mmap__exit__method, METH_VARARGS},
{NULL, NULL} /* sentinel */
};
-/* Functions for treating an mmap'ed file as a buffer */
+static PyGetSetDef mmap_object_getset[] = {
+ {"closed", (getter) mmap_closed_get, NULL, NULL},
+ {NULL}
+};
-static Py_ssize_t
-mmap_buffer_getreadbuf(mmap_object *self, Py_ssize_t index, const void **ptr)
-{
- CHECK_VALID(-1);
- if (index != 0) {
- PyErr_SetString(PyExc_SystemError,
- "Accessing non-existent mmap segment");
- return -1;
- }
- *ptr = self->data;
- return self->size;
-}
-static Py_ssize_t
-mmap_buffer_getwritebuf(mmap_object *self, Py_ssize_t index, const void **ptr)
+/* Functions for treating an mmap'ed file as a buffer */
+
+static int
+mmap_buffer_getbuf(mmap_object *self, Py_buffer *view, int flags)
{
CHECK_VALID(-1);
- if (index != 0) {
- PyErr_SetString(PyExc_SystemError,
- "Accessing non-existent mmap segment");
- return -1;
- }
- if (!is_writeable(self))
+ if (PyBuffer_FillInfo(view, (PyObject*)self, self->data, self->size,
+ (self->access == ACCESS_READ), flags) < 0)
return -1;
- *ptr = self->data;
- return self->size;
+ self->exports++;
+ return 0;
}
-static Py_ssize_t
-mmap_buffer_getsegcount(mmap_object *self, Py_ssize_t *lenp)
+static void
+mmap_buffer_releasebuf(mmap_object *self, Py_buffer *view)
{
- CHECK_VALID(-1);
- if (lenp)
- *lenp = self->size;
- return 1;
-}
-
-static Py_ssize_t
-mmap_buffer_getcharbuffer(mmap_object *self, Py_ssize_t index, const void **ptr)
-{
- if (index != 0) {
- PyErr_SetString(PyExc_SystemError,
- "accessing non-existent buffer segment");
- return -1;
- }
- *ptr = (const char *)self->data;
- return self->size;
+ self->exports--;
}
static Py_ssize_t
@@ -733,25 +743,7 @@ mmap_item(mmap_object *self, Py_ssize_t i)
PyErr_SetString(PyExc_IndexError, "mmap index out of range");
return NULL;
}
- return PyString_FromStringAndSize(self->data + i, 1);
-}
-
-static PyObject *
-mmap_slice(mmap_object *self, Py_ssize_t ilow, Py_ssize_t ihigh)
-{
- CHECK_VALID(NULL);
- if (ilow < 0)
- ilow = 0;
- else if ((size_t)ilow > self->size)
- ilow = self->size;
- if (ihigh < 0)
- ihigh = 0;
- if (ihigh < ilow)
- ihigh = ilow;
- else if ((size_t)ihigh > self->size)
- ihigh = self->size;
-
- return PyString_FromStringAndSize(self->data + ilow, ihigh-ilow);
+ return PyBytes_FromStringAndSize(self->data + i, 1);
}
static PyObject *
@@ -769,20 +761,20 @@ mmap_subscript(mmap_object *self, PyObject *item)
"mmap index out of range");
return NULL;
}
- return PyString_FromStringAndSize(self->data + i, 1);
+ return PyLong_FromLong(Py_CHARMASK(self->data[i]));
}
else if (PySlice_Check(item)) {
Py_ssize_t start, stop, step, slicelen;
- if (PySlice_GetIndicesEx((PySliceObject *)item, self->size,
+ if (PySlice_GetIndicesEx(item, self->size,
&start, &stop, &step, &slicelen) < 0) {
return NULL;
}
if (slicelen <= 0)
- return PyString_FromStringAndSize("", 0);
+ return PyBytes_FromStringAndSize("", 0);
else if (step == 1)
- return PyString_FromStringAndSize(self->data + start,
+ return PyBytes_FromStringAndSize(self->data + start,
slicelen);
else {
char *result_buf = (char *)PyMem_Malloc(slicelen);
@@ -795,7 +787,7 @@ mmap_subscript(mmap_object *self, PyObject *item)
cur += step, i++) {
result_buf[i] = self->data[cur];
}
- result = PyString_FromStringAndSize(result_buf,
+ result = PyBytes_FromStringAndSize(result_buf,
slicelen);
PyMem_Free(result_buf);
return result;
@@ -827,45 +819,6 @@ mmap_repeat(mmap_object *self, Py_ssize_t n)
}
static int
-mmap_ass_slice(mmap_object *self, Py_ssize_t ilow, Py_ssize_t ihigh, PyObject *v)
-{
- const char *buf;
-
- CHECK_VALID(-1);
- if (ilow < 0)
- ilow = 0;
- else if ((size_t)ilow > self->size)
- ilow = self->size;
- if (ihigh < 0)
- ihigh = 0;
- if (ihigh < ilow)
- ihigh = ilow;
- else if ((size_t)ihigh > self->size)
- ihigh = self->size;
-
- if (v == NULL) {
- PyErr_SetString(PyExc_TypeError,
- "mmap object doesn't support slice deletion");
- return -1;
- }
- if (! (PyString_Check(v)) ) {
- PyErr_SetString(PyExc_IndexError,
- "mmap slice assignment must be a string");
- return -1;
- }
- if (PyString_Size(v) != (ihigh - ilow)) {
- PyErr_SetString(PyExc_IndexError,
- "mmap slice assignment is wrong size");
- return -1;
- }
- if (!is_writeable(self))
- return -1;
- buf = PyString_AsString(v);
- memcpy(self->data + ilow, buf, ihigh-ilow);
- return 0;
-}
-
-static int
mmap_ass_item(mmap_object *self, Py_ssize_t i, PyObject *v)
{
const char *buf;
@@ -880,14 +833,14 @@ mmap_ass_item(mmap_object *self, Py_ssize_t i, PyObject *v)
"mmap object doesn't support item deletion");
return -1;
}
- if (! (PyString_Check(v) && PyString_Size(v)==1) ) {
+ if (! (PyBytes_Check(v) && PyBytes_Size(v)==1) ) {
PyErr_SetString(PyExc_IndexError,
- "mmap assignment must be single-character string");
+ "mmap assignment must be length-1 bytes()");
return -1;
}
- if (!is_writeable(self))
+ if (!is_writable(self))
return -1;
- buf = PyString_AsString(v);
+ buf = PyBytes_AsString(v);
self->data[i] = buf[0];
return 0;
}
@@ -897,9 +850,12 @@ mmap_ass_subscript(mmap_object *self, PyObject *item, PyObject *value)
{
CHECK_VALID(-1);
+ if (!is_writable(self))
+ return -1;
+
if (PyIndex_Check(item)) {
Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
- const char *buf;
+ Py_ssize_t v;
if (i == -1 && PyErr_Occurred())
return -1;
@@ -907,29 +863,36 @@ mmap_ass_subscript(mmap_object *self, PyObject *item, PyObject *value)
i += self->size;
if (i < 0 || (size_t)i >= self->size) {
PyErr_SetString(PyExc_IndexError,
- "mmap index out of range");
+ "mmap index out of range");
return -1;
}
if (value == NULL) {
PyErr_SetString(PyExc_TypeError,
- "mmap object doesn't support item deletion");
+ "mmap doesn't support item deletion");
return -1;
}
- if (!PyString_Check(value) || PyString_Size(value) != 1) {
- PyErr_SetString(PyExc_IndexError,
- "mmap assignment must be single-character string");
+ if (!PyIndex_Check(value)) {
+ PyErr_SetString(PyExc_TypeError,
+ "mmap item value must be an int");
return -1;
}
- if (!is_writeable(self))
+ v = PyNumber_AsSsize_t(value, PyExc_TypeError);
+ if (v == -1 && PyErr_Occurred())
return -1;
- buf = PyString_AsString(value);
- self->data[i] = buf[0];
+ if (v < 0 || v > 255) {
+ PyErr_SetString(PyExc_ValueError,
+ "mmap item value must be "
+ "in range(0, 256)");
+ return -1;
+ }
+ self->data[i] = (char) v;
return 0;
}
else if (PySlice_Check(item)) {
Py_ssize_t start, stop, step, slicelen;
+ Py_buffer vbuf;
- if (PySlice_GetIndicesEx((PySliceObject *)item,
+ if (PySlice_GetIndicesEx(item,
self->size, &start, &stop,
&step, &slicelen) < 0) {
return -1;
@@ -939,41 +902,32 @@ mmap_ass_subscript(mmap_object *self, PyObject *item, PyObject *value)
"mmap object doesn't support slice deletion");
return -1;
}
- if (!PyString_Check(value)) {
- PyErr_SetString(PyExc_IndexError,
- "mmap slice assignment must be a string");
+ if (PyObject_GetBuffer(value, &vbuf, PyBUF_SIMPLE) < 0)
return -1;
- }
- if (PyString_Size(value) != slicelen) {
+ if (vbuf.len != slicelen) {
PyErr_SetString(PyExc_IndexError,
"mmap slice assignment is wrong size");
+ PyBuffer_Release(&vbuf);
return -1;
}
- if (!is_writeable(self))
- return -1;
- if (slicelen == 0)
- return 0;
+ if (slicelen == 0) {
+ }
else if (step == 1) {
- const char *buf = PyString_AsString(value);
-
- if (buf == NULL)
- return -1;
- memcpy(self->data + start, buf, slicelen);
- return 0;
+ memcpy(self->data + start, vbuf.buf, slicelen);
}
else {
Py_ssize_t cur, i;
- const char *buf = PyString_AsString(value);
- if (buf == NULL)
- return -1;
- for (cur = start, i = 0; i < slicelen;
- cur += step, i++) {
- self->data[cur] = buf[i];
+ for (cur = start, i = 0;
+ i < slicelen;
+ cur += step, i++)
+ {
+ self->data[cur] = ((char *)vbuf.buf)[i];
}
- return 0;
}
+ PyBuffer_Release(&vbuf);
+ return 0;
}
else {
PyErr_SetString(PyExc_TypeError,
@@ -987,9 +941,9 @@ static PySequenceMethods mmap_as_sequence = {
(binaryfunc)mmap_concat, /*sq_concat*/
(ssizeargfunc)mmap_repeat, /*sq_repeat*/
(ssizeargfunc)mmap_item, /*sq_item*/
- (ssizessizeargfunc)mmap_slice, /*sq_slice*/
+ 0, /*sq_slice*/
(ssizeobjargproc)mmap_ass_item, /*sq_ass_item*/
- (ssizessizeobjargproc)mmap_ass_slice, /*sq_ass_slice*/
+ 0, /*sq_ass_slice*/
};
static PyMappingMethods mmap_as_mapping = {
@@ -999,10 +953,8 @@ static PyMappingMethods mmap_as_mapping = {
};
static PyBufferProcs mmap_as_buffer = {
- (readbufferproc)mmap_buffer_getreadbuf,
- (writebufferproc)mmap_buffer_getwritebuf,
- (segcountproc)mmap_buffer_getsegcount,
- (charbufferproc)mmap_buffer_getcharbuffer,
+ (getbufferproc)mmap_buffer_getbuf,
+ (releasebufferproc)mmap_buffer_releasebuf,
};
static PyObject *
@@ -1042,7 +994,7 @@ static PyTypeObject mmap_object_type = {
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
- 0, /* tp_compare */
+ 0, /* tp_reserved */
0, /* tp_repr */
0, /* tp_as_number */
&mmap_as_sequence, /*tp_as_sequence*/
@@ -1053,7 +1005,7 @@ static PyTypeObject mmap_object_type = {
PyObject_GenericGetAttr, /*tp_getattro*/
0, /*tp_setattro*/
&mmap_as_buffer, /*tp_as_buffer*/
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GETCHARBUFFER, /*tp_flags*/
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
mmap_doc, /*tp_doc*/
0, /* tp_traverse */
0, /* tp_clear */
@@ -1063,7 +1015,7 @@ static PyTypeObject mmap_object_type = {
0, /* tp_iternext */
mmap_object_methods, /* tp_methods */
0, /* tp_members */
- 0, /* tp_getset */
+ mmap_object_getset, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
@@ -1218,6 +1170,7 @@ new_mmap_object(PyTypeObject *type, PyObject *args, PyObject *kwdict)
m_obj->data = NULL;
m_obj->size = (size_t) map_size;
m_obj->pos = (size_t) 0;
+ m_obj->exports = 0;
m_obj->offset = offset;
if (fd == -1) {
m_obj->fd = -1;
@@ -1331,8 +1284,9 @@ new_mmap_object(PyTypeObject *type, PyObject *args, PyObject *kwdict)
XXX: fileno == 0 is a valid fd, but was accepted prior to 2.5.
XXX: Should this code be added?
if (fileno == 0)
- PyErr_Warn(PyExc_DeprecationWarning,
- "don't use 0 for anonymous memory");
+ PyErr_WarnEx(PyExc_DeprecationWarning,
+ "don't use 0 for anonymous memory",
+ 1);
*/
if (fileno != -1 && fileno != 0) {
/* Ensure that fileno is within the CRT's valid range */
@@ -1418,6 +1372,7 @@ new_mmap_object(PyTypeObject *type, PyObject *args, PyObject *kwdict)
/* set the initial position */
m_obj->pos = (size_t) 0;
+ m_obj->exports = 0;
/* set the tag name */
if (tagname != NULL && *tagname != '\0') {
m_obj->tagname = PyMem_Malloc(strlen(tagname)+1);
@@ -1468,30 +1423,43 @@ new_mmap_object(PyTypeObject *type, PyObject *args, PyObject *kwdict)
static void
setint(PyObject *d, const char *name, long value)
{
- PyObject *o = PyInt_FromLong(value);
+ PyObject *o = PyLong_FromLong(value);
if (o && PyDict_SetItemString(d, name, o) == 0) {
Py_DECREF(o);
}
}
+
+static struct PyModuleDef mmapmodule = {
+ PyModuleDef_HEAD_INIT,
+ "mmap",
+ NULL,
+ -1,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
PyMODINIT_FUNC
-initmmap(void)
+PyInit_mmap(void)
{
PyObject *dict, *module;
if (PyType_Ready(&mmap_object_type) < 0)
- return;
+ return NULL;
- module = Py_InitModule("mmap", NULL);
+ module = PyModule_Create(&mmapmodule);
if (module == NULL)
- return;
+ return NULL;
dict = PyModule_GetDict(module);
if (!dict)
- return;
+ return NULL;
mmap_module_error = PyErr_NewException("mmap.error",
PyExc_EnvironmentError , NULL);
if (mmap_module_error == NULL)
- return;
+ return NULL;
PyDict_SetItemString(dict, "error", mmap_module_error);
PyDict_SetItemString(dict, "mmap", (PyObject*) &mmap_object_type);
#ifdef PROT_EXEC
@@ -1528,4 +1496,5 @@ initmmap(void)
setint(dict, "ACCESS_READ", ACCESS_READ);
setint(dict, "ACCESS_WRITE", ACCESS_WRITE);
setint(dict, "ACCESS_COPY", ACCESS_COPY);
+ return module;
}