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.
43 /* This is missing e.g. on SunOS 4.1.4 */
47 #if defined(HAVE_SYSCONF) && defined(_SC_PAGESIZE)
51 return sysconf(_SC_PAGESIZE
);
54 #define my_getpagesize getpagesize
60 #include <sys/types.h>
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 */
107 if (m_obj
->data
!=NULL
) {
108 msync(m_obj
->data
, m_obj
->size
, MS_SYNC
);
109 munmap(m_obj
->data
, m_obj
->size
);
117 mmap_close_method(mmap_object
*self
, PyObject
*args
)
119 if (!PyArg_ParseTuple(args
, ":close"))
122 /* For each resource we maintain, we need to check
123 the value is valid, and if so, free the resource
124 and set the member value to an invalid value so
125 the dealloc does not attempt to resource clearing
127 TODO - should we check for errors in the close operations???
129 if (self
->data
!= NULL
) {
130 UnmapViewOfFile (self
->data
);
133 if (self
->map_handle
!= INVALID_HANDLE_VALUE
) {
134 CloseHandle (self
->map_handle
);
135 self
->map_handle
= INVALID_HANDLE_VALUE
;
137 if (self
->file_handle
!= INVALID_HANDLE_VALUE
) {
138 CloseHandle (self
->file_handle
);
139 self
->file_handle
= INVALID_HANDLE_VALUE
;
141 #endif /* MS_WINDOWS */
144 if (self
->data
!= NULL
) {
145 munmap(self
->data
, self
->size
);
155 #define CHECK_VALID(err) \
157 if (self->map_handle == INVALID_HANDLE_VALUE) { \
158 PyErr_SetString (PyExc_ValueError, "mmap closed or invalid"); \
162 #endif /* MS_WINDOWS */
165 #define CHECK_VALID(err) \
167 if (self->data == NULL) { \
168 PyErr_SetString (PyExc_ValueError, "mmap closed or invalid"); \
175 mmap_read_byte_method(mmap_object
*self
,
179 if (!PyArg_ParseTuple(args
, ":read_byte"))
181 if (self
->pos
< self
->size
) {
182 char value
= self
->data
[self
->pos
];
184 return Py_BuildValue("c", value
);
186 PyErr_SetString (PyExc_ValueError
, "read byte out of range");
192 mmap_read_line_method(mmap_object
*self
,
195 char *start
= self
->data
+self
->pos
;
196 char *eof
= self
->data
+self
->size
;
201 if (!PyArg_ParseTuple(args
, ":readline"))
204 eol
= memchr(start
, '\n', self
->size
- self
->pos
);
208 ++eol
; /* we're interested in the position after the
210 result
= PyString_FromStringAndSize(start
, (eol
- start
));
211 self
->pos
+= (eol
- start
);
216 mmap_read_method(mmap_object
*self
,
223 if (!PyArg_ParseTuple(args
, "l:read", &num_bytes
))
226 /* silently 'adjust' out-of-range requests */
227 if ((self
->pos
+ num_bytes
) > self
->size
) {
228 num_bytes
-= (self
->pos
+num_bytes
) - self
->size
;
230 result
= Py_BuildValue("s#", self
->data
+self
->pos
, num_bytes
);
231 self
->pos
+= num_bytes
;
236 mmap_find_method(mmap_object
*self
,
239 long start
= self
->pos
;
244 if (!PyArg_ParseTuple (args
, "s#|l:find", &needle
, &len
, &start
)) {
248 char *e
= self
->data
+ self
->size
;
254 else if ((size_t)start
> self
->size
)
257 for (p
= self
->data
+ start
; p
+ len
<= e
; ++p
) {
259 for (i
= 0; i
< len
&& needle
[i
] == p
[i
]; ++i
)
262 return Py_BuildValue (
264 (long) (p
- self
->data
));
267 return Py_BuildValue ("l", (long) -1);
272 is_writeable(mmap_object
*self
)
274 if (self
->access
!= ACCESS_READ
)
276 PyErr_Format(PyExc_TypeError
, "mmap can't modify a readonly memory map.");
281 is_resizeable(mmap_object
*self
)
283 if ((self
->access
== ACCESS_WRITE
) || (self
->access
== ACCESS_DEFAULT
))
285 PyErr_Format(PyExc_TypeError
,
286 "mmap can't resize a readonly or copy-on-write memory map.");
292 mmap_write_method(mmap_object
*self
,
299 if (!PyArg_ParseTuple (args
, "s#:write", &data
, &length
))
302 if (!is_writeable(self
))
305 if ((self
->pos
+ length
) > self
->size
) {
306 PyErr_SetString (PyExc_ValueError
, "data out of range");
309 memcpy (self
->data
+self
->pos
, data
, length
);
310 self
->pos
= self
->pos
+length
;
316 mmap_write_byte_method(mmap_object
*self
,
322 if (!PyArg_ParseTuple (args
, "c:write_byte", &value
))
325 if (!is_writeable(self
))
327 *(self
->data
+self
->pos
) = value
;
334 mmap_size_method(mmap_object
*self
,
338 if (!PyArg_ParseTuple(args
, ":size"))
342 if (self
->file_handle
!= INVALID_HANDLE_VALUE
) {
343 return (Py_BuildValue (
345 GetFileSize (self
->file_handle
, NULL
)));
347 return (Py_BuildValue ("l", (long) self
->size
) );
349 #endif /* MS_WINDOWS */
354 if (-1 == fstat(self
->fd
, &buf
)) {
355 PyErr_SetFromErrno(mmap_module_error
);
358 return (Py_BuildValue ("l", (long) buf
.st_size
) );
363 /* This assumes that you want the entire file mapped,
364 / and when recreating the map will make the new file
367 / Is this really necessary? This could easily be done
368 / from python by just closing and re-opening with the
373 mmap_resize_method(mmap_object
*self
,
376 unsigned long new_size
;
378 if (!PyArg_ParseTuple (args
, "l:resize", &new_size
) ||
379 !is_resizeable(self
)) {
384 /* First, unmap the file view */
385 UnmapViewOfFile (self
->data
);
386 /* Close the mapping object */
387 CloseHandle (self
->map_handle
);
388 /* Move to the desired EOF position */
389 SetFilePointer (self
->file_handle
,
390 new_size
, NULL
, FILE_BEGIN
);
391 /* Change the size of the file */
392 SetEndOfFile (self
->file_handle
);
393 /* Create another mapping object and remap the file view */
394 self
->map_handle
= CreateFileMapping (
401 if (self
->map_handle
!= NULL
) {
402 self
->data
= (char *) MapViewOfFile (self
->map_handle
,
407 if (self
->data
!= NULL
) {
408 self
->size
= new_size
;
412 dwErrCode
= GetLastError();
415 dwErrCode
= GetLastError();
417 PyErr_SetFromWindowsErr(dwErrCode
);
419 #endif /* MS_WINDOWS */
424 PyErr_SetString(PyExc_SystemError
,
425 "mmap: resizing not available--no mremap()");
431 #ifdef MREMAP_MAYMOVE
432 newmap
= mremap(self
->data
, self
->size
, new_size
, MREMAP_MAYMOVE
);
434 newmap
= mremap(self
->data
, self
->size
, new_size
, 0);
436 if (newmap
== (void *)-1)
438 PyErr_SetFromErrno(mmap_module_error
);
442 self
->size
= new_size
;
445 #endif /* HAVE_MREMAP */
451 mmap_tell_method(mmap_object
*self
, PyObject
*args
)
454 if (!PyArg_ParseTuple(args
, ":tell"))
456 return (Py_BuildValue ("l", (long) self
->pos
) );
460 mmap_flush_method(mmap_object
*self
, PyObject
*args
)
463 size_t size
= self
->size
;
465 if (!PyArg_ParseTuple (args
, "|ll:flush", &offset
, &size
)) {
467 } else if ((offset
+ size
) > self
->size
) {
468 PyErr_SetString (PyExc_ValueError
,
469 "flush values out of range");
473 return (Py_BuildValue("l", (long)
474 FlushViewOfFile(self
->data
+offset
, size
)));
475 #endif /* MS_WINDOWS */
477 /* XXX semantics of return value? */
478 /* XXX flags for msync? */
479 if (-1 == msync(self
->data
+ offset
, size
,
482 PyErr_SetFromErrno(mmap_module_error
);
485 return Py_BuildValue ("l", (long) 0);
491 mmap_seek_method(mmap_object
*self
, PyObject
*args
)
496 if (!PyArg_ParseTuple (args
, "i|i:seek", &dist
, &how
)) {
501 case 0: /* relative to start */
506 case 1: /* relative to current position */
507 if ((int)self
->pos
+ dist
< 0)
509 where
= self
->pos
+ dist
;
511 case 2: /* relative to end */
512 if ((int)self
->size
+ dist
< 0)
514 where
= self
->size
+ dist
;
517 PyErr_SetString (PyExc_ValueError
,
518 "unknown seek type");
521 if (where
> self
->size
)
529 PyErr_SetString (PyExc_ValueError
, "seek out of range");
534 mmap_move_method(mmap_object
*self
, PyObject
*args
)
536 unsigned long dest
, src
, count
;
538 if (!PyArg_ParseTuple (args
, "iii:move", &dest
, &src
, &count
) ||
539 !is_writeable(self
)) {
542 /* bounds check the values */
543 if (/* end of source after end of data?? */
544 ((src
+count
) > self
->size
)
546 || (dest
+count
> self
->size
)) {
547 PyErr_SetString (PyExc_ValueError
,
548 "source or destination out of range");
551 memmove (self
->data
+dest
, self
->data
+src
, count
);
558 static struct PyMethodDef mmap_object_methods
[] = {
559 {"close", (PyCFunction
) mmap_close_method
, METH_VARARGS
},
560 {"find", (PyCFunction
) mmap_find_method
, METH_VARARGS
},
561 {"flush", (PyCFunction
) mmap_flush_method
, METH_VARARGS
},
562 {"move", (PyCFunction
) mmap_move_method
, METH_VARARGS
},
563 {"read", (PyCFunction
) mmap_read_method
, METH_VARARGS
},
564 {"read_byte", (PyCFunction
) mmap_read_byte_method
, METH_VARARGS
},
565 {"readline", (PyCFunction
) mmap_read_line_method
, METH_VARARGS
},
566 {"resize", (PyCFunction
) mmap_resize_method
, METH_VARARGS
},
567 {"seek", (PyCFunction
) mmap_seek_method
, METH_VARARGS
},
568 {"size", (PyCFunction
) mmap_size_method
, METH_VARARGS
},
569 {"tell", (PyCFunction
) mmap_tell_method
, METH_VARARGS
},
570 {"write", (PyCFunction
) mmap_write_method
, METH_VARARGS
},
571 {"write_byte", (PyCFunction
) mmap_write_byte_method
, METH_VARARGS
},
572 {NULL
, NULL
} /* sentinel */
575 /* Functions for treating an mmap'ed file as a buffer */
578 mmap_buffer_getreadbuf(mmap_object
*self
, int index
, const void **ptr
)
582 PyErr_SetString(PyExc_SystemError
,
583 "Accessing non-existent mmap segment");
591 mmap_buffer_getwritebuf(mmap_object
*self
, int index
, const void **ptr
)
595 PyErr_SetString(PyExc_SystemError
,
596 "Accessing non-existent mmap segment");
599 if (!is_writeable(self
))
606 mmap_buffer_getsegcount(mmap_object
*self
, int *lenp
)
615 mmap_buffer_getcharbuffer(mmap_object
*self
, int index
, const void **ptr
)
618 PyErr_SetString(PyExc_SystemError
,
619 "accessing non-existent buffer segment");
622 *ptr
= (const char *)self
->data
;
627 mmap_object_getattr(mmap_object
*self
, char *name
)
629 return Py_FindMethod (mmap_object_methods
, (PyObject
*)self
, name
);
633 mmap_length(mmap_object
*self
)
640 mmap_item(mmap_object
*self
, int i
)
643 if (i
< 0 || (size_t)i
>= self
->size
) {
644 PyErr_SetString(PyExc_IndexError
, "mmap index out of range");
647 return PyString_FromStringAndSize(self
->data
+ i
, 1);
651 mmap_slice(mmap_object
*self
, int ilow
, int ihigh
)
656 else if ((size_t)ilow
> self
->size
)
662 else if ((size_t)ihigh
> self
->size
)
665 return PyString_FromStringAndSize(self
->data
+ ilow
, ihigh
-ilow
);
669 mmap_concat(mmap_object
*self
, PyObject
*bb
)
672 PyErr_SetString(PyExc_SystemError
,
673 "mmaps don't support concatenation");
678 mmap_repeat(mmap_object
*self
, int n
)
681 PyErr_SetString(PyExc_SystemError
,
682 "mmaps don't support repeat operation");
687 mmap_ass_slice(mmap_object
*self
, int ilow
, int ihigh
, PyObject
*v
)
694 else if ((size_t)ilow
> self
->size
)
700 else if ((size_t)ihigh
> self
->size
)
704 PyErr_SetString(PyExc_TypeError
,
705 "mmap object doesn't support slice deletion");
708 if (! (PyString_Check(v
)) ) {
709 PyErr_SetString(PyExc_IndexError
,
710 "mmap slice assignment must be a string");
713 if ( PyString_Size(v
) != (ihigh
- ilow
) ) {
714 PyErr_SetString(PyExc_IndexError
,
715 "mmap slice assignment is wrong size");
718 if (!is_writeable(self
))
720 buf
= PyString_AsString(v
);
721 memcpy(self
->data
+ ilow
, buf
, ihigh
-ilow
);
726 mmap_ass_item(mmap_object
*self
, int i
, PyObject
*v
)
731 if (i
< 0 || (size_t)i
>= self
->size
) {
732 PyErr_SetString(PyExc_IndexError
, "mmap index out of range");
736 PyErr_SetString(PyExc_TypeError
,
737 "mmap object doesn't support item deletion");
740 if (! (PyString_Check(v
) && PyString_Size(v
)==1) ) {
741 PyErr_SetString(PyExc_IndexError
,
742 "mmap assignment must be single-character string");
745 if (!is_writeable(self
))
747 buf
= PyString_AsString(v
);
748 self
->data
[i
] = buf
[0];
752 static PySequenceMethods mmap_as_sequence
= {
753 (inquiry
)mmap_length
, /*sq_length*/
754 (binaryfunc
)mmap_concat
, /*sq_concat*/
755 (intargfunc
)mmap_repeat
, /*sq_repeat*/
756 (intargfunc
)mmap_item
, /*sq_item*/
757 (intintargfunc
)mmap_slice
, /*sq_slice*/
758 (intobjargproc
)mmap_ass_item
, /*sq_ass_item*/
759 (intintobjargproc
)mmap_ass_slice
, /*sq_ass_slice*/
762 static PyBufferProcs mmap_as_buffer
= {
763 (getreadbufferproc
)mmap_buffer_getreadbuf
,
764 (getwritebufferproc
)mmap_buffer_getwritebuf
,
765 (getsegcountproc
)mmap_buffer_getsegcount
,
766 (getcharbufferproc
)mmap_buffer_getcharbuffer
,
769 static PyTypeObject mmap_object_type
= {
770 PyObject_HEAD_INIT(0) /* patched in module init */
772 "mmap.mmap", /* tp_name */
773 sizeof(mmap_object
), /* tp_size */
776 (destructor
) mmap_object_dealloc
, /* tp_dealloc */
778 (getattrfunc
) mmap_object_getattr
, /* tp_getattr */
782 0, /* tp_as_number */
783 &mmap_as_sequence
, /*tp_as_sequence*/
790 &mmap_as_buffer
, /*tp_as_buffer*/
791 Py_TPFLAGS_HAVE_GETCHARBUFFER
, /*tp_flags*/
796 /* extract the map size from the given PyObject
798 The map size is restricted to [0, INT_MAX] because this is the current
799 Python limitation on object sizes. Although the mmap object *could* handle
800 a larger map size, there is no point because all the useful operations
801 (len(), slicing(), sequence indexing) are limited by a C int.
803 Returns -1 on error, with an appropriate Python exception raised. On
804 success, the map size is returned. */
806 _GetMapSize(PyObject
*o
)
808 if (PyInt_Check(o
)) {
809 long i
= PyInt_AsLong(o
);
810 if (PyErr_Occurred())
818 else if (PyLong_Check(o
)) {
819 long i
= PyLong_AsLong(o
);
820 if (PyErr_Occurred()) {
821 /* yes negative overflow is mistaken for positive overflow
822 but not worth the trouble to check sign of 'i' */
823 if (PyErr_ExceptionMatches(PyExc_OverflowError
))
835 PyErr_SetString(PyExc_TypeError
,
836 "map size must be an integral value");
841 PyErr_SetString(PyExc_OverflowError
,
842 "memory mapped size must be positive");
846 PyErr_SetString(PyExc_OverflowError
,
847 "memory mapped size is too large (limited by C int)");
853 new_mmap_object(PyObject
*self
, PyObject
*args
, PyObject
*kwdict
)
859 PyObject
*map_size_obj
= NULL
;
861 int fd
, flags
= MAP_SHARED
, prot
= PROT_WRITE
| PROT_READ
;
862 access_mode access
= ACCESS_DEFAULT
;
863 char *keywords
[] = {"fileno", "length",
867 if (!PyArg_ParseTupleAndKeywords(args
, kwdict
, "iO|iii", keywords
,
868 &fd
, &map_size_obj
, &flags
, &prot
, &access
))
870 map_size
= _GetMapSize(map_size_obj
);
874 if ((access
!= ACCESS_DEFAULT
) &&
875 ((flags
!= MAP_SHARED
) || ( prot
!= (PROT_WRITE
| PROT_READ
))))
876 return PyErr_Format(PyExc_ValueError
,
877 "mmap can't specify both access and flags, prot.");
885 prot
= PROT_READ
| PROT_WRITE
;
889 prot
= PROT_READ
| PROT_WRITE
;
892 /* use the specified or default values of flags and prot */
895 return PyErr_Format(PyExc_ValueError
,
896 "mmap invalid access parameter.");
901 /* on OpenVMS we must ensure that all bytes are written to the file */
904 if (fstat(fd
, &st
) == 0 && S_ISREG(st
.st_mode
) &&
905 (size_t)map_size
> st
.st_size
) {
906 PyErr_SetString(PyExc_ValueError
,
907 "mmap length is greater than file size");
911 m_obj
= PyObject_New (mmap_object
, &mmap_object_type
);
912 if (m_obj
== NULL
) {return NULL
;}
913 m_obj
->size
= (size_t) map_size
;
914 m_obj
->pos
= (size_t) 0;
916 m_obj
->data
= mmap(NULL
, map_size
,
919 if (m_obj
->data
== (char *)-1) {
921 PyErr_SetFromErrno(mmap_module_error
);
924 m_obj
->access
= access
;
925 return (PyObject
*)m_obj
;
931 new_mmap_object(PyObject
*self
, PyObject
*args
, PyObject
*kwdict
)
934 PyObject
*map_size_obj
= NULL
;
940 access_mode access
= ACCESS_DEFAULT
;
941 DWORD flProtect
, dwDesiredAccess
;
942 char *keywords
[] = { "fileno", "length",
946 if (!PyArg_ParseTupleAndKeywords(args
, kwdict
, "iO|zi", keywords
,
947 &fileno
, &map_size_obj
,
948 &tagname
, &access
)) {
954 flProtect
= PAGE_READONLY
;
955 dwDesiredAccess
= FILE_MAP_READ
;
957 case ACCESS_DEFAULT
: case ACCESS_WRITE
:
958 flProtect
= PAGE_READWRITE
;
959 dwDesiredAccess
= FILE_MAP_WRITE
;
962 flProtect
= PAGE_WRITECOPY
;
963 dwDesiredAccess
= FILE_MAP_COPY
;
966 return PyErr_Format(PyExc_ValueError
,
967 "mmap invalid access parameter.");
970 map_size
= _GetMapSize(map_size_obj
);
974 /* if an actual filename has been specified */
976 fh
= (HANDLE
)_get_osfhandle(fileno
);
977 if (fh
==(HANDLE
)-1) {
978 PyErr_SetFromErrno(mmap_module_error
);
981 /* Win9x appears to need us seeked to zero */
982 lseek(fileno
, 0, SEEK_SET
);
985 m_obj
= PyObject_New (mmap_object
, &mmap_object_type
);
988 /* Set every field to an invalid marker, so we can safely
989 destruct the object in the face of failure */
991 m_obj
->file_handle
= INVALID_HANDLE_VALUE
;
992 m_obj
->map_handle
= INVALID_HANDLE_VALUE
;
993 m_obj
->tagname
= NULL
;
996 /* It is necessary to duplicate the handle, so the
997 Python code can close it on us */
998 if (!DuplicateHandle(
999 GetCurrentProcess(), /* source process handle */
1000 fh
, /* handle to be duplicated */
1001 GetCurrentProcess(), /* target proc handle */
1002 (LPHANDLE
)&m_obj
->file_handle
, /* result */
1003 0, /* access - ignored due to options value */
1004 FALSE
, /* inherited by child processes? */
1005 DUPLICATE_SAME_ACCESS
)) { /* options */
1006 dwErr
= GetLastError();
1008 PyErr_SetFromWindowsErr(dwErr
);
1012 m_obj
->size
= GetFileSize (fh
, NULL
);
1014 m_obj
->size
= map_size
;
1018 m_obj
->size
= map_size
;
1021 /* set the initial position */
1022 m_obj
->pos
= (size_t) 0;
1024 /* set the tag name */
1025 if (tagname
!= NULL
&& *tagname
!= '\0') {
1026 m_obj
->tagname
= PyMem_Malloc(strlen(tagname
)+1);
1027 if (m_obj
->tagname
== NULL
) {
1032 strcpy(m_obj
->tagname
, tagname
);
1035 m_obj
->tagname
= NULL
;
1037 m_obj
->access
= access
;
1038 m_obj
->map_handle
= CreateFileMapping (m_obj
->file_handle
,
1044 if (m_obj
->map_handle
!= NULL
) {
1045 m_obj
->data
= (char *) MapViewOfFile (m_obj
->map_handle
,
1050 if (m_obj
->data
!= NULL
) {
1051 return ((PyObject
*) m_obj
);
1053 dwErr
= GetLastError();
1056 dwErr
= GetLastError();
1059 PyErr_SetFromWindowsErr(dwErr
);
1062 #endif /* MS_WINDOWS */
1064 /* List of functions exported by this module */
1065 static struct PyMethodDef mmap_functions
[] = {
1066 {"mmap", (PyCFunction
) new_mmap_object
,
1067 METH_VARARGS
|METH_KEYWORDS
},
1068 {NULL
, NULL
} /* Sentinel */
1074 PyObject
*dict
, *module
;
1076 /* Patch the object type */
1077 mmap_object_type
.ob_type
= &PyType_Type
;
1079 module
= Py_InitModule ("mmap", mmap_functions
);
1080 dict
= PyModule_GetDict (module
);
1081 mmap_module_error
= PyExc_EnvironmentError
;
1082 Py_INCREF(mmap_module_error
);
1083 PyDict_SetItemString (dict
, "error", mmap_module_error
);
1085 PyDict_SetItemString (dict
, "PROT_EXEC", PyInt_FromLong(PROT_EXEC
) );
1088 PyDict_SetItemString (dict
, "PROT_READ", PyInt_FromLong(PROT_READ
) );
1091 PyDict_SetItemString (dict
, "PROT_WRITE", PyInt_FromLong(PROT_WRITE
) );
1095 PyDict_SetItemString (dict
, "MAP_SHARED", PyInt_FromLong(MAP_SHARED
) );
1098 PyDict_SetItemString (dict
, "MAP_PRIVATE",
1099 PyInt_FromLong(MAP_PRIVATE
) );
1101 #ifdef MAP_DENYWRITE
1102 PyDict_SetItemString (dict
, "MAP_DENYWRITE",
1103 PyInt_FromLong(MAP_DENYWRITE
) );
1105 #ifdef MAP_EXECUTABLE
1106 PyDict_SetItemString (dict
, "MAP_EXECUTABLE",
1107 PyInt_FromLong(MAP_EXECUTABLE
) );
1110 PyDict_SetItemString (dict
, "MAP_ANON", PyInt_FromLong(MAP_ANON
) );
1111 PyDict_SetItemString (dict
, "MAP_ANONYMOUS",
1112 PyInt_FromLong(MAP_ANON
) );
1115 PyDict_SetItemString (dict
, "PAGESIZE",
1116 PyInt_FromLong( (long)my_getpagesize() ) );
1118 PyDict_SetItemString (dict
, "ACCESS_READ",
1119 PyInt_FromLong(ACCESS_READ
));
1120 PyDict_SetItemString (dict
, "ACCESS_WRITE",
1121 PyInt_FromLong(ACCESS_WRITE
));
1122 PyDict_SetItemString (dict
, "ACCESS_COPY",
1123 PyInt_FromLong(ACCESS_COPY
));