[Python-checkins] CVS: python/dist/src/Modules mmapmodule.c,2.33,2.34
Tim Peters
tim_one@users.sourceforge.net
Tue, 13 Nov 2001 15:11:21 -0800
Update of /cvsroot/python/python/dist/src/Modules
In directory usw-pr-cvs1:/tmp/cvs-serv31339/python/Modules
Modified Files:
mmapmodule.c
Log Message:
CVS patch #477161: New "access" keyword for mmap, from Jay T Miller.
This gives mmap() on Windows the ability to create read-only, write-
through and copy-on-write mmaps. A new keyword argument is introduced
because the mmap() signatures diverged between Windows and Unix, so
while they (now) both support this functionality, there wasn't a way to
spell it in a common way without introducing a new spelling gimmick.
The old spellings are still accepted, so there isn't a backward-
compatibility issue here.
Index: mmapmodule.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Modules/mmapmodule.c,v
retrieving revision 2.33
retrieving revision 2.34
diff -C2 -d -r2.33 -r2.34
*** mmapmodule.c 2001/11/05 21:22:41 2.33
--- mmapmodule.c 2001/11/13 23:11:19 2.34
***************
*** 30,36 ****
my_getpagesize(void)
{
! SYSTEM_INFO si;
! GetSystemInfo(&si);
! return si.dwPageSize;
}
#endif
--- 30,36 ----
my_getpagesize(void)
{
! SYSTEM_INFO si;
! GetSystemInfo(&si);
! return si.dwPageSize;
}
#endif
***************
*** 50,54 ****
my_getpagesize(void)
{
! return sysconf(_SC_PAGESIZE);
}
#else
--- 50,54 ----
my_getpagesize(void)
{
! return sysconf(_SC_PAGESIZE);
}
#else
***************
*** 63,66 ****
--- 63,74 ----
static PyObject *mmap_module_error;
+ typedef enum
+ {
+ ACCESS_DEFAULT,
+ ACCESS_READ,
+ ACCESS_WRITE,
+ ACCESS_COPY
+ } access_mode;
+
typedef struct {
PyObject_HEAD
***************
*** 78,83 ****
--- 86,94 ----
int fd;
#endif
+
+ access_mode access;
} mmap_object;
+
static void
mmap_object_dealloc(mmap_object *m_obj)
***************
*** 179,183 ****
static PyObject *
mmap_read_line_method(mmap_object *self,
! PyObject *args)
{
char *start = self->data+self->pos;
--- 190,194 ----
static PyObject *
mmap_read_line_method(mmap_object *self,
! PyObject *args)
{
char *start = self->data+self->pos;
***************
*** 237,245 ****
if (start < 0)
! start += self->size;
if (start < 0)
! start = 0;
else if ((size_t)start > self->size)
! start = self->size;
p = self->data + start;
--- 248,256 ----
if (start < 0)
! start += self->size;
if (start < 0)
! start = 0;
else if ((size_t)start > self->size)
! start = self->size;
p = self->data + start;
***************
*** 261,264 ****
--- 272,295 ----
}
+ static int
+ is_writeable(mmap_object *self)
+ {
+ if (self->access != ACCESS_READ)
+ return 1;
+ PyErr_Format(PyExc_TypeError, "mmap can't modify a readonly memory map.");
+ return 0;
+ }
+
+ static int
+ is_resizeable(mmap_object *self)
+ {
+ if ((self->access == ACCESS_WRITE) || (self->access == ACCESS_DEFAULT))
+ return 1;
+ PyErr_Format(PyExc_TypeError,
+ "mmap can't resize a readonly or copy-on-write memory map.");
+ return 0;
+ }
+
+
static PyObject *
mmap_write_method(mmap_object *self,
***************
*** 272,275 ****
--- 303,309 ----
return(NULL);
+ if (!is_writeable(self))
+ return NULL;
+
if ((self->pos + length) > self->size) {
PyErr_SetString (PyExc_ValueError, "data out of range");
***************
*** 292,295 ****
--- 326,331 ----
return(NULL);
+ if (!is_writeable(self))
+ return NULL;
*(self->data+self->pos) = value;
self->pos += 1;
***************
*** 297,301 ****
return (Py_None);
}
!
static PyObject *
mmap_size_method(mmap_object *self,
--- 333,337 ----
return (Py_None);
}
!
static PyObject *
mmap_size_method(mmap_object *self,
***************
*** 343,347 ****
unsigned long new_size;
CHECK_VALID(NULL);
! if (!PyArg_ParseTuple (args, "l:resize", &new_size)) {
return NULL;
#ifdef MS_WIN32
--- 379,384 ----
unsigned long new_size;
CHECK_VALID(NULL);
! if (!PyArg_ParseTuple (args, "l:resize", &new_size) ||
! !is_resizeable(self)) {
return NULL;
#ifdef MS_WIN32
***************
*** 387,415 ****
#ifdef UNIX
#ifndef HAVE_MREMAP
! } else {
! PyErr_SetString(PyExc_SystemError,
! "mmap: resizing not available--no mremap()");
! return NULL;
#else
! } else {
! void *newmap;
#ifdef MREMAP_MAYMOVE
! newmap = mremap(self->data, self->size, new_size, MREMAP_MAYMOVE);
#else
! newmap = mremap(self->data, self->size, new_size, 0);
#endif
! if (newmap == (void *)-1)
! {
! PyErr_SetFromErrno(mmap_module_error);
! return NULL;
! }
! self->data = newmap;
! self->size = new_size;
! Py_INCREF(Py_None);
! return Py_None;
#endif /* HAVE_MREMAP */
#endif /* UNIX */
! }
}
--- 424,452 ----
#ifdef UNIX
#ifndef HAVE_MREMAP
! } else {
! PyErr_SetString(PyExc_SystemError,
! "mmap: resizing not available--no mremap()");
! return NULL;
#else
! } else {
! void *newmap;
#ifdef MREMAP_MAYMOVE
! newmap = mremap(self->data, self->size, new_size, MREMAP_MAYMOVE);
#else
! newmap = mremap(self->data, self->size, new_size, 0);
#endif
! if (newmap == (void *)-1)
! {
! PyErr_SetFromErrno(mmap_module_error);
! return NULL;
! }
! self->data = newmap;
! self->size = new_size;
! Py_INCREF(Py_None);
! return Py_None;
#endif /* HAVE_MREMAP */
#endif /* UNIX */
! }
}
***************
*** 492,496 ****
}
! onoutofrange:
PyErr_SetString (PyExc_ValueError, "seek out of range");
return NULL;
--- 529,533 ----
}
! onoutofrange:
PyErr_SetString (PyExc_ValueError, "seek out of range");
return NULL;
***************
*** 502,506 ****
unsigned long dest, src, count;
CHECK_VALID(NULL);
! if (!PyArg_ParseTuple (args, "iii:move", &dest, &src, &count)) {
return NULL;
} else {
--- 539,544 ----
unsigned long dest, src, count;
CHECK_VALID(NULL);
! if (!PyArg_ParseTuple (args, "iii:move", &dest, &src, &count) ||
! !is_writeable(self)) {
return NULL;
} else {
***************
*** 562,565 ****
--- 600,605 ----
return -1;
}
+ if (!is_writeable(self))
+ return -1;
*ptr = self->data;
return self->size;
***************
*** 666,670 ****
if (v == NULL) {
PyErr_SetString(PyExc_TypeError,
! "mmap object doesn't support slice deletion");
return -1;
}
--- 706,710 ----
if (v == NULL) {
PyErr_SetString(PyExc_TypeError,
! "mmap object doesn't support slice deletion");
return -1;
}
***************
*** 679,682 ****
--- 719,724 ----
return -1;
}
+ if (!is_writeable(self))
+ return -1;
buf = PyString_AsString(v);
memcpy(self->data + ilow, buf, ihigh-ilow);
***************
*** 696,707 ****
if (v == NULL) {
PyErr_SetString(PyExc_TypeError,
! "mmap object doesn't support item deletion");
return -1;
}
if (! (PyString_Check(v) && PyString_Size(v)==1) ) {
PyErr_SetString(PyExc_IndexError,
! "mmap assignment must be single-character string");
return -1;
}
buf = PyString_AsString(v);
self->data[i] = buf[0];
--- 738,751 ----
if (v == NULL) {
PyErr_SetString(PyExc_TypeError,
! "mmap object doesn't support item deletion");
return -1;
}
if (! (PyString_Check(v) && PyString_Size(v)==1) ) {
PyErr_SetString(PyExc_IndexError,
! "mmap assignment must be single-character string");
return -1;
}
+ if (!is_writeable(self))
+ return -1;
buf = PyString_AsString(v);
self->data[i] = buf[0];
***************
*** 793,808 ****
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;
}
--- 837,852 ----
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;
}
***************
*** 816,829 ****
int map_size;
int fd, flags = MAP_SHARED, prot = PROT_WRITE | PROT_READ;
! char *keywords[] = {"file", "size", "flags", "prot", NULL};
! if (!PyArg_ParseTupleAndKeywords(args, kwdict,
! "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);
--- 860,899 ----
int map_size;
int fd, flags = MAP_SHARED, prot = PROT_WRITE | PROT_READ;
! access_mode access = ACCESS_DEFAULT;
! char *keywords[] = {"fileno", "length",
! "flags", "prot",
! "access", NULL};
! if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iO|iii", keywords,
! &fd, &map_size_obj, &flags, &prot, &access))
return NULL;
map_size = _GetMapSize(map_size_obj);
if (map_size < 0)
return NULL;
+
+ if ((access != ACCESS_DEFAULT) &&
+ ((flags != MAP_SHARED) || ( prot != (PROT_WRITE | PROT_READ))))
+ return PyErr_Format(PyExc_ValueError,
+ "mmap can't specify both access and flags, prot.");
+ switch(access) {
+ case ACCESS_READ:
+ flags = MAP_SHARED;
+ prot = PROT_READ;
+ break;
+ case ACCESS_WRITE:
+ flags = MAP_SHARED;
+ prot = PROT_READ | PROT_WRITE;
+ break;
+ case ACCESS_COPY:
+ flags = MAP_PRIVATE;
+ prot = PROT_READ | PROT_WRITE;
+ break;
+ case ACCESS_DEFAULT:
+ /* use the specified or default values of flags and prot */
+ break;
+ default:
+ return PyErr_Format(PyExc_ValueError,
+ "mmap invalid access parameter.");
+ }
m_obj = PyObject_New (mmap_object, &mmap_object_type);
***************
*** 835,844 ****
prot, flags,
fd, 0);
! if (m_obj->data == (char *)-1)
! {
Py_DECREF(m_obj);
PyErr_SetFromErrno(mmap_module_error);
return NULL;
}
return (PyObject *)m_obj;
}
--- 905,914 ----
prot, flags,
fd, 0);
! if (m_obj->data == (char *)-1) {
Py_DECREF(m_obj);
PyErr_SetFromErrno(mmap_module_error);
return NULL;
}
+ m_obj->access = access;
return (PyObject *)m_obj;
}
***************
*** 847,851 ****
#ifdef MS_WIN32
static PyObject *
! new_mmap_object(PyObject *self, PyObject *args)
{
mmap_object *m_obj;
--- 917,921 ----
#ifdef MS_WIN32
static PyObject *
! new_mmap_object(PyObject *self, PyObject *args, PyObject *kwdict)
{
mmap_object *m_obj;
***************
*** 853,869 ****
int map_size;
char *tagname = "";
-
DWORD dwErr = 0;
int fileno;
HANDLE fh = 0;
! if (!PyArg_ParseTuple(args,
! "iO|z",
! &fileno,
! &map_size_obj,
! &tagname)
! )
return NULL;
!
map_size = _GetMapSize(map_size_obj);
if (map_size < 0)
--- 923,959 ----
int map_size;
char *tagname = "";
DWORD dwErr = 0;
int fileno;
HANDLE fh = 0;
+ access_mode access = ACCESS_DEFAULT;
+ DWORD flProtect, dwDesiredAccess;
+ char *keywords[] = { "fileno", "length",
+ "tagname",
+ "access", NULL };
! if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iO|zi", keywords,
! &fileno, &map_size_obj,
! &tagname, &access)) {
return NULL;
! }
!
! switch(access) {
! case ACCESS_READ:
! flProtect = PAGE_READONLY;
! dwDesiredAccess = FILE_MAP_READ;
! break;
! case ACCESS_DEFAULT: case ACCESS_WRITE:
! flProtect = PAGE_READWRITE;
! dwDesiredAccess = FILE_MAP_WRITE;
! break;
! case ACCESS_COPY:
! flProtect = PAGE_WRITECOPY;
! dwDesiredAccess = FILE_MAP_COPY;
! break;
! default:
! return PyErr_Format(PyExc_ValueError,
! "mmap invalid access parameter.");
! }
!
map_size = _GetMapSize(map_size_obj);
if (map_size < 0)
***************
*** 874,879 ****
fh = (HANDLE)_get_osfhandle(fileno);
if (fh==(HANDLE)-1) {
! PyErr_SetFromErrno(mmap_module_error);
! return NULL;
}
/* Win9x appears to need us seeked to zero */
--- 964,969 ----
fh = (HANDLE)_get_osfhandle(fileno);
if (fh==(HANDLE)-1) {
! PyErr_SetFromErrno(mmap_module_error);
! return NULL;
}
/* Win9x appears to need us seeked to zero */
***************
*** 895,905 ****
Python code can close it on us */
if (!DuplicateHandle(
! GetCurrentProcess(), /* source process handle */
! fh, /* handle to be duplicated */
! GetCurrentProcess(), /* target proc handle */
! (LPHANDLE)&m_obj->file_handle, /* result */
! 0, /* access - ignored due to options value */
! FALSE, /* inherited by child processes? */
! DUPLICATE_SAME_ACCESS)) { /* options */
dwErr = GetLastError();
Py_DECREF(m_obj);
--- 985,995 ----
Python code can close it on us */
if (!DuplicateHandle(
! GetCurrentProcess(), /* source process handle */
! fh, /* handle to be duplicated */
! GetCurrentProcess(), /* target proc handle */
! (LPHANDLE)&m_obj->file_handle, /* result */
! 0, /* access - ignored due to options value */
! FALSE, /* inherited by child processes? */
! DUPLICATE_SAME_ACCESS)) { /* options */
dwErr = GetLastError();
Py_DECREF(m_obj);
***************
*** 933,939 ****
m_obj->tagname = NULL;
m_obj->map_handle = CreateFileMapping (m_obj->file_handle,
NULL,
! PAGE_READWRITE,
0,
m_obj->size,
--- 1023,1030 ----
m_obj->tagname = NULL;
+ m_obj->access = access;
m_obj->map_handle = CreateFileMapping (m_obj->file_handle,
NULL,
! flProtect,
0,
m_obj->size,
***************
*** 941,945 ****
if (m_obj->map_handle != NULL) {
m_obj->data = (char *) MapViewOfFile (m_obj->map_handle,
! FILE_MAP_WRITE,
0,
0,
--- 1032,1036 ----
if (m_obj->map_handle != NULL) {
m_obj->data = (char *) MapViewOfFile (m_obj->map_handle,
! dwDesiredAccess,
0,
0,
***************
*** 948,952 ****
return ((PyObject *) m_obj);
} else {
! dwErr = GetLastError();
}
} else {
--- 1039,1043 ----
return ((PyObject *) m_obj);
} else {
! dwErr = GetLastError();
}
} else {
***************
*** 967,971 ****
DL_EXPORT(void)
! initmmap(void)
{
PyObject *dict, *module;
--- 1058,1062 ----
DL_EXPORT(void)
! initmmap(void)
{
PyObject *dict, *module;
***************
*** 1012,1015 ****
PyDict_SetItemString (dict, "PAGESIZE",
PyInt_FromLong( (long)my_getpagesize() ) );
- }
--- 1103,1112 ----
PyDict_SetItemString (dict, "PAGESIZE",
PyInt_FromLong( (long)my_getpagesize() ) );
+ PyDict_SetItemString (dict, "ACCESS_READ",
+ PyInt_FromLong(ACCESS_READ));
+ PyDict_SetItemString (dict, "ACCESS_WRITE",
+ PyInt_FromLong(ACCESS_WRITE));
+ PyDict_SetItemString (dict, "ACCESS_COPY",
+ PyInt_FromLong(ACCESS_COPY));
+ }