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_WIN32 */
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_WIN32 */
144 munmap(self
->data
, self
->size
);
153 #define CHECK_VALID(err) \
155 if (!self->map_handle) { \
156 PyErr_SetString (PyExc_ValueError, "mmap closed or invalid"); \
160 #endif /* MS_WIN32 */
163 #define CHECK_VALID(err) \
165 if (self->data == NULL) { \
166 PyErr_SetString (PyExc_ValueError, "mmap closed or invalid"); \
173 mmap_read_byte_method(mmap_object
*self
,
177 if (!PyArg_ParseTuple(args
, ":read_byte"))
179 if (self
->pos
< self
->size
) {
180 char value
= self
->data
[self
->pos
];
182 return Py_BuildValue("c", value
);
184 PyErr_SetString (PyExc_ValueError
, "read byte out of range");
190 mmap_read_line_method(mmap_object
*self
,
193 char *start
= self
->data
+self
->pos
;
194 char *eof
= self
->data
+self
->size
;
199 if (!PyArg_ParseTuple(args
, ":readline"))
202 eol
= memchr(start
, '\n', self
->size
- self
->pos
);
206 ++eol
; /* we're interested in the position after the
208 result
= PyString_FromStringAndSize(start
, (eol
- start
));
209 self
->pos
+= (eol
- start
);
214 mmap_read_method(mmap_object
*self
,
221 if (!PyArg_ParseTuple(args
, "l:read", &num_bytes
))
224 /* silently 'adjust' out-of-range requests */
225 if ((self
->pos
+ num_bytes
) > self
->size
) {
226 num_bytes
-= (self
->pos
+num_bytes
) - self
->size
;
228 result
= Py_BuildValue("s#", self
->data
+self
->pos
, num_bytes
);
229 self
->pos
+= num_bytes
;
234 mmap_find_method(mmap_object
*self
,
237 long start
= self
->pos
;
242 if (!PyArg_ParseTuple (args
, "s#|l:find", &needle
, &len
, &start
)) {
246 char *e
= self
->data
+ self
->size
;
252 else if ((size_t)start
> self
->size
)
255 for (p
= self
->data
+ start
; p
+ len
<= e
; ++p
) {
257 for (i
= 0; i
< len
&& needle
[i
] == p
[i
]; ++i
)
260 return Py_BuildValue (
262 (long) (p
- self
->data
));
265 return Py_BuildValue ("l", (long) -1);
270 is_writeable(mmap_object
*self
)
272 if (self
->access
!= ACCESS_READ
)
274 PyErr_Format(PyExc_TypeError
, "mmap can't modify a readonly memory map.");
279 is_resizeable(mmap_object
*self
)
281 if ((self
->access
== ACCESS_WRITE
) || (self
->access
== ACCESS_DEFAULT
))
283 PyErr_Format(PyExc_TypeError
,
284 "mmap can't resize a readonly or copy-on-write memory map.");
290 mmap_write_method(mmap_object
*self
,
297 if (!PyArg_ParseTuple (args
, "s#:write", &data
, &length
))
300 if (!is_writeable(self
))
303 if ((self
->pos
+ length
) > self
->size
) {
304 PyErr_SetString (PyExc_ValueError
, "data out of range");
307 memcpy (self
->data
+self
->pos
, data
, length
);
308 self
->pos
= self
->pos
+length
;
314 mmap_write_byte_method(mmap_object
*self
,
320 if (!PyArg_ParseTuple (args
, "c:write_byte", &value
))
323 if (!is_writeable(self
))
325 *(self
->data
+self
->pos
) = value
;
332 mmap_size_method(mmap_object
*self
,
336 if (!PyArg_ParseTuple(args
, ":size"))
340 if (self
->file_handle
!= INVALID_HANDLE_VALUE
) {
341 return (Py_BuildValue (
343 GetFileSize (self
->file_handle
, NULL
)));
345 return (Py_BuildValue ("l", (long) self
->size
) );
347 #endif /* MS_WIN32 */
352 if (-1 == fstat(self
->fd
, &buf
)) {
353 PyErr_SetFromErrno(mmap_module_error
);
356 return (Py_BuildValue ("l", (long) buf
.st_size
) );
361 /* This assumes that you want the entire file mapped,
362 / and when recreating the map will make the new file
365 / Is this really necessary? This could easily be done
366 / from python by just closing and re-opening with the
371 mmap_resize_method(mmap_object
*self
,
374 unsigned long new_size
;
376 if (!PyArg_ParseTuple (args
, "l:resize", &new_size
) ||
377 !is_resizeable(self
)) {
382 /* First, unmap the file view */
383 UnmapViewOfFile (self
->data
);
384 /* Close the mapping object */
385 CloseHandle (self
->map_handle
);
386 /* Move to the desired EOF position */
387 SetFilePointer (self
->file_handle
,
388 new_size
, NULL
, FILE_BEGIN
);
389 /* Change the size of the file */
390 SetEndOfFile (self
->file_handle
);
391 /* Create another mapping object and remap the file view */
392 self
->map_handle
= CreateFileMapping (
399 if (self
->map_handle
!= NULL
) {
400 self
->data
= (char *) MapViewOfFile (self
->map_handle
,
405 if (self
->data
!= NULL
) {
406 self
->size
= new_size
;
410 dwErrCode
= GetLastError();
413 dwErrCode
= GetLastError();
415 PyErr_SetFromWindowsErr(dwErrCode
);
417 #endif /* MS_WIN32 */
422 PyErr_SetString(PyExc_SystemError
,
423 "mmap: resizing not available--no mremap()");
429 #ifdef MREMAP_MAYMOVE
430 newmap
= mremap(self
->data
, self
->size
, new_size
, MREMAP_MAYMOVE
);
432 newmap
= mremap(self
->data
, self
->size
, new_size
, 0);
434 if (newmap
== (void *)-1)
436 PyErr_SetFromErrno(mmap_module_error
);
440 self
->size
= new_size
;
443 #endif /* HAVE_MREMAP */
449 mmap_tell_method(mmap_object
*self
, PyObject
*args
)
452 if (!PyArg_ParseTuple(args
, ":tell"))
454 return (Py_BuildValue ("l", (long) self
->pos
) );
458 mmap_flush_method(mmap_object
*self
, PyObject
*args
)
461 size_t size
= self
->size
;
463 if (!PyArg_ParseTuple (args
, "|ll:flush", &offset
, &size
)) {
465 } else if ((offset
+ size
) > self
->size
) {
466 PyErr_SetString (PyExc_ValueError
,
467 "flush values out of range");
471 return (Py_BuildValue("l", (long)
472 FlushViewOfFile(self
->data
+offset
, size
)));
473 #endif /* MS_WIN32 */
475 /* XXX semantics of return value? */
476 /* XXX flags for msync? */
477 if (-1 == msync(self
->data
+ offset
, size
,
480 PyErr_SetFromErrno(mmap_module_error
);
483 return Py_BuildValue ("l", (long) 0);
489 mmap_seek_method(mmap_object
*self
, PyObject
*args
)
494 if (!PyArg_ParseTuple (args
, "i|i:seek", &dist
, &how
)) {
499 case 0: /* relative to start */
504 case 1: /* relative to current position */
505 if ((int)self
->pos
+ dist
< 0)
507 where
= self
->pos
+ dist
;
509 case 2: /* relative to end */
510 if ((int)self
->size
+ dist
< 0)
512 where
= self
->size
+ dist
;
515 PyErr_SetString (PyExc_ValueError
,
516 "unknown seek type");
519 if (where
> self
->size
)
527 PyErr_SetString (PyExc_ValueError
, "seek out of range");
532 mmap_move_method(mmap_object
*self
, PyObject
*args
)
534 unsigned long dest
, src
, count
;
536 if (!PyArg_ParseTuple (args
, "iii:move", &dest
, &src
, &count
) ||
537 !is_writeable(self
)) {
540 /* bounds check the values */
541 if (/* end of source after end of data?? */
542 ((src
+count
) > self
->size
)
544 || (dest
+count
> self
->size
)) {
545 PyErr_SetString (PyExc_ValueError
,
546 "source or destination out of range");
549 memmove (self
->data
+dest
, self
->data
+src
, count
);
556 static struct PyMethodDef mmap_object_methods
[] = {
557 {"close", (PyCFunction
) mmap_close_method
, METH_VARARGS
},
558 {"find", (PyCFunction
) mmap_find_method
, METH_VARARGS
},
559 {"flush", (PyCFunction
) mmap_flush_method
, METH_VARARGS
},
560 {"move", (PyCFunction
) mmap_move_method
, METH_VARARGS
},
561 {"read", (PyCFunction
) mmap_read_method
, METH_VARARGS
},
562 {"read_byte", (PyCFunction
) mmap_read_byte_method
, METH_VARARGS
},
563 {"readline", (PyCFunction
) mmap_read_line_method
, METH_VARARGS
},
564 {"resize", (PyCFunction
) mmap_resize_method
, METH_VARARGS
},
565 {"seek", (PyCFunction
) mmap_seek_method
, METH_VARARGS
},
566 {"size", (PyCFunction
) mmap_size_method
, METH_VARARGS
},
567 {"tell", (PyCFunction
) mmap_tell_method
, METH_VARARGS
},
568 {"write", (PyCFunction
) mmap_write_method
, METH_VARARGS
},
569 {"write_byte", (PyCFunction
) mmap_write_byte_method
, METH_VARARGS
},
570 {NULL
, NULL
} /* sentinel */
573 /* Functions for treating an mmap'ed file as a buffer */
576 mmap_buffer_getreadbuf(mmap_object
*self
, int index
, const void **ptr
)
580 PyErr_SetString(PyExc_SystemError
,
581 "Accessing non-existent mmap segment");
589 mmap_buffer_getwritebuf(mmap_object
*self
, int index
, const void **ptr
)
593 PyErr_SetString(PyExc_SystemError
,
594 "Accessing non-existent mmap segment");
597 if (!is_writeable(self
))
604 mmap_buffer_getsegcount(mmap_object
*self
, int *lenp
)
613 mmap_buffer_getcharbuffer(mmap_object
*self
, int index
, const void **ptr
)
616 PyErr_SetString(PyExc_SystemError
,
617 "accessing non-existent buffer segment");
620 *ptr
= (const char *)self
->data
;
625 mmap_object_getattr(mmap_object
*self
, char *name
)
627 return Py_FindMethod (mmap_object_methods
, (PyObject
*)self
, name
);
631 mmap_length(mmap_object
*self
)
638 mmap_item(mmap_object
*self
, int i
)
641 if (i
< 0 || (size_t)i
>= self
->size
) {
642 PyErr_SetString(PyExc_IndexError
, "mmap index out of range");
645 return PyString_FromStringAndSize(self
->data
+ i
, 1);
649 mmap_slice(mmap_object
*self
, int ilow
, int ihigh
)
654 else if ((size_t)ilow
> self
->size
)
660 else if ((size_t)ihigh
> self
->size
)
663 return PyString_FromStringAndSize(self
->data
+ ilow
, ihigh
-ilow
);
667 mmap_concat(mmap_object
*self
, PyObject
*bb
)
670 PyErr_SetString(PyExc_SystemError
,
671 "mmaps don't support concatenation");
676 mmap_repeat(mmap_object
*self
, int n
)
679 PyErr_SetString(PyExc_SystemError
,
680 "mmaps don't support repeat operation");
685 mmap_ass_slice(mmap_object
*self
, int ilow
, int ihigh
, PyObject
*v
)
692 else if ((size_t)ilow
> self
->size
)
698 else if ((size_t)ihigh
> self
->size
)
702 PyErr_SetString(PyExc_TypeError
,
703 "mmap object doesn't support slice deletion");
706 if (! (PyString_Check(v
)) ) {
707 PyErr_SetString(PyExc_IndexError
,
708 "mmap slice assignment must be a string");
711 if ( PyString_Size(v
) != (ihigh
- ilow
) ) {
712 PyErr_SetString(PyExc_IndexError
,
713 "mmap slice assignment is wrong size");
716 if (!is_writeable(self
))
718 buf
= PyString_AsString(v
);
719 memcpy(self
->data
+ ilow
, buf
, ihigh
-ilow
);
724 mmap_ass_item(mmap_object
*self
, int i
, PyObject
*v
)
729 if (i
< 0 || (size_t)i
>= self
->size
) {
730 PyErr_SetString(PyExc_IndexError
, "mmap index out of range");
734 PyErr_SetString(PyExc_TypeError
,
735 "mmap object doesn't support item deletion");
738 if (! (PyString_Check(v
) && PyString_Size(v
)==1) ) {
739 PyErr_SetString(PyExc_IndexError
,
740 "mmap assignment must be single-character string");
743 if (!is_writeable(self
))
745 buf
= PyString_AsString(v
);
746 self
->data
[i
] = buf
[0];
750 static PySequenceMethods mmap_as_sequence
= {
751 (inquiry
)mmap_length
, /*sq_length*/
752 (binaryfunc
)mmap_concat
, /*sq_concat*/
753 (intargfunc
)mmap_repeat
, /*sq_repeat*/
754 (intargfunc
)mmap_item
, /*sq_item*/
755 (intintargfunc
)mmap_slice
, /*sq_slice*/
756 (intobjargproc
)mmap_ass_item
, /*sq_ass_item*/
757 (intintobjargproc
)mmap_ass_slice
, /*sq_ass_slice*/
760 static PyBufferProcs mmap_as_buffer
= {
761 (getreadbufferproc
)mmap_buffer_getreadbuf
,
762 (getwritebufferproc
)mmap_buffer_getwritebuf
,
763 (getsegcountproc
)mmap_buffer_getsegcount
,
764 (getcharbufferproc
)mmap_buffer_getcharbuffer
,
767 static PyTypeObject mmap_object_type
= {
768 PyObject_HEAD_INIT(0) /* patched in module init */
770 "mmap.mmap", /* tp_name */
771 sizeof(mmap_object
), /* tp_size */
774 (destructor
) mmap_object_dealloc
, /* tp_dealloc */
776 (getattrfunc
) mmap_object_getattr
, /* tp_getattr */
780 0, /* tp_as_number */
781 &mmap_as_sequence
, /*tp_as_sequence*/
788 &mmap_as_buffer
, /*tp_as_buffer*/
789 Py_TPFLAGS_HAVE_GETCHARBUFFER
, /*tp_flags*/
794 /* extract the map size from the given PyObject
796 The map size is restricted to [0, INT_MAX] because this is the current
797 Python limitation on object sizes. Although the mmap object *could* handle
798 a larger map size, there is no point because all the useful operations
799 (len(), slicing(), sequence indexing) are limited by a C int.
801 Returns -1 on error, with an appropriate Python exception raised. On
802 success, the map size is returned. */
804 _GetMapSize(PyObject
*o
)
806 if (PyInt_Check(o
)) {
807 long i
= PyInt_AsLong(o
);
808 if (PyErr_Occurred())
816 else if (PyLong_Check(o
)) {
817 long i
= PyLong_AsLong(o
);
818 if (PyErr_Occurred()) {
819 /* yes negative overflow is mistaken for positive overflow
820 but not worth the trouble to check sign of 'i' */
821 if (PyErr_ExceptionMatches(PyExc_OverflowError
))
833 PyErr_SetString(PyExc_TypeError
,
834 "map size must be an integral value");
839 PyErr_SetString(PyExc_OverflowError
,
840 "memory mapped size must be positive");
844 PyErr_SetString(PyExc_OverflowError
,
845 "memory mapped size is too large (limited by C int)");
851 new_mmap_object(PyObject
*self
, PyObject
*args
, PyObject
*kwdict
)
854 PyObject
*map_size_obj
= NULL
;
856 int fd
, flags
= MAP_SHARED
, prot
= PROT_WRITE
| PROT_READ
;
857 access_mode access
= ACCESS_DEFAULT
;
858 char *keywords
[] = {"fileno", "length",
862 if (!PyArg_ParseTupleAndKeywords(args
, kwdict
, "iO|iii", keywords
,
863 &fd
, &map_size_obj
, &flags
, &prot
, &access
))
865 map_size
= _GetMapSize(map_size_obj
);
869 if ((access
!= ACCESS_DEFAULT
) &&
870 ((flags
!= MAP_SHARED
) || ( prot
!= (PROT_WRITE
| PROT_READ
))))
871 return PyErr_Format(PyExc_ValueError
,
872 "mmap can't specify both access and flags, prot.");
880 prot
= PROT_READ
| PROT_WRITE
;
884 prot
= PROT_READ
| PROT_WRITE
;
887 /* use the specified or default values of flags and prot */
890 return PyErr_Format(PyExc_ValueError
,
891 "mmap invalid access parameter.");
894 m_obj
= PyObject_New (mmap_object
, &mmap_object_type
);
895 if (m_obj
== NULL
) {return NULL
;}
896 m_obj
->size
= (size_t) map_size
;
897 m_obj
->pos
= (size_t) 0;
899 m_obj
->data
= mmap(NULL
, map_size
,
902 if (m_obj
->data
== (char *)-1) {
904 PyErr_SetFromErrno(mmap_module_error
);
907 m_obj
->access
= access
;
908 return (PyObject
*)m_obj
;
914 new_mmap_object(PyObject
*self
, PyObject
*args
, PyObject
*kwdict
)
917 PyObject
*map_size_obj
= NULL
;
923 access_mode access
= ACCESS_DEFAULT
;
924 DWORD flProtect
, dwDesiredAccess
;
925 char *keywords
[] = { "fileno", "length",
929 if (!PyArg_ParseTupleAndKeywords(args
, kwdict
, "iO|zi", keywords
,
930 &fileno
, &map_size_obj
,
931 &tagname
, &access
)) {
937 flProtect
= PAGE_READONLY
;
938 dwDesiredAccess
= FILE_MAP_READ
;
940 case ACCESS_DEFAULT
: case ACCESS_WRITE
:
941 flProtect
= PAGE_READWRITE
;
942 dwDesiredAccess
= FILE_MAP_WRITE
;
945 flProtect
= PAGE_WRITECOPY
;
946 dwDesiredAccess
= FILE_MAP_COPY
;
949 return PyErr_Format(PyExc_ValueError
,
950 "mmap invalid access parameter.");
953 map_size
= _GetMapSize(map_size_obj
);
957 /* if an actual filename has been specified */
959 fh
= (HANDLE
)_get_osfhandle(fileno
);
960 if (fh
==(HANDLE
)-1) {
961 PyErr_SetFromErrno(mmap_module_error
);
964 /* Win9x appears to need us seeked to zero */
965 fseek(&_iob
[fileno
], 0, SEEK_SET
);
968 m_obj
= PyObject_New (mmap_object
, &mmap_object_type
);
971 /* Set every field to an invalid marker, so we can safely
972 destruct the object in the face of failure */
974 m_obj
->file_handle
= INVALID_HANDLE_VALUE
;
975 m_obj
->map_handle
= INVALID_HANDLE_VALUE
;
976 m_obj
->tagname
= NULL
;
979 /* It is necessary to duplicate the handle, so the
980 Python code can close it on us */
981 if (!DuplicateHandle(
982 GetCurrentProcess(), /* source process handle */
983 fh
, /* handle to be duplicated */
984 GetCurrentProcess(), /* target proc handle */
985 (LPHANDLE
)&m_obj
->file_handle
, /* result */
986 0, /* access - ignored due to options value */
987 FALSE
, /* inherited by child processes? */
988 DUPLICATE_SAME_ACCESS
)) { /* options */
989 dwErr
= GetLastError();
991 PyErr_SetFromWindowsErr(dwErr
);
995 m_obj
->size
= GetFileSize (fh
, NULL
);
997 m_obj
->size
= map_size
;
1001 m_obj
->size
= map_size
;
1004 /* set the initial position */
1005 m_obj
->pos
= (size_t) 0;
1007 /* set the tag name */
1008 if (tagname
!= NULL
&& *tagname
!= '\0') {
1009 m_obj
->tagname
= PyMem_Malloc(strlen(tagname
)+1);
1010 if (m_obj
->tagname
== NULL
) {
1015 strcpy(m_obj
->tagname
, tagname
);
1018 m_obj
->tagname
= NULL
;
1020 m_obj
->access
= access
;
1021 m_obj
->map_handle
= CreateFileMapping (m_obj
->file_handle
,
1027 if (m_obj
->map_handle
!= NULL
) {
1028 m_obj
->data
= (char *) MapViewOfFile (m_obj
->map_handle
,
1033 if (m_obj
->data
!= NULL
) {
1034 return ((PyObject
*) m_obj
);
1036 dwErr
= GetLastError();
1039 dwErr
= GetLastError();
1042 PyErr_SetFromWindowsErr(dwErr
);
1045 #endif /* MS_WIN32 */
1047 /* List of functions exported by this module */
1048 static struct PyMethodDef mmap_functions
[] = {
1049 {"mmap", (PyCFunction
) new_mmap_object
,
1050 METH_VARARGS
|METH_KEYWORDS
},
1051 {NULL
, NULL
} /* Sentinel */
1057 PyObject
*dict
, *module
;
1059 /* Patch the object type */
1060 mmap_object_type
.ob_type
= &PyType_Type
;
1062 module
= Py_InitModule ("mmap", mmap_functions
);
1063 dict
= PyModule_GetDict (module
);
1064 mmap_module_error
= PyExc_EnvironmentError
;
1065 Py_INCREF(mmap_module_error
);
1066 PyDict_SetItemString (dict
, "error", mmap_module_error
);
1068 PyDict_SetItemString (dict
, "PROT_EXEC", PyInt_FromLong(PROT_EXEC
) );
1071 PyDict_SetItemString (dict
, "PROT_READ", PyInt_FromLong(PROT_READ
) );
1074 PyDict_SetItemString (dict
, "PROT_WRITE", PyInt_FromLong(PROT_WRITE
) );
1078 PyDict_SetItemString (dict
, "MAP_SHARED", PyInt_FromLong(MAP_SHARED
) );
1081 PyDict_SetItemString (dict
, "MAP_PRIVATE",
1082 PyInt_FromLong(MAP_PRIVATE
) );
1084 #ifdef MAP_DENYWRITE
1085 PyDict_SetItemString (dict
, "MAP_DENYWRITE",
1086 PyInt_FromLong(MAP_DENYWRITE
) );
1088 #ifdef MAP_EXECUTABLE
1089 PyDict_SetItemString (dict
, "MAP_EXECUTABLE",
1090 PyInt_FromLong(MAP_EXECUTABLE
) );
1093 PyDict_SetItemString (dict
, "MAP_ANON", PyInt_FromLong(MAP_ANON
) );
1094 PyDict_SetItemString (dict
, "MAP_ANONYMOUS",
1095 PyInt_FromLong(MAP_ANON
) );
1098 PyDict_SetItemString (dict
, "PAGESIZE",
1099 PyInt_FromLong( (long)my_getpagesize() ) );
1101 PyDict_SetItemString (dict
, "ACCESS_READ",
1102 PyInt_FromLong(ACCESS_READ
));
1103 PyDict_SetItemString (dict
, "ACCESS_WRITE",
1104 PyInt_FromLong(ACCESS_WRITE
));
1105 PyDict_SetItemString (dict
, "ACCESS_COPY",
1106 PyInt_FromLong(ACCESS_COPY
));