blob: f660d6bb0ba2f138b1a647543648e2a1dc5b9659 [file] [log] [blame]
Guido van Rossum09fdf072000-03-31 01:17:07 +00001/*
2 / Author: Sam Rushing <rushing@nightmare.com>
Andrew M. Kuchling10f9c072001-11-05 21:25:42 +00003 / Hacked for Unix by AMK
Guido van Rossum09fdf072000-03-31 01:17:07 +00004 / $Id$
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00005
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00006 / Modified to support mmap with offset - to map a 'window' of a file
7 / Author: Yotam Medini yotamm@mellanox.co.il
8 /
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00009 / mmapmodule.cpp -- map a view of a file into memory
10 /
11 / todo: need permission flags, perhaps a 'chsize' analog
12 / not all functions check range yet!!!
13 /
14 /
Mark Hammond071864a2000-07-30 02:46:26 +000015 / 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
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +000018 / ftp://squirl.nightmare.com/pub/python/python-ext.
19*/
20
Martin v. Löwiscfe7e092006-02-17 06:59:14 +000021#define PY_SSIZE_T_CLEAN
Guido van Rossum09fdf072000-03-31 01:17:07 +000022#include <Python.h>
23
Martin v. Löwis6238d2b2002-06-30 15:26:10 +000024#ifndef MS_WINDOWS
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +000025#define UNIX
26#endif
27
Martin v. Löwis6238d2b2002-06-30 15:26:10 +000028#ifdef MS_WINDOWS
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +000029#include <windows.h>
Fred Drake145f96e2000-10-01 17:50:46 +000030static int
31my_getpagesize(void)
32{
Tim Peters5ebfd362001-11-13 23:11:19 +000033 SYSTEM_INFO si;
34 GetSystemInfo(&si);
35 return si.dwPageSize;
Fred Drake145f96e2000-10-01 17:50:46 +000036}
Travis E. Oliphant8feafab2007-10-23 02:40:56 +000037
38static int
39my_getallocationgranularity (void)
40{
41
42 SYSTEM_INFO si;
43 GetSystemInfo(&si);
44 return si.dwAllocationGranularity;
45}
46
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +000047#endif
48
49#ifdef UNIX
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +000050#include <sys/mman.h>
Andrew M. Kuchling7b9fb922000-06-17 22:41:22 +000051#include <sys/stat.h>
Guido van Rossum4b36e6b2000-09-25 13:16:15 +000052
Fred Drake145f96e2000-10-01 17:50:46 +000053#if defined(HAVE_SYSCONF) && defined(_SC_PAGESIZE)
54static int
55my_getpagesize(void)
56{
Tim Peters5ebfd362001-11-13 23:11:19 +000057 return sysconf(_SC_PAGESIZE);
Fred Drake145f96e2000-10-01 17:50:46 +000058}
Travis E. Oliphant8feafab2007-10-23 02:40:56 +000059
60#define my_getallocationgranularity my_getpagesize
Fred Drake145f96e2000-10-01 17:50:46 +000061#else
62#define my_getpagesize getpagesize
63#endif
64
Guido van Rossum4b36e6b2000-09-25 13:16:15 +000065#endif /* UNIX */
66
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +000067#include <string.h>
Martin v. Löwis0e8bd7e2006-06-10 12:23:46 +000068
69#ifdef HAVE_SYS_TYPES_H
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +000070#include <sys/types.h>
Martin v. Löwis0e8bd7e2006-06-10 12:23:46 +000071#endif /* HAVE_SYS_TYPES_H */
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +000072
Neal Norwitz3eaf2b52006-02-16 08:08:54 +000073/* Prefer MAP_ANONYMOUS since MAP_ANON is deprecated according to man page. */
Neal Norwitz0e6bc8c2006-02-05 05:45:43 +000074#if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)
75# define MAP_ANONYMOUS MAP_ANON
76#endif
77
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +000078static PyObject *mmap_module_error;
79
Tim Peters5ebfd362001-11-13 23:11:19 +000080typedef enum
81{
82 ACCESS_DEFAULT,
83 ACCESS_READ,
84 ACCESS_WRITE,
85 ACCESS_COPY
86} access_mode;
87
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +000088typedef struct {
Guido van Rossum09fdf072000-03-31 01:17:07 +000089 PyObject_HEAD
90 char * data;
91 size_t size;
Travis E. Oliphant8feafab2007-10-23 02:40:56 +000092 size_t pos; /* relative to offset */
93 size_t offset;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +000094
Martin v. Löwis6238d2b2002-06-30 15:26:10 +000095#ifdef MS_WINDOWS
Guido van Rossum09fdf072000-03-31 01:17:07 +000096 HANDLE map_handle;
Mark Hammond071864a2000-07-30 02:46:26 +000097 HANDLE file_handle;
Guido van Rossum09fdf072000-03-31 01:17:07 +000098 char * tagname;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +000099#endif
100
101#ifdef UNIX
Andrew M. Kuchling7b9fb922000-06-17 22:41:22 +0000102 int fd;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000103#endif
Tim Peters5ebfd362001-11-13 23:11:19 +0000104
105 access_mode access;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000106} mmap_object;
107
Tim Peters5ebfd362001-11-13 23:11:19 +0000108
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000109static void
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000110mmap_object_dealloc(mmap_object *m_obj)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000111{
Martin v. Löwis6238d2b2002-06-30 15:26:10 +0000112#ifdef MS_WINDOWS
Mark Hammond2cbed002000-07-30 02:22:43 +0000113 if (m_obj->data != NULL)
114 UnmapViewOfFile (m_obj->data);
Hirokazu Yamamoto264fc122009-03-05 14:21:12 +0000115 if (m_obj->map_handle != NULL)
Mark Hammond2cbed002000-07-30 02:22:43 +0000116 CloseHandle (m_obj->map_handle);
Mark Hammond071864a2000-07-30 02:46:26 +0000117 if (m_obj->file_handle != INVALID_HANDLE_VALUE)
118 CloseHandle (m_obj->file_handle);
Mark Hammond2cbed002000-07-30 02:22:43 +0000119 if (m_obj->tagname)
120 PyMem_Free(m_obj->tagname);
Martin v. Löwis6238d2b2002-06-30 15:26:10 +0000121#endif /* MS_WINDOWS */
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000122
123#ifdef UNIX
Neal Norwitz6eac2002005-11-02 05:36:37 +0000124 if (m_obj->fd >= 0)
125 (void) close(m_obj->fd);
Guido van Rossum09fdf072000-03-31 01:17:07 +0000126 if (m_obj->data!=NULL) {
Andrew M. Kuchling9bc5f332000-06-18 04:25:08 +0000127 msync(m_obj->data, m_obj->size, MS_SYNC);
Guido van Rossum09fdf072000-03-31 01:17:07 +0000128 munmap(m_obj->data, m_obj->size);
129 }
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000130#endif /* UNIX */
131
Christian Heimes501dbbf2008-01-23 14:00:25 +0000132 Py_TYPE(m_obj)->tp_free((PyObject*)m_obj);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000133}
134
135static PyObject *
Georg Brandl96a8c392006-05-29 21:04:52 +0000136mmap_close_method(mmap_object *self, PyObject *unused)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000137{
Martin v. Löwis6238d2b2002-06-30 15:26:10 +0000138#ifdef MS_WINDOWS
Mark Hammond071864a2000-07-30 02:46:26 +0000139 /* For each resource we maintain, we need to check
Tim Petersec0a5f02006-02-16 23:47:20 +0000140 the value is valid, and if so, free the resource
Mark Hammond071864a2000-07-30 02:46:26 +0000141 and set the member value to an invalid value so
142 the dealloc does not attempt to resource clearing
143 again.
144 TODO - should we check for errors in the close operations???
145 */
146 if (self->data != NULL) {
Tim Peters8f9cc292006-02-17 00:00:20 +0000147 UnmapViewOfFile(self->data);
Mark Hammond071864a2000-07-30 02:46:26 +0000148 self->data = NULL;
149 }
Hirokazu Yamamoto264fc122009-03-05 14:21:12 +0000150 if (self->map_handle != NULL) {
Tim Peters8f9cc292006-02-17 00:00:20 +0000151 CloseHandle(self->map_handle);
Hirokazu Yamamoto264fc122009-03-05 14:21:12 +0000152 self->map_handle = NULL;
Mark Hammond071864a2000-07-30 02:46:26 +0000153 }
154 if (self->file_handle != INVALID_HANDLE_VALUE) {
Tim Peters8f9cc292006-02-17 00:00:20 +0000155 CloseHandle(self->file_handle);
Mark Hammond071864a2000-07-30 02:46:26 +0000156 self->file_handle = INVALID_HANDLE_VALUE;
157 }
Martin v. Löwis6238d2b2002-06-30 15:26:10 +0000158#endif /* MS_WINDOWS */
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000159
160#ifdef UNIX
Neal Norwitz6eac2002005-11-02 05:36:37 +0000161 (void) close(self->fd);
162 self->fd = -1;
Neal Norwitze604c022003-01-10 20:52:16 +0000163 if (self->data != NULL) {
164 munmap(self->data, self->size);
165 self->data = NULL;
166 }
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000167#endif
168
Tim Peters8f9cc292006-02-17 00:00:20 +0000169 Py_INCREF(Py_None);
Tim Peters23721ee2006-02-16 23:50:16 +0000170 return Py_None;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000171}
172
Martin v. Löwis6238d2b2002-06-30 15:26:10 +0000173#ifdef MS_WINDOWS
Guido van Rossum09fdf072000-03-31 01:17:07 +0000174#define CHECK_VALID(err) \
175do { \
Hirokazu Yamamoto264fc122009-03-05 14:21:12 +0000176 if (self->map_handle == NULL) { \
Tim Peters8f9cc292006-02-17 00:00:20 +0000177 PyErr_SetString(PyExc_ValueError, "mmap closed or invalid"); \
Guido van Rossum09fdf072000-03-31 01:17:07 +0000178 return err; \
179 } \
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000180} while (0)
Martin v. Löwis6238d2b2002-06-30 15:26:10 +0000181#endif /* MS_WINDOWS */
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000182
183#ifdef UNIX
Guido van Rossum09fdf072000-03-31 01:17:07 +0000184#define CHECK_VALID(err) \
185do { \
186 if (self->data == NULL) { \
Tim Peters8f9cc292006-02-17 00:00:20 +0000187 PyErr_SetString(PyExc_ValueError, "mmap closed or invalid"); \
Guido van Rossum09fdf072000-03-31 01:17:07 +0000188 return err; \
189 } \
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000190} while (0)
191#endif /* UNIX */
192
193static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000194mmap_read_byte_method(mmap_object *self,
Georg Brandl96a8c392006-05-29 21:04:52 +0000195 PyObject *unused)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000196{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000197 CHECK_VALID(NULL);
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000198 if (self->pos < self->size) {
Tim Petersd6283b82001-05-09 18:48:26 +0000199 char value = self->data[self->pos];
Guido van Rossum09fdf072000-03-31 01:17:07 +0000200 self->pos += 1;
Tim Petersd6283b82001-05-09 18:48:26 +0000201 return Py_BuildValue("c", value);
Guido van Rossum09fdf072000-03-31 01:17:07 +0000202 } else {
Tim Peters8f9cc292006-02-17 00:00:20 +0000203 PyErr_SetString(PyExc_ValueError, "read byte out of range");
Guido van Rossum09fdf072000-03-31 01:17:07 +0000204 return NULL;
205 }
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000206}
207
208static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000209mmap_read_line_method(mmap_object *self,
Georg Brandl96a8c392006-05-29 21:04:52 +0000210 PyObject *unused)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000211{
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000212 char *start = self->data+self->pos;
213 char *eof = self->data+self->size;
214 char *eol;
215 PyObject *result;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000216
Guido van Rossum09fdf072000-03-31 01:17:07 +0000217 CHECK_VALID(NULL);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000218
Fred Drake56a87a02000-04-04 18:17:35 +0000219 eol = memchr(start, '\n', self->size - self->pos);
220 if (!eol)
221 eol = eof;
222 else
223 ++eol; /* we're interested in the position after the
224 newline. */
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000225 result = PyString_FromStringAndSize(start, (eol - start));
Guido van Rossum09fdf072000-03-31 01:17:07 +0000226 self->pos += (eol - start);
Tim Peters23721ee2006-02-16 23:50:16 +0000227 return result;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000228}
229
230static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000231mmap_read_method(mmap_object *self,
232 PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000233{
Martin v. Löwisad0a4622006-02-16 14:30:23 +0000234 Py_ssize_t num_bytes;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000235 PyObject *result;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000236
Guido van Rossum09fdf072000-03-31 01:17:07 +0000237 CHECK_VALID(NULL);
Martin v. Löwisad0a4622006-02-16 14:30:23 +0000238 if (!PyArg_ParseTuple(args, "n:read", &num_bytes))
Guido van Rossum09fdf072000-03-31 01:17:07 +0000239 return(NULL);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000240
Guido van Rossum09fdf072000-03-31 01:17:07 +0000241 /* silently 'adjust' out-of-range requests */
Neal Norwitze7d8be82008-07-31 17:17:14 +0000242 if (num_bytes > self->size - self->pos) {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000243 num_bytes -= (self->pos+num_bytes) - self->size;
244 }
245 result = Py_BuildValue("s#", self->data+self->pos, num_bytes);
Tim Petersec0a5f02006-02-16 23:47:20 +0000246 self->pos += num_bytes;
Tim Peters23721ee2006-02-16 23:50:16 +0000247 return result;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000248}
249
250static PyObject *
Andrew M. Kuchling5c60bfc2008-01-19 18:18:41 +0000251mmap_gfind(mmap_object *self,
252 PyObject *args,
253 int reverse)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000254{
Martin v. Löwisad0a4622006-02-16 14:30:23 +0000255 Py_ssize_t start = self->pos;
Neal Norwitz739a3c42008-01-26 20:24:36 +0000256 Py_ssize_t end = self->size;
257 const char *needle;
Martin v. Löwiscfe7e092006-02-17 06:59:14 +0000258 Py_ssize_t len;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000259
Guido van Rossum09fdf072000-03-31 01:17:07 +0000260 CHECK_VALID(NULL);
Andrew M. Kuchling5c60bfc2008-01-19 18:18:41 +0000261 if (!PyArg_ParseTuple(args, reverse ? "s#|nn:rfind" : "s#|nn:find",
262 &needle, &len, &start, &end)) {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000263 return NULL;
264 } else {
Neal Norwitz739a3c42008-01-26 20:24:36 +0000265 const char *p, *start_p, *end_p;
Neal Norwitze1027f92008-01-27 07:37:38 +0000266 int sign = reverse ? -1 : 1;
Greg Stein834f4dd2001-05-14 09:32:26 +0000267
268 if (start < 0)
Tim Peters5ebfd362001-11-13 23:11:19 +0000269 start += self->size;
Greg Stein834f4dd2001-05-14 09:32:26 +0000270 if (start < 0)
Tim Peters5ebfd362001-11-13 23:11:19 +0000271 start = 0;
Tim Petersd401edd2001-05-14 23:19:12 +0000272 else if ((size_t)start > self->size)
Tim Peters5ebfd362001-11-13 23:11:19 +0000273 start = self->size;
Greg Stein834f4dd2001-05-14 09:32:26 +0000274
Andrew M. Kuchling5c60bfc2008-01-19 18:18:41 +0000275 if (end < 0)
276 end += self->size;
277 if (end < 0)
278 end = 0;
279 else if ((size_t)end > self->size)
280 end = self->size;
281
Neal Norwitz739a3c42008-01-26 20:24:36 +0000282 start_p = self->data + start;
283 end_p = self->data + end;
Andrew M. Kuchling5c60bfc2008-01-19 18:18:41 +0000284
Neal Norwitz739a3c42008-01-26 20:24:36 +0000285 for (p = (reverse ? end_p - len : start_p);
286 (p >= start_p) && (p + len <= end_p); p += sign) {
Martin v. Löwiscfe7e092006-02-17 06:59:14 +0000287 Py_ssize_t i;
Tim Petersc9ffa062002-03-08 05:43:32 +0000288 for (i = 0; i < len && needle[i] == p[i]; ++i)
289 /* nothing */;
290 if (i == len) {
Martin v. Löwiscfe7e092006-02-17 06:59:14 +0000291 return PyInt_FromSsize_t(p - self->data);
Guido van Rossum09fdf072000-03-31 01:17:07 +0000292 }
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000293 }
Martin v. Löwiscfe7e092006-02-17 06:59:14 +0000294 return PyInt_FromLong(-1);
Guido van Rossum09fdf072000-03-31 01:17:07 +0000295 }
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000296}
297
Andrew M. Kuchling5c60bfc2008-01-19 18:18:41 +0000298static PyObject *
299mmap_find_method(mmap_object *self,
300 PyObject *args)
301{
302 return mmap_gfind(self, args, 0);
303}
304
305static PyObject *
306mmap_rfind_method(mmap_object *self,
307 PyObject *args)
308{
309 return mmap_gfind(self, args, 1);
310}
311
Tim Petersec0a5f02006-02-16 23:47:20 +0000312static int
Tim Peters5ebfd362001-11-13 23:11:19 +0000313is_writeable(mmap_object *self)
314{
315 if (self->access != ACCESS_READ)
Tim Petersec0a5f02006-02-16 23:47:20 +0000316 return 1;
Tim Peters5ebfd362001-11-13 23:11:19 +0000317 PyErr_Format(PyExc_TypeError, "mmap can't modify a readonly memory map.");
318 return 0;
319}
320
Tim Petersec0a5f02006-02-16 23:47:20 +0000321static int
Tim Peters5ebfd362001-11-13 23:11:19 +0000322is_resizeable(mmap_object *self)
323{
324 if ((self->access == ACCESS_WRITE) || (self->access == ACCESS_DEFAULT))
Tim Petersec0a5f02006-02-16 23:47:20 +0000325 return 1;
326 PyErr_Format(PyExc_TypeError,
Tim Peters5ebfd362001-11-13 23:11:19 +0000327 "mmap can't resize a readonly or copy-on-write memory map.");
328 return 0;
329}
330
331
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000332static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000333mmap_write_method(mmap_object *self,
334 PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000335{
Martin v. Löwiscfe7e092006-02-17 06:59:14 +0000336 Py_ssize_t length;
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000337 char *data;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000338
Guido van Rossum09fdf072000-03-31 01:17:07 +0000339 CHECK_VALID(NULL);
Tim Peters8f9cc292006-02-17 00:00:20 +0000340 if (!PyArg_ParseTuple(args, "s#:write", &data, &length))
Guido van Rossum09fdf072000-03-31 01:17:07 +0000341 return(NULL);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000342
Tim Peters5ebfd362001-11-13 23:11:19 +0000343 if (!is_writeable(self))
344 return NULL;
345
Guido van Rossum09fdf072000-03-31 01:17:07 +0000346 if ((self->pos + length) > self->size) {
Tim Peters8f9cc292006-02-17 00:00:20 +0000347 PyErr_SetString(PyExc_ValueError, "data out of range");
Guido van Rossum09fdf072000-03-31 01:17:07 +0000348 return NULL;
349 }
Tim Peters8f9cc292006-02-17 00:00:20 +0000350 memcpy(self->data+self->pos, data, length);
Guido van Rossum09fdf072000-03-31 01:17:07 +0000351 self->pos = self->pos+length;
Tim Peters8f9cc292006-02-17 00:00:20 +0000352 Py_INCREF(Py_None);
Tim Peters23721ee2006-02-16 23:50:16 +0000353 return Py_None;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000354}
355
356static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000357mmap_write_byte_method(mmap_object *self,
358 PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000359{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000360 char value;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000361
Guido van Rossum09fdf072000-03-31 01:17:07 +0000362 CHECK_VALID(NULL);
Tim Peters8f9cc292006-02-17 00:00:20 +0000363 if (!PyArg_ParseTuple(args, "c:write_byte", &value))
Guido van Rossum09fdf072000-03-31 01:17:07 +0000364 return(NULL);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000365
Tim Peters5ebfd362001-11-13 23:11:19 +0000366 if (!is_writeable(self))
367 return NULL;
Hirokazu Yamamotof2dc8852009-02-28 10:31:54 +0000368
369 if (self->pos < self->size) {
370 *(self->data+self->pos) = value;
371 self->pos += 1;
372 Py_INCREF(Py_None);
373 return Py_None;
374 }
375 else {
376 PyErr_SetString(PyExc_ValueError, "write byte out of range");
377 return NULL;
378 }
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000379}
Tim Petersec0a5f02006-02-16 23:47:20 +0000380
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000381static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000382mmap_size_method(mmap_object *self,
Georg Brandl96a8c392006-05-29 21:04:52 +0000383 PyObject *unused)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000384{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000385 CHECK_VALID(NULL);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000386
Martin v. Löwis6238d2b2002-06-30 15:26:10 +0000387#ifdef MS_WINDOWS
Mark Hammond071864a2000-07-30 02:46:26 +0000388 if (self->file_handle != INVALID_HANDLE_VALUE) {
Martin v. Löwis15186072006-02-18 12:38:35 +0000389 DWORD low,high;
390 PY_LONG_LONG size;
391 low = GetFileSize(self->file_handle, &high);
392 if (low == INVALID_FILE_SIZE) {
393 /* It might be that the function appears to have failed,
394 when indeed its size equals INVALID_FILE_SIZE */
395 DWORD error = GetLastError();
396 if (error != NO_ERROR)
397 return PyErr_SetFromWindowsErr(error);
398 }
399 if (!high && low < LONG_MAX)
400 return PyInt_FromLong((long)low);
401 size = (((PY_LONG_LONG)high)<<32) + low;
402 return PyLong_FromLongLong(size);
Guido van Rossum09fdf072000-03-31 01:17:07 +0000403 } else {
Martin v. Löwis15186072006-02-18 12:38:35 +0000404 return PyInt_FromSsize_t(self->size);
Guido van Rossum09fdf072000-03-31 01:17:07 +0000405 }
Martin v. Löwis6238d2b2002-06-30 15:26:10 +0000406#endif /* MS_WINDOWS */
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000407
408#ifdef UNIX
Andrew M. Kuchling7b9fb922000-06-17 22:41:22 +0000409 {
410 struct stat buf;
411 if (-1 == fstat(self->fd, &buf)) {
412 PyErr_SetFromErrno(mmap_module_error);
413 return NULL;
414 }
Martin v. Löwis15186072006-02-18 12:38:35 +0000415 return PyInt_FromSsize_t(buf.st_size);
Andrew M. Kuchling7b9fb922000-06-17 22:41:22 +0000416 }
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000417#endif /* UNIX */
418}
419
420/* This assumes that you want the entire file mapped,
421 / and when recreating the map will make the new file
422 / have the new size
423 /
424 / Is this really necessary? This could easily be done
425 / from python by just closing and re-opening with the
426 / new size?
427 */
428
429static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000430mmap_resize_method(mmap_object *self,
431 PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000432{
Martin v. Löwiscfe7e092006-02-17 06:59:14 +0000433 Py_ssize_t new_size;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000434 CHECK_VALID(NULL);
Martin v. Löwiscfe7e092006-02-17 06:59:14 +0000435 if (!PyArg_ParseTuple(args, "n:resize", &new_size) ||
Tim Peters5ebfd362001-11-13 23:11:19 +0000436 !is_resizeable(self)) {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000437 return NULL;
Martin v. Löwis6238d2b2002-06-30 15:26:10 +0000438#ifdef MS_WINDOWS
Tim Petersec0a5f02006-02-16 23:47:20 +0000439 } else {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000440 DWORD dwErrCode = 0;
Travis E. Oliphant8feafab2007-10-23 02:40:56 +0000441 DWORD off_hi, off_lo, newSizeLow, newSizeHigh;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000442 /* First, unmap the file view */
Tim Peters8f9cc292006-02-17 00:00:20 +0000443 UnmapViewOfFile(self->data);
Hirokazu Yamamoto264fc122009-03-05 14:21:12 +0000444 self->data = NULL;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000445 /* Close the mapping object */
Tim Peters8f9cc292006-02-17 00:00:20 +0000446 CloseHandle(self->map_handle);
Hirokazu Yamamoto264fc122009-03-05 14:21:12 +0000447 self->map_handle = NULL;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000448 /* Move to the desired EOF position */
Martin v. Löwis15186072006-02-18 12:38:35 +0000449#if SIZEOF_SIZE_T > 4
Travis E. Oliphant8feafab2007-10-23 02:40:56 +0000450 newSizeHigh = (DWORD)((self->offset + new_size) >> 32);
451 newSizeLow = (DWORD)((self->offset + new_size) & 0xFFFFFFFF);
452 off_hi = (DWORD)(self->offset >> 32);
453 off_lo = (DWORD)(self->offset & 0xFFFFFFFF);
Martin v. Löwis15186072006-02-18 12:38:35 +0000454#else
455 newSizeHigh = 0;
Hirokazu Yamamoto17a837e2009-02-17 13:17:26 +0000456 newSizeLow = (DWORD)(self->offset + new_size);
Travis E. Oliphant8feafab2007-10-23 02:40:56 +0000457 off_hi = 0;
458 off_lo = (DWORD)self->offset;
Martin v. Löwis15186072006-02-18 12:38:35 +0000459#endif
Tim Peters8f9cc292006-02-17 00:00:20 +0000460 SetFilePointer(self->file_handle,
Martin v. Löwis15186072006-02-18 12:38:35 +0000461 newSizeLow, &newSizeHigh, FILE_BEGIN);
Guido van Rossum09fdf072000-03-31 01:17:07 +0000462 /* Change the size of the file */
Tim Peters8f9cc292006-02-17 00:00:20 +0000463 SetEndOfFile(self->file_handle);
Guido van Rossum09fdf072000-03-31 01:17:07 +0000464 /* Create another mapping object and remap the file view */
Tim Peters8f9cc292006-02-17 00:00:20 +0000465 self->map_handle = CreateFileMapping(
Mark Hammond071864a2000-07-30 02:46:26 +0000466 self->file_handle,
Guido van Rossum09fdf072000-03-31 01:17:07 +0000467 NULL,
468 PAGE_READWRITE,
Travis E. Oliphant8feafab2007-10-23 02:40:56 +0000469 0,
470 0,
Guido van Rossum09fdf072000-03-31 01:17:07 +0000471 self->tagname);
472 if (self->map_handle != NULL) {
Tim Peters8f9cc292006-02-17 00:00:20 +0000473 self->data = (char *) MapViewOfFile(self->map_handle,
474 FILE_MAP_WRITE,
Travis E. Oliphant8feafab2007-10-23 02:40:56 +0000475 off_hi,
476 off_lo,
477 new_size);
Guido van Rossum09fdf072000-03-31 01:17:07 +0000478 if (self->data != NULL) {
479 self->size = new_size;
Tim Peters8f9cc292006-02-17 00:00:20 +0000480 Py_INCREF(Py_None);
Guido van Rossum09fdf072000-03-31 01:17:07 +0000481 return Py_None;
482 } else {
483 dwErrCode = GetLastError();
Hirokazu Yamamoto264fc122009-03-05 14:21:12 +0000484 CloseHandle(self->map_handle);
485 self->map_handle = NULL;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000486 }
487 } else {
488 dwErrCode = GetLastError();
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000489 }
Guido van Rossum09fdf072000-03-31 01:17:07 +0000490 PyErr_SetFromWindowsErr(dwErrCode);
Tim Peters23721ee2006-02-16 23:50:16 +0000491 return NULL;
Martin v. Löwis6238d2b2002-06-30 15:26:10 +0000492#endif /* MS_WINDOWS */
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000493
494#ifdef UNIX
Tim Petersec0a5f02006-02-16 23:47:20 +0000495#ifndef HAVE_MREMAP
Tim Peters5ebfd362001-11-13 23:11:19 +0000496 } else {
497 PyErr_SetString(PyExc_SystemError,
498 "mmap: resizing not available--no mremap()");
499 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000500#else
Tim Peters5ebfd362001-11-13 23:11:19 +0000501 } else {
Armin Rigo335ffe82005-09-20 19:04:02 +0000502 void *newmap;
503
Hirokazu Yamamoto17a837e2009-02-17 13:17:26 +0000504 if (ftruncate(self->fd, self->offset + new_size) == -1) {
Georg Brandl38387b82005-08-24 07:17:40 +0000505 PyErr_SetFromErrno(mmap_module_error);
506 return NULL;
507 }
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000508
Andrew M. Kuchling6fef30e2000-06-18 14:51:21 +0000509#ifdef MREMAP_MAYMOVE
Tim Peters5ebfd362001-11-13 23:11:19 +0000510 newmap = mremap(self->data, self->size, new_size, MREMAP_MAYMOVE);
Andrew M. Kuchling6fef30e2000-06-18 14:51:21 +0000511#else
Jesse Noller40a61642009-03-31 18:12:35 +0000512 #if defined(__NetBSD__)
513 newmap = mremap(self->data, self->size, self->data, new_size, 0);
514 #else
515 newmap = mremap(self->data, self->size, new_size, 0);
516 #endif /* __NetBSD__ */
Andrew M. Kuchling6fef30e2000-06-18 14:51:21 +0000517#endif
Tim Petersec0a5f02006-02-16 23:47:20 +0000518 if (newmap == (void *)-1)
Tim Peters5ebfd362001-11-13 23:11:19 +0000519 {
520 PyErr_SetFromErrno(mmap_module_error);
521 return NULL;
522 }
523 self->data = newmap;
524 self->size = new_size;
525 Py_INCREF(Py_None);
526 return Py_None;
Andrew M. Kuchling6fef30e2000-06-18 14:51:21 +0000527#endif /* HAVE_MREMAP */
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000528#endif /* UNIX */
Tim Peters5ebfd362001-11-13 23:11:19 +0000529 }
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000530}
531
532static PyObject *
Georg Brandl96a8c392006-05-29 21:04:52 +0000533mmap_tell_method(mmap_object *self, PyObject *unused)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000534{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000535 CHECK_VALID(NULL);
Neal Norwitz670f8752006-08-22 13:56:56 +0000536 return PyInt_FromSize_t(self->pos);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000537}
538
539static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000540mmap_flush_method(mmap_object *self, PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000541{
Martin v. Löwisad0a4622006-02-16 14:30:23 +0000542 Py_ssize_t offset = 0;
543 Py_ssize_t size = self->size;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000544 CHECK_VALID(NULL);
Tim Petersf2882952006-02-17 01:07:39 +0000545 if (!PyArg_ParseTuple(args, "|nn:flush", &offset, &size))
Guido van Rossum09fdf072000-03-31 01:17:07 +0000546 return NULL;
Tim Petersf2882952006-02-17 01:07:39 +0000547 if ((size_t)(offset + size) > self->size) {
Tim Peters8f9cc292006-02-17 00:00:20 +0000548 PyErr_SetString(PyExc_ValueError, "flush values out of range");
Guido van Rossum09fdf072000-03-31 01:17:07 +0000549 return NULL;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000550 }
Neal Norwitz448654f2008-01-27 07:36:03 +0000551#ifdef MS_WINDOWS
552 return PyInt_FromLong((long) FlushViewOfFile(self->data+offset, size));
553#elif defined(UNIX)
554 /* XXX semantics of return value? */
555 /* XXX flags for msync? */
556 if (-1 == msync(self->data + offset, size, MS_SYNC)) {
557 PyErr_SetFromErrno(mmap_module_error);
558 return NULL;
559 }
560 return PyInt_FromLong(0);
561#else
562 PyErr_SetString(PyExc_ValueError, "flush not supported on this system");
563 return NULL;
564#endif
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000565}
566
567static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000568mmap_seek_method(mmap_object *self, PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000569{
Martin v. Löwiscfe7e092006-02-17 06:59:14 +0000570 Py_ssize_t dist;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000571 int how=0;
572 CHECK_VALID(NULL);
Martin v. Löwiscfe7e092006-02-17 06:59:14 +0000573 if (!PyArg_ParseTuple(args, "n|i:seek", &dist, &how))
Tim Peters8f9cc292006-02-17 00:00:20 +0000574 return NULL;
575 else {
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000576 size_t where;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000577 switch (how) {
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000578 case 0: /* relative to start */
579 if (dist < 0)
580 goto onoutofrange;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000581 where = dist;
582 break;
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000583 case 1: /* relative to current position */
Martin v. Löwiscfe7e092006-02-17 06:59:14 +0000584 if ((Py_ssize_t)self->pos + dist < 0)
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000585 goto onoutofrange;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000586 where = self->pos + dist;
587 break;
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000588 case 2: /* relative to end */
Martin v. Löwiscfe7e092006-02-17 06:59:14 +0000589 if ((Py_ssize_t)self->size + dist < 0)
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000590 goto onoutofrange;
591 where = self->size + dist;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000592 break;
593 default:
Tim Peters8f9cc292006-02-17 00:00:20 +0000594 PyErr_SetString(PyExc_ValueError, "unknown seek type");
Guido van Rossum09fdf072000-03-31 01:17:07 +0000595 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000596 }
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000597 if (where > self->size)
598 goto onoutofrange;
599 self->pos = where;
Tim Peters8f9cc292006-02-17 00:00:20 +0000600 Py_INCREF(Py_None);
Tim Peters23721ee2006-02-16 23:50:16 +0000601 return Py_None;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000602 }
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000603
Tim Peters5ebfd362001-11-13 23:11:19 +0000604 onoutofrange:
Tim Peters8f9cc292006-02-17 00:00:20 +0000605 PyErr_SetString(PyExc_ValueError, "seek out of range");
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000606 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000607}
608
609static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000610mmap_move_method(mmap_object *self, PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000611{
Jack Diederich2ecd3c32009-04-01 20:26:13 +0000612 unsigned long dest, src, cnt;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000613 CHECK_VALID(NULL);
Jack Diederich2ecd3c32009-04-01 20:26:13 +0000614 if (!PyArg_ParseTuple(args, "kkk:move", &dest, &src, &cnt) ||
Tim Peters5ebfd362001-11-13 23:11:19 +0000615 !is_writeable(self)) {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000616 return NULL;
617 } else {
618 /* bounds check the values */
Jack Diederich2ecd3c32009-04-01 20:26:13 +0000619 if (cnt < 0 || (cnt + dest) < cnt || (cnt + src) < cnt ||
620 src < 0 || src > self->size || (src + cnt) > self->size ||
621 dest < 0 || dest > self->size || (dest + cnt) > self->size) {
Tim Peters8f9cc292006-02-17 00:00:20 +0000622 PyErr_SetString(PyExc_ValueError,
Jack Diederich2ecd3c32009-04-01 20:26:13 +0000623 "source, destination, or count out of range");
Guido van Rossum09fdf072000-03-31 01:17:07 +0000624 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000625 }
Jack Diederich2ecd3c32009-04-01 20:26:13 +0000626 memmove(self->data+dest, self->data+src, cnt);
627 Py_INCREF(Py_None);
628 return Py_None;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000629 }
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000630}
631
632static struct PyMethodDef mmap_object_methods[] = {
Georg Brandl96a8c392006-05-29 21:04:52 +0000633 {"close", (PyCFunction) mmap_close_method, METH_NOARGS},
Martin v. Löwis43b936d2002-01-17 23:15:58 +0000634 {"find", (PyCFunction) mmap_find_method, METH_VARARGS},
Andrew M. Kuchling5c60bfc2008-01-19 18:18:41 +0000635 {"rfind", (PyCFunction) mmap_rfind_method, METH_VARARGS},
Martin v. Löwis43b936d2002-01-17 23:15:58 +0000636 {"flush", (PyCFunction) mmap_flush_method, METH_VARARGS},
637 {"move", (PyCFunction) mmap_move_method, METH_VARARGS},
638 {"read", (PyCFunction) mmap_read_method, METH_VARARGS},
Georg Brandl96a8c392006-05-29 21:04:52 +0000639 {"read_byte", (PyCFunction) mmap_read_byte_method, METH_NOARGS},
640 {"readline", (PyCFunction) mmap_read_line_method, METH_NOARGS},
Martin v. Löwis43b936d2002-01-17 23:15:58 +0000641 {"resize", (PyCFunction) mmap_resize_method, METH_VARARGS},
642 {"seek", (PyCFunction) mmap_seek_method, METH_VARARGS},
Georg Brandl96a8c392006-05-29 21:04:52 +0000643 {"size", (PyCFunction) mmap_size_method, METH_NOARGS},
644 {"tell", (PyCFunction) mmap_tell_method, METH_NOARGS},
Martin v. Löwis43b936d2002-01-17 23:15:58 +0000645 {"write", (PyCFunction) mmap_write_method, METH_VARARGS},
646 {"write_byte", (PyCFunction) mmap_write_byte_method, METH_VARARGS},
Guido van Rossum09fdf072000-03-31 01:17:07 +0000647 {NULL, NULL} /* sentinel */
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000648};
649
650/* Functions for treating an mmap'ed file as a buffer */
651
Martin v. Löwis18e16552006-02-15 17:27:45 +0000652static Py_ssize_t
653mmap_buffer_getreadbuf(mmap_object *self, Py_ssize_t index, const void **ptr)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000654{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000655 CHECK_VALID(-1);
Tim Peters8f9cc292006-02-17 00:00:20 +0000656 if (index != 0) {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000657 PyErr_SetString(PyExc_SystemError,
658 "Accessing non-existent mmap segment");
659 return -1;
660 }
661 *ptr = self->data;
662 return self->size;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000663}
664
Martin v. Löwis18e16552006-02-15 17:27:45 +0000665static Py_ssize_t
666mmap_buffer_getwritebuf(mmap_object *self, Py_ssize_t index, const void **ptr)
Tim Petersec0a5f02006-02-16 23:47:20 +0000667{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000668 CHECK_VALID(-1);
Tim Peters8f9cc292006-02-17 00:00:20 +0000669 if (index != 0) {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000670 PyErr_SetString(PyExc_SystemError,
671 "Accessing non-existent mmap segment");
672 return -1;
673 }
Tim Peters5ebfd362001-11-13 23:11:19 +0000674 if (!is_writeable(self))
675 return -1;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000676 *ptr = self->data;
677 return self->size;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000678}
679
Martin v. Löwis18e16552006-02-15 17:27:45 +0000680static Py_ssize_t
681mmap_buffer_getsegcount(mmap_object *self, Py_ssize_t *lenp)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000682{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000683 CHECK_VALID(-1);
Tim Petersec0a5f02006-02-16 23:47:20 +0000684 if (lenp)
Guido van Rossum09fdf072000-03-31 01:17:07 +0000685 *lenp = self->size;
686 return 1;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000687}
688
Martin v. Löwis18e16552006-02-15 17:27:45 +0000689static Py_ssize_t
690mmap_buffer_getcharbuffer(mmap_object *self, Py_ssize_t index, const void **ptr)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000691{
Tim Peters8f9cc292006-02-17 00:00:20 +0000692 if (index != 0) {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000693 PyErr_SetString(PyExc_SystemError,
694 "accessing non-existent buffer segment");
695 return -1;
696 }
697 *ptr = (const char *)self->data;
698 return self->size;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000699}
700
Martin v. Löwis18e16552006-02-15 17:27:45 +0000701static Py_ssize_t
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000702mmap_length(mmap_object *self)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000703{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000704 CHECK_VALID(-1);
705 return self->size;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000706}
707
708static PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000709mmap_item(mmap_object *self, Py_ssize_t i)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000710{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000711 CHECK_VALID(NULL);
Guido van Rossumce8e1dc2000-07-01 00:51:51 +0000712 if (i < 0 || (size_t)i >= self->size) {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000713 PyErr_SetString(PyExc_IndexError, "mmap index out of range");
714 return NULL;
715 }
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000716 return PyString_FromStringAndSize(self->data + i, 1);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000717}
718
719static PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000720mmap_slice(mmap_object *self, Py_ssize_t ilow, Py_ssize_t ihigh)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000721{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000722 CHECK_VALID(NULL);
723 if (ilow < 0)
724 ilow = 0;
Guido van Rossumce8e1dc2000-07-01 00:51:51 +0000725 else if ((size_t)ilow > self->size)
Guido van Rossum09fdf072000-03-31 01:17:07 +0000726 ilow = self->size;
727 if (ihigh < 0)
728 ihigh = 0;
729 if (ihigh < ilow)
730 ihigh = ilow;
Guido van Rossumce8e1dc2000-07-01 00:51:51 +0000731 else if ((size_t)ihigh > self->size)
Guido van Rossum09fdf072000-03-31 01:17:07 +0000732 ihigh = self->size;
Tim Petersec0a5f02006-02-16 23:47:20 +0000733
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000734 return PyString_FromStringAndSize(self->data + ilow, ihigh-ilow);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000735}
736
737static PyObject *
Thomas Wouters3ccec682007-08-28 15:28:19 +0000738mmap_subscript(mmap_object *self, PyObject *item)
739{
740 CHECK_VALID(NULL);
741 if (PyIndex_Check(item)) {
742 Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
743 if (i == -1 && PyErr_Occurred())
744 return NULL;
745 if (i < 0)
746 i += self->size;
Hirokazu Yamamotof6bbd0e2009-02-17 10:12:10 +0000747 if (i < 0 || (size_t)i >= self->size) {
Thomas Wouters3ccec682007-08-28 15:28:19 +0000748 PyErr_SetString(PyExc_IndexError,
749 "mmap index out of range");
750 return NULL;
751 }
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000752 return PyString_FromStringAndSize(self->data + i, 1);
Thomas Wouters3ccec682007-08-28 15:28:19 +0000753 }
754 else if (PySlice_Check(item)) {
755 Py_ssize_t start, stop, step, slicelen;
756
757 if (PySlice_GetIndicesEx((PySliceObject *)item, self->size,
758 &start, &stop, &step, &slicelen) < 0) {
759 return NULL;
760 }
761
762 if (slicelen <= 0)
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000763 return PyString_FromStringAndSize("", 0);
Thomas Wouters3ccec682007-08-28 15:28:19 +0000764 else if (step == 1)
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000765 return PyString_FromStringAndSize(self->data + start,
Thomas Wouters3ccec682007-08-28 15:28:19 +0000766 slicelen);
767 else {
768 char *result_buf = (char *)PyMem_Malloc(slicelen);
769 Py_ssize_t cur, i;
770 PyObject *result;
771
772 if (result_buf == NULL)
773 return PyErr_NoMemory();
774 for (cur = start, i = 0; i < slicelen;
775 cur += step, i++) {
776 result_buf[i] = self->data[cur];
777 }
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000778 result = PyString_FromStringAndSize(result_buf,
Thomas Wouters3ccec682007-08-28 15:28:19 +0000779 slicelen);
780 PyMem_Free(result_buf);
781 return result;
782 }
783 }
784 else {
785 PyErr_SetString(PyExc_TypeError,
786 "mmap indices must be integers");
787 return NULL;
788 }
789}
790
791static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000792mmap_concat(mmap_object *self, PyObject *bb)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000793{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000794 CHECK_VALID(NULL);
795 PyErr_SetString(PyExc_SystemError,
796 "mmaps don't support concatenation");
797 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000798}
799
800static PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000801mmap_repeat(mmap_object *self, Py_ssize_t n)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000802{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000803 CHECK_VALID(NULL);
804 PyErr_SetString(PyExc_SystemError,
805 "mmaps don't support repeat operation");
806 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000807}
808
809static int
Martin v. Löwis18e16552006-02-15 17:27:45 +0000810mmap_ass_slice(mmap_object *self, Py_ssize_t ilow, Py_ssize_t ihigh, PyObject *v)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000811{
Guido van Rossum36d4f8b2000-04-10 21:34:37 +0000812 const char *buf;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000813
Guido van Rossum09fdf072000-03-31 01:17:07 +0000814 CHECK_VALID(-1);
815 if (ilow < 0)
816 ilow = 0;
Guido van Rossumce8e1dc2000-07-01 00:51:51 +0000817 else if ((size_t)ilow > self->size)
Guido van Rossum09fdf072000-03-31 01:17:07 +0000818 ilow = self->size;
819 if (ihigh < 0)
820 ihigh = 0;
821 if (ihigh < ilow)
822 ihigh = ilow;
Guido van Rossumce8e1dc2000-07-01 00:51:51 +0000823 else if ((size_t)ihigh > self->size)
Guido van Rossum09fdf072000-03-31 01:17:07 +0000824 ihigh = self->size;
Tim Petersec0a5f02006-02-16 23:47:20 +0000825
Thomas Wouters1baac722001-07-16 15:47:36 +0000826 if (v == NULL) {
827 PyErr_SetString(PyExc_TypeError,
Tim Peters5ebfd362001-11-13 23:11:19 +0000828 "mmap object doesn't support slice deletion");
Thomas Wouters1baac722001-07-16 15:47:36 +0000829 return -1;
830 }
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000831 if (! (PyString_Check(v)) ) {
Tim Petersec0a5f02006-02-16 23:47:20 +0000832 PyErr_SetString(PyExc_IndexError,
Guido van Rossum09fdf072000-03-31 01:17:07 +0000833 "mmap slice assignment must be a string");
834 return -1;
835 }
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000836 if (PyString_Size(v) != (ihigh - ilow)) {
Tim Petersec0a5f02006-02-16 23:47:20 +0000837 PyErr_SetString(PyExc_IndexError,
Guido van Rossum09fdf072000-03-31 01:17:07 +0000838 "mmap slice assignment is wrong size");
839 return -1;
840 }
Tim Peters5ebfd362001-11-13 23:11:19 +0000841 if (!is_writeable(self))
842 return -1;
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000843 buf = PyString_AsString(v);
Guido van Rossum09fdf072000-03-31 01:17:07 +0000844 memcpy(self->data + ilow, buf, ihigh-ilow);
845 return 0;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000846}
847
848static int
Martin v. Löwis18e16552006-02-15 17:27:45 +0000849mmap_ass_item(mmap_object *self, Py_ssize_t i, PyObject *v)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000850{
Guido van Rossum36d4f8b2000-04-10 21:34:37 +0000851 const char *buf;
Tim Petersec0a5f02006-02-16 23:47:20 +0000852
Guido van Rossum09fdf072000-03-31 01:17:07 +0000853 CHECK_VALID(-1);
Guido van Rossumce8e1dc2000-07-01 00:51:51 +0000854 if (i < 0 || (size_t)i >= self->size) {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000855 PyErr_SetString(PyExc_IndexError, "mmap index out of range");
856 return -1;
857 }
Thomas Wouters1baac722001-07-16 15:47:36 +0000858 if (v == NULL) {
859 PyErr_SetString(PyExc_TypeError,
Tim Peters5ebfd362001-11-13 23:11:19 +0000860 "mmap object doesn't support item deletion");
Thomas Wouters1baac722001-07-16 15:47:36 +0000861 return -1;
862 }
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000863 if (! (PyString_Check(v) && PyString_Size(v)==1) ) {
Tim Petersec0a5f02006-02-16 23:47:20 +0000864 PyErr_SetString(PyExc_IndexError,
Tim Peters5ebfd362001-11-13 23:11:19 +0000865 "mmap assignment must be single-character string");
Guido van Rossum09fdf072000-03-31 01:17:07 +0000866 return -1;
867 }
Tim Peters5ebfd362001-11-13 23:11:19 +0000868 if (!is_writeable(self))
869 return -1;
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000870 buf = PyString_AsString(v);
Guido van Rossum09fdf072000-03-31 01:17:07 +0000871 self->data[i] = buf[0];
872 return 0;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000873}
874
Thomas Wouters3ccec682007-08-28 15:28:19 +0000875static int
876mmap_ass_subscript(mmap_object *self, PyObject *item, PyObject *value)
877{
878 CHECK_VALID(-1);
879
880 if (PyIndex_Check(item)) {
881 Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
882 const char *buf;
883
884 if (i == -1 && PyErr_Occurred())
885 return -1;
886 if (i < 0)
887 i += self->size;
Hirokazu Yamamotof6bbd0e2009-02-17 10:12:10 +0000888 if (i < 0 || (size_t)i >= self->size) {
Thomas Wouters3ccec682007-08-28 15:28:19 +0000889 PyErr_SetString(PyExc_IndexError,
890 "mmap index out of range");
891 return -1;
892 }
893 if (value == NULL) {
894 PyErr_SetString(PyExc_TypeError,
895 "mmap object doesn't support item deletion");
896 return -1;
897 }
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000898 if (!PyString_Check(value) || PyString_Size(value) != 1) {
Thomas Wouters3ccec682007-08-28 15:28:19 +0000899 PyErr_SetString(PyExc_IndexError,
900 "mmap assignment must be single-character string");
901 return -1;
902 }
903 if (!is_writeable(self))
904 return -1;
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000905 buf = PyString_AsString(value);
Thomas Wouters3ccec682007-08-28 15:28:19 +0000906 self->data[i] = buf[0];
907 return 0;
908 }
909 else if (PySlice_Check(item)) {
910 Py_ssize_t start, stop, step, slicelen;
911
912 if (PySlice_GetIndicesEx((PySliceObject *)item,
913 self->size, &start, &stop,
914 &step, &slicelen) < 0) {
915 return -1;
916 }
917 if (value == NULL) {
918 PyErr_SetString(PyExc_TypeError,
919 "mmap object doesn't support slice deletion");
920 return -1;
921 }
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000922 if (!PyString_Check(value)) {
Thomas Wouters3ccec682007-08-28 15:28:19 +0000923 PyErr_SetString(PyExc_IndexError,
924 "mmap slice assignment must be a string");
925 return -1;
926 }
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000927 if (PyString_Size(value) != slicelen) {
Thomas Wouters3ccec682007-08-28 15:28:19 +0000928 PyErr_SetString(PyExc_IndexError,
929 "mmap slice assignment is wrong size");
930 return -1;
931 }
932 if (!is_writeable(self))
933 return -1;
934
935 if (slicelen == 0)
936 return 0;
937 else if (step == 1) {
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000938 const char *buf = PyString_AsString(value);
Thomas Wouters3ccec682007-08-28 15:28:19 +0000939
940 if (buf == NULL)
941 return -1;
942 memcpy(self->data + start, buf, slicelen);
943 return 0;
944 }
945 else {
946 Py_ssize_t cur, i;
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000947 const char *buf = PyString_AsString(value);
Thomas Wouters3ccec682007-08-28 15:28:19 +0000948
949 if (buf == NULL)
950 return -1;
951 for (cur = start, i = 0; i < slicelen;
952 cur += step, i++) {
953 self->data[cur] = buf[i];
954 }
955 return 0;
956 }
957 }
958 else {
959 PyErr_SetString(PyExc_TypeError,
960 "mmap indices must be integer");
961 return -1;
962 }
963}
964
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000965static PySequenceMethods mmap_as_sequence = {
Martin v. Löwis18e16552006-02-15 17:27:45 +0000966 (lenfunc)mmap_length, /*sq_length*/
Guido van Rossum09fdf072000-03-31 01:17:07 +0000967 (binaryfunc)mmap_concat, /*sq_concat*/
Martin v. Löwis18e16552006-02-15 17:27:45 +0000968 (ssizeargfunc)mmap_repeat, /*sq_repeat*/
969 (ssizeargfunc)mmap_item, /*sq_item*/
970 (ssizessizeargfunc)mmap_slice, /*sq_slice*/
971 (ssizeobjargproc)mmap_ass_item, /*sq_ass_item*/
972 (ssizessizeobjargproc)mmap_ass_slice, /*sq_ass_slice*/
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000973};
974
Thomas Wouters3ccec682007-08-28 15:28:19 +0000975static PyMappingMethods mmap_as_mapping = {
976 (lenfunc)mmap_length,
977 (binaryfunc)mmap_subscript,
978 (objobjargproc)mmap_ass_subscript,
979};
980
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000981static PyBufferProcs mmap_as_buffer = {
Martin v. Löwis18e16552006-02-15 17:27:45 +0000982 (readbufferproc)mmap_buffer_getreadbuf,
983 (writebufferproc)mmap_buffer_getwritebuf,
984 (segcountproc)mmap_buffer_getsegcount,
985 (charbufferproc)mmap_buffer_getcharbuffer,
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000986};
987
Georg Brandl845c4032008-01-21 14:16:46 +0000988static PyObject *
989new_mmap_object(PyTypeObject *type, PyObject *args, PyObject *kwdict);
990
Georg Brandlef928022008-01-20 14:50:05 +0000991PyDoc_STRVAR(mmap_doc,
992"Windows: mmap(fileno, length[, tagname[, access[, offset]]])\n\
993\n\
994Maps length bytes from the file specified by the file handle fileno,\n\
995and returns a mmap object. If length is larger than the current size\n\
996of the file, the file is extended to contain length bytes. If length\n\
997is 0, the maximum length of the map is the current size of the file,\n\
998except that if the file is empty Windows raises an exception (you cannot\n\
999create an empty mapping on Windows).\n\
1000\n\
1001Unix: mmap(fileno, length[, flags[, prot[, access[, offset]]]])\n\
1002\n\
1003Maps length bytes from the file specified by the file descriptor fileno,\n\
1004and returns a mmap object. If length is 0, the maximum length of the map\n\
1005will be the current size of the file when mmap is called.\n\
1006flags specifies the nature of the mapping. MAP_PRIVATE creates a\n\
1007private copy-on-write mapping, so changes to the contents of the mmap\n\
Thomas Heller66260992008-08-19 17:47:13 +00001008object will be private to this process, and MAP_SHARED creates a mapping\n\
Georg Brandlef928022008-01-20 14:50:05 +00001009that's shared with all other processes mapping the same areas of the file.\n\
1010The default value is MAP_SHARED.\n\
1011\n\
1012To map anonymous memory, pass -1 as the fileno (both versions).");
1013
1014
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001015static PyTypeObject mmap_object_type = {
Georg Brandl845c4032008-01-21 14:16:46 +00001016 PyVarObject_HEAD_INIT(NULL, 0)
Guido van Rossum14648392001-12-08 18:02:58 +00001017 "mmap.mmap", /* tp_name */
Guido van Rossum09fdf072000-03-31 01:17:07 +00001018 sizeof(mmap_object), /* tp_size */
1019 0, /* tp_itemsize */
1020 /* methods */
1021 (destructor) mmap_object_dealloc, /* tp_dealloc */
1022 0, /* tp_print */
Georg Brandlef928022008-01-20 14:50:05 +00001023 0, /* tp_getattr */
Guido van Rossum09fdf072000-03-31 01:17:07 +00001024 0, /* tp_setattr */
1025 0, /* tp_compare */
1026 0, /* tp_repr */
1027 0, /* tp_as_number */
1028 &mmap_as_sequence, /*tp_as_sequence*/
Thomas Wouters3ccec682007-08-28 15:28:19 +00001029 &mmap_as_mapping, /*tp_as_mapping*/
Guido van Rossum09fdf072000-03-31 01:17:07 +00001030 0, /*tp_hash*/
1031 0, /*tp_call*/
1032 0, /*tp_str*/
Georg Brandlef928022008-01-20 14:50:05 +00001033 PyObject_GenericGetAttr, /*tp_getattro*/
Guido van Rossum09fdf072000-03-31 01:17:07 +00001034 0, /*tp_setattro*/
1035 &mmap_as_buffer, /*tp_as_buffer*/
Georg Brandl845c4032008-01-21 14:16:46 +00001036 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GETCHARBUFFER, /*tp_flags*/
Georg Brandlef928022008-01-20 14:50:05 +00001037 mmap_doc, /*tp_doc*/
1038 0, /* tp_traverse */
1039 0, /* tp_clear */
1040 0, /* tp_richcompare */
1041 0, /* tp_weaklistoffset */
Georg Brandl845c4032008-01-21 14:16:46 +00001042 0, /* tp_iter */
1043 0, /* tp_iternext */
Georg Brandlef928022008-01-20 14:50:05 +00001044 mmap_object_methods, /* tp_methods */
Georg Brandl845c4032008-01-21 14:16:46 +00001045 0, /* tp_members */
1046 0, /* tp_getset */
1047 0, /* tp_base */
1048 0, /* tp_dict */
1049 0, /* tp_descr_get */
1050 0, /* tp_descr_set */
1051 0, /* tp_dictoffset */
1052 0, /* tp_init */
1053 PyType_GenericAlloc, /* tp_alloc */
1054 new_mmap_object, /* tp_new */
1055 PyObject_Del, /* tp_free */
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001056};
1057
Andrew M. Kuchling70d27422000-06-18 04:45:14 +00001058
1059/* extract the map size from the given PyObject
1060
Thomas Wouters7e474022000-07-16 12:04:32 +00001061 Returns -1 on error, with an appropriate Python exception raised. On
Andrew M. Kuchling70d27422000-06-18 04:45:14 +00001062 success, the map size is returned. */
Martin v. Löwiscfe7e092006-02-17 06:59:14 +00001063static Py_ssize_t
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001064_GetMapSize(PyObject *o, const char* param)
Andrew M. Kuchling70d27422000-06-18 04:45:14 +00001065{
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001066 if (o == NULL)
1067 return 0;
Neal Norwitz8a87f5d2006-08-12 17:03:09 +00001068 if (PyIndex_Check(o)) {
1069 Py_ssize_t i = PyNumber_AsSsize_t(o, PyExc_OverflowError);
Guido van Rossum38fff8c2006-03-07 18:50:55 +00001070 if (i==-1 && PyErr_Occurred())
Andrew M. Kuchling70d27422000-06-18 04:45:14 +00001071 return -1;
Neal Norwitz8a87f5d2006-08-12 17:03:09 +00001072 if (i < 0) {
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001073 PyErr_Format(PyExc_OverflowError,
1074 "memory mapped %s must be positive",
1075 param);
Neal Norwitz8a87f5d2006-08-12 17:03:09 +00001076 return -1;
1077 }
Martin v. Löwiscfe7e092006-02-17 06:59:14 +00001078 return i;
Andrew M. Kuchling70d27422000-06-18 04:45:14 +00001079 }
Andrew M. Kuchling70d27422000-06-18 04:45:14 +00001080
Neal Norwitz8a87f5d2006-08-12 17:03:09 +00001081 PyErr_SetString(PyExc_TypeError, "map size must be an integral value");
Andrew M. Kuchling70d27422000-06-18 04:45:14 +00001082 return -1;
1083}
1084
Tim Petersec0a5f02006-02-16 23:47:20 +00001085#ifdef UNIX
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001086static PyObject *
Georg Brandl845c4032008-01-21 14:16:46 +00001087new_mmap_object(PyTypeObject *type, PyObject *args, PyObject *kwdict)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001088{
Neal Norwitzb5673922002-09-05 21:48:07 +00001089#ifdef HAVE_FSTAT
1090 struct stat st;
1091#endif
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +00001092 mmap_object *m_obj;
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001093 PyObject *map_size_obj = NULL, *offset_obj = NULL;
1094 Py_ssize_t map_size, offset;
Guido van Rossum09fdf072000-03-31 01:17:07 +00001095 int fd, flags = MAP_SHARED, prot = PROT_WRITE | PROT_READ;
Neal Norwitz0e6bc8c2006-02-05 05:45:43 +00001096 int devzero = -1;
Neal Norwitz8856fb72005-12-18 03:34:22 +00001097 int access = (int)ACCESS_DEFAULT;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001098 static char *keywords[] = {"fileno", "length",
Tim Petersec0a5f02006-02-16 23:47:20 +00001099 "flags", "prot",
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001100 "access", "offset", NULL};
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001101
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001102 if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iO|iiiO", keywords,
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001103 &fd, &map_size_obj, &flags, &prot,
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001104 &access, &offset_obj))
Guido van Rossum09fdf072000-03-31 01:17:07 +00001105 return NULL;
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001106 map_size = _GetMapSize(map_size_obj, "size");
Andrew M. Kuchling70d27422000-06-18 04:45:14 +00001107 if (map_size < 0)
1108 return NULL;
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001109 offset = _GetMapSize(offset_obj, "offset");
1110 if (offset < 0)
1111 return NULL;
Tim Peters5ebfd362001-11-13 23:11:19 +00001112
Tim Petersec0a5f02006-02-16 23:47:20 +00001113 if ((access != (int)ACCESS_DEFAULT) &&
Neal Norwitzd1cfc8a2006-02-05 03:36:57 +00001114 ((flags != MAP_SHARED) || (prot != (PROT_WRITE | PROT_READ))))
Tim Petersec0a5f02006-02-16 23:47:20 +00001115 return PyErr_Format(PyExc_ValueError,
Tim Peters5ebfd362001-11-13 23:11:19 +00001116 "mmap can't specify both access and flags, prot.");
Neal Norwitzd1cfc8a2006-02-05 03:36:57 +00001117 switch ((access_mode)access) {
Tim Peters5ebfd362001-11-13 23:11:19 +00001118 case ACCESS_READ:
1119 flags = MAP_SHARED;
1120 prot = PROT_READ;
1121 break;
1122 case ACCESS_WRITE:
1123 flags = MAP_SHARED;
1124 prot = PROT_READ | PROT_WRITE;
1125 break;
1126 case ACCESS_COPY:
1127 flags = MAP_PRIVATE;
1128 prot = PROT_READ | PROT_WRITE;
1129 break;
Tim Petersec0a5f02006-02-16 23:47:20 +00001130 case ACCESS_DEFAULT:
Tim Peters5ebfd362001-11-13 23:11:19 +00001131 /* use the specified or default values of flags and prot */
1132 break;
1133 default:
Tim Petersec0a5f02006-02-16 23:47:20 +00001134 return PyErr_Format(PyExc_ValueError,
Tim Peters5ebfd362001-11-13 23:11:19 +00001135 "mmap invalid access parameter.");
1136 }
Neal Norwitzb5673922002-09-05 21:48:07 +00001137
Christian Heimes7adfad82008-02-15 08:20:11 +00001138 if (prot == PROT_READ) {
1139 access = ACCESS_READ;
1140 }
1141
Neal Norwitzb5673922002-09-05 21:48:07 +00001142#ifdef HAVE_FSTAT
Martin v. Löwisc16f3bd2003-05-03 09:14:54 +00001143# ifdef __VMS
1144 /* on OpenVMS we must ensure that all bytes are written to the file */
Andrew M. Kuchling7c22ccc2008-01-10 13:37:12 +00001145 if (fd != -1) {
1146 fsync(fd);
1147 }
Martin v. Löwisc16f3bd2003-05-03 09:14:54 +00001148# endif
Andrew M. Kuchling7c22ccc2008-01-10 13:37:12 +00001149 if (fd != -1 && fstat(fd, &st) == 0 && S_ISREG(st.st_mode)) {
Martin v. Löwis7fe60c02005-03-03 11:22:44 +00001150 if (map_size == 0) {
Martin v. Löwiscfe7e092006-02-17 06:59:14 +00001151 map_size = st.st_size;
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001152 } else if ((size_t)offset + (size_t)map_size > st.st_size) {
Tim Petersec0a5f02006-02-16 23:47:20 +00001153 PyErr_SetString(PyExc_ValueError,
Martin v. Löwis7fe60c02005-03-03 11:22:44 +00001154 "mmap length is greater than file size");
1155 return NULL;
1156 }
Neal Norwitzb5673922002-09-05 21:48:07 +00001157 }
1158#endif
Georg Brandl845c4032008-01-21 14:16:46 +00001159 m_obj = (mmap_object *)type->tp_alloc(type, 0);
Guido van Rossum09fdf072000-03-31 01:17:07 +00001160 if (m_obj == NULL) {return NULL;}
Neal Norwitz3b4fff82006-01-11 08:54:45 +00001161 m_obj->data = NULL;
Guido van Rossum09fdf072000-03-31 01:17:07 +00001162 m_obj->size = (size_t) map_size;
1163 m_obj->pos = (size_t) 0;
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001164 m_obj->offset = offset;
Neal Norwitz0e6bc8c2006-02-05 05:45:43 +00001165 if (fd == -1) {
1166 m_obj->fd = -1;
1167 /* Assume the caller wants to map anonymous memory.
1168 This is the same behaviour as Windows. mmap.mmap(-1, size)
1169 on both Windows and Unix map anonymous memory.
1170 */
1171#ifdef MAP_ANONYMOUS
1172 /* BSD way to map anonymous memory */
1173 flags |= MAP_ANONYMOUS;
1174#else
1175 /* SVR4 method to map anonymous memory is to open /dev/zero */
1176 fd = devzero = open("/dev/zero", O_RDWR);
1177 if (devzero == -1) {
1178 Py_DECREF(m_obj);
1179 PyErr_SetFromErrno(mmap_module_error);
1180 return NULL;
1181 }
1182#endif
1183 } else {
1184 m_obj->fd = dup(fd);
1185 if (m_obj->fd == -1) {
1186 Py_DECREF(m_obj);
1187 PyErr_SetFromErrno(mmap_module_error);
1188 return NULL;
1189 }
Georg Brandl38387b82005-08-24 07:17:40 +00001190 }
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001191
Tim Petersec0a5f02006-02-16 23:47:20 +00001192 m_obj->data = mmap(NULL, map_size,
Guido van Rossum09fdf072000-03-31 01:17:07 +00001193 prot, flags,
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001194 fd, offset);
Neal Norwitz0e6bc8c2006-02-05 05:45:43 +00001195
1196 if (devzero != -1) {
1197 close(devzero);
1198 }
1199
Tim Peters5ebfd362001-11-13 23:11:19 +00001200 if (m_obj->data == (char *)-1) {
Andrew M. Kuchling16581c82004-05-19 14:39:08 +00001201 m_obj->data = NULL;
Guido van Rossum09fdf072000-03-31 01:17:07 +00001202 Py_DECREF(m_obj);
1203 PyErr_SetFromErrno(mmap_module_error);
1204 return NULL;
1205 }
Neal Norwitz8856fb72005-12-18 03:34:22 +00001206 m_obj->access = (access_mode)access;
Guido van Rossum09fdf072000-03-31 01:17:07 +00001207 return (PyObject *)m_obj;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001208}
1209#endif /* UNIX */
1210
Martin v. Löwis6238d2b2002-06-30 15:26:10 +00001211#ifdef MS_WINDOWS
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001212static PyObject *
Georg Brandl845c4032008-01-21 14:16:46 +00001213new_mmap_object(PyTypeObject *type, PyObject *args, PyObject *kwdict)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001214{
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +00001215 mmap_object *m_obj;
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001216 PyObject *map_size_obj = NULL, *offset_obj = NULL;
1217 Py_ssize_t map_size, offset;
1218 DWORD off_hi; /* upper 32 bits of offset */
1219 DWORD off_lo; /* lower 32 bits of offset */
1220 DWORD size_hi; /* upper 32 bits of size */
1221 DWORD size_lo; /* lower 32 bits of size */
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +00001222 char *tagname = "";
Guido van Rossum09fdf072000-03-31 01:17:07 +00001223 DWORD dwErr = 0;
1224 int fileno;
Mark Hammond071864a2000-07-30 02:46:26 +00001225 HANDLE fh = 0;
Neal Norwitz8856fb72005-12-18 03:34:22 +00001226 int access = (access_mode)ACCESS_DEFAULT;
Tim Peters5ebfd362001-11-13 23:11:19 +00001227 DWORD flProtect, dwDesiredAccess;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001228 static char *keywords[] = { "fileno", "length",
Tim Petersec0a5f02006-02-16 23:47:20 +00001229 "tagname",
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001230 "access", "offset", NULL };
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001231
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001232 if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iO|ziO", keywords,
Tim Petersec0a5f02006-02-16 23:47:20 +00001233 &fileno, &map_size_obj,
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001234 &tagname, &access, &offset_obj)) {
Guido van Rossum09fdf072000-03-31 01:17:07 +00001235 return NULL;
Tim Peters5ebfd362001-11-13 23:11:19 +00001236 }
1237
Neal Norwitz8856fb72005-12-18 03:34:22 +00001238 switch((access_mode)access) {
Tim Peters5ebfd362001-11-13 23:11:19 +00001239 case ACCESS_READ:
1240 flProtect = PAGE_READONLY;
1241 dwDesiredAccess = FILE_MAP_READ;
1242 break;
1243 case ACCESS_DEFAULT: case ACCESS_WRITE:
1244 flProtect = PAGE_READWRITE;
1245 dwDesiredAccess = FILE_MAP_WRITE;
1246 break;
1247 case ACCESS_COPY:
1248 flProtect = PAGE_WRITECOPY;
1249 dwDesiredAccess = FILE_MAP_COPY;
1250 break;
1251 default:
Tim Petersec0a5f02006-02-16 23:47:20 +00001252 return PyErr_Format(PyExc_ValueError,
Tim Peters5ebfd362001-11-13 23:11:19 +00001253 "mmap invalid access parameter.");
1254 }
1255
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001256 map_size = _GetMapSize(map_size_obj, "size");
Andrew M. Kuchling70d27422000-06-18 04:45:14 +00001257 if (map_size < 0)
1258 return NULL;
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001259 offset = _GetMapSize(offset_obj, "offset");
1260 if (offset < 0)
1261 return NULL;
Tim Petersec0a5f02006-02-16 23:47:20 +00001262
Neal Norwitz0e6bc8c2006-02-05 05:45:43 +00001263 /* assume -1 and 0 both mean invalid filedescriptor
1264 to 'anonymously' map memory.
1265 XXX: fileno == 0 is a valid fd, but was accepted prior to 2.5.
1266 XXX: Should this code be added?
1267 if (fileno == 0)
1268 PyErr_Warn(PyExc_DeprecationWarning,
1269 "don't use 0 for anonymous memory");
1270 */
1271 if (fileno != -1 && fileno != 0) {
Mark Hammond071864a2000-07-30 02:46:26 +00001272 fh = (HANDLE)_get_osfhandle(fileno);
1273 if (fh==(HANDLE)-1) {
Tim Peters5ebfd362001-11-13 23:11:19 +00001274 PyErr_SetFromErrno(mmap_module_error);
1275 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001276 }
Fred Drake1ef4e2d2000-04-05 14:15:31 +00001277 /* Win9x appears to need us seeked to zero */
Guido van Rossum69c2b882003-04-09 19:31:02 +00001278 lseek(fileno, 0, SEEK_SET);
Guido van Rossum09fdf072000-03-31 01:17:07 +00001279 }
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001280
Georg Brandl845c4032008-01-21 14:16:46 +00001281 m_obj = (mmap_object *)type->tp_alloc(type, 0);
Tim Peters8f9cc292006-02-17 00:00:20 +00001282 if (m_obj == NULL)
Mark Hammond2cbed002000-07-30 02:22:43 +00001283 return NULL;
1284 /* Set every field to an invalid marker, so we can safely
1285 destruct the object in the face of failure */
1286 m_obj->data = NULL;
Mark Hammond071864a2000-07-30 02:46:26 +00001287 m_obj->file_handle = INVALID_HANDLE_VALUE;
Hirokazu Yamamoto264fc122009-03-05 14:21:12 +00001288 m_obj->map_handle = NULL;
Mark Hammond2cbed002000-07-30 02:22:43 +00001289 m_obj->tagname = NULL;
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001290 m_obj->offset = offset;
Mark Hammond2cbed002000-07-30 02:22:43 +00001291
Guido van Rossum09fdf072000-03-31 01:17:07 +00001292 if (fh) {
Mark Hammond2cbed002000-07-30 02:22:43 +00001293 /* It is necessary to duplicate the handle, so the
1294 Python code can close it on us */
1295 if (!DuplicateHandle(
Tim Peters5ebfd362001-11-13 23:11:19 +00001296 GetCurrentProcess(), /* source process handle */
1297 fh, /* handle to be duplicated */
1298 GetCurrentProcess(), /* target proc handle */
1299 (LPHANDLE)&m_obj->file_handle, /* result */
1300 0, /* access - ignored due to options value */
1301 FALSE, /* inherited by child processes? */
1302 DUPLICATE_SAME_ACCESS)) { /* options */
Mark Hammond2cbed002000-07-30 02:22:43 +00001303 dwErr = GetLastError();
1304 Py_DECREF(m_obj);
1305 PyErr_SetFromWindowsErr(dwErr);
1306 return NULL;
1307 }
Guido van Rossum09fdf072000-03-31 01:17:07 +00001308 if (!map_size) {
Martin v. Löwis15186072006-02-18 12:38:35 +00001309 DWORD low,high;
1310 low = GetFileSize(fh, &high);
1311 /* low might just happen to have the value INVALID_FILE_SIZE;
1312 so we need to check the last error also. */
1313 if (low == INVALID_FILE_SIZE &&
1314 (dwErr = GetLastError()) != NO_ERROR) {
1315 Py_DECREF(m_obj);
1316 return PyErr_SetFromWindowsErr(dwErr);
1317 }
1318
1319#if SIZEOF_SIZE_T > 4
1320 m_obj->size = (((size_t)high)<<32) + low;
1321#else
1322 if (high)
1323 /* File is too large to map completely */
1324 m_obj->size = (size_t)-1;
1325 else
1326 m_obj->size = low;
1327#endif
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001328 } else {
Guido van Rossum09fdf072000-03-31 01:17:07 +00001329 m_obj->size = map_size;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001330 }
Guido van Rossum09fdf072000-03-31 01:17:07 +00001331 }
1332 else {
Guido van Rossum09fdf072000-03-31 01:17:07 +00001333 m_obj->size = map_size;
1334 }
1335
1336 /* set the initial position */
1337 m_obj->pos = (size_t) 0;
1338
Mark Hammond2cbed002000-07-30 02:22:43 +00001339 /* set the tag name */
Tim Peters0d9f9dc2001-01-10 05:42:18 +00001340 if (tagname != NULL && *tagname != '\0') {
Mark Hammond2cbed002000-07-30 02:22:43 +00001341 m_obj->tagname = PyMem_Malloc(strlen(tagname)+1);
1342 if (m_obj->tagname == NULL) {
1343 PyErr_NoMemory();
1344 Py_DECREF(m_obj);
1345 return NULL;
1346 }
1347 strcpy(m_obj->tagname, tagname);
1348 }
1349 else
1350 m_obj->tagname = NULL;
1351
Neal Norwitz8856fb72005-12-18 03:34:22 +00001352 m_obj->access = (access_mode)access;
Tim Peterse564e7f2006-02-16 23:46:01 +00001353 /* DWORD is a 4-byte int. If we're on a box where size_t consumes
Thomas Wouters2c98a7b2006-02-17 09:59:00 +00001354 * more than 4 bytes, we need to break it apart. Else (size_t
Tim Peterse564e7f2006-02-16 23:46:01 +00001355 * consumes 4 bytes), C doesn't define what happens if we shift
1356 * right by 32, so we need different code.
1357 */
1358#if SIZEOF_SIZE_T > 4
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001359 size_hi = (DWORD)((offset + m_obj->size) >> 32);
1360 size_lo = (DWORD)((offset + m_obj->size) & 0xFFFFFFFF);
1361 off_hi = (DWORD)(offset >> 32);
1362 off_lo = (DWORD)(offset & 0xFFFFFFFF);
Tim Peterse564e7f2006-02-16 23:46:01 +00001363#else
1364 size_hi = 0;
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001365 size_lo = (DWORD)(offset + m_obj->size);
1366 off_hi = 0;
1367 off_lo = (DWORD)offset;
Tim Peterse564e7f2006-02-16 23:46:01 +00001368#endif
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001369 /* For files, it would be sufficient to pass 0 as size.
1370 For anonymous maps, we have to pass the size explicitly. */
Tim Peters8f9cc292006-02-17 00:00:20 +00001371 m_obj->map_handle = CreateFileMapping(m_obj->file_handle,
1372 NULL,
1373 flProtect,
1374 size_hi,
1375 size_lo,
1376 m_obj->tagname);
Guido van Rossum09fdf072000-03-31 01:17:07 +00001377 if (m_obj->map_handle != NULL) {
Tim Peters8f9cc292006-02-17 00:00:20 +00001378 m_obj->data = (char *) MapViewOfFile(m_obj->map_handle,
1379 dwDesiredAccess,
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001380 off_hi,
1381 off_lo,
Hirokazu Yamamotob0e10c72009-02-28 12:13:07 +00001382 m_obj->size);
Tim Peters23721ee2006-02-16 23:50:16 +00001383 if (m_obj->data != NULL)
1384 return (PyObject *)m_obj;
Hirokazu Yamamoto264fc122009-03-05 14:21:12 +00001385 else {
Tim Peters5ebfd362001-11-13 23:11:19 +00001386 dwErr = GetLastError();
Hirokazu Yamamoto264fc122009-03-05 14:21:12 +00001387 CloseHandle(m_obj->map_handle);
1388 m_obj->map_handle = NULL;
1389 }
Tim Peters23721ee2006-02-16 23:50:16 +00001390 } else
Guido van Rossum09fdf072000-03-31 01:17:07 +00001391 dwErr = GetLastError();
Mark Hammond2cbed002000-07-30 02:22:43 +00001392 Py_DECREF(m_obj);
Guido van Rossum09fdf072000-03-31 01:17:07 +00001393 PyErr_SetFromWindowsErr(dwErr);
Tim Peters23721ee2006-02-16 23:50:16 +00001394 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001395}
Martin v. Löwis6238d2b2002-06-30 15:26:10 +00001396#endif /* MS_WINDOWS */
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001397
Neal Norwitze9ac0bb2006-08-13 18:11:27 +00001398static void
1399setint(PyObject *d, const char *name, long value)
1400{
1401 PyObject *o = PyInt_FromLong(value);
Neal Norwitz5ed49972006-08-13 18:41:15 +00001402 if (o && PyDict_SetItemString(d, name, o) == 0) {
Neal Norwitze9ac0bb2006-08-13 18:11:27 +00001403 Py_DECREF(o);
Neal Norwitz5ed49972006-08-13 18:41:15 +00001404 }
Neal Norwitze9ac0bb2006-08-13 18:11:27 +00001405}
1406
Mark Hammond62b1ab12002-07-23 06:31:15 +00001407PyMODINIT_FUNC
Georg Brandl845c4032008-01-21 14:16:46 +00001408initmmap(void)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001409{
Guido van Rossum09fdf072000-03-31 01:17:07 +00001410 PyObject *dict, *module;
Tim Peters2caf8df2001-01-14 05:05:51 +00001411
Georg Brandl845c4032008-01-21 14:16:46 +00001412 if (PyType_Ready(&mmap_object_type) < 0)
1413 return;
Tim Peters2caf8df2001-01-14 05:05:51 +00001414
Georg Brandl845c4032008-01-21 14:16:46 +00001415 module = Py_InitModule("mmap", NULL);
Neal Norwitz1ac754f2006-01-19 06:09:39 +00001416 if (module == NULL)
1417 return;
Tim Peters8f9cc292006-02-17 00:00:20 +00001418 dict = PyModule_GetDict(module);
Neal Norwitze9ac0bb2006-08-13 18:11:27 +00001419 if (!dict)
1420 return;
Facundo Batistae1396882008-02-17 18:59:29 +00001421 mmap_module_error = PyErr_NewException("mmap.error",
1422 PyExc_EnvironmentError , NULL);
1423 if (mmap_module_error == NULL)
1424 return;
Tim Peters8f9cc292006-02-17 00:00:20 +00001425 PyDict_SetItemString(dict, "error", mmap_module_error);
Georg Brandl845c4032008-01-21 14:16:46 +00001426 PyDict_SetItemString(dict, "mmap", (PyObject*) &mmap_object_type);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001427#ifdef PROT_EXEC
Neal Norwitze9ac0bb2006-08-13 18:11:27 +00001428 setint(dict, "PROT_EXEC", PROT_EXEC);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001429#endif
1430#ifdef PROT_READ
Neal Norwitze9ac0bb2006-08-13 18:11:27 +00001431 setint(dict, "PROT_READ", PROT_READ);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001432#endif
1433#ifdef PROT_WRITE
Neal Norwitze9ac0bb2006-08-13 18:11:27 +00001434 setint(dict, "PROT_WRITE", PROT_WRITE);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001435#endif
1436
1437#ifdef MAP_SHARED
Neal Norwitze9ac0bb2006-08-13 18:11:27 +00001438 setint(dict, "MAP_SHARED", MAP_SHARED);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001439#endif
1440#ifdef MAP_PRIVATE
Neal Norwitze9ac0bb2006-08-13 18:11:27 +00001441 setint(dict, "MAP_PRIVATE", MAP_PRIVATE);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001442#endif
1443#ifdef MAP_DENYWRITE
Neal Norwitze9ac0bb2006-08-13 18:11:27 +00001444 setint(dict, "MAP_DENYWRITE", MAP_DENYWRITE);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001445#endif
1446#ifdef MAP_EXECUTABLE
Neal Norwitze9ac0bb2006-08-13 18:11:27 +00001447 setint(dict, "MAP_EXECUTABLE", MAP_EXECUTABLE);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001448#endif
Neal Norwitz0e6bc8c2006-02-05 05:45:43 +00001449#ifdef MAP_ANONYMOUS
Neal Norwitze9ac0bb2006-08-13 18:11:27 +00001450 setint(dict, "MAP_ANON", MAP_ANONYMOUS);
1451 setint(dict, "MAP_ANONYMOUS", MAP_ANONYMOUS);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001452#endif
1453
Neal Norwitze9ac0bb2006-08-13 18:11:27 +00001454 setint(dict, "PAGESIZE", (long)my_getpagesize());
Andrew M. Kuchling961fe172000-06-03 19:41:42 +00001455
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001456 setint(dict, "ALLOCATIONGRANULARITY", (long)my_getallocationgranularity());
1457
Neal Norwitze9ac0bb2006-08-13 18:11:27 +00001458 setint(dict, "ACCESS_READ", ACCESS_READ);
1459 setint(dict, "ACCESS_WRITE", ACCESS_WRITE);
1460 setint(dict, "ACCESS_COPY", ACCESS_COPY);
Tim Peters5ebfd362001-11-13 23:11:19 +00001461}