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 static PyObject
*mmap_module_error
;
88 mmap_object_dealloc(mmap_object
*m_obj
)
91 if (m_obj
->data
!= NULL
)
92 UnmapViewOfFile (m_obj
->data
);
93 if (m_obj
->map_handle
!= INVALID_HANDLE_VALUE
)
94 CloseHandle (m_obj
->map_handle
);
95 if (m_obj
->file_handle
!= INVALID_HANDLE_VALUE
)
96 CloseHandle (m_obj
->file_handle
);
98 PyMem_Free(m_obj
->tagname
);
99 #endif /* MS_WINDOWS */
103 (void) close(m_obj
->fd
);
104 if (m_obj
->data
!=NULL
) {
105 msync(m_obj
->data
, m_obj
->size
, MS_SYNC
);
106 munmap(m_obj
->data
, m_obj
->size
);
114 mmap_close_method(mmap_object
*self
, PyObject
*args
)
116 if (!PyArg_ParseTuple(args
, ":close"))
119 /* For each resource we maintain, we need to check
120 the value is valid, and if so, free the resource
121 and set the member value to an invalid value so
122 the dealloc does not attempt to resource clearing
124 TODO - should we check for errors in the close operations???
126 if (self
->data
!= NULL
) {
127 UnmapViewOfFile (self
->data
);
130 if (self
->map_handle
!= INVALID_HANDLE_VALUE
) {
131 CloseHandle (self
->map_handle
);
132 self
->map_handle
= INVALID_HANDLE_VALUE
;
134 if (self
->file_handle
!= INVALID_HANDLE_VALUE
) {
135 CloseHandle (self
->file_handle
);
136 self
->file_handle
= INVALID_HANDLE_VALUE
;
138 #endif /* MS_WINDOWS */
141 (void) close(self
->fd
);
143 if (self
->data
!= NULL
) {
144 munmap(self
->data
, self
->size
);
154 #define CHECK_VALID(err) \
156 if (self->map_handle == INVALID_HANDLE_VALUE) { \
157 PyErr_SetString (PyExc_ValueError, "mmap closed or invalid"); \
161 #endif /* MS_WINDOWS */
164 #define CHECK_VALID(err) \
166 if (self->data == NULL) { \
167 PyErr_SetString (PyExc_ValueError, "mmap closed or invalid"); \
174 mmap_read_byte_method(mmap_object
*self
,
178 if (!PyArg_ParseTuple(args
, ":read_byte"))
180 if (self
->pos
< self
->size
) {
181 char value
= self
->data
[self
->pos
];
183 return Py_BuildValue("c", value
);
185 PyErr_SetString (PyExc_ValueError
, "read byte out of range");
191 mmap_read_line_method(mmap_object
*self
,
194 char *start
= self
->data
+self
->pos
;
195 char *eof
= self
->data
+self
->size
;
200 if (!PyArg_ParseTuple(args
, ":readline"))
203 eol
= memchr(start
, '\n', self
->size
- self
->pos
);
207 ++eol
; /* we're interested in the position after the
209 result
= PyString_FromStringAndSize(start
, (eol
- start
));
210 self
->pos
+= (eol
- start
);
215 mmap_read_method(mmap_object
*self
,
222 if (!PyArg_ParseTuple(args
, "l:read", &num_bytes
))
225 /* silently 'adjust' out-of-range requests */
226 if ((self
->pos
+ num_bytes
) > self
->size
) {
227 num_bytes
-= (self
->pos
+num_bytes
) - self
->size
;
229 result
= Py_BuildValue("s#", self
->data
+self
->pos
, num_bytes
);
230 self
->pos
+= num_bytes
;
235 mmap_find_method(mmap_object
*self
,
238 long start
= self
->pos
;
243 if (!PyArg_ParseTuple (args
, "s#|l:find", &needle
, &len
, &start
)) {
247 char *e
= self
->data
+ self
->size
;
253 else if ((size_t)start
> self
->size
)
256 for (p
= self
->data
+ start
; p
+ len
<= e
; ++p
) {
258 for (i
= 0; i
< len
&& needle
[i
] == p
[i
]; ++i
)
261 return Py_BuildValue (
263 (long) (p
- self
->data
));
266 return Py_BuildValue ("l", (long) -1);
271 is_writeable(mmap_object
*self
)
273 if (self
->access
!= ACCESS_READ
)
275 PyErr_Format(PyExc_TypeError
, "mmap can't modify a readonly memory map.");
280 is_resizeable(mmap_object
*self
)
282 if ((self
->access
== ACCESS_WRITE
) || (self
->access
== ACCESS_DEFAULT
))
284 PyErr_Format(PyExc_TypeError
,
285 "mmap can't resize a readonly or copy-on-write memory map.");
291 mmap_write_method(mmap_object
*self
,
298 if (!PyArg_ParseTuple (args
, "s#:write", &data
, &length
))
301 if (!is_writeable(self
))
304 if ((self
->pos
+ length
) > self
->size
) {
305 PyErr_SetString (PyExc_ValueError
, "data out of range");
308 memcpy (self
->data
+self
->pos
, data
, length
);
309 self
->pos
= self
->pos
+length
;
315 mmap_write_byte_method(mmap_object
*self
,
321 if (!PyArg_ParseTuple (args
, "c:write_byte", &value
))
324 if (!is_writeable(self
))
326 *(self
->data
+self
->pos
) = value
;
333 mmap_size_method(mmap_object
*self
,
337 if (!PyArg_ParseTuple(args
, ":size"))
341 if (self
->file_handle
!= INVALID_HANDLE_VALUE
) {
342 return (Py_BuildValue (
344 GetFileSize (self
->file_handle
, NULL
)));
346 return (Py_BuildValue ("l", (long) self
->size
) );
348 #endif /* MS_WINDOWS */
353 if (-1 == fstat(self
->fd
, &buf
)) {
354 PyErr_SetFromErrno(mmap_module_error
);
357 return (Py_BuildValue ("l", (long) buf
.st_size
) );
362 /* This assumes that you want the entire file mapped,
363 / and when recreating the map will make the new file
366 / Is this really necessary? This could easily be done
367 / from python by just closing and re-opening with the
372 mmap_resize_method(mmap_object
*self
,
375 unsigned long new_size
;
377 if (!PyArg_ParseTuple (args
, "k:resize", &new_size
) ||
378 !is_resizeable(self
)) {
383 /* First, unmap the file view */
384 UnmapViewOfFile (self
->data
);
385 /* Close the mapping object */
386 CloseHandle (self
->map_handle
);
387 /* Move to the desired EOF position */
388 SetFilePointer (self
->file_handle
,
389 new_size
, NULL
, FILE_BEGIN
);
390 /* Change the size of the file */
391 SetEndOfFile (self
->file_handle
);
392 /* Create another mapping object and remap the file view */
393 self
->map_handle
= CreateFileMapping (
400 if (self
->map_handle
!= NULL
) {
401 self
->data
= (char *) MapViewOfFile (self
->map_handle
,
406 if (self
->data
!= NULL
) {
407 self
->size
= new_size
;
411 dwErrCode
= GetLastError();
414 dwErrCode
= GetLastError();
416 PyErr_SetFromWindowsErr(dwErrCode
);
418 #endif /* MS_WINDOWS */
423 PyErr_SetString(PyExc_SystemError
,
424 "mmap: resizing not available--no mremap()");
430 if (ftruncate(self
->fd
, new_size
) == -1) {
431 PyErr_SetFromErrno(mmap_module_error
);
435 #ifdef MREMAP_MAYMOVE
436 newmap
= mremap(self
->data
, self
->size
, new_size
, MREMAP_MAYMOVE
);
438 newmap
= mremap(self
->data
, self
->size
, new_size
, 0);
440 if (newmap
== (void *)-1)
442 PyErr_SetFromErrno(mmap_module_error
);
446 self
->size
= new_size
;
449 #endif /* HAVE_MREMAP */
455 mmap_tell_method(mmap_object
*self
, PyObject
*args
)
458 if (!PyArg_ParseTuple(args
, ":tell"))
460 return (Py_BuildValue ("l", (long) self
->pos
) );
464 mmap_flush_method(mmap_object
*self
, PyObject
*args
)
466 unsigned long offset
= 0;
467 unsigned long size
= self
->size
;
469 if (!PyArg_ParseTuple (args
, "|kk:flush", &offset
, &size
)) {
471 } else if ((offset
+ size
) > self
->size
) {
472 PyErr_SetString (PyExc_ValueError
,
473 "flush values out of range");
477 return (Py_BuildValue("l", (long)
478 FlushViewOfFile(self
->data
+offset
, size
)));
479 #endif /* MS_WINDOWS */
481 /* XXX semantics of return value? */
482 /* XXX flags for msync? */
483 if (-1 == msync(self
->data
+ offset
, size
,
486 PyErr_SetFromErrno(mmap_module_error
);
489 return Py_BuildValue ("l", (long) 0);
495 mmap_seek_method(mmap_object
*self
, PyObject
*args
)
500 if (!PyArg_ParseTuple (args
, "i|i:seek", &dist
, &how
)) {
505 case 0: /* relative to start */
510 case 1: /* relative to current position */
511 if ((int)self
->pos
+ dist
< 0)
513 where
= self
->pos
+ dist
;
515 case 2: /* relative to end */
516 if ((int)self
->size
+ dist
< 0)
518 where
= self
->size
+ dist
;
521 PyErr_SetString (PyExc_ValueError
,
522 "unknown seek type");
525 if (where
> self
->size
)
533 PyErr_SetString (PyExc_ValueError
, "seek out of range");
538 mmap_move_method(mmap_object
*self
, PyObject
*args
)
540 unsigned long dest
, src
, count
;
542 if (!PyArg_ParseTuple (args
, "kkk:move", &dest
, &src
, &count
) ||
543 !is_writeable(self
)) {
546 /* bounds check the values */
547 if (/* end of source after end of data?? */
548 ((src
+count
) > self
->size
)
550 || (dest
+count
> self
->size
)) {
551 PyErr_SetString (PyExc_ValueError
,
552 "source or destination out of range");
555 memmove (self
->data
+dest
, self
->data
+src
, count
);
562 static struct PyMethodDef mmap_object_methods
[] = {
563 {"close", (PyCFunction
) mmap_close_method
, METH_VARARGS
},
564 {"find", (PyCFunction
) mmap_find_method
, METH_VARARGS
},
565 {"flush", (PyCFunction
) mmap_flush_method
, METH_VARARGS
},
566 {"move", (PyCFunction
) mmap_move_method
, METH_VARARGS
},
567 {"read", (PyCFunction
) mmap_read_method
, METH_VARARGS
},
568 {"read_byte", (PyCFunction
) mmap_read_byte_method
, METH_VARARGS
},
569 {"readline", (PyCFunction
) mmap_read_line_method
, METH_VARARGS
},
570 {"resize", (PyCFunction
) mmap_resize_method
, METH_VARARGS
},
571 {"seek", (PyCFunction
) mmap_seek_method
, METH_VARARGS
},
572 {"size", (PyCFunction
) mmap_size_method
, METH_VARARGS
},
573 {"tell", (PyCFunction
) mmap_tell_method
, METH_VARARGS
},
574 {"write", (PyCFunction
) mmap_write_method
, METH_VARARGS
},
575 {"write_byte", (PyCFunction
) mmap_write_byte_method
, METH_VARARGS
},
576 {NULL
, NULL
} /* sentinel */
579 /* Functions for treating an mmap'ed file as a buffer */
582 mmap_buffer_getreadbuf(mmap_object
*self
, int index
, const void **ptr
)
586 PyErr_SetString(PyExc_SystemError
,
587 "Accessing non-existent mmap segment");
595 mmap_buffer_getwritebuf(mmap_object
*self
, int index
, const void **ptr
)
599 PyErr_SetString(PyExc_SystemError
,
600 "Accessing non-existent mmap segment");
603 if (!is_writeable(self
))
610 mmap_buffer_getsegcount(mmap_object
*self
, int *lenp
)
619 mmap_buffer_getcharbuffer(mmap_object
*self
, int index
, const void **ptr
)
622 PyErr_SetString(PyExc_SystemError
,
623 "accessing non-existent buffer segment");
626 *ptr
= (const char *)self
->data
;
631 mmap_object_getattr(mmap_object
*self
, char *name
)
633 return Py_FindMethod (mmap_object_methods
, (PyObject
*)self
, name
);
637 mmap_length(mmap_object
*self
)
644 mmap_item(mmap_object
*self
, int i
)
647 if (i
< 0 || (size_t)i
>= self
->size
) {
648 PyErr_SetString(PyExc_IndexError
, "mmap index out of range");
651 return PyString_FromStringAndSize(self
->data
+ i
, 1);
655 mmap_slice(mmap_object
*self
, int ilow
, int ihigh
)
660 else if ((size_t)ilow
> self
->size
)
666 else if ((size_t)ihigh
> self
->size
)
669 return PyString_FromStringAndSize(self
->data
+ ilow
, ihigh
-ilow
);
673 mmap_concat(mmap_object
*self
, PyObject
*bb
)
676 PyErr_SetString(PyExc_SystemError
,
677 "mmaps don't support concatenation");
682 mmap_repeat(mmap_object
*self
, int n
)
685 PyErr_SetString(PyExc_SystemError
,
686 "mmaps don't support repeat operation");
691 mmap_ass_slice(mmap_object
*self
, int ilow
, int ihigh
, PyObject
*v
)
698 else if ((size_t)ilow
> self
->size
)
704 else if ((size_t)ihigh
> self
->size
)
708 PyErr_SetString(PyExc_TypeError
,
709 "mmap object doesn't support slice deletion");
712 if (! (PyString_Check(v
)) ) {
713 PyErr_SetString(PyExc_IndexError
,
714 "mmap slice assignment must be a string");
717 if ( PyString_Size(v
) != (ihigh
- ilow
) ) {
718 PyErr_SetString(PyExc_IndexError
,
719 "mmap slice assignment is wrong size");
722 if (!is_writeable(self
))
724 buf
= PyString_AsString(v
);
725 memcpy(self
->data
+ ilow
, buf
, ihigh
-ilow
);
730 mmap_ass_item(mmap_object
*self
, int i
, PyObject
*v
)
735 if (i
< 0 || (size_t)i
>= self
->size
) {
736 PyErr_SetString(PyExc_IndexError
, "mmap index out of range");
740 PyErr_SetString(PyExc_TypeError
,
741 "mmap object doesn't support item deletion");
744 if (! (PyString_Check(v
) && PyString_Size(v
)==1) ) {
745 PyErr_SetString(PyExc_IndexError
,
746 "mmap assignment must be single-character string");
749 if (!is_writeable(self
))
751 buf
= PyString_AsString(v
);
752 self
->data
[i
] = buf
[0];
756 static PySequenceMethods mmap_as_sequence
= {
757 (inquiry
)mmap_length
, /*sq_length*/
758 (binaryfunc
)mmap_concat
, /*sq_concat*/
759 (intargfunc
)mmap_repeat
, /*sq_repeat*/
760 (intargfunc
)mmap_item
, /*sq_item*/
761 (intintargfunc
)mmap_slice
, /*sq_slice*/
762 (intobjargproc
)mmap_ass_item
, /*sq_ass_item*/
763 (intintobjargproc
)mmap_ass_slice
, /*sq_ass_slice*/
766 static PyBufferProcs mmap_as_buffer
= {
767 (getreadbufferproc
)mmap_buffer_getreadbuf
,
768 (getwritebufferproc
)mmap_buffer_getwritebuf
,
769 (getsegcountproc
)mmap_buffer_getsegcount
,
770 (getcharbufferproc
)mmap_buffer_getcharbuffer
,
773 static PyTypeObject mmap_object_type
= {
774 PyObject_HEAD_INIT(0) /* patched in module init */
776 "mmap.mmap", /* tp_name */
777 sizeof(mmap_object
), /* tp_size */
780 (destructor
) mmap_object_dealloc
, /* tp_dealloc */
782 (getattrfunc
) mmap_object_getattr
, /* tp_getattr */
786 0, /* tp_as_number */
787 &mmap_as_sequence
, /*tp_as_sequence*/
794 &mmap_as_buffer
, /*tp_as_buffer*/
795 Py_TPFLAGS_HAVE_GETCHARBUFFER
, /*tp_flags*/
800 /* extract the map size from the given PyObject
802 The map size is restricted to [0, INT_MAX] because this is the current
803 Python limitation on object sizes. Although the mmap object *could* handle
804 a larger map size, there is no point because all the useful operations
805 (len(), slicing(), sequence indexing) are limited by a C int.
807 Returns -1 on error, with an appropriate Python exception raised. On
808 success, the map size is returned. */
810 _GetMapSize(PyObject
*o
)
812 if (PyInt_Check(o
)) {
813 long i
= PyInt_AsLong(o
);
814 if (PyErr_Occurred())
822 else if (PyLong_Check(o
)) {
823 long i
= PyLong_AsLong(o
);
824 if (PyErr_Occurred()) {
825 /* yes negative overflow is mistaken for positive overflow
826 but not worth the trouble to check sign of 'i' */
827 if (PyErr_ExceptionMatches(PyExc_OverflowError
))
839 PyErr_SetString(PyExc_TypeError
,
840 "map size must be an integral value");
845 PyErr_SetString(PyExc_OverflowError
,
846 "memory mapped size must be positive");
850 PyErr_SetString(PyExc_OverflowError
,
851 "memory mapped size is too large (limited by C int)");
857 new_mmap_object(PyObject
*self
, PyObject
*args
, PyObject
*kwdict
)
863 PyObject
*map_size_obj
= NULL
;
865 int fd
, flags
= MAP_SHARED
, prot
= PROT_WRITE
| PROT_READ
;
866 int access
= (int)ACCESS_DEFAULT
;
867 static const char *keywords
[] = {"fileno", "length",
871 if (!PyArg_ParseTupleAndKeywords(args
, kwdict
, "iO|iii", keywords
,
872 &fd
, &map_size_obj
, &flags
, &prot
,
875 map_size
= _GetMapSize(map_size_obj
);
879 if ((access
!= (int)ACCESS_DEFAULT
) &&
880 ((flags
!= MAP_SHARED
) || ( prot
!= (PROT_WRITE
| PROT_READ
))))
881 return PyErr_Format(PyExc_ValueError
,
882 "mmap can't specify both access and flags, prot.");
883 switch((access_mode
)access
) {
890 prot
= PROT_READ
| PROT_WRITE
;
894 prot
= PROT_READ
| PROT_WRITE
;
897 /* use the specified or default values of flags and prot */
900 return PyErr_Format(PyExc_ValueError
,
901 "mmap invalid access parameter.");
906 /* on OpenVMS we must ensure that all bytes are written to the file */
909 if (fstat(fd
, &st
) == 0 && S_ISREG(st
.st_mode
)) {
911 map_size
= (int)st
.st_size
;
912 } else if ((size_t)map_size
> st
.st_size
) {
913 PyErr_SetString(PyExc_ValueError
,
914 "mmap length is greater than file size");
919 m_obj
= PyObject_New (mmap_object
, &mmap_object_type
);
920 if (m_obj
== NULL
) {return NULL
;}
922 m_obj
->size
= (size_t) map_size
;
923 m_obj
->pos
= (size_t) 0;
925 if (m_obj
->fd
== -1) {
927 PyErr_SetFromErrno(mmap_module_error
);
930 m_obj
->data
= mmap(NULL
, map_size
,
933 if (m_obj
->data
== (char *)-1) {
936 PyErr_SetFromErrno(mmap_module_error
);
939 m_obj
->access
= (access_mode
)access
;
940 return (PyObject
*)m_obj
;
946 new_mmap_object(PyObject
*self
, PyObject
*args
, PyObject
*kwdict
)
949 PyObject
*map_size_obj
= NULL
;
955 int access
= (access_mode
)ACCESS_DEFAULT
;
956 DWORD flProtect
, dwDesiredAccess
;
957 static const char *keywords
[] = { "fileno", "length",
961 if (!PyArg_ParseTupleAndKeywords(args
, kwdict
, "iO|zi", keywords
,
962 &fileno
, &map_size_obj
,
963 &tagname
, &access
)) {
967 switch((access_mode
)access
) {
969 flProtect
= PAGE_READONLY
;
970 dwDesiredAccess
= FILE_MAP_READ
;
972 case ACCESS_DEFAULT
: case ACCESS_WRITE
:
973 flProtect
= PAGE_READWRITE
;
974 dwDesiredAccess
= FILE_MAP_WRITE
;
977 flProtect
= PAGE_WRITECOPY
;
978 dwDesiredAccess
= FILE_MAP_COPY
;
981 return PyErr_Format(PyExc_ValueError
,
982 "mmap invalid access parameter.");
985 map_size
= _GetMapSize(map_size_obj
);
989 /* if an actual filename has been specified */
991 fh
= (HANDLE
)_get_osfhandle(fileno
);
992 if (fh
==(HANDLE
)-1) {
993 PyErr_SetFromErrno(mmap_module_error
);
996 /* Win9x appears to need us seeked to zero */
997 lseek(fileno
, 0, SEEK_SET
);
1000 m_obj
= PyObject_New (mmap_object
, &mmap_object_type
);
1003 /* Set every field to an invalid marker, so we can safely
1004 destruct the object in the face of failure */
1006 m_obj
->file_handle
= INVALID_HANDLE_VALUE
;
1007 m_obj
->map_handle
= INVALID_HANDLE_VALUE
;
1008 m_obj
->tagname
= NULL
;
1011 /* It is necessary to duplicate the handle, so the
1012 Python code can close it on us */
1013 if (!DuplicateHandle(
1014 GetCurrentProcess(), /* source process handle */
1015 fh
, /* handle to be duplicated */
1016 GetCurrentProcess(), /* target proc handle */
1017 (LPHANDLE
)&m_obj
->file_handle
, /* result */
1018 0, /* access - ignored due to options value */
1019 FALSE
, /* inherited by child processes? */
1020 DUPLICATE_SAME_ACCESS
)) { /* options */
1021 dwErr
= GetLastError();
1023 PyErr_SetFromWindowsErr(dwErr
);
1027 m_obj
->size
= GetFileSize (fh
, NULL
);
1029 m_obj
->size
= map_size
;
1033 m_obj
->size
= map_size
;
1036 /* set the initial position */
1037 m_obj
->pos
= (size_t) 0;
1039 /* set the tag name */
1040 if (tagname
!= NULL
&& *tagname
!= '\0') {
1041 m_obj
->tagname
= PyMem_Malloc(strlen(tagname
)+1);
1042 if (m_obj
->tagname
== NULL
) {
1047 strcpy(m_obj
->tagname
, tagname
);
1050 m_obj
->tagname
= NULL
;
1052 m_obj
->access
= (access_mode
)access
;
1053 m_obj
->map_handle
= CreateFileMapping (m_obj
->file_handle
,
1059 if (m_obj
->map_handle
!= NULL
) {
1060 m_obj
->data
= (char *) MapViewOfFile (m_obj
->map_handle
,
1065 if (m_obj
->data
!= NULL
) {
1066 return ((PyObject
*) m_obj
);
1068 dwErr
= GetLastError();
1071 dwErr
= GetLastError();
1074 PyErr_SetFromWindowsErr(dwErr
);
1077 #endif /* MS_WINDOWS */
1079 /* List of functions exported by this module */
1080 static struct PyMethodDef mmap_functions
[] = {
1081 {"mmap", (PyCFunction
) new_mmap_object
,
1082 METH_VARARGS
|METH_KEYWORDS
},
1083 {NULL
, NULL
} /* Sentinel */
1089 PyObject
*dict
, *module
;
1091 /* Patch the object type */
1092 mmap_object_type
.ob_type
= &PyType_Type
;
1094 module
= Py_InitModule ("mmap", mmap_functions
);
1095 dict
= PyModule_GetDict (module
);
1096 mmap_module_error
= PyExc_EnvironmentError
;
1097 Py_INCREF(mmap_module_error
);
1098 PyDict_SetItemString (dict
, "error", mmap_module_error
);
1100 PyDict_SetItemString (dict
, "PROT_EXEC", PyInt_FromLong(PROT_EXEC
) );
1103 PyDict_SetItemString (dict
, "PROT_READ", PyInt_FromLong(PROT_READ
) );
1106 PyDict_SetItemString (dict
, "PROT_WRITE", PyInt_FromLong(PROT_WRITE
) );
1110 PyDict_SetItemString (dict
, "MAP_SHARED", PyInt_FromLong(MAP_SHARED
) );
1113 PyDict_SetItemString (dict
, "MAP_PRIVATE",
1114 PyInt_FromLong(MAP_PRIVATE
) );
1116 #ifdef MAP_DENYWRITE
1117 PyDict_SetItemString (dict
, "MAP_DENYWRITE",
1118 PyInt_FromLong(MAP_DENYWRITE
) );
1120 #ifdef MAP_EXECUTABLE
1121 PyDict_SetItemString (dict
, "MAP_EXECUTABLE",
1122 PyInt_FromLong(MAP_EXECUTABLE
) );
1125 PyDict_SetItemString (dict
, "MAP_ANON", PyInt_FromLong(MAP_ANON
) );
1126 PyDict_SetItemString (dict
, "MAP_ANONYMOUS",
1127 PyInt_FromLong(MAP_ANON
) );
1130 PyDict_SetItemString (dict
, "PAGESIZE",
1131 PyInt_FromLong( (long)my_getpagesize() ) );
1133 PyDict_SetItemString (dict
, "ACCESS_READ",
1134 PyInt_FromLong(ACCESS_READ
));
1135 PyDict_SetItemString (dict
, "ACCESS_WRITE",
1136 PyInt_FromLong(ACCESS_WRITE
));
1137 PyDict_SetItemString (dict
, "ACCESS_COPY",
1138 PyInt_FromLong(ACCESS_COPY
));