Index: Modules/mmapmodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Modules/mmapmodule.c,v retrieving revision 2.43 diff -c -r2.43 mmapmodule.c *** Modules/mmapmodule.c 7 Feb 2003 19:44:56 -0000 2.43 --- Modules/mmapmodule.c 23 Mar 2003 14:16:43 -0000 *************** *** 3,8 **** --- 3,11 ---- / Hacked for Unix by AMK / $Id: mmapmodule.c,v 2.43 2003/02/07 19:44:56 nnorwitz Exp $ + / Modified to support mmap with offset - to map a 'window' fo a file + / Author: Yotam Medini yotamm@mellanox.co.il + / / mmapmodule.cpp -- map a view of a file into memory / / todo: need permission flags, perhaps a 'chsize' analog *************** *** 73,79 **** PyObject_HEAD char * data; size_t size; ! size_t pos; #ifdef MS_WINDOWS HANDLE map_handle; --- 76,83 ---- PyObject_HEAD char * data; size_t size; ! size_t pos; /* relative to offset */ ! size_t offset; /* always 0 for MS_WINDOWS */ #ifdef MS_WINDOWS HANDLE map_handle; *************** *** 261,267 **** if (i == len) { return Py_BuildValue ( "l", ! (long) (p - self->data)); } } return Py_BuildValue ("l", (long) -1); --- 265,271 ---- if (i == len) { return Py_BuildValue ( "l", ! (long)(self->offset + (p - self->data))); } } return Py_BuildValue ("l", (long) -1); *************** *** 453,459 **** CHECK_VALID(NULL); if (!PyArg_ParseTuple(args, ":tell")) return NULL; ! return (Py_BuildValue ("l", (long) self->pos) ); } static PyObject * --- 457,463 ---- CHECK_VALID(NULL); if (!PyArg_ParseTuple(args, ":tell")) return NULL; ! return (Py_BuildValue ("l", (long) (self->offset + self->pos)) ); } static PyObject * *************** *** 499,504 **** --- 503,509 ---- size_t where; switch (how) { case 0: /* relative to start */ + dist -= self->offset; if (dist < 0) goto onoutofrange; where = dist; *************** *** 539,544 **** --- 544,551 ---- !is_writeable(self)) { return NULL; } else { + dest -= self->offset; + src -= self->offset; /* bounds check the values */ if (/* end of source after end of data?? */ ((src+count) > self->size) *************** *** 857,875 **** #endif mmap_object *m_obj; PyObject *map_size_obj = NULL; 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)))) --- 864,896 ---- #endif mmap_object *m_obj; PyObject *map_size_obj = NULL; + PyObject *map_offset_obj = NULL; int map_size; int fd, flags = MAP_SHARED, prot = PROT_WRITE | PROT_READ; access_mode access = ACCESS_DEFAULT; + off_t offset = 0; char *keywords[] = {"fileno", "length", "flags", "prot", ! "access", "offset", NULL}; ! if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iO|iiiO", keywords, ! &fd, &map_size_obj, &flags, &prot, ! &access, &map_offset_obj)) return NULL; map_size = _GetMapSize(map_size_obj); if (map_size < 0) return NULL; + if (map_offset_obj) + { + int tmp_offset = PyInt_AsLong(map_offset_obj); + if (tmp_offset < 0) { + if (!PyErr_Occurred()) + PyErr_SetString(PyExc_ValueError, + "offset must be a non-negative integer"); + return NULL; + } + offset = (off_t) tmp_offset; + } if ((access != ACCESS_DEFAULT) && ((flags != MAP_SHARED) || ( prot != (PROT_WRITE | PROT_READ)))) *************** *** 897,903 **** } #ifdef HAVE_FSTAT ! if (fstat(fd, &st) == 0 && (size_t)map_size > st.st_size) { PyErr_SetString(PyExc_ValueError, "mmap length is greater than file size"); return NULL; --- 918,927 ---- } #ifdef HAVE_FSTAT ! if (fstat(fd, &st) == 0 && ! !S_ISCHR(st.st_mode) && ! offset + (size_t)map_size > st.st_size) ! { PyErr_SetString(PyExc_ValueError, "mmap length is greater than file size"); return NULL; *************** *** 907,916 **** if (m_obj == NULL) {return NULL;} m_obj->size = (size_t) map_size; m_obj->pos = (size_t) 0; m_obj->fd = fd; m_obj->data = mmap(NULL, map_size, prot, flags, ! fd, 0); if (m_obj->data == (char *)-1) { Py_DECREF(m_obj); PyErr_SetFromErrno(mmap_module_error); --- 931,941 ---- if (m_obj == NULL) {return NULL;} m_obj->size = (size_t) map_size; m_obj->pos = (size_t) 0; + m_obj->offset = offset; m_obj->fd = fd; m_obj->data = mmap(NULL, map_size, prot, flags, ! fd, offset); if (m_obj->data == (char *)-1) { Py_DECREF(m_obj); PyErr_SetFromErrno(mmap_module_error); *************** *** 986,991 **** --- 1011,1017 ---- m_obj->file_handle = INVALID_HANDLE_VALUE; m_obj->map_handle = INVALID_HANDLE_VALUE; m_obj->tagname = NULL; + m_obj->offset = 0; if (fh) { /* It is necessary to duplicate the handle, so the Index: Lib/test/test_mmap.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/test_mmap.py,v retrieving revision 1.30 diff -c -r1.30 test_mmap.py *** Lib/test/test_mmap.py 13 Jan 2003 21:38:45 -0000 1.30 --- Lib/test/test_mmap.py 23 Mar 2003 14:16:44 -0000 *************** *** 267,272 **** --- 267,283 ---- else: verify(0, "Incompatible parameters should raise ValueError.") f.close() + + # Try invalid offset + f = open(TESTFN, "r+b") + for offset in [-2, -1, None]: + try: + m = mmap.mmap(f.fileno(), mapsize, offset=offset) + except (ValueError, TypeError): + pass + else: + verify(0, "Invalid offset should raise ValueError.") + f.close() finally: try: os.unlink(TESTFN) Index: Doc/lib/libmmap.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/libmmap.tex,v retrieving revision 1.8 diff -c -r1.8 libmmap.tex *** Doc/lib/libmmap.tex 3 Dec 2001 18:27:22 -0000 1.8 --- Doc/lib/libmmap.tex 23 Mar 2003 14:16:44 -0000 *************** *** 57,63 **** \end{funcdesc} \begin{funcdescni}{mmap}{fileno, length\optional{, flags\optional{, ! prot\optional{, access}}}} \strong{(\UNIX{} version)} Maps \var{length} bytes from the file specified by the file descriptor \var{fileno}, and returns a mmap object. --- 57,63 ---- \end{funcdesc} \begin{funcdescni}{mmap}{fileno, length\optional{, flags\optional{, ! prot\optional{, access\optional{, offset}}}} \strong{(\UNIX{} version)} Maps \var{length} bytes from the file specified by the file descriptor \var{fileno}, and returns a mmap object. *************** *** 78,83 **** --- 78,88 ---- as an optional keyword parameter. It is an error to specify both \var{flags}, \var{prot} and \var{access}. See the description of \var{access} above for information on how to use this parameter. + + \var{offset} may be specified as a non-negative integer offset. + mmap references will be relative to the offset from the beginning + of the file. + \versionchanged[The offset parameter was added]{2.3} \end{funcdescni}