2 / Author: Sam Rushing <rushing@nightmare.com>
3 / Hacked for Unix by AMK
6 / mmapmodule.cpp -- map a view of a file into memory
8 / todo: need permission flags, perhaps a 'chsize' analog
9 / not all functions check range yet!!!
12 / Note: This module currently only deals with 32-bit file
15 / This version of mmapmodule.c has been changed significantly
16 / from the original mmapfile.c on which it was based.
17 / The original version of mmapfile is maintained by Sam at
18 / ftp://squirl.nightmare.com/pub/python/python-ext.
42 #if defined(HAVE_SYSCONF) && defined(_SC_PAGESIZE)
46 return sysconf(_SC_PAGESIZE
);
49 #define my_getpagesize getpagesize
55 #include <sys/types.h>
57 /* maybe define MAP_ANON in terms of MAP_ANONYMOUS */
58 #if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)
59 # define MAP_ANONYMOUS MAP_ANON
62 static PyObject
*mmap_module_error
;
93 mmap_object_dealloc(mmap_object
*m_obj
)
96 if (m_obj
->data
!= NULL
)
97 UnmapViewOfFile (m_obj
->data
);
98 if (m_obj
->map_handle
!= INVALID_HANDLE_VALUE
)
99 CloseHandle (m_obj
->map_handle
);
100 if (m_obj
->file_handle
!= INVALID_HANDLE_VALUE
)
101 CloseHandle (m_obj
->file_handle
);
103 PyMem_Free(m_obj
->tagname
);
104 #endif /* MS_WINDOWS */
108 (void) close(m_obj
->fd
);
109 if (m_obj
->data
!=NULL
) {
110 msync(m_obj
->data
, m_obj
->size
, MS_SYNC
);
111 munmap(m_obj
->data
, m_obj
->size
);
119 mmap_close_method(mmap_object
*self
, PyObject
*args
)
121 if (!PyArg_ParseTuple(args
, ":close"))
124 /* For each resource we maintain, we need to check
125 the value is valid, and if so, free the resource
126 and set the member value to an invalid value so
127 the dealloc does not attempt to resource clearing
129 TODO - should we check for errors in the close operations???
131 if (self
->data
!= NULL
) {
132 UnmapViewOfFile (self
->data
);
135 if (self
->map_handle
!= INVALID_HANDLE_VALUE
) {
136 CloseHandle (self
->map_handle
);
137 self
->map_handle
= INVALID_HANDLE_VALUE
;
139 if (self
->file_handle
!= INVALID_HANDLE_VALUE
) {
140 CloseHandle (self
->file_handle
);
141 self
->file_handle
= INVALID_HANDLE_VALUE
;
143 #endif /* MS_WINDOWS */
146 (void) close(self
->fd
);
148 if (self
->data
!= NULL
) {
149 munmap(self
->data
, self
->size
);
159 #define CHECK_VALID(err) \
161 if (self->map_handle == INVALID_HANDLE_VALUE) { \
162 PyErr_SetString (PyExc_ValueError, "mmap closed or invalid"); \
166 #endif /* MS_WINDOWS */
169 #define CHECK_VALID(err) \
171 if (self->data == NULL) { \
172 PyErr_SetString (PyExc_ValueError, "mmap closed or invalid"); \
179 mmap_read_byte_method(mmap_object
*self
,
183 if (!PyArg_ParseTuple(args
, ":read_byte"))
185 if (self
->pos
< self
->size
) {
186 char value
= self
->data
[self
->pos
];
188 return Py_BuildValue("c", value
);
190 PyErr_SetString (PyExc_ValueError
, "read byte out of range");
196 mmap_read_line_method(mmap_object
*self
,
199 char *start
= self
->data
+self
->pos
;
200 char *eof
= self
->data
+self
->size
;
205 if (!PyArg_ParseTuple(args
, ":readline"))
208 eol
= memchr(start
, '\n', self
->size
- self
->pos
);
212 ++eol
; /* we're interested in the position after the
214 result
= PyString_FromStringAndSize(start
, (eol
- start
));
215 self
->pos
+= (eol
- start
);
220 mmap_read_method(mmap_object
*self
,
227 if (!PyArg_ParseTuple(args
, "l:read", &num_bytes
))
230 /* silently 'adjust' out-of-range requests */
231 if ((self
->pos
+ num_bytes
) > self
->size
) {
232 num_bytes
-= (self
->pos
+num_bytes
) - self
->size
;
234 result
= Py_BuildValue("s#", self
->data
+self
->pos
, num_bytes
);
235 self
->pos
+= num_bytes
;
240 mmap_find_method(mmap_object
*self
,
243 long start
= self
->pos
;
248 if (!PyArg_ParseTuple (args
, "s#|l:find", &needle
, &len
, &start
)) {
252 char *e
= self
->data
+ self
->size
;
258 else if ((size_t)start
> self
->size
)
261 for (p
= self
->data
+ start
; p
+ len
<= e
; ++p
) {
263 for (i
= 0; i
< len
&& needle
[i
] == p
[i
]; ++i
)
266 return Py_BuildValue (
268 (long) (p
- self
->data
));
271 return Py_BuildValue ("l", (long) -1);
276 is_writeable(mmap_object
*self
)
278 if (self
->access
!= ACCESS_READ
)
280 PyErr_Format(PyExc_TypeError
, "mmap can't modify a readonly memory map.");
285 is_resizeable(mmap_object
*self
)
287 if ((self
->access
== ACCESS_WRITE
) || (self
->access
== ACCESS_DEFAULT
))
289 PyErr_Format(PyExc_TypeError
,
290 "mmap can't resize a readonly or copy-on-write memory map.");
296 mmap_write_method(mmap_object
*self
,
303 if (!PyArg_ParseTuple (args
, "s#:write", &data
, &length
))
306 if (!is_writeable(self
))
309 if ((self
->pos
+ length
) > self
->size
) {
310 PyErr_SetString (PyExc_ValueError
, "data out of range");
313 memcpy (self
->data
+self
->pos
, data
, length
);
314 self
->pos
= self
->pos
+length
;
320 mmap_write_byte_method(mmap_object
*self
,
326 if (!PyArg_ParseTuple (args
, "c:write_byte", &value
))
329 if (!is_writeable(self
))
331 *(self
->data
+self
->pos
) = value
;
338 mmap_size_method(mmap_object
*self
,
342 if (!PyArg_ParseTuple(args
, ":size"))
346 if (self
->file_handle
!= INVALID_HANDLE_VALUE
) {
347 return (Py_BuildValue (
349 GetFileSize (self
->file_handle
, NULL
)));
351 return (Py_BuildValue ("l", (long) self
->size
) );
353 #endif /* MS_WINDOWS */
358 if (-1 == fstat(self
->fd
, &buf
)) {
359 PyErr_SetFromErrno(mmap_module_error
);
362 return (Py_BuildValue ("l", (long) buf
.st_size
) );
367 /* This assumes that you want the entire file mapped,
368 / and when recreating the map will make the new file
371 / Is this really necessary? This could easily be done
372 / from python by just closing and re-opening with the
377 mmap_resize_method(mmap_object
*self
,
380 unsigned long new_size
;
382 if (!PyArg_ParseTuple (args
, "k:resize", &new_size
) ||
383 !is_resizeable(self
)) {
388 /* First, unmap the file view */
389 UnmapViewOfFile (self
->data
);
390 /* Close the mapping object */
391 CloseHandle (self
->map_handle
);
392 /* Move to the desired EOF position */
393 SetFilePointer (self
->file_handle
,
394 new_size
, NULL
, FILE_BEGIN
);
395 /* Change the size of the file */
396 SetEndOfFile (self
->file_handle
);
397 /* Create another mapping object and remap the file view */
398 self
->map_handle
= CreateFileMapping (
405 if (self
->map_handle
!= NULL
) {
406 self
->data
= (char *) MapViewOfFile (self
->map_handle
,
411 if (self
->data
!= NULL
) {
412 self
->size
= new_size
;
416 dwErrCode
= GetLastError();
419 dwErrCode
= GetLastError();
421 PyErr_SetFromWindowsErr(dwErrCode
);
423 #endif /* MS_WINDOWS */
428 PyErr_SetString(PyExc_SystemError
,
429 "mmap: resizing not available--no mremap()");
435 if (ftruncate(self
->fd
, new_size
) == -1) {
436 PyErr_SetFromErrno(mmap_module_error
);
440 #ifdef MREMAP_MAYMOVE
441 newmap
= mremap(self
->data
, self
->size
, new_size
, MREMAP_MAYMOVE
);
443 newmap
= mremap(self
->data
, self
->size
, new_size
, 0);
445 if (newmap
== (void *)-1)
447 PyErr_SetFromErrno(mmap_module_error
);
451 self
->size
= new_size
;
454 #endif /* HAVE_MREMAP */
460 mmap_tell_method(mmap_object
*self
, PyObject
*args
)
463 if (!PyArg_ParseTuple(args
, ":tell"))
465 return (Py_BuildValue ("l", (long) self
->pos
) );
469 mmap_flush_method(mmap_object
*self
, PyObject
*args
)
471 unsigned long offset
= 0;
472 unsigned long size
= self
->size
;
474 if (!PyArg_ParseTuple (args
, "|kk:flush", &offset
, &size
)) {
476 } else if ((offset
+ size
) > self
->size
) {
477 PyErr_SetString (PyExc_ValueError
,
478 "flush values out of range");
482 return (Py_BuildValue("l", (long)
483 FlushViewOfFile(self
->data
+offset
, size
)));
484 #endif /* MS_WINDOWS */
486 /* XXX semantics of return value? */
487 /* XXX flags for msync? */
488 if (-1 == msync(self
->data
+ offset
, size
,
491 PyErr_SetFromErrno(mmap_module_error
);
494 return Py_BuildValue ("l", (long) 0);
500 mmap_seek_method(mmap_object
*self
, PyObject
*args
)
505 if (!PyArg_ParseTuple (args
, "i|i:seek", &dist
, &how
)) {
510 case 0: /* relative to start */
515 case 1: /* relative to current position */
516 if ((int)self
->pos
+ dist
< 0)
518 where
= self
->pos
+ dist
;
520 case 2: /* relative to end */
521 if ((int)self
->size
+ dist
< 0)
523 where
= self
->size
+ dist
;
526 PyErr_SetString (PyExc_ValueError
,
527 "unknown seek type");
530 if (where
> self
->size
)
538 PyErr_SetString (PyExc_ValueError
, "seek out of range");
543 mmap_move_method(mmap_object
*self
, PyObject
*args
)
545 unsigned long dest
, src
, count
;
547 if (!PyArg_ParseTuple (args
, "kkk:move", &dest
, &src
, &count
) ||
548 !is_writeable(self
)) {
551 /* bounds check the values */
552 if (/* end of source after end of data?? */
553 ((src
+count
) > self
->size
)
555 || (dest
+count
> self
->size
)) {
556 PyErr_SetString (PyExc_ValueError
,
557 "source or destination out of range");
560 memmove (self
->data
+dest
, self
->data
+src
, count
);
567 static struct PyMethodDef mmap_object_methods
[] = {
568 {"close", (PyCFunction
) mmap_close_method
, METH_VARARGS
},
569 {"find", (PyCFunction
) mmap_find_method
, METH_VARARGS
},
570 {"flush", (PyCFunction
) mmap_flush_method
, METH_VARARGS
},
571 {"move", (PyCFunction
) mmap_move_method
, METH_VARARGS
},
572 {"read", (PyCFunction
) mmap_read_method
, METH_VARARGS
},
573 {"read_byte", (PyCFunction
) mmap_read_byte_method
, METH_VARARGS
},
574 {"readline", (PyCFunction
) mmap_read_line_method
, METH_VARARGS
},
575 {"resize", (PyCFunction
) mmap_resize_method
, METH_VARARGS
},
576 {"seek", (PyCFunction
) mmap_seek_method
, METH_VARARGS
},
577 {"size", (PyCFunction
) mmap_size_method
, METH_VARARGS
},
578 {"tell", (PyCFunction
) mmap_tell_method
, METH_VARARGS
},
579 {"write", (PyCFunction
) mmap_write_method
, METH_VARARGS
},
580 {"write_byte", (PyCFunction
) mmap_write_byte_method
, METH_VARARGS
},
581 {NULL
, NULL
} /* sentinel */
584 /* Functions for treating an mmap'ed file as a buffer */
587 mmap_buffer_getreadbuf(mmap_object
*self
, int index
, const void **ptr
)
591 PyErr_SetString(PyExc_SystemError
,
592 "Accessing non-existent mmap segment");
600 mmap_buffer_getwritebuf(mmap_object
*self
, int index
, const void **ptr
)
604 PyErr_SetString(PyExc_SystemError
,
605 "Accessing non-existent mmap segment");
608 if (!is_writeable(self
))
615 mmap_buffer_getsegcount(mmap_object
*self
, int *lenp
)
624 mmap_buffer_getcharbuffer(mmap_object
*self
, int index
, const void **ptr
)
627 PyErr_SetString(PyExc_SystemError
,
628 "accessing non-existent buffer segment");
631 *ptr
= (const char *)self
->data
;
636 mmap_object_getattr(mmap_object
*self
, char *name
)
638 return Py_FindMethod (mmap_object_methods
, (PyObject
*)self
, name
);
642 mmap_length(mmap_object
*self
)
649 mmap_item(mmap_object
*self
, int i
)
652 if (i
< 0 || (size_t)i
>= self
->size
) {
653 PyErr_SetString(PyExc_IndexError
, "mmap index out of range");
656 return PyString_FromStringAndSize(self
->data
+ i
, 1);
660 mmap_slice(mmap_object
*self
, int ilow
, int ihigh
)
665 else if ((size_t)ilow
> self
->size
)
671 else if ((size_t)ihigh
> self
->size
)
674 return PyString_FromStringAndSize(self
->data
+ ilow
, ihigh
-ilow
);
678 mmap_concat(mmap_object
*self
, PyObject
*bb
)
681 PyErr_SetString(PyExc_SystemError
,
682 "mmaps don't support concatenation");
687 mmap_repeat(mmap_object
*self
, int n
)
690 PyErr_SetString(PyExc_SystemError
,
691 "mmaps don't support repeat operation");
696 mmap_ass_slice(mmap_object
*self
, int ilow
, int ihigh
, PyObject
*v
)
703 else if ((size_t)ilow
> self
->size
)
709 else if ((size_t)ihigh
> self
->size
)
713 PyErr_SetString(PyExc_TypeError
,
714 "mmap object doesn't support slice deletion");
717 if (! (PyString_Check(v
)) ) {
718 PyErr_SetString(PyExc_IndexError
,
719 "mmap slice assignment must be a string");
722 if ( PyString_Size(v
) != (ihigh
- ilow
) ) {
723 PyErr_SetString(PyExc_IndexError
,
724 "mmap slice assignment is wrong size");
727 if (!is_writeable(self
))
729 buf
= PyString_AsString(v
);
730 memcpy(self
->data
+ ilow
, buf
, ihigh
-ilow
);
735 mmap_ass_item(mmap_object
*self
, int i
, PyObject
*v
)
740 if (i
< 0 || (size_t)i
>= self
->size
) {
741 PyErr_SetString(PyExc_IndexError
, "mmap index out of range");
745 PyErr_SetString(PyExc_TypeError
,
746 "mmap object doesn't support item deletion");
749 if (! (PyString_Check(v
) && PyString_Size(v
)==1) ) {
750 PyErr_SetString(PyExc_IndexError
,
751 "mmap assignment must be single-character string");
754 if (!is_writeable(self
))
756 buf
= PyString_AsString(v
);
757 self
->data
[i
] = buf
[0];
761 static PySequenceMethods mmap_as_sequence
= {
762 (inquiry
)mmap_length
, /*sq_length*/
763 (binaryfunc
)mmap_concat
, /*sq_concat*/
764 (intargfunc
)mmap_repeat
, /*sq_repeat*/
765 (intargfunc
)mmap_item
, /*sq_item*/
766 (intintargfunc
)mmap_slice
, /*sq_slice*/
767 (intobjargproc
)mmap_ass_item
, /*sq_ass_item*/
768 (intintobjargproc
)mmap_ass_slice
, /*sq_ass_slice*/
771 static PyBufferProcs mmap_as_buffer
= {
772 (getreadbufferproc
)mmap_buffer_getreadbuf
,
773 (getwritebufferproc
)mmap_buffer_getwritebuf
,
774 (getsegcountproc
)mmap_buffer_getsegcount
,
775 (getcharbufferproc
)mmap_buffer_getcharbuffer
,
778 static PyTypeObject mmap_object_type
= {
779 PyObject_HEAD_INIT(0) /* patched in module init */
781 "mmap.mmap", /* tp_name */
782 sizeof(mmap_object
), /* tp_size */
785 (destructor
) mmap_object_dealloc
, /* tp_dealloc */
787 (getattrfunc
) mmap_object_getattr
, /* tp_getattr */
791 0, /* tp_as_number */
792 &mmap_as_sequence
, /*tp_as_sequence*/
799 &mmap_as_buffer
, /*tp_as_buffer*/
800 Py_TPFLAGS_HAVE_GETCHARBUFFER
, /*tp_flags*/
805 /* extract the map size from the given PyObject
807 The map size is restricted to [0, INT_MAX] because this is the current
808 Python limitation on object sizes. Although the mmap object *could* handle
809 a larger map size, there is no point because all the useful operations
810 (len(), slicing(), sequence indexing) are limited by a C int.
812 Returns -1 on error, with an appropriate Python exception raised. On
813 success, the map size is returned. */
815 _GetMapSize(PyObject
*o
)
817 if (PyInt_Check(o
)) {
818 long i
= PyInt_AsLong(o
);
819 if (PyErr_Occurred())
827 else if (PyLong_Check(o
)) {
828 long i
= PyLong_AsLong(o
);
829 if (PyErr_Occurred()) {
830 /* yes negative overflow is mistaken for positive overflow
831 but not worth the trouble to check sign of 'i' */
832 if (PyErr_ExceptionMatches(PyExc_OverflowError
))
844 PyErr_SetString(PyExc_TypeError
,
845 "map size must be an integral value");
850 PyErr_SetString(PyExc_OverflowError
,
851 "memory mapped size must be positive");
855 PyErr_SetString(PyExc_OverflowError
,
856 "memory mapped size is too large (limited by C int)");
862 new_mmap_object(PyObject
*self
, PyObject
*args
, PyObject
*kwdict
)
868 PyObject
*map_size_obj
= NULL
;
870 int fd
, flags
= MAP_SHARED
, prot
= PROT_WRITE
| PROT_READ
;
872 int access
= (int)ACCESS_DEFAULT
;
873 static const char *keywords
[] = {"fileno", "length",
877 if (!PyArg_ParseTupleAndKeywords(args
, kwdict
, "iO|iii", keywords
,
878 &fd
, &map_size_obj
, &flags
, &prot
,
881 map_size
= _GetMapSize(map_size_obj
);
885 if ((access
!= (int)ACCESS_DEFAULT
) &&
886 ((flags
!= MAP_SHARED
) || (prot
!= (PROT_WRITE
| PROT_READ
))))
887 return PyErr_Format(PyExc_ValueError
,
888 "mmap can't specify both access and flags, prot.");
889 switch ((access_mode
)access
) {
896 prot
= PROT_READ
| PROT_WRITE
;
900 prot
= PROT_READ
| PROT_WRITE
;
903 /* use the specified or default values of flags and prot */
906 return PyErr_Format(PyExc_ValueError
,
907 "mmap invalid access parameter.");
912 /* on OpenVMS we must ensure that all bytes are written to the file */
915 if (fstat(fd
, &st
) == 0 && S_ISREG(st
.st_mode
)) {
917 map_size
= (int)st
.st_size
;
918 } else if ((size_t)map_size
> st
.st_size
) {
919 PyErr_SetString(PyExc_ValueError
,
920 "mmap length is greater than file size");
925 m_obj
= PyObject_New (mmap_object
, &mmap_object_type
);
926 if (m_obj
== NULL
) {return NULL
;}
928 m_obj
->size
= (size_t) map_size
;
929 m_obj
->pos
= (size_t) 0;
932 /* Assume the caller wants to map anonymous memory.
933 This is the same behaviour as Windows. mmap.mmap(-1, size)
934 on both Windows and Unix map anonymous memory.
937 /* BSD way to map anonymous memory */
938 flags
|= MAP_ANONYMOUS
;
940 /* SVR4 method to map anonymous memory is to open /dev/zero */
941 fd
= devzero
= open("/dev/zero", O_RDWR
);
944 PyErr_SetFromErrno(mmap_module_error
);
950 if (m_obj
->fd
== -1) {
952 PyErr_SetFromErrno(mmap_module_error
);
957 m_obj
->data
= mmap(NULL
, map_size
,
965 if (m_obj
->data
== (char *)-1) {
968 PyErr_SetFromErrno(mmap_module_error
);
971 m_obj
->access
= (access_mode
)access
;
972 return (PyObject
*)m_obj
;
978 new_mmap_object(PyObject
*self
, PyObject
*args
, PyObject
*kwdict
)
981 PyObject
*map_size_obj
= NULL
;
987 int access
= (access_mode
)ACCESS_DEFAULT
;
988 DWORD flProtect
, dwDesiredAccess
;
989 static const char *keywords
[] = { "fileno", "length",
993 if (!PyArg_ParseTupleAndKeywords(args
, kwdict
, "iO|zi", keywords
,
994 &fileno
, &map_size_obj
,
995 &tagname
, &access
)) {
999 switch((access_mode
)access
) {
1001 flProtect
= PAGE_READONLY
;
1002 dwDesiredAccess
= FILE_MAP_READ
;
1004 case ACCESS_DEFAULT
: case ACCESS_WRITE
:
1005 flProtect
= PAGE_READWRITE
;
1006 dwDesiredAccess
= FILE_MAP_WRITE
;
1009 flProtect
= PAGE_WRITECOPY
;
1010 dwDesiredAccess
= FILE_MAP_COPY
;
1013 return PyErr_Format(PyExc_ValueError
,
1014 "mmap invalid access parameter.");
1017 map_size
= _GetMapSize(map_size_obj
);
1021 /* assume -1 and 0 both mean invalid filedescriptor
1022 to 'anonymously' map memory.
1023 XXX: fileno == 0 is a valid fd, but was accepted prior to 2.5.
1024 XXX: Should this code be added?
1026 PyErr_Warn(PyExc_DeprecationWarning,
1027 "don't use 0 for anonymous memory");
1029 if (fileno
!= -1 && fileno
!= 0) {
1030 fh
= (HANDLE
)_get_osfhandle(fileno
);
1031 if (fh
==(HANDLE
)-1) {
1032 PyErr_SetFromErrno(mmap_module_error
);
1035 /* Win9x appears to need us seeked to zero */
1036 lseek(fileno
, 0, SEEK_SET
);
1039 m_obj
= PyObject_New (mmap_object
, &mmap_object_type
);
1042 /* Set every field to an invalid marker, so we can safely
1043 destruct the object in the face of failure */
1045 m_obj
->file_handle
= INVALID_HANDLE_VALUE
;
1046 m_obj
->map_handle
= INVALID_HANDLE_VALUE
;
1047 m_obj
->tagname
= NULL
;
1050 /* It is necessary to duplicate the handle, so the
1051 Python code can close it on us */
1052 if (!DuplicateHandle(
1053 GetCurrentProcess(), /* source process handle */
1054 fh
, /* handle to be duplicated */
1055 GetCurrentProcess(), /* target proc handle */
1056 (LPHANDLE
)&m_obj
->file_handle
, /* result */
1057 0, /* access - ignored due to options value */
1058 FALSE
, /* inherited by child processes? */
1059 DUPLICATE_SAME_ACCESS
)) { /* options */
1060 dwErr
= GetLastError();
1062 PyErr_SetFromWindowsErr(dwErr
);
1066 m_obj
->size
= GetFileSize (fh
, NULL
);
1068 m_obj
->size
= map_size
;
1072 m_obj
->size
= map_size
;
1075 /* set the initial position */
1076 m_obj
->pos
= (size_t) 0;
1078 /* set the tag name */
1079 if (tagname
!= NULL
&& *tagname
!= '\0') {
1080 m_obj
->tagname
= PyMem_Malloc(strlen(tagname
)+1);
1081 if (m_obj
->tagname
== NULL
) {
1086 strcpy(m_obj
->tagname
, tagname
);
1089 m_obj
->tagname
= NULL
;
1091 m_obj
->access
= (access_mode
)access
;
1092 m_obj
->map_handle
= CreateFileMapping (m_obj
->file_handle
,
1098 if (m_obj
->map_handle
!= NULL
) {
1099 m_obj
->data
= (char *) MapViewOfFile (m_obj
->map_handle
,
1104 if (m_obj
->data
!= NULL
) {
1105 return ((PyObject
*) m_obj
);
1107 dwErr
= GetLastError();
1110 dwErr
= GetLastError();
1113 PyErr_SetFromWindowsErr(dwErr
);
1116 #endif /* MS_WINDOWS */
1118 /* List of functions exported by this module */
1119 static struct PyMethodDef mmap_functions
[] = {
1120 {"mmap", (PyCFunction
) new_mmap_object
,
1121 METH_VARARGS
|METH_KEYWORDS
},
1122 {NULL
, NULL
} /* Sentinel */
1128 PyObject
*dict
, *module
;
1130 /* Patch the object type */
1131 mmap_object_type
.ob_type
= &PyType_Type
;
1133 module
= Py_InitModule ("mmap", mmap_functions
);
1136 dict
= PyModule_GetDict (module
);
1137 mmap_module_error
= PyExc_EnvironmentError
;
1138 Py_INCREF(mmap_module_error
);
1139 PyDict_SetItemString (dict
, "error", mmap_module_error
);
1141 PyDict_SetItemString (dict
, "PROT_EXEC", PyInt_FromLong(PROT_EXEC
) );
1144 PyDict_SetItemString (dict
, "PROT_READ", PyInt_FromLong(PROT_READ
) );
1147 PyDict_SetItemString (dict
, "PROT_WRITE", PyInt_FromLong(PROT_WRITE
) );
1151 PyDict_SetItemString (dict
, "MAP_SHARED", PyInt_FromLong(MAP_SHARED
) );
1154 PyDict_SetItemString (dict
, "MAP_PRIVATE",
1155 PyInt_FromLong(MAP_PRIVATE
) );
1157 #ifdef MAP_DENYWRITE
1158 PyDict_SetItemString (dict
, "MAP_DENYWRITE",
1159 PyInt_FromLong(MAP_DENYWRITE
) );
1161 #ifdef MAP_EXECUTABLE
1162 PyDict_SetItemString (dict
, "MAP_EXECUTABLE",
1163 PyInt_FromLong(MAP_EXECUTABLE
) );
1165 #ifdef MAP_ANONYMOUS
1166 PyDict_SetItemString (dict
, "MAP_ANON", PyInt_FromLong(MAP_ANONYMOUS
) );
1167 PyDict_SetItemString (dict
, "MAP_ANONYMOUS",
1168 PyInt_FromLong(MAP_ANONYMOUS
) );
1171 PyDict_SetItemString (dict
, "PAGESIZE",
1172 PyInt_FromLong( (long)my_getpagesize() ) );
1174 PyDict_SetItemString (dict
, "ACCESS_READ",
1175 PyInt_FromLong(ACCESS_READ
));
1176 PyDict_SetItemString (dict
, "ACCESS_WRITE",
1177 PyInt_FromLong(ACCESS_WRITE
));
1178 PyDict_SetItemString (dict
, "ACCESS_COPY",
1179 PyInt_FromLong(ACCESS_COPY
));