blob: bff22b2102851159782082e7f0669483ab60ba83 [file] [log] [blame]
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001/* -*- Mode: C++; tab-width: 4 -*-
2 / Author: Sam Rushing <rushing@nightmare.com>
3 / Hacked for Unix by A.M. Kuchling <amk1@bigfoot.com>
4 / $Id$
5
6 / mmapmodule.cpp -- map a view of a file into memory
7 /
8 / todo: need permission flags, perhaps a 'chsize' analog
9 / not all functions check range yet!!!
10 /
11 /
12 / Note: This module currently only deals with 32-bit file
13 / sizes.
14 /
15 / The latest version of mmapfile is maintained by Sam at
16 / ftp://squirl.nightmare.com/pub/python/python-ext.
17*/
18
19#ifndef MS_WIN32
20#define UNIX
21#endif
22
23#ifdef MS_WIN32
24#include <windows.h>
25#endif
26
27#ifdef UNIX
28#include <unistd.h>
29#include <sys/mman.h>
30#endif
31
32#include <Python.h>
33
34#include <string.h>
35#include <sys/types.h>
36
37static PyObject *mmap_module_error;
38
39typedef struct {
40 PyObject_HEAD
41 char * data;
42 size_t size;
43 size_t pos;
44
45#ifdef MS_WIN32
46 HANDLE map_handle;
47 HFILE file_handle;
48 char * tagname;
49#endif
50
51#ifdef UNIX
52 /* No Unix-specific information at this point in time */
53#endif
54} mmap_object;
55
56static void
57mmap_object_dealloc(mmap_object * m_obj)
58{
59#ifdef MS_WIN32
60 UnmapViewOfFile (m_obj->data);
61 CloseHandle (m_obj->map_handle);
62 CloseHandle ((HANDLE)m_obj->file_handle);
63#endif /* MS_WIN32 */
64
65#ifdef UNIX
66 if (m_obj->data!=NULL) {
67 msync(m_obj->data, m_obj->size, MS_SYNC | MS_INVALIDATE);
68 munmap(m_obj->data, m_obj->size);
69 }
70#endif /* UNIX */
71
72 PyMem_DEL(m_obj);
73}
74
75static PyObject *
76mmap_close_method (mmap_object * self, PyObject * args)
77{
78#ifdef MS_WIN32
79 UnmapViewOfFile (self->data);
80 CloseHandle (self->map_handle);
81 CloseHandle ((HANDLE)self->file_handle);
82 self->map_handle = (HANDLE) NULL;
83#endif /* MS_WIN32 */
84
85#ifdef UNIX
86 munmap(self->data, self->size);
87 self->data = NULL;
88#endif
89
90 Py_INCREF (Py_None);
91 return (Py_None);
92}
93
94#ifdef MS_WIN32
95#define CHECK_VALID(err) \
96do { \
97 if (!self->map_handle) { \
98 PyErr_SetString (PyExc_ValueError, "mmap closed or invalid");\
99 return err; \
100 } \
101} while (0)
102#endif /* MS_WIN32 */
103
104#ifdef UNIX
105#define CHECK_VALID(err) \
106do { \
107 if (self->data == NULL) { \
108 PyErr_SetString (PyExc_ValueError, "mmap closed or invalid"); \
109 return err; \
110 } \
111} while (0)
112#endif /* UNIX */
113
114static PyObject *
115mmap_read_byte_method (mmap_object * self,
116 PyObject * args)
117{
118 char value;
119 char * where = (self->data+self->pos);
120 CHECK_VALID(NULL);
121 if ((where >= 0) && (where < (self->data+self->size))) {
122 value = (char) *(where);
123 self->pos += 1;
124 return Py_BuildValue("c", (char) *(where));
125 } else {
126 PyErr_SetString (PyExc_ValueError, "read byte out of range");
127 return NULL;
128 }
129}
130
131static PyObject *
132mmap_read_line_method (mmap_object * self,
133 PyObject * args)
134{
135 char * start;
136 char * eof = self->data+self->size;
137 char * eol;
138 PyObject * result;
139
140 CHECK_VALID(NULL);
141 start = self->data+self->pos;
142
143 /* strchr was a bad idea here - there's no way to range
144 check it. there is no 'strnchr' */
145 for (eol = start; (eol < eof) && (*eol != '\n') ; eol++)
146 { /* do nothing */ }
147
148 result = Py_BuildValue("s#", start, (long) (++eol - start));
149 self->pos += (eol - start);
150 return (result);
151}
152
153static PyObject *
154mmap_read_method (mmap_object * self,
155 PyObject * args)
156{
157 long num_bytes;
158 PyObject *result;
159
160 CHECK_VALID(NULL);
161 if (!PyArg_ParseTuple (args, "l", &num_bytes))
162 return(NULL);
163
164 /* silently 'adjust' out-of-range requests */
165 if ((self->pos + num_bytes) > self->size) {
166 num_bytes -= (self->pos+num_bytes) - self->size;
167 }
168 result = Py_BuildValue("s#", self->data+self->pos, num_bytes);
169 self->pos += num_bytes;
170 return (result);
171}
172
173static PyObject *
174mmap_find_method (mmap_object *self,
175 PyObject *args)
176{
177 long start = self->pos;
178 char * needle;
179 int len;
180
181 CHECK_VALID(NULL);
182 if (!PyArg_ParseTuple (args, "s#|l", &needle, &len, &start)) {
183 return NULL;
184 } else {
185 char * p = self->data+self->pos;
186 char * e = self->data+self->size;
187 while (p < e) {
188 char * s = p;
189 char * n = needle;
190 while ((s<e) && (*n) && !(*s-*n)) {
191 s++, n++;
192 }
193 if (!*n) {
194 return Py_BuildValue ("l", (long) (p - (self->data + start)));
195 }
196 p++;
197 }
198 return Py_BuildValue ("l", (long) -1);
199 }
200}
201
202static PyObject *
203mmap_write_method (mmap_object * self,
204 PyObject * args)
205{
206 long length;
207 char * data;
208
209 CHECK_VALID(NULL);
210 if (!PyArg_ParseTuple (args, "s#", &data, &length))
211 return(NULL);
212
213 if ((self->pos + length) > self->size) {
214 PyErr_SetString (mmap_module_error, "data out of range");
215 return NULL;
216 }
217 memcpy (self->data+self->pos, data, length);
218 self->pos = self->pos+length;
219 Py_INCREF (Py_None);
220 return (Py_None);
221}
222
223static PyObject *
224mmap_write_byte_method (mmap_object * self,
225 PyObject * args)
226{
227 char value;
228
229 CHECK_VALID(NULL);
230 if (!PyArg_ParseTuple (args, "c", &value))
231 return(NULL);
232
233 *(self->data+self->pos) = value;
234 self->pos += 1;
235 Py_INCREF (Py_None);
236 return (Py_None);
237}
238
239static PyObject *
240mmap_size_method (mmap_object * self,
241 PyObject * args)
242{
243 CHECK_VALID(NULL);
244
245#ifdef MS_WIN32
246 if (self->file_handle != (HFILE) 0xFFFFFFFF) {
247 return (Py_BuildValue ("l", GetFileSize ((HANDLE)self->file_handle, NULL)));
248 } else {
249 return (Py_BuildValue ("l", self->size) );
250 }
251#endif /* MS_WIN32 */
252
253#ifdef UNIX
254 return (Py_BuildValue ("l", self->size) );
255#endif /* UNIX */
256}
257
258/* This assumes that you want the entire file mapped,
259 / and when recreating the map will make the new file
260 / have the new size
261 /
262 / Is this really necessary? This could easily be done
263 / from python by just closing and re-opening with the
264 / new size?
265 */
266
267static PyObject *
268mmap_resize_method (mmap_object * self,
269 PyObject * args)
270{
271 unsigned long new_size;
272 CHECK_VALID(NULL);
273 if (!PyArg_ParseTuple (args, "l", &new_size)) {
274 return NULL;
275#ifdef MS_WIN32
276 } else {
277 /* First, unmap the file view */
278 UnmapViewOfFile (self->data);
279 /* Close the mapping object */
280 CloseHandle ((HANDLE)self->map_handle);
281 /* Move to the desired EOF position */
282 SetFilePointer ((HANDLE)self->file_handle, new_size, NULL, FILE_BEGIN);
283 /* Change the size of the file */
284 SetEndOfFile ((HANDLE)self->file_handle);
285 /* Create another mapping object and remap the file view */
286 self->map_handle = CreateFileMapping ((HANDLE) self->file_handle,
287 NULL,
288 PAGE_READWRITE,
289 0,
290 new_size,
291 self->tagname);
292 char complaint[256];
293 if (self->map_handle != NULL) {
294 self->data = (char *) MapViewOfFile (self->map_handle,
295 FILE_MAP_WRITE,
296 0,
297 0,
298 0);
299 if (self->data != NULL) {
300 self->size = new_size;
301 Py_INCREF (Py_None);
302 return Py_None;
303 } else {
304 sprintf (complaint, "MapViewOfFile failed: %ld", GetLastError());
305 }
306 } else {
307 sprintf (complaint, "CreateFileMapping failed: %ld", GetLastError());
308 }
309 PyErr_SetString (mmap_module_error, complaint);
310 return (NULL);
311 }
312#endif /* MS_WIN32 */
313
314#ifdef UNIX
315#ifndef MREMAP_MAYMOVE
316} else {
317 PyErr_SetString(PyExc_SystemError, "mmap: resizing not available--no mremap()");
318 return NULL;
319#else
320} else {
321 void *newmap;
322
323 newmap = mremap(self->data, self->size, new_size, MREMAP_MAYMOVE);
324 if (newmap == (void *)-1)
325 {
326 PyErr_SetFromErrno(mmap_module_error);
327 return NULL;
328 }
329 self->data = newmap;
330 self->size = new_size;
331 Py_INCREF(Py_None);
332 return Py_None;
333#endif /* MREMAP_MAYMOVE */
334#endif /* UNIX */
335}
336}
337
338static PyObject *
339mmap_tell_method (mmap_object * self, PyObject * args)
340{
341 CHECK_VALID(NULL);
342 return (Py_BuildValue ("l", self->pos) );
343}
344
345static PyObject *
346mmap_flush_method (mmap_object * self, PyObject * args)
347{
348 size_t offset = 0;
349 size_t size = self->size;
350 CHECK_VALID(NULL);
351 if (!PyArg_ParseTuple (args, "|ll", &offset, &size)) {
352 return NULL;
353 } else if ((offset + size) > self->size) {
354 PyErr_SetString (PyExc_ValueError, "flush values out of range");
355 return NULL;
356 } else {
357#ifdef MS_WIN32
358 return (Py_BuildValue ("l", FlushViewOfFile (self->data+offset, size)));
359#endif /* MS_WIN32 */
360#ifdef UNIX
361 /* XXX semantics of return value? */
362 /* XXX flags for msync? */
363 if (-1 == msync(self->data + offset, size, MS_SYNC | MS_INVALIDATE))
364 {
365 PyErr_SetFromErrno(mmap_module_error);
366 return NULL;
367 }
368 return Py_BuildValue ("l", 0);
369#endif /* UNIX */
370 }
371}
372
373static PyObject *
374mmap_seek_method (mmap_object * self, PyObject * args)
375{
376 /* ptrdiff_t dist; */
377 long dist;
378 int how=0;
379 CHECK_VALID(NULL);
380 if (!PyArg_ParseTuple (args, "l|i", &dist, &how)) {
381 return(NULL);
382 } else {
383 unsigned long where;
384 switch (how) {
385 case 0:
386 where = dist;
387 break;
388 case 1:
389 where = self->pos + dist;
390 break;
391 case 2:
392 where = self->size - dist;
393 break;
394 default:
395 PyErr_SetString (PyExc_ValueError, "unknown seek type");
396 return NULL;
397 }
398 if ((where >= 0) && (where < (self->size))) {
399 self->pos = where;
400 Py_INCREF (Py_None);
401 return (Py_None);
402 } else {
403 PyErr_SetString (PyExc_ValueError, "seek out of range");
404 return NULL;
405 }
406 }
407}
408
409static PyObject *
410mmap_move_method (mmap_object * self, PyObject * args)
411{
412 unsigned long dest, src, count;
413 CHECK_VALID(NULL);
414 if (!PyArg_ParseTuple (args, "iii", &dest, &src, &count)) {
415 return NULL;
416 } else {
417 /* bounds check the values */
418 if (/* end of source after end of data?? */
419 ((src+count) > self->size)
420 /* dest will fit? */
421 || (dest+count > self->size)) {
422 PyErr_SetString (PyExc_ValueError,
423 "source or destination out of range");
424 return NULL;
425 } else {
426 memmove (self->data+dest, self->data+src, count);
427 Py_INCREF (Py_None);
428 return Py_None;
429 }
430 }
431}
432
433static struct PyMethodDef mmap_object_methods[] = {
434 {"close", (PyCFunction) mmap_close_method, 1},
435 {"find", (PyCFunction) mmap_find_method, 1},
436 {"flush", (PyCFunction) mmap_flush_method, 1},
437 {"move", (PyCFunction) mmap_move_method, 1},
438 {"read", (PyCFunction) mmap_read_method, 1},
439 {"read_byte", (PyCFunction) mmap_read_byte_method, 1},
440 {"readline", (PyCFunction) mmap_read_line_method, 1},
441 {"resize", (PyCFunction) mmap_resize_method, 1},
442 {"seek", (PyCFunction) mmap_seek_method, 1},
443 {"size", (PyCFunction) mmap_size_method, 1},
444 {"tell", (PyCFunction) mmap_tell_method, 1},
445 {"write", (PyCFunction) mmap_write_method, 1},
446 {"write_byte",(PyCFunction) mmap_write_byte_method, 1},
447 {NULL, NULL} /* sentinel */
448};
449
450/* Functions for treating an mmap'ed file as a buffer */
451
452static int
453mmap_buffer_getreadbuf(self, index, ptr)
454 mmap_object *self;
455int index;
456const void **ptr;
457{
458 CHECK_VALID(-1);
459 if ( index != 0 ) {
460 PyErr_SetString(PyExc_SystemError, "Accessing non-existent mmap segment");
461 return -1;
462 }
463 *ptr = self->data;
464 return self->size;
465}
466
467static int
468mmap_buffer_getwritebuf(self, index, ptr)
469 mmap_object *self;
470int index;
471const void **ptr;
472{
473 CHECK_VALID(-1);
474 if ( index != 0 ) {
475 PyErr_SetString(PyExc_SystemError, "Accessing non-existent mmap segment");
476 return -1;
477 }
478 *ptr = self->data;
479 return self->size;
480}
481
482static int
483mmap_buffer_getsegcount(self, lenp)
484 mmap_object *self;
485int *lenp;
486{
487 CHECK_VALID(-1);
488 if (lenp)
489 *lenp = self->size;
490 return 1;
491}
492
493static int
494mmap_buffer_getcharbuffer(self, index, ptr)
495 mmap_object *self;
496int index;
497const void **ptr;
498{
499 if ( index != 0 ) {
500 PyErr_SetString(PyExc_SystemError,
501 "accessing non-existent buffer segment");
502 return -1;
503 }
504 *ptr = (const char *)self->data;
505 return self->size;
506}
507
508static PyObject *
509mmap_object_getattr(mmap_object * self, char * name)
510{
511 return Py_FindMethod (mmap_object_methods, (PyObject *)self, name);
512}
513
514static int
515mmap_length(self)
516 mmap_object *self;
517{
518 CHECK_VALID(-1);
519 return self->size;
520}
521
522static PyObject *
523mmap_item(self, i)
524 mmap_object *self;
525int i;
526{
527 CHECK_VALID(NULL);
528 if (i < 0 || i >= self->size) {
529 PyErr_SetString(PyExc_IndexError, "mmap index out of range");
530 return NULL;
531 }
532 return PyString_FromStringAndSize(self->data + i, 1);
533}
534
535static PyObject *
536mmap_slice(self, ilow, ihigh)
537 mmap_object *self;
538int ilow, ihigh;
539{
540 CHECK_VALID(NULL);
541 if (ilow < 0)
542 ilow = 0;
543 else if (ilow > self->size)
544 ilow = self->size;
545 if (ihigh < 0)
546 ihigh = 0;
547 if (ihigh < ilow)
548 ihigh = ilow;
549 else if (ihigh > self->size)
550 ihigh = self->size;
551
552 return PyString_FromStringAndSize(self->data + ilow, ihigh-ilow);
553}
554
555static PyObject *
556mmap_concat(self, bb)
557 mmap_object *self;
558PyObject *bb;
559{
560 CHECK_VALID(NULL);
561 PyErr_SetString(PyExc_SystemError, "mmaps don't support concatenation");
562 return NULL;
563}
564
565static PyObject *
566mmap_repeat(self, n)
567 mmap_object *self;
568int n;
569{
570 CHECK_VALID(NULL);
571 PyErr_SetString(PyExc_SystemError, "mmaps don't support repeat operation");
572 return NULL;
573}
574
575static int
576mmap_ass_slice(self, ilow, ihigh, v)
577 mmap_object *self;
578int ilow, ihigh;
579PyObject *v;
580{
581 unsigned char *buf;
582
583 CHECK_VALID(-1);
584 if (ilow < 0)
585 ilow = 0;
586 else if (ilow > self->size)
587 ilow = self->size;
588 if (ihigh < 0)
589 ihigh = 0;
590 if (ihigh < ilow)
591 ihigh = ilow;
592 else if (ihigh > self->size)
593 ihigh = self->size;
594
595 if (! (PyString_Check(v)) ) {
596 PyErr_SetString(PyExc_IndexError,
597 "mmap slice assignment must be a string");
598 return -1;
599 }
600 if ( PyString_Size(v) != (ihigh - ilow) ) {
601 PyErr_SetString(PyExc_IndexError,
602 "mmap slice assignment is wrong size");
603 return -1;
604 }
605 buf = PyString_AsString(v);
606 memcpy(self->data + ilow, buf, ihigh-ilow);
607 return 0;
608}
609
610static int
611mmap_ass_item(self, i, v)
612 mmap_object *self;
613int i;
614PyObject *v;
615{
616 unsigned char *buf;
617
618 CHECK_VALID(-1);
619 if (i < 0 || i >= self->size) {
620 PyErr_SetString(PyExc_IndexError, "mmap index out of range");
621 return -1;
622 }
623 if (! (PyString_Check(v) && PyString_Size(v)==1) ) {
624 PyErr_SetString(PyExc_IndexError,
625 "mmap assignment must be single-character string");
626 return -1;
627 }
628 buf = PyString_AsString(v);
629 self->data[i] = buf[0];
630 return 0;
631}
632
633static PySequenceMethods mmap_as_sequence = {
634 (inquiry)mmap_length, /*sq_length*/
635 (binaryfunc)mmap_concat, /*sq_concat*/
636 (intargfunc)mmap_repeat, /*sq_repeat*/
637 (intargfunc)mmap_item, /*sq_item*/
638 (intintargfunc)mmap_slice, /*sq_slice*/
639 (intobjargproc)mmap_ass_item, /*sq_ass_item*/
640 (intintobjargproc)mmap_ass_slice, /*sq_ass_slice*/
641};
642
643static PyBufferProcs mmap_as_buffer = {
644 (getreadbufferproc)mmap_buffer_getreadbuf,
645 (getwritebufferproc)mmap_buffer_getwritebuf,
646 (getsegcountproc)mmap_buffer_getsegcount,
647 (getcharbufferproc)mmap_buffer_getcharbuffer,
648};
649
650static PyTypeObject mmap_object_type = {
651 PyObject_HEAD_INIT(&PyType_Type)
652 0, /* ob_size */
653 "mmap", /* tp_name */
654 sizeof(mmap_object), /* tp_size */
655 0, /* tp_itemsize */
656 /* methods */
657 (destructor) mmap_object_dealloc, /* tp_dealloc */
658 0, /* tp_print */
659 (getattrfunc) mmap_object_getattr,/* tp_getattr */
660 0, /* tp_setattr */
661 0, /* tp_compare */
662 0, /* tp_repr */
663 0, /* tp_as_number */
664 &mmap_as_sequence, /*tp_as_sequence*/
665 0, /*tp_as_mapping*/
666 0, /*tp_hash*/
667 0, /*tp_call*/
668 0, /*tp_str*/
669 0, /*tp_getattro*/
670 0, /*tp_setattro*/
671 &mmap_as_buffer, /*tp_as_buffer*/
672 Py_TPFLAGS_HAVE_GETCHARBUFFER, /*tp_flags*/
673 0, /*tp_doc*/
674};
675
676#ifdef UNIX
677static PyObject *
678new_mmap_object (PyObject * self, PyObject * args, PyObject *kwdict)
679{
680 mmap_object * m_obj;
681 unsigned long map_size;
682 int fd, flags = MAP_SHARED, prot = PROT_WRITE | PROT_READ;
683 char * filename;
684 int namelen;
685 char *keywords[] = {"file", "size", "flags", "prot", NULL};
686
687 if (!PyArg_ParseTupleAndKeywords(args, kwdict,
688 "il|ii", keywords,
689 &fd, &map_size, &flags, &prot)
690 )
691 return NULL;
692
693 m_obj = PyObject_NEW (mmap_object, &mmap_object_type);
694 if (m_obj == NULL) {return NULL;}
695 m_obj->size = (size_t) map_size;
696 m_obj->pos = (size_t) 0;
697 m_obj->data = mmap(NULL, map_size,
698 prot, flags,
699 fd, 0);
700 if (m_obj->data == (void *)-1)
701 {
702 Py_DECREF(m_obj);
703 PyErr_SetFromErrno(mmap_module_error);
704 return NULL;
705 }
706 return (PyObject *)m_obj;
707}
708#endif /* UNIX */
709
710#ifdef MS_WIN32
711static PyObject *
712new_mmap_object (PyObject * self, PyObject * args)
713{
714 mmap_object * m_obj;
715 unsigned long map_size;
716 char * filename;
717 int namelen;
718 char * tagname;
719
720 char complaint[256];
721 HFILE fh = 0;
722 OFSTRUCT file_info;
723
724 if (!PyArg_Parse (args,
725 "(s#zl)",
726 &filename,
727 &namelen,
728 &tagname,
729 &map_size)
730 )
731 return NULL;
732
733 /* if an actual filename has been specified */
734 if (namelen != 0) {
735 fh = OpenFile (filename, &file_info, OF_READWRITE);
736 if (fh == HFILE_ERROR) {
737 sprintf (complaint, "OpenFile failed: %ld", GetLastError());
738 PyErr_SetString(mmap_module_error, complaint);
739 return NULL;
740 }
741 }
742
743 m_obj = PyObject_NEW (mmap_object, &mmap_object_type);
744
745 if (fh) {
746 m_obj->file_handle = fh;
747 if (!map_size) {
748 m_obj->size = GetFileSize ((HANDLE)fh, NULL);
749 } else {
750 m_obj->size = map_size;
751 }
752 }
753 else {
754 m_obj->file_handle = (HFILE) 0xFFFFFFFF;
755 m_obj->size = map_size;
756 }
757
758 /* set the initial position */
759 m_obj->pos = (size_t) 0;
760
761 m_obj->map_handle = CreateFileMapping ((HANDLE) m_obj->file_handle,
762 NULL,
763 PAGE_READWRITE,
764 0,
765 m_obj->size,
766 tagname);
767 if (m_obj->map_handle != NULL) {
768 m_obj->data = (char *) MapViewOfFile (m_obj->map_handle,
769 FILE_MAP_WRITE,
770 0,
771 0,
772 0);
773 if (m_obj->data != NULL) {
774 return ((PyObject *) m_obj);
775 } else {
776 sprintf (complaint, "MapViewOfFile failed: %ld", GetLastError());
777 }
778 } else {
779 sprintf (complaint, "CreateFileMapping failed: %ld", GetLastError());
780 }
781 PyErr_SetString (mmap_module_error, complaint);
782 return (NULL);
783}
784#endif /* MS_WIN32 */
785
786/* List of functions exported by this module */
787static struct PyMethodDef mmap_functions[] = {
788#ifdef MS_WIN32
789 {"mmap", (PyCFunction) new_mmap_object},
790#endif /* MS_WIN32 */
791
792#ifdef UNIX
793 {"mmap", (PyCFunction) new_mmap_object,
794 METH_VARARGS|METH_KEYWORDS},
795#endif /* UNIX */
796 {NULL, NULL} /* Sentinel */
797};
798
799#ifdef MS_WIN32
800extern"C" __declspec(dllexport) void
801#endif /* MS_WIN32 */
802#ifdef UNIX
803extern void
804#endif
805
806initmmap(void)
807{
808 PyObject *dict, *module;
809 module = Py_InitModule ("mmap", mmap_functions);
810 dict = PyModule_GetDict (module);
811 mmap_module_error = PyString_FromString ("mmap error");
812 PyDict_SetItemString (dict, "error", mmap_module_error);
813
814#ifdef PROT_EXEC
815 PyDict_SetItemString (dict, "PROT_EXEC", PyInt_FromLong(PROT_EXEC) );
816#endif
817#ifdef PROT_READ
818 PyDict_SetItemString (dict, "PROT_READ", PyInt_FromLong(PROT_READ) );
819#endif
820#ifdef PROT_WRITE
821 PyDict_SetItemString (dict, "PROT_WRITE", PyInt_FromLong(PROT_WRITE) );
822#endif
823
824#ifdef MAP_SHARED
825 PyDict_SetItemString (dict, "MAP_SHARED", PyInt_FromLong(MAP_SHARED) );
826#endif
827#ifdef MAP_PRIVATE
828 PyDict_SetItemString (dict, "MAP_PRIVATE", PyInt_FromLong(MAP_PRIVATE) );
829#endif
830#ifdef MAP_DENYWRITE
831 PyDict_SetItemString (dict, "MAP_DENYWRITE", PyInt_FromLong(MAP_DENYWRITE) );
832#endif
833#ifdef MAP_EXECUTABLE
834 PyDict_SetItemString (dict, "MAP_EXECUTABLE", PyInt_FromLong(MAP_EXECUTABLE) );
835#endif
836#ifdef MAP_ANON
837 PyDict_SetItemString (dict, "MAP_ANON", PyInt_FromLong(MAP_ANON) );
838 PyDict_SetItemString (dict, "MAP_ANONYMOUS", PyInt_FromLong(MAP_ANON) );
839#endif
840
841#ifdef UNIX
842 PyDict_SetItemString (dict, "PAGESIZE", PyInt_FromLong( (long)getpagesize() ) );
843#endif
844
845}
846
847
848