blob: 5e0b3ad6211bed5cc986405a1fd5ba670975a9fd [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
Hirokazu Yamamoto983a4652009-06-14 03:53:55 +0000161 if (0 <= self->fd)
162 (void) close(self->fd);
Neal Norwitz6eac2002005-11-02 05:36:37 +0000163 self->fd = -1;
Neal Norwitze604c022003-01-10 20:52:16 +0000164 if (self->data != NULL) {
165 munmap(self->data, self->size);
166 self->data = NULL;
167 }
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000168#endif
169
Tim Peters8f9cc292006-02-17 00:00:20 +0000170 Py_INCREF(Py_None);
Tim Peters23721ee2006-02-16 23:50:16 +0000171 return Py_None;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000172}
173
Martin v. Löwis6238d2b2002-06-30 15:26:10 +0000174#ifdef MS_WINDOWS
Guido van Rossum09fdf072000-03-31 01:17:07 +0000175#define CHECK_VALID(err) \
176do { \
Hirokazu Yamamoto264fc122009-03-05 14:21:12 +0000177 if (self->map_handle == NULL) { \
Tim Peters8f9cc292006-02-17 00:00:20 +0000178 PyErr_SetString(PyExc_ValueError, "mmap closed or invalid"); \
Guido van Rossum09fdf072000-03-31 01:17:07 +0000179 return err; \
180 } \
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000181} while (0)
Martin v. Löwis6238d2b2002-06-30 15:26:10 +0000182#endif /* MS_WINDOWS */
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000183
184#ifdef UNIX
Guido van Rossum09fdf072000-03-31 01:17:07 +0000185#define CHECK_VALID(err) \
186do { \
187 if (self->data == NULL) { \
Tim Peters8f9cc292006-02-17 00:00:20 +0000188 PyErr_SetString(PyExc_ValueError, "mmap closed or invalid"); \
Guido van Rossum09fdf072000-03-31 01:17:07 +0000189 return err; \
190 } \
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000191} while (0)
192#endif /* UNIX */
193
194static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000195mmap_read_byte_method(mmap_object *self,
Georg Brandl96a8c392006-05-29 21:04:52 +0000196 PyObject *unused)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000197{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000198 CHECK_VALID(NULL);
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000199 if (self->pos < self->size) {
Tim Petersd6283b82001-05-09 18:48:26 +0000200 char value = self->data[self->pos];
Guido van Rossum09fdf072000-03-31 01:17:07 +0000201 self->pos += 1;
Tim Petersd6283b82001-05-09 18:48:26 +0000202 return Py_BuildValue("c", value);
Guido van Rossum09fdf072000-03-31 01:17:07 +0000203 } else {
Tim Peters8f9cc292006-02-17 00:00:20 +0000204 PyErr_SetString(PyExc_ValueError, "read byte out of range");
Guido van Rossum09fdf072000-03-31 01:17:07 +0000205 return NULL;
206 }
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000207}
208
209static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000210mmap_read_line_method(mmap_object *self,
Georg Brandl96a8c392006-05-29 21:04:52 +0000211 PyObject *unused)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000212{
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000213 char *start = self->data+self->pos;
214 char *eof = self->data+self->size;
215 char *eol;
216 PyObject *result;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000217
Guido van Rossum09fdf072000-03-31 01:17:07 +0000218 CHECK_VALID(NULL);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000219
Fred Drake56a87a02000-04-04 18:17:35 +0000220 eol = memchr(start, '\n', self->size - self->pos);
221 if (!eol)
222 eol = eof;
223 else
224 ++eol; /* we're interested in the position after the
225 newline. */
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000226 result = PyString_FromStringAndSize(start, (eol - start));
Guido van Rossum09fdf072000-03-31 01:17:07 +0000227 self->pos += (eol - start);
Tim Peters23721ee2006-02-16 23:50:16 +0000228 return result;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000229}
230
231static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000232mmap_read_method(mmap_object *self,
233 PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000234{
Hirokazu Yamamoto8839fd72009-06-29 13:25:16 +0000235 Py_ssize_t num_bytes, n;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000236 PyObject *result;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000237
Guido van Rossum09fdf072000-03-31 01:17:07 +0000238 CHECK_VALID(NULL);
Martin v. Löwisad0a4622006-02-16 14:30:23 +0000239 if (!PyArg_ParseTuple(args, "n:read", &num_bytes))
Guido van Rossum09fdf072000-03-31 01:17:07 +0000240 return(NULL);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000241
Guido van Rossum09fdf072000-03-31 01:17:07 +0000242 /* silently 'adjust' out-of-range requests */
Hirokazu Yamamoto8839fd72009-06-29 13:25:16 +0000243 assert(self->size >= self->pos);
244 n = self->size - self->pos;
245 /* The difference can overflow, only if self->size is greater than
246 * PY_SSIZE_T_MAX. But then the operation cannot possibly succeed,
247 * because the mapped area and the returned string each need more
248 * than half of the addressable memory. So we clip the size, and let
249 * the code below raise MemoryError.
250 */
251 if (n < 0)
252 n = PY_SSIZE_T_MAX;
253 if (num_bytes < 0 || num_bytes > n) {
254 num_bytes = n;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000255 }
256 result = Py_BuildValue("s#", self->data+self->pos, num_bytes);
Tim Petersec0a5f02006-02-16 23:47:20 +0000257 self->pos += num_bytes;
Tim Peters23721ee2006-02-16 23:50:16 +0000258 return result;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000259}
260
261static PyObject *
Andrew M. Kuchling5c60bfc2008-01-19 18:18:41 +0000262mmap_gfind(mmap_object *self,
263 PyObject *args,
264 int reverse)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000265{
Martin v. Löwisad0a4622006-02-16 14:30:23 +0000266 Py_ssize_t start = self->pos;
Neal Norwitz739a3c42008-01-26 20:24:36 +0000267 Py_ssize_t end = self->size;
268 const char *needle;
Martin v. Löwiscfe7e092006-02-17 06:59:14 +0000269 Py_ssize_t len;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000270
Guido van Rossum09fdf072000-03-31 01:17:07 +0000271 CHECK_VALID(NULL);
Andrew M. Kuchling5c60bfc2008-01-19 18:18:41 +0000272 if (!PyArg_ParseTuple(args, reverse ? "s#|nn:rfind" : "s#|nn:find",
273 &needle, &len, &start, &end)) {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000274 return NULL;
275 } else {
Neal Norwitz739a3c42008-01-26 20:24:36 +0000276 const char *p, *start_p, *end_p;
Neal Norwitze1027f92008-01-27 07:37:38 +0000277 int sign = reverse ? -1 : 1;
Greg Stein834f4dd2001-05-14 09:32:26 +0000278
279 if (start < 0)
Tim Peters5ebfd362001-11-13 23:11:19 +0000280 start += self->size;
Greg Stein834f4dd2001-05-14 09:32:26 +0000281 if (start < 0)
Tim Peters5ebfd362001-11-13 23:11:19 +0000282 start = 0;
Tim Petersd401edd2001-05-14 23:19:12 +0000283 else if ((size_t)start > self->size)
Tim Peters5ebfd362001-11-13 23:11:19 +0000284 start = self->size;
Greg Stein834f4dd2001-05-14 09:32:26 +0000285
Andrew M. Kuchling5c60bfc2008-01-19 18:18:41 +0000286 if (end < 0)
287 end += self->size;
288 if (end < 0)
289 end = 0;
290 else if ((size_t)end > self->size)
291 end = self->size;
292
Neal Norwitz739a3c42008-01-26 20:24:36 +0000293 start_p = self->data + start;
294 end_p = self->data + end;
Andrew M. Kuchling5c60bfc2008-01-19 18:18:41 +0000295
Neal Norwitz739a3c42008-01-26 20:24:36 +0000296 for (p = (reverse ? end_p - len : start_p);
297 (p >= start_p) && (p + len <= end_p); p += sign) {
Martin v. Löwiscfe7e092006-02-17 06:59:14 +0000298 Py_ssize_t i;
Tim Petersc9ffa062002-03-08 05:43:32 +0000299 for (i = 0; i < len && needle[i] == p[i]; ++i)
300 /* nothing */;
301 if (i == len) {
Martin v. Löwiscfe7e092006-02-17 06:59:14 +0000302 return PyInt_FromSsize_t(p - self->data);
Guido van Rossum09fdf072000-03-31 01:17:07 +0000303 }
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000304 }
Martin v. Löwiscfe7e092006-02-17 06:59:14 +0000305 return PyInt_FromLong(-1);
Guido van Rossum09fdf072000-03-31 01:17:07 +0000306 }
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000307}
308
Andrew M. Kuchling5c60bfc2008-01-19 18:18:41 +0000309static PyObject *
310mmap_find_method(mmap_object *self,
311 PyObject *args)
312{
313 return mmap_gfind(self, args, 0);
314}
315
316static PyObject *
317mmap_rfind_method(mmap_object *self,
318 PyObject *args)
319{
320 return mmap_gfind(self, args, 1);
321}
322
Tim Petersec0a5f02006-02-16 23:47:20 +0000323static int
Tim Peters5ebfd362001-11-13 23:11:19 +0000324is_writeable(mmap_object *self)
325{
326 if (self->access != ACCESS_READ)
Tim Petersec0a5f02006-02-16 23:47:20 +0000327 return 1;
Tim Peters5ebfd362001-11-13 23:11:19 +0000328 PyErr_Format(PyExc_TypeError, "mmap can't modify a readonly memory map.");
329 return 0;
330}
331
Tim Petersec0a5f02006-02-16 23:47:20 +0000332static int
Tim Peters5ebfd362001-11-13 23:11:19 +0000333is_resizeable(mmap_object *self)
334{
335 if ((self->access == ACCESS_WRITE) || (self->access == ACCESS_DEFAULT))
Tim Petersec0a5f02006-02-16 23:47:20 +0000336 return 1;
337 PyErr_Format(PyExc_TypeError,
Tim Peters5ebfd362001-11-13 23:11:19 +0000338 "mmap can't resize a readonly or copy-on-write memory map.");
339 return 0;
340}
341
342
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000343static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000344mmap_write_method(mmap_object *self,
345 PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000346{
Martin v. Löwiscfe7e092006-02-17 06:59:14 +0000347 Py_ssize_t length;
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000348 char *data;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000349
Guido van Rossum09fdf072000-03-31 01:17:07 +0000350 CHECK_VALID(NULL);
Tim Peters8f9cc292006-02-17 00:00:20 +0000351 if (!PyArg_ParseTuple(args, "s#:write", &data, &length))
Guido van Rossum09fdf072000-03-31 01:17:07 +0000352 return(NULL);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000353
Tim Peters5ebfd362001-11-13 23:11:19 +0000354 if (!is_writeable(self))
355 return NULL;
356
Guido van Rossum09fdf072000-03-31 01:17:07 +0000357 if ((self->pos + length) > self->size) {
Tim Peters8f9cc292006-02-17 00:00:20 +0000358 PyErr_SetString(PyExc_ValueError, "data out of range");
Guido van Rossum09fdf072000-03-31 01:17:07 +0000359 return NULL;
360 }
Tim Peters8f9cc292006-02-17 00:00:20 +0000361 memcpy(self->data+self->pos, data, length);
Guido van Rossum09fdf072000-03-31 01:17:07 +0000362 self->pos = self->pos+length;
Tim Peters8f9cc292006-02-17 00:00:20 +0000363 Py_INCREF(Py_None);
Tim Peters23721ee2006-02-16 23:50:16 +0000364 return Py_None;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000365}
366
367static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000368mmap_write_byte_method(mmap_object *self,
369 PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000370{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000371 char value;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000372
Guido van Rossum09fdf072000-03-31 01:17:07 +0000373 CHECK_VALID(NULL);
Tim Peters8f9cc292006-02-17 00:00:20 +0000374 if (!PyArg_ParseTuple(args, "c:write_byte", &value))
Guido van Rossum09fdf072000-03-31 01:17:07 +0000375 return(NULL);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000376
Tim Peters5ebfd362001-11-13 23:11:19 +0000377 if (!is_writeable(self))
378 return NULL;
Hirokazu Yamamotof2dc8852009-02-28 10:31:54 +0000379
380 if (self->pos < self->size) {
381 *(self->data+self->pos) = value;
382 self->pos += 1;
383 Py_INCREF(Py_None);
384 return Py_None;
385 }
386 else {
387 PyErr_SetString(PyExc_ValueError, "write byte out of range");
388 return NULL;
389 }
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000390}
Tim Petersec0a5f02006-02-16 23:47:20 +0000391
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000392static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000393mmap_size_method(mmap_object *self,
Georg Brandl96a8c392006-05-29 21:04:52 +0000394 PyObject *unused)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000395{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000396 CHECK_VALID(NULL);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000397
Martin v. Löwis6238d2b2002-06-30 15:26:10 +0000398#ifdef MS_WINDOWS
Mark Hammond071864a2000-07-30 02:46:26 +0000399 if (self->file_handle != INVALID_HANDLE_VALUE) {
Martin v. Löwis15186072006-02-18 12:38:35 +0000400 DWORD low,high;
401 PY_LONG_LONG size;
402 low = GetFileSize(self->file_handle, &high);
403 if (low == INVALID_FILE_SIZE) {
404 /* It might be that the function appears to have failed,
405 when indeed its size equals INVALID_FILE_SIZE */
406 DWORD error = GetLastError();
407 if (error != NO_ERROR)
408 return PyErr_SetFromWindowsErr(error);
409 }
410 if (!high && low < LONG_MAX)
411 return PyInt_FromLong((long)low);
412 size = (((PY_LONG_LONG)high)<<32) + low;
413 return PyLong_FromLongLong(size);
Guido van Rossum09fdf072000-03-31 01:17:07 +0000414 } else {
Martin v. Löwis15186072006-02-18 12:38:35 +0000415 return PyInt_FromSsize_t(self->size);
Guido van Rossum09fdf072000-03-31 01:17:07 +0000416 }
Martin v. Löwis6238d2b2002-06-30 15:26:10 +0000417#endif /* MS_WINDOWS */
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000418
419#ifdef UNIX
Andrew M. Kuchling7b9fb922000-06-17 22:41:22 +0000420 {
421 struct stat buf;
422 if (-1 == fstat(self->fd, &buf)) {
423 PyErr_SetFromErrno(mmap_module_error);
424 return NULL;
425 }
Martin v. Löwis15186072006-02-18 12:38:35 +0000426 return PyInt_FromSsize_t(buf.st_size);
Andrew M. Kuchling7b9fb922000-06-17 22:41:22 +0000427 }
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000428#endif /* UNIX */
429}
430
431/* This assumes that you want the entire file mapped,
432 / and when recreating the map will make the new file
433 / have the new size
434 /
435 / Is this really necessary? This could easily be done
436 / from python by just closing and re-opening with the
437 / new size?
438 */
439
440static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000441mmap_resize_method(mmap_object *self,
442 PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000443{
Martin v. Löwiscfe7e092006-02-17 06:59:14 +0000444 Py_ssize_t new_size;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000445 CHECK_VALID(NULL);
Martin v. Löwiscfe7e092006-02-17 06:59:14 +0000446 if (!PyArg_ParseTuple(args, "n:resize", &new_size) ||
Tim Peters5ebfd362001-11-13 23:11:19 +0000447 !is_resizeable(self)) {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000448 return NULL;
Martin v. Löwis6238d2b2002-06-30 15:26:10 +0000449#ifdef MS_WINDOWS
Tim Petersec0a5f02006-02-16 23:47:20 +0000450 } else {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000451 DWORD dwErrCode = 0;
Travis E. Oliphant8feafab2007-10-23 02:40:56 +0000452 DWORD off_hi, off_lo, newSizeLow, newSizeHigh;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000453 /* First, unmap the file view */
Tim Peters8f9cc292006-02-17 00:00:20 +0000454 UnmapViewOfFile(self->data);
Hirokazu Yamamoto264fc122009-03-05 14:21:12 +0000455 self->data = NULL;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000456 /* Close the mapping object */
Tim Peters8f9cc292006-02-17 00:00:20 +0000457 CloseHandle(self->map_handle);
Hirokazu Yamamoto264fc122009-03-05 14:21:12 +0000458 self->map_handle = NULL;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000459 /* Move to the desired EOF position */
Martin v. Löwis15186072006-02-18 12:38:35 +0000460#if SIZEOF_SIZE_T > 4
Travis E. Oliphant8feafab2007-10-23 02:40:56 +0000461 newSizeHigh = (DWORD)((self->offset + new_size) >> 32);
462 newSizeLow = (DWORD)((self->offset + new_size) & 0xFFFFFFFF);
463 off_hi = (DWORD)(self->offset >> 32);
464 off_lo = (DWORD)(self->offset & 0xFFFFFFFF);
Martin v. Löwis15186072006-02-18 12:38:35 +0000465#else
466 newSizeHigh = 0;
Hirokazu Yamamoto17a837e2009-02-17 13:17:26 +0000467 newSizeLow = (DWORD)(self->offset + new_size);
Travis E. Oliphant8feafab2007-10-23 02:40:56 +0000468 off_hi = 0;
469 off_lo = (DWORD)self->offset;
Martin v. Löwis15186072006-02-18 12:38:35 +0000470#endif
Tim Peters8f9cc292006-02-17 00:00:20 +0000471 SetFilePointer(self->file_handle,
Martin v. Löwis15186072006-02-18 12:38:35 +0000472 newSizeLow, &newSizeHigh, FILE_BEGIN);
Guido van Rossum09fdf072000-03-31 01:17:07 +0000473 /* Change the size of the file */
Tim Peters8f9cc292006-02-17 00:00:20 +0000474 SetEndOfFile(self->file_handle);
Guido van Rossum09fdf072000-03-31 01:17:07 +0000475 /* Create another mapping object and remap the file view */
Tim Peters8f9cc292006-02-17 00:00:20 +0000476 self->map_handle = CreateFileMapping(
Mark Hammond071864a2000-07-30 02:46:26 +0000477 self->file_handle,
Guido van Rossum09fdf072000-03-31 01:17:07 +0000478 NULL,
479 PAGE_READWRITE,
Travis E. Oliphant8feafab2007-10-23 02:40:56 +0000480 0,
481 0,
Guido van Rossum09fdf072000-03-31 01:17:07 +0000482 self->tagname);
483 if (self->map_handle != NULL) {
Tim Peters8f9cc292006-02-17 00:00:20 +0000484 self->data = (char *) MapViewOfFile(self->map_handle,
485 FILE_MAP_WRITE,
Travis E. Oliphant8feafab2007-10-23 02:40:56 +0000486 off_hi,
487 off_lo,
488 new_size);
Guido van Rossum09fdf072000-03-31 01:17:07 +0000489 if (self->data != NULL) {
490 self->size = new_size;
Tim Peters8f9cc292006-02-17 00:00:20 +0000491 Py_INCREF(Py_None);
Guido van Rossum09fdf072000-03-31 01:17:07 +0000492 return Py_None;
493 } else {
494 dwErrCode = GetLastError();
Hirokazu Yamamoto264fc122009-03-05 14:21:12 +0000495 CloseHandle(self->map_handle);
496 self->map_handle = NULL;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000497 }
498 } else {
499 dwErrCode = GetLastError();
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000500 }
Guido van Rossum09fdf072000-03-31 01:17:07 +0000501 PyErr_SetFromWindowsErr(dwErrCode);
Tim Peters23721ee2006-02-16 23:50:16 +0000502 return NULL;
Martin v. Löwis6238d2b2002-06-30 15:26:10 +0000503#endif /* MS_WINDOWS */
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000504
505#ifdef UNIX
Tim Petersec0a5f02006-02-16 23:47:20 +0000506#ifndef HAVE_MREMAP
Tim Peters5ebfd362001-11-13 23:11:19 +0000507 } else {
508 PyErr_SetString(PyExc_SystemError,
509 "mmap: resizing not available--no mremap()");
510 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000511#else
Tim Peters5ebfd362001-11-13 23:11:19 +0000512 } else {
Armin Rigo335ffe82005-09-20 19:04:02 +0000513 void *newmap;
514
Hirokazu Yamamoto17a837e2009-02-17 13:17:26 +0000515 if (ftruncate(self->fd, self->offset + new_size) == -1) {
Georg Brandl38387b82005-08-24 07:17:40 +0000516 PyErr_SetFromErrno(mmap_module_error);
517 return NULL;
518 }
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000519
Andrew M. Kuchling6fef30e2000-06-18 14:51:21 +0000520#ifdef MREMAP_MAYMOVE
Tim Peters5ebfd362001-11-13 23:11:19 +0000521 newmap = mremap(self->data, self->size, new_size, MREMAP_MAYMOVE);
Andrew M. Kuchling6fef30e2000-06-18 14:51:21 +0000522#else
Jesse Noller40a61642009-03-31 18:12:35 +0000523 #if defined(__NetBSD__)
524 newmap = mremap(self->data, self->size, self->data, new_size, 0);
525 #else
526 newmap = mremap(self->data, self->size, new_size, 0);
527 #endif /* __NetBSD__ */
Andrew M. Kuchling6fef30e2000-06-18 14:51:21 +0000528#endif
Tim Petersec0a5f02006-02-16 23:47:20 +0000529 if (newmap == (void *)-1)
Tim Peters5ebfd362001-11-13 23:11:19 +0000530 {
531 PyErr_SetFromErrno(mmap_module_error);
532 return NULL;
533 }
534 self->data = newmap;
535 self->size = new_size;
536 Py_INCREF(Py_None);
537 return Py_None;
Andrew M. Kuchling6fef30e2000-06-18 14:51:21 +0000538#endif /* HAVE_MREMAP */
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000539#endif /* UNIX */
Tim Peters5ebfd362001-11-13 23:11:19 +0000540 }
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000541}
542
543static PyObject *
Georg Brandl96a8c392006-05-29 21:04:52 +0000544mmap_tell_method(mmap_object *self, PyObject *unused)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000545{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000546 CHECK_VALID(NULL);
Neal Norwitz670f8752006-08-22 13:56:56 +0000547 return PyInt_FromSize_t(self->pos);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000548}
549
550static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000551mmap_flush_method(mmap_object *self, PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000552{
Martin v. Löwisad0a4622006-02-16 14:30:23 +0000553 Py_ssize_t offset = 0;
554 Py_ssize_t size = self->size;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000555 CHECK_VALID(NULL);
Tim Petersf2882952006-02-17 01:07:39 +0000556 if (!PyArg_ParseTuple(args, "|nn:flush", &offset, &size))
Guido van Rossum09fdf072000-03-31 01:17:07 +0000557 return NULL;
Tim Petersf2882952006-02-17 01:07:39 +0000558 if ((size_t)(offset + size) > self->size) {
Tim Peters8f9cc292006-02-17 00:00:20 +0000559 PyErr_SetString(PyExc_ValueError, "flush values out of range");
Guido van Rossum09fdf072000-03-31 01:17:07 +0000560 return NULL;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000561 }
Neal Norwitz448654f2008-01-27 07:36:03 +0000562#ifdef MS_WINDOWS
563 return PyInt_FromLong((long) FlushViewOfFile(self->data+offset, size));
564#elif defined(UNIX)
565 /* XXX semantics of return value? */
566 /* XXX flags for msync? */
567 if (-1 == msync(self->data + offset, size, MS_SYNC)) {
568 PyErr_SetFromErrno(mmap_module_error);
569 return NULL;
570 }
571 return PyInt_FromLong(0);
572#else
573 PyErr_SetString(PyExc_ValueError, "flush not supported on this system");
574 return NULL;
575#endif
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000576}
577
578static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000579mmap_seek_method(mmap_object *self, PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000580{
Martin v. Löwiscfe7e092006-02-17 06:59:14 +0000581 Py_ssize_t dist;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000582 int how=0;
583 CHECK_VALID(NULL);
Martin v. Löwiscfe7e092006-02-17 06:59:14 +0000584 if (!PyArg_ParseTuple(args, "n|i:seek", &dist, &how))
Tim Peters8f9cc292006-02-17 00:00:20 +0000585 return NULL;
586 else {
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000587 size_t where;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000588 switch (how) {
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000589 case 0: /* relative to start */
590 if (dist < 0)
591 goto onoutofrange;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000592 where = dist;
593 break;
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000594 case 1: /* relative to current position */
Martin v. Löwiscfe7e092006-02-17 06:59:14 +0000595 if ((Py_ssize_t)self->pos + dist < 0)
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000596 goto onoutofrange;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000597 where = self->pos + dist;
598 break;
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000599 case 2: /* relative to end */
Martin v. Löwiscfe7e092006-02-17 06:59:14 +0000600 if ((Py_ssize_t)self->size + dist < 0)
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000601 goto onoutofrange;
602 where = self->size + dist;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000603 break;
604 default:
Tim Peters8f9cc292006-02-17 00:00:20 +0000605 PyErr_SetString(PyExc_ValueError, "unknown seek type");
Guido van Rossum09fdf072000-03-31 01:17:07 +0000606 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000607 }
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000608 if (where > self->size)
609 goto onoutofrange;
610 self->pos = where;
Tim Peters8f9cc292006-02-17 00:00:20 +0000611 Py_INCREF(Py_None);
Tim Peters23721ee2006-02-16 23:50:16 +0000612 return Py_None;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000613 }
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000614
Tim Peters5ebfd362001-11-13 23:11:19 +0000615 onoutofrange:
Tim Peters8f9cc292006-02-17 00:00:20 +0000616 PyErr_SetString(PyExc_ValueError, "seek out of range");
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000617 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000618}
619
620static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000621mmap_move_method(mmap_object *self, PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000622{
Jack Diederich2ecd3c32009-04-01 20:26:13 +0000623 unsigned long dest, src, cnt;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000624 CHECK_VALID(NULL);
Jack Diederich2ecd3c32009-04-01 20:26:13 +0000625 if (!PyArg_ParseTuple(args, "kkk:move", &dest, &src, &cnt) ||
Tim Peters5ebfd362001-11-13 23:11:19 +0000626 !is_writeable(self)) {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000627 return NULL;
628 } else {
629 /* bounds check the values */
Jack Diederich2ecd3c32009-04-01 20:26:13 +0000630 if (cnt < 0 || (cnt + dest) < cnt || (cnt + src) < cnt ||
631 src < 0 || src > self->size || (src + cnt) > self->size ||
632 dest < 0 || dest > self->size || (dest + cnt) > self->size) {
Tim Peters8f9cc292006-02-17 00:00:20 +0000633 PyErr_SetString(PyExc_ValueError,
Jack Diederich2ecd3c32009-04-01 20:26:13 +0000634 "source, destination, or count out of range");
Guido van Rossum09fdf072000-03-31 01:17:07 +0000635 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000636 }
Jack Diederich2ecd3c32009-04-01 20:26:13 +0000637 memmove(self->data+dest, self->data+src, cnt);
638 Py_INCREF(Py_None);
639 return Py_None;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000640 }
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000641}
642
643static struct PyMethodDef mmap_object_methods[] = {
Georg Brandl96a8c392006-05-29 21:04:52 +0000644 {"close", (PyCFunction) mmap_close_method, METH_NOARGS},
Martin v. Löwis43b936d2002-01-17 23:15:58 +0000645 {"find", (PyCFunction) mmap_find_method, METH_VARARGS},
Andrew M. Kuchling5c60bfc2008-01-19 18:18:41 +0000646 {"rfind", (PyCFunction) mmap_rfind_method, METH_VARARGS},
Martin v. Löwis43b936d2002-01-17 23:15:58 +0000647 {"flush", (PyCFunction) mmap_flush_method, METH_VARARGS},
648 {"move", (PyCFunction) mmap_move_method, METH_VARARGS},
649 {"read", (PyCFunction) mmap_read_method, METH_VARARGS},
Georg Brandl96a8c392006-05-29 21:04:52 +0000650 {"read_byte", (PyCFunction) mmap_read_byte_method, METH_NOARGS},
651 {"readline", (PyCFunction) mmap_read_line_method, METH_NOARGS},
Martin v. Löwis43b936d2002-01-17 23:15:58 +0000652 {"resize", (PyCFunction) mmap_resize_method, METH_VARARGS},
653 {"seek", (PyCFunction) mmap_seek_method, METH_VARARGS},
Georg Brandl96a8c392006-05-29 21:04:52 +0000654 {"size", (PyCFunction) mmap_size_method, METH_NOARGS},
655 {"tell", (PyCFunction) mmap_tell_method, METH_NOARGS},
Martin v. Löwis43b936d2002-01-17 23:15:58 +0000656 {"write", (PyCFunction) mmap_write_method, METH_VARARGS},
657 {"write_byte", (PyCFunction) mmap_write_byte_method, METH_VARARGS},
Guido van Rossum09fdf072000-03-31 01:17:07 +0000658 {NULL, NULL} /* sentinel */
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000659};
660
661/* Functions for treating an mmap'ed file as a buffer */
662
Martin v. Löwis18e16552006-02-15 17:27:45 +0000663static Py_ssize_t
664mmap_buffer_getreadbuf(mmap_object *self, Py_ssize_t index, const void **ptr)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000665{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000666 CHECK_VALID(-1);
Tim Peters8f9cc292006-02-17 00:00:20 +0000667 if (index != 0) {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000668 PyErr_SetString(PyExc_SystemError,
669 "Accessing non-existent mmap segment");
670 return -1;
671 }
672 *ptr = self->data;
673 return self->size;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000674}
675
Martin v. Löwis18e16552006-02-15 17:27:45 +0000676static Py_ssize_t
677mmap_buffer_getwritebuf(mmap_object *self, Py_ssize_t index, const void **ptr)
Tim Petersec0a5f02006-02-16 23:47:20 +0000678{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000679 CHECK_VALID(-1);
Tim Peters8f9cc292006-02-17 00:00:20 +0000680 if (index != 0) {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000681 PyErr_SetString(PyExc_SystemError,
682 "Accessing non-existent mmap segment");
683 return -1;
684 }
Tim Peters5ebfd362001-11-13 23:11:19 +0000685 if (!is_writeable(self))
686 return -1;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000687 *ptr = self->data;
688 return self->size;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000689}
690
Martin v. Löwis18e16552006-02-15 17:27:45 +0000691static Py_ssize_t
692mmap_buffer_getsegcount(mmap_object *self, Py_ssize_t *lenp)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000693{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000694 CHECK_VALID(-1);
Tim Petersec0a5f02006-02-16 23:47:20 +0000695 if (lenp)
Guido van Rossum09fdf072000-03-31 01:17:07 +0000696 *lenp = self->size;
697 return 1;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000698}
699
Martin v. Löwis18e16552006-02-15 17:27:45 +0000700static Py_ssize_t
701mmap_buffer_getcharbuffer(mmap_object *self, Py_ssize_t index, const void **ptr)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000702{
Tim Peters8f9cc292006-02-17 00:00:20 +0000703 if (index != 0) {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000704 PyErr_SetString(PyExc_SystemError,
705 "accessing non-existent buffer segment");
706 return -1;
707 }
708 *ptr = (const char *)self->data;
709 return self->size;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000710}
711
Martin v. Löwis18e16552006-02-15 17:27:45 +0000712static Py_ssize_t
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000713mmap_length(mmap_object *self)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000714{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000715 CHECK_VALID(-1);
716 return self->size;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000717}
718
719static PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000720mmap_item(mmap_object *self, Py_ssize_t i)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000721{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000722 CHECK_VALID(NULL);
Guido van Rossumce8e1dc2000-07-01 00:51:51 +0000723 if (i < 0 || (size_t)i >= self->size) {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000724 PyErr_SetString(PyExc_IndexError, "mmap index out of range");
725 return NULL;
726 }
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000727 return PyString_FromStringAndSize(self->data + i, 1);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000728}
729
730static PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000731mmap_slice(mmap_object *self, Py_ssize_t ilow, Py_ssize_t ihigh)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000732{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000733 CHECK_VALID(NULL);
734 if (ilow < 0)
735 ilow = 0;
Guido van Rossumce8e1dc2000-07-01 00:51:51 +0000736 else if ((size_t)ilow > self->size)
Guido van Rossum09fdf072000-03-31 01:17:07 +0000737 ilow = self->size;
738 if (ihigh < 0)
739 ihigh = 0;
740 if (ihigh < ilow)
741 ihigh = ilow;
Guido van Rossumce8e1dc2000-07-01 00:51:51 +0000742 else if ((size_t)ihigh > self->size)
Guido van Rossum09fdf072000-03-31 01:17:07 +0000743 ihigh = self->size;
Tim Petersec0a5f02006-02-16 23:47:20 +0000744
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000745 return PyString_FromStringAndSize(self->data + ilow, ihigh-ilow);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000746}
747
748static PyObject *
Thomas Wouters3ccec682007-08-28 15:28:19 +0000749mmap_subscript(mmap_object *self, PyObject *item)
750{
751 CHECK_VALID(NULL);
752 if (PyIndex_Check(item)) {
753 Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
754 if (i == -1 && PyErr_Occurred())
755 return NULL;
756 if (i < 0)
757 i += self->size;
Hirokazu Yamamotof6bbd0e2009-02-17 10:12:10 +0000758 if (i < 0 || (size_t)i >= self->size) {
Thomas Wouters3ccec682007-08-28 15:28:19 +0000759 PyErr_SetString(PyExc_IndexError,
760 "mmap index out of range");
761 return NULL;
762 }
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000763 return PyString_FromStringAndSize(self->data + i, 1);
Thomas Wouters3ccec682007-08-28 15:28:19 +0000764 }
765 else if (PySlice_Check(item)) {
766 Py_ssize_t start, stop, step, slicelen;
767
768 if (PySlice_GetIndicesEx((PySliceObject *)item, self->size,
769 &start, &stop, &step, &slicelen) < 0) {
770 return NULL;
771 }
772
773 if (slicelen <= 0)
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000774 return PyString_FromStringAndSize("", 0);
Thomas Wouters3ccec682007-08-28 15:28:19 +0000775 else if (step == 1)
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000776 return PyString_FromStringAndSize(self->data + start,
Thomas Wouters3ccec682007-08-28 15:28:19 +0000777 slicelen);
778 else {
779 char *result_buf = (char *)PyMem_Malloc(slicelen);
780 Py_ssize_t cur, i;
781 PyObject *result;
782
783 if (result_buf == NULL)
784 return PyErr_NoMemory();
785 for (cur = start, i = 0; i < slicelen;
786 cur += step, i++) {
787 result_buf[i] = self->data[cur];
788 }
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000789 result = PyString_FromStringAndSize(result_buf,
Thomas Wouters3ccec682007-08-28 15:28:19 +0000790 slicelen);
791 PyMem_Free(result_buf);
792 return result;
793 }
794 }
795 else {
796 PyErr_SetString(PyExc_TypeError,
797 "mmap indices must be integers");
798 return NULL;
799 }
800}
801
802static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000803mmap_concat(mmap_object *self, PyObject *bb)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000804{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000805 CHECK_VALID(NULL);
806 PyErr_SetString(PyExc_SystemError,
807 "mmaps don't support concatenation");
808 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000809}
810
811static PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000812mmap_repeat(mmap_object *self, Py_ssize_t n)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000813{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000814 CHECK_VALID(NULL);
815 PyErr_SetString(PyExc_SystemError,
816 "mmaps don't support repeat operation");
817 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000818}
819
820static int
Martin v. Löwis18e16552006-02-15 17:27:45 +0000821mmap_ass_slice(mmap_object *self, Py_ssize_t ilow, Py_ssize_t ihigh, PyObject *v)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000822{
Guido van Rossum36d4f8b2000-04-10 21:34:37 +0000823 const char *buf;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000824
Guido van Rossum09fdf072000-03-31 01:17:07 +0000825 CHECK_VALID(-1);
826 if (ilow < 0)
827 ilow = 0;
Guido van Rossumce8e1dc2000-07-01 00:51:51 +0000828 else if ((size_t)ilow > self->size)
Guido van Rossum09fdf072000-03-31 01:17:07 +0000829 ilow = self->size;
830 if (ihigh < 0)
831 ihigh = 0;
832 if (ihigh < ilow)
833 ihigh = ilow;
Guido van Rossumce8e1dc2000-07-01 00:51:51 +0000834 else if ((size_t)ihigh > self->size)
Guido van Rossum09fdf072000-03-31 01:17:07 +0000835 ihigh = self->size;
Tim Petersec0a5f02006-02-16 23:47:20 +0000836
Thomas Wouters1baac722001-07-16 15:47:36 +0000837 if (v == NULL) {
838 PyErr_SetString(PyExc_TypeError,
Tim Peters5ebfd362001-11-13 23:11:19 +0000839 "mmap object doesn't support slice deletion");
Thomas Wouters1baac722001-07-16 15:47:36 +0000840 return -1;
841 }
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000842 if (! (PyString_Check(v)) ) {
Tim Petersec0a5f02006-02-16 23:47:20 +0000843 PyErr_SetString(PyExc_IndexError,
Guido van Rossum09fdf072000-03-31 01:17:07 +0000844 "mmap slice assignment must be a string");
845 return -1;
846 }
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000847 if (PyString_Size(v) != (ihigh - ilow)) {
Tim Petersec0a5f02006-02-16 23:47:20 +0000848 PyErr_SetString(PyExc_IndexError,
Guido van Rossum09fdf072000-03-31 01:17:07 +0000849 "mmap slice assignment is wrong size");
850 return -1;
851 }
Tim Peters5ebfd362001-11-13 23:11:19 +0000852 if (!is_writeable(self))
853 return -1;
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000854 buf = PyString_AsString(v);
Guido van Rossum09fdf072000-03-31 01:17:07 +0000855 memcpy(self->data + ilow, buf, ihigh-ilow);
856 return 0;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000857}
858
859static int
Martin v. Löwis18e16552006-02-15 17:27:45 +0000860mmap_ass_item(mmap_object *self, Py_ssize_t i, PyObject *v)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000861{
Guido van Rossum36d4f8b2000-04-10 21:34:37 +0000862 const char *buf;
Tim Petersec0a5f02006-02-16 23:47:20 +0000863
Guido van Rossum09fdf072000-03-31 01:17:07 +0000864 CHECK_VALID(-1);
Guido van Rossumce8e1dc2000-07-01 00:51:51 +0000865 if (i < 0 || (size_t)i >= self->size) {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000866 PyErr_SetString(PyExc_IndexError, "mmap index out of range");
867 return -1;
868 }
Thomas Wouters1baac722001-07-16 15:47:36 +0000869 if (v == NULL) {
870 PyErr_SetString(PyExc_TypeError,
Tim Peters5ebfd362001-11-13 23:11:19 +0000871 "mmap object doesn't support item deletion");
Thomas Wouters1baac722001-07-16 15:47:36 +0000872 return -1;
873 }
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000874 if (! (PyString_Check(v) && PyString_Size(v)==1) ) {
Tim Petersec0a5f02006-02-16 23:47:20 +0000875 PyErr_SetString(PyExc_IndexError,
Tim Peters5ebfd362001-11-13 23:11:19 +0000876 "mmap assignment must be single-character string");
Guido van Rossum09fdf072000-03-31 01:17:07 +0000877 return -1;
878 }
Tim Peters5ebfd362001-11-13 23:11:19 +0000879 if (!is_writeable(self))
880 return -1;
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000881 buf = PyString_AsString(v);
Guido van Rossum09fdf072000-03-31 01:17:07 +0000882 self->data[i] = buf[0];
883 return 0;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000884}
885
Thomas Wouters3ccec682007-08-28 15:28:19 +0000886static int
887mmap_ass_subscript(mmap_object *self, PyObject *item, PyObject *value)
888{
889 CHECK_VALID(-1);
890
891 if (PyIndex_Check(item)) {
892 Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
893 const char *buf;
894
895 if (i == -1 && PyErr_Occurred())
896 return -1;
897 if (i < 0)
898 i += self->size;
Hirokazu Yamamotof6bbd0e2009-02-17 10:12:10 +0000899 if (i < 0 || (size_t)i >= self->size) {
Thomas Wouters3ccec682007-08-28 15:28:19 +0000900 PyErr_SetString(PyExc_IndexError,
901 "mmap index out of range");
902 return -1;
903 }
904 if (value == NULL) {
905 PyErr_SetString(PyExc_TypeError,
906 "mmap object doesn't support item deletion");
907 return -1;
908 }
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000909 if (!PyString_Check(value) || PyString_Size(value) != 1) {
Thomas Wouters3ccec682007-08-28 15:28:19 +0000910 PyErr_SetString(PyExc_IndexError,
911 "mmap assignment must be single-character string");
912 return -1;
913 }
914 if (!is_writeable(self))
915 return -1;
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000916 buf = PyString_AsString(value);
Thomas Wouters3ccec682007-08-28 15:28:19 +0000917 self->data[i] = buf[0];
918 return 0;
919 }
920 else if (PySlice_Check(item)) {
921 Py_ssize_t start, stop, step, slicelen;
922
923 if (PySlice_GetIndicesEx((PySliceObject *)item,
924 self->size, &start, &stop,
925 &step, &slicelen) < 0) {
926 return -1;
927 }
928 if (value == NULL) {
929 PyErr_SetString(PyExc_TypeError,
930 "mmap object doesn't support slice deletion");
931 return -1;
932 }
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000933 if (!PyString_Check(value)) {
Thomas Wouters3ccec682007-08-28 15:28:19 +0000934 PyErr_SetString(PyExc_IndexError,
935 "mmap slice assignment must be a string");
936 return -1;
937 }
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000938 if (PyString_Size(value) != slicelen) {
Thomas Wouters3ccec682007-08-28 15:28:19 +0000939 PyErr_SetString(PyExc_IndexError,
940 "mmap slice assignment is wrong size");
941 return -1;
942 }
943 if (!is_writeable(self))
944 return -1;
945
946 if (slicelen == 0)
947 return 0;
948 else if (step == 1) {
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000949 const char *buf = PyString_AsString(value);
Thomas Wouters3ccec682007-08-28 15:28:19 +0000950
951 if (buf == NULL)
952 return -1;
953 memcpy(self->data + start, buf, slicelen);
954 return 0;
955 }
956 else {
957 Py_ssize_t cur, i;
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000958 const char *buf = PyString_AsString(value);
Thomas Wouters3ccec682007-08-28 15:28:19 +0000959
960 if (buf == NULL)
961 return -1;
962 for (cur = start, i = 0; i < slicelen;
963 cur += step, i++) {
964 self->data[cur] = buf[i];
965 }
966 return 0;
967 }
968 }
969 else {
970 PyErr_SetString(PyExc_TypeError,
971 "mmap indices must be integer");
972 return -1;
973 }
974}
975
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000976static PySequenceMethods mmap_as_sequence = {
Martin v. Löwis18e16552006-02-15 17:27:45 +0000977 (lenfunc)mmap_length, /*sq_length*/
Guido van Rossum09fdf072000-03-31 01:17:07 +0000978 (binaryfunc)mmap_concat, /*sq_concat*/
Martin v. Löwis18e16552006-02-15 17:27:45 +0000979 (ssizeargfunc)mmap_repeat, /*sq_repeat*/
980 (ssizeargfunc)mmap_item, /*sq_item*/
981 (ssizessizeargfunc)mmap_slice, /*sq_slice*/
982 (ssizeobjargproc)mmap_ass_item, /*sq_ass_item*/
983 (ssizessizeobjargproc)mmap_ass_slice, /*sq_ass_slice*/
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000984};
985
Thomas Wouters3ccec682007-08-28 15:28:19 +0000986static PyMappingMethods mmap_as_mapping = {
987 (lenfunc)mmap_length,
988 (binaryfunc)mmap_subscript,
989 (objobjargproc)mmap_ass_subscript,
990};
991
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000992static PyBufferProcs mmap_as_buffer = {
Martin v. Löwis18e16552006-02-15 17:27:45 +0000993 (readbufferproc)mmap_buffer_getreadbuf,
994 (writebufferproc)mmap_buffer_getwritebuf,
995 (segcountproc)mmap_buffer_getsegcount,
996 (charbufferproc)mmap_buffer_getcharbuffer,
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000997};
998
Georg Brandl845c4032008-01-21 14:16:46 +0000999static PyObject *
1000new_mmap_object(PyTypeObject *type, PyObject *args, PyObject *kwdict);
1001
Georg Brandlef928022008-01-20 14:50:05 +00001002PyDoc_STRVAR(mmap_doc,
1003"Windows: mmap(fileno, length[, tagname[, access[, offset]]])\n\
1004\n\
1005Maps length bytes from the file specified by the file handle fileno,\n\
1006and returns a mmap object. If length is larger than the current size\n\
1007of the file, the file is extended to contain length bytes. If length\n\
1008is 0, the maximum length of the map is the current size of the file,\n\
1009except that if the file is empty Windows raises an exception (you cannot\n\
1010create an empty mapping on Windows).\n\
1011\n\
1012Unix: mmap(fileno, length[, flags[, prot[, access[, offset]]]])\n\
1013\n\
1014Maps length bytes from the file specified by the file descriptor fileno,\n\
1015and returns a mmap object. If length is 0, the maximum length of the map\n\
1016will be the current size of the file when mmap is called.\n\
1017flags specifies the nature of the mapping. MAP_PRIVATE creates a\n\
1018private copy-on-write mapping, so changes to the contents of the mmap\n\
Thomas Heller66260992008-08-19 17:47:13 +00001019object will be private to this process, and MAP_SHARED creates a mapping\n\
Georg Brandlef928022008-01-20 14:50:05 +00001020that's shared with all other processes mapping the same areas of the file.\n\
1021The default value is MAP_SHARED.\n\
1022\n\
1023To map anonymous memory, pass -1 as the fileno (both versions).");
1024
1025
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001026static PyTypeObject mmap_object_type = {
Georg Brandl845c4032008-01-21 14:16:46 +00001027 PyVarObject_HEAD_INIT(NULL, 0)
Guido van Rossum14648392001-12-08 18:02:58 +00001028 "mmap.mmap", /* tp_name */
Guido van Rossum09fdf072000-03-31 01:17:07 +00001029 sizeof(mmap_object), /* tp_size */
1030 0, /* tp_itemsize */
1031 /* methods */
1032 (destructor) mmap_object_dealloc, /* tp_dealloc */
1033 0, /* tp_print */
Georg Brandlef928022008-01-20 14:50:05 +00001034 0, /* tp_getattr */
Guido van Rossum09fdf072000-03-31 01:17:07 +00001035 0, /* tp_setattr */
1036 0, /* tp_compare */
1037 0, /* tp_repr */
1038 0, /* tp_as_number */
1039 &mmap_as_sequence, /*tp_as_sequence*/
Thomas Wouters3ccec682007-08-28 15:28:19 +00001040 &mmap_as_mapping, /*tp_as_mapping*/
Guido van Rossum09fdf072000-03-31 01:17:07 +00001041 0, /*tp_hash*/
1042 0, /*tp_call*/
1043 0, /*tp_str*/
Georg Brandlef928022008-01-20 14:50:05 +00001044 PyObject_GenericGetAttr, /*tp_getattro*/
Guido van Rossum09fdf072000-03-31 01:17:07 +00001045 0, /*tp_setattro*/
1046 &mmap_as_buffer, /*tp_as_buffer*/
Georg Brandl845c4032008-01-21 14:16:46 +00001047 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GETCHARBUFFER, /*tp_flags*/
Georg Brandlef928022008-01-20 14:50:05 +00001048 mmap_doc, /*tp_doc*/
1049 0, /* tp_traverse */
1050 0, /* tp_clear */
1051 0, /* tp_richcompare */
1052 0, /* tp_weaklistoffset */
Georg Brandl845c4032008-01-21 14:16:46 +00001053 0, /* tp_iter */
1054 0, /* tp_iternext */
Georg Brandlef928022008-01-20 14:50:05 +00001055 mmap_object_methods, /* tp_methods */
Georg Brandl845c4032008-01-21 14:16:46 +00001056 0, /* tp_members */
1057 0, /* tp_getset */
1058 0, /* tp_base */
1059 0, /* tp_dict */
1060 0, /* tp_descr_get */
1061 0, /* tp_descr_set */
1062 0, /* tp_dictoffset */
1063 0, /* tp_init */
1064 PyType_GenericAlloc, /* tp_alloc */
1065 new_mmap_object, /* tp_new */
1066 PyObject_Del, /* tp_free */
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001067};
1068
Andrew M. Kuchling70d27422000-06-18 04:45:14 +00001069
1070/* extract the map size from the given PyObject
1071
Thomas Wouters7e474022000-07-16 12:04:32 +00001072 Returns -1 on error, with an appropriate Python exception raised. On
Andrew M. Kuchling70d27422000-06-18 04:45:14 +00001073 success, the map size is returned. */
Martin v. Löwiscfe7e092006-02-17 06:59:14 +00001074static Py_ssize_t
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001075_GetMapSize(PyObject *o, const char* param)
Andrew M. Kuchling70d27422000-06-18 04:45:14 +00001076{
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001077 if (o == NULL)
1078 return 0;
Neal Norwitz8a87f5d2006-08-12 17:03:09 +00001079 if (PyIndex_Check(o)) {
1080 Py_ssize_t i = PyNumber_AsSsize_t(o, PyExc_OverflowError);
Guido van Rossum38fff8c2006-03-07 18:50:55 +00001081 if (i==-1 && PyErr_Occurred())
Andrew M. Kuchling70d27422000-06-18 04:45:14 +00001082 return -1;
Neal Norwitz8a87f5d2006-08-12 17:03:09 +00001083 if (i < 0) {
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001084 PyErr_Format(PyExc_OverflowError,
1085 "memory mapped %s must be positive",
1086 param);
Neal Norwitz8a87f5d2006-08-12 17:03:09 +00001087 return -1;
1088 }
Martin v. Löwiscfe7e092006-02-17 06:59:14 +00001089 return i;
Andrew M. Kuchling70d27422000-06-18 04:45:14 +00001090 }
Andrew M. Kuchling70d27422000-06-18 04:45:14 +00001091
Neal Norwitz8a87f5d2006-08-12 17:03:09 +00001092 PyErr_SetString(PyExc_TypeError, "map size must be an integral value");
Andrew M. Kuchling70d27422000-06-18 04:45:14 +00001093 return -1;
1094}
1095
Tim Petersec0a5f02006-02-16 23:47:20 +00001096#ifdef UNIX
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001097static PyObject *
Georg Brandl845c4032008-01-21 14:16:46 +00001098new_mmap_object(PyTypeObject *type, PyObject *args, PyObject *kwdict)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001099{
Neal Norwitzb5673922002-09-05 21:48:07 +00001100#ifdef HAVE_FSTAT
1101 struct stat st;
1102#endif
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +00001103 mmap_object *m_obj;
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001104 PyObject *map_size_obj = NULL, *offset_obj = NULL;
1105 Py_ssize_t map_size, offset;
Guido van Rossum09fdf072000-03-31 01:17:07 +00001106 int fd, flags = MAP_SHARED, prot = PROT_WRITE | PROT_READ;
Neal Norwitz0e6bc8c2006-02-05 05:45:43 +00001107 int devzero = -1;
Neal Norwitz8856fb72005-12-18 03:34:22 +00001108 int access = (int)ACCESS_DEFAULT;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001109 static char *keywords[] = {"fileno", "length",
Tim Petersec0a5f02006-02-16 23:47:20 +00001110 "flags", "prot",
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001111 "access", "offset", NULL};
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001112
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001113 if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iO|iiiO", keywords,
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001114 &fd, &map_size_obj, &flags, &prot,
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001115 &access, &offset_obj))
Guido van Rossum09fdf072000-03-31 01:17:07 +00001116 return NULL;
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001117 map_size = _GetMapSize(map_size_obj, "size");
Andrew M. Kuchling70d27422000-06-18 04:45:14 +00001118 if (map_size < 0)
1119 return NULL;
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001120 offset = _GetMapSize(offset_obj, "offset");
1121 if (offset < 0)
1122 return NULL;
Tim Peters5ebfd362001-11-13 23:11:19 +00001123
Tim Petersec0a5f02006-02-16 23:47:20 +00001124 if ((access != (int)ACCESS_DEFAULT) &&
Neal Norwitzd1cfc8a2006-02-05 03:36:57 +00001125 ((flags != MAP_SHARED) || (prot != (PROT_WRITE | PROT_READ))))
Tim Petersec0a5f02006-02-16 23:47:20 +00001126 return PyErr_Format(PyExc_ValueError,
Tim Peters5ebfd362001-11-13 23:11:19 +00001127 "mmap can't specify both access and flags, prot.");
Neal Norwitzd1cfc8a2006-02-05 03:36:57 +00001128 switch ((access_mode)access) {
Tim Peters5ebfd362001-11-13 23:11:19 +00001129 case ACCESS_READ:
1130 flags = MAP_SHARED;
1131 prot = PROT_READ;
1132 break;
1133 case ACCESS_WRITE:
1134 flags = MAP_SHARED;
1135 prot = PROT_READ | PROT_WRITE;
1136 break;
1137 case ACCESS_COPY:
1138 flags = MAP_PRIVATE;
1139 prot = PROT_READ | PROT_WRITE;
1140 break;
Tim Petersec0a5f02006-02-16 23:47:20 +00001141 case ACCESS_DEFAULT:
Tim Peters5ebfd362001-11-13 23:11:19 +00001142 /* use the specified or default values of flags and prot */
1143 break;
1144 default:
Tim Petersec0a5f02006-02-16 23:47:20 +00001145 return PyErr_Format(PyExc_ValueError,
Tim Peters5ebfd362001-11-13 23:11:19 +00001146 "mmap invalid access parameter.");
1147 }
Neal Norwitzb5673922002-09-05 21:48:07 +00001148
Christian Heimes7adfad82008-02-15 08:20:11 +00001149 if (prot == PROT_READ) {
1150 access = ACCESS_READ;
1151 }
1152
Neal Norwitzb5673922002-09-05 21:48:07 +00001153#ifdef HAVE_FSTAT
Martin v. Löwisc16f3bd2003-05-03 09:14:54 +00001154# ifdef __VMS
1155 /* on OpenVMS we must ensure that all bytes are written to the file */
Andrew M. Kuchling7c22ccc2008-01-10 13:37:12 +00001156 if (fd != -1) {
1157 fsync(fd);
1158 }
Martin v. Löwisc16f3bd2003-05-03 09:14:54 +00001159# endif
Andrew M. Kuchling7c22ccc2008-01-10 13:37:12 +00001160 if (fd != -1 && fstat(fd, &st) == 0 && S_ISREG(st.st_mode)) {
Martin v. Löwis7fe60c02005-03-03 11:22:44 +00001161 if (map_size == 0) {
Martin v. Löwiscfe7e092006-02-17 06:59:14 +00001162 map_size = st.st_size;
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001163 } else if ((size_t)offset + (size_t)map_size > st.st_size) {
Tim Petersec0a5f02006-02-16 23:47:20 +00001164 PyErr_SetString(PyExc_ValueError,
Martin v. Löwis7fe60c02005-03-03 11:22:44 +00001165 "mmap length is greater than file size");
1166 return NULL;
1167 }
Neal Norwitzb5673922002-09-05 21:48:07 +00001168 }
1169#endif
Georg Brandl845c4032008-01-21 14:16:46 +00001170 m_obj = (mmap_object *)type->tp_alloc(type, 0);
Guido van Rossum09fdf072000-03-31 01:17:07 +00001171 if (m_obj == NULL) {return NULL;}
Neal Norwitz3b4fff82006-01-11 08:54:45 +00001172 m_obj->data = NULL;
Guido van Rossum09fdf072000-03-31 01:17:07 +00001173 m_obj->size = (size_t) map_size;
1174 m_obj->pos = (size_t) 0;
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001175 m_obj->offset = offset;
Neal Norwitz0e6bc8c2006-02-05 05:45:43 +00001176 if (fd == -1) {
1177 m_obj->fd = -1;
1178 /* Assume the caller wants to map anonymous memory.
1179 This is the same behaviour as Windows. mmap.mmap(-1, size)
1180 on both Windows and Unix map anonymous memory.
1181 */
1182#ifdef MAP_ANONYMOUS
1183 /* BSD way to map anonymous memory */
1184 flags |= MAP_ANONYMOUS;
1185#else
1186 /* SVR4 method to map anonymous memory is to open /dev/zero */
1187 fd = devzero = open("/dev/zero", O_RDWR);
1188 if (devzero == -1) {
1189 Py_DECREF(m_obj);
1190 PyErr_SetFromErrno(mmap_module_error);
1191 return NULL;
1192 }
1193#endif
1194 } else {
1195 m_obj->fd = dup(fd);
1196 if (m_obj->fd == -1) {
1197 Py_DECREF(m_obj);
1198 PyErr_SetFromErrno(mmap_module_error);
1199 return NULL;
1200 }
Georg Brandl38387b82005-08-24 07:17:40 +00001201 }
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001202
Tim Petersec0a5f02006-02-16 23:47:20 +00001203 m_obj->data = mmap(NULL, map_size,
Guido van Rossum09fdf072000-03-31 01:17:07 +00001204 prot, flags,
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001205 fd, offset);
Neal Norwitz0e6bc8c2006-02-05 05:45:43 +00001206
1207 if (devzero != -1) {
1208 close(devzero);
1209 }
1210
Tim Peters5ebfd362001-11-13 23:11:19 +00001211 if (m_obj->data == (char *)-1) {
Andrew M. Kuchling16581c82004-05-19 14:39:08 +00001212 m_obj->data = NULL;
Guido van Rossum09fdf072000-03-31 01:17:07 +00001213 Py_DECREF(m_obj);
1214 PyErr_SetFromErrno(mmap_module_error);
1215 return NULL;
1216 }
Neal Norwitz8856fb72005-12-18 03:34:22 +00001217 m_obj->access = (access_mode)access;
Guido van Rossum09fdf072000-03-31 01:17:07 +00001218 return (PyObject *)m_obj;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001219}
1220#endif /* UNIX */
1221
Martin v. Löwis6238d2b2002-06-30 15:26:10 +00001222#ifdef MS_WINDOWS
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001223static PyObject *
Georg Brandl845c4032008-01-21 14:16:46 +00001224new_mmap_object(PyTypeObject *type, PyObject *args, PyObject *kwdict)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001225{
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +00001226 mmap_object *m_obj;
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001227 PyObject *map_size_obj = NULL, *offset_obj = NULL;
1228 Py_ssize_t map_size, offset;
1229 DWORD off_hi; /* upper 32 bits of offset */
1230 DWORD off_lo; /* lower 32 bits of offset */
1231 DWORD size_hi; /* upper 32 bits of size */
1232 DWORD size_lo; /* lower 32 bits of size */
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +00001233 char *tagname = "";
Guido van Rossum09fdf072000-03-31 01:17:07 +00001234 DWORD dwErr = 0;
1235 int fileno;
Mark Hammond071864a2000-07-30 02:46:26 +00001236 HANDLE fh = 0;
Neal Norwitz8856fb72005-12-18 03:34:22 +00001237 int access = (access_mode)ACCESS_DEFAULT;
Tim Peters5ebfd362001-11-13 23:11:19 +00001238 DWORD flProtect, dwDesiredAccess;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001239 static char *keywords[] = { "fileno", "length",
Tim Petersec0a5f02006-02-16 23:47:20 +00001240 "tagname",
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001241 "access", "offset", NULL };
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001242
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001243 if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iO|ziO", keywords,
Tim Petersec0a5f02006-02-16 23:47:20 +00001244 &fileno, &map_size_obj,
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001245 &tagname, &access, &offset_obj)) {
Guido van Rossum09fdf072000-03-31 01:17:07 +00001246 return NULL;
Tim Peters5ebfd362001-11-13 23:11:19 +00001247 }
1248
Neal Norwitz8856fb72005-12-18 03:34:22 +00001249 switch((access_mode)access) {
Tim Peters5ebfd362001-11-13 23:11:19 +00001250 case ACCESS_READ:
1251 flProtect = PAGE_READONLY;
1252 dwDesiredAccess = FILE_MAP_READ;
1253 break;
1254 case ACCESS_DEFAULT: case ACCESS_WRITE:
1255 flProtect = PAGE_READWRITE;
1256 dwDesiredAccess = FILE_MAP_WRITE;
1257 break;
1258 case ACCESS_COPY:
1259 flProtect = PAGE_WRITECOPY;
1260 dwDesiredAccess = FILE_MAP_COPY;
1261 break;
1262 default:
Tim Petersec0a5f02006-02-16 23:47:20 +00001263 return PyErr_Format(PyExc_ValueError,
Tim Peters5ebfd362001-11-13 23:11:19 +00001264 "mmap invalid access parameter.");
1265 }
1266
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001267 map_size = _GetMapSize(map_size_obj, "size");
Andrew M. Kuchling70d27422000-06-18 04:45:14 +00001268 if (map_size < 0)
1269 return NULL;
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001270 offset = _GetMapSize(offset_obj, "offset");
1271 if (offset < 0)
1272 return NULL;
Tim Petersec0a5f02006-02-16 23:47:20 +00001273
Neal Norwitz0e6bc8c2006-02-05 05:45:43 +00001274 /* assume -1 and 0 both mean invalid filedescriptor
1275 to 'anonymously' map memory.
1276 XXX: fileno == 0 is a valid fd, but was accepted prior to 2.5.
1277 XXX: Should this code be added?
1278 if (fileno == 0)
1279 PyErr_Warn(PyExc_DeprecationWarning,
1280 "don't use 0 for anonymous memory");
1281 */
1282 if (fileno != -1 && fileno != 0) {
Mark Hammond071864a2000-07-30 02:46:26 +00001283 fh = (HANDLE)_get_osfhandle(fileno);
1284 if (fh==(HANDLE)-1) {
Tim Peters5ebfd362001-11-13 23:11:19 +00001285 PyErr_SetFromErrno(mmap_module_error);
1286 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001287 }
Fred Drake1ef4e2d2000-04-05 14:15:31 +00001288 /* Win9x appears to need us seeked to zero */
Guido van Rossum69c2b882003-04-09 19:31:02 +00001289 lseek(fileno, 0, SEEK_SET);
Guido van Rossum09fdf072000-03-31 01:17:07 +00001290 }
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001291
Georg Brandl845c4032008-01-21 14:16:46 +00001292 m_obj = (mmap_object *)type->tp_alloc(type, 0);
Tim Peters8f9cc292006-02-17 00:00:20 +00001293 if (m_obj == NULL)
Mark Hammond2cbed002000-07-30 02:22:43 +00001294 return NULL;
1295 /* Set every field to an invalid marker, so we can safely
1296 destruct the object in the face of failure */
1297 m_obj->data = NULL;
Mark Hammond071864a2000-07-30 02:46:26 +00001298 m_obj->file_handle = INVALID_HANDLE_VALUE;
Hirokazu Yamamoto264fc122009-03-05 14:21:12 +00001299 m_obj->map_handle = NULL;
Mark Hammond2cbed002000-07-30 02:22:43 +00001300 m_obj->tagname = NULL;
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001301 m_obj->offset = offset;
Mark Hammond2cbed002000-07-30 02:22:43 +00001302
Guido van Rossum09fdf072000-03-31 01:17:07 +00001303 if (fh) {
Mark Hammond2cbed002000-07-30 02:22:43 +00001304 /* It is necessary to duplicate the handle, so the
1305 Python code can close it on us */
1306 if (!DuplicateHandle(
Tim Peters5ebfd362001-11-13 23:11:19 +00001307 GetCurrentProcess(), /* source process handle */
1308 fh, /* handle to be duplicated */
1309 GetCurrentProcess(), /* target proc handle */
1310 (LPHANDLE)&m_obj->file_handle, /* result */
1311 0, /* access - ignored due to options value */
1312 FALSE, /* inherited by child processes? */
1313 DUPLICATE_SAME_ACCESS)) { /* options */
Mark Hammond2cbed002000-07-30 02:22:43 +00001314 dwErr = GetLastError();
1315 Py_DECREF(m_obj);
1316 PyErr_SetFromWindowsErr(dwErr);
1317 return NULL;
1318 }
Guido van Rossum09fdf072000-03-31 01:17:07 +00001319 if (!map_size) {
Martin v. Löwis15186072006-02-18 12:38:35 +00001320 DWORD low,high;
1321 low = GetFileSize(fh, &high);
1322 /* low might just happen to have the value INVALID_FILE_SIZE;
1323 so we need to check the last error also. */
1324 if (low == INVALID_FILE_SIZE &&
1325 (dwErr = GetLastError()) != NO_ERROR) {
1326 Py_DECREF(m_obj);
1327 return PyErr_SetFromWindowsErr(dwErr);
1328 }
1329
1330#if SIZEOF_SIZE_T > 4
1331 m_obj->size = (((size_t)high)<<32) + low;
1332#else
1333 if (high)
1334 /* File is too large to map completely */
1335 m_obj->size = (size_t)-1;
1336 else
1337 m_obj->size = low;
1338#endif
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001339 } else {
Guido van Rossum09fdf072000-03-31 01:17:07 +00001340 m_obj->size = map_size;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001341 }
Guido van Rossum09fdf072000-03-31 01:17:07 +00001342 }
1343 else {
Guido van Rossum09fdf072000-03-31 01:17:07 +00001344 m_obj->size = map_size;
1345 }
1346
1347 /* set the initial position */
1348 m_obj->pos = (size_t) 0;
1349
Mark Hammond2cbed002000-07-30 02:22:43 +00001350 /* set the tag name */
Tim Peters0d9f9dc2001-01-10 05:42:18 +00001351 if (tagname != NULL && *tagname != '\0') {
Mark Hammond2cbed002000-07-30 02:22:43 +00001352 m_obj->tagname = PyMem_Malloc(strlen(tagname)+1);
1353 if (m_obj->tagname == NULL) {
1354 PyErr_NoMemory();
1355 Py_DECREF(m_obj);
1356 return NULL;
1357 }
1358 strcpy(m_obj->tagname, tagname);
1359 }
1360 else
1361 m_obj->tagname = NULL;
1362
Neal Norwitz8856fb72005-12-18 03:34:22 +00001363 m_obj->access = (access_mode)access;
Tim Peterse564e7f2006-02-16 23:46:01 +00001364 /* DWORD is a 4-byte int. If we're on a box where size_t consumes
Thomas Wouters2c98a7b2006-02-17 09:59:00 +00001365 * more than 4 bytes, we need to break it apart. Else (size_t
Tim Peterse564e7f2006-02-16 23:46:01 +00001366 * consumes 4 bytes), C doesn't define what happens if we shift
1367 * right by 32, so we need different code.
1368 */
1369#if SIZEOF_SIZE_T > 4
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001370 size_hi = (DWORD)((offset + m_obj->size) >> 32);
1371 size_lo = (DWORD)((offset + m_obj->size) & 0xFFFFFFFF);
1372 off_hi = (DWORD)(offset >> 32);
1373 off_lo = (DWORD)(offset & 0xFFFFFFFF);
Tim Peterse564e7f2006-02-16 23:46:01 +00001374#else
1375 size_hi = 0;
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001376 size_lo = (DWORD)(offset + m_obj->size);
1377 off_hi = 0;
1378 off_lo = (DWORD)offset;
Tim Peterse564e7f2006-02-16 23:46:01 +00001379#endif
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001380 /* For files, it would be sufficient to pass 0 as size.
1381 For anonymous maps, we have to pass the size explicitly. */
Tim Peters8f9cc292006-02-17 00:00:20 +00001382 m_obj->map_handle = CreateFileMapping(m_obj->file_handle,
1383 NULL,
1384 flProtect,
1385 size_hi,
1386 size_lo,
1387 m_obj->tagname);
Guido van Rossum09fdf072000-03-31 01:17:07 +00001388 if (m_obj->map_handle != NULL) {
Tim Peters8f9cc292006-02-17 00:00:20 +00001389 m_obj->data = (char *) MapViewOfFile(m_obj->map_handle,
1390 dwDesiredAccess,
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001391 off_hi,
1392 off_lo,
Hirokazu Yamamotob0e10c72009-02-28 12:13:07 +00001393 m_obj->size);
Tim Peters23721ee2006-02-16 23:50:16 +00001394 if (m_obj->data != NULL)
1395 return (PyObject *)m_obj;
Hirokazu Yamamoto264fc122009-03-05 14:21:12 +00001396 else {
Tim Peters5ebfd362001-11-13 23:11:19 +00001397 dwErr = GetLastError();
Hirokazu Yamamoto264fc122009-03-05 14:21:12 +00001398 CloseHandle(m_obj->map_handle);
1399 m_obj->map_handle = NULL;
1400 }
Tim Peters23721ee2006-02-16 23:50:16 +00001401 } else
Guido van Rossum09fdf072000-03-31 01:17:07 +00001402 dwErr = GetLastError();
Mark Hammond2cbed002000-07-30 02:22:43 +00001403 Py_DECREF(m_obj);
Guido van Rossum09fdf072000-03-31 01:17:07 +00001404 PyErr_SetFromWindowsErr(dwErr);
Tim Peters23721ee2006-02-16 23:50:16 +00001405 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001406}
Martin v. Löwis6238d2b2002-06-30 15:26:10 +00001407#endif /* MS_WINDOWS */
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001408
Neal Norwitze9ac0bb2006-08-13 18:11:27 +00001409static void
1410setint(PyObject *d, const char *name, long value)
1411{
1412 PyObject *o = PyInt_FromLong(value);
Neal Norwitz5ed49972006-08-13 18:41:15 +00001413 if (o && PyDict_SetItemString(d, name, o) == 0) {
Neal Norwitze9ac0bb2006-08-13 18:11:27 +00001414 Py_DECREF(o);
Neal Norwitz5ed49972006-08-13 18:41:15 +00001415 }
Neal Norwitze9ac0bb2006-08-13 18:11:27 +00001416}
1417
Mark Hammond62b1ab12002-07-23 06:31:15 +00001418PyMODINIT_FUNC
Georg Brandl845c4032008-01-21 14:16:46 +00001419initmmap(void)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001420{
Guido van Rossum09fdf072000-03-31 01:17:07 +00001421 PyObject *dict, *module;
Tim Peters2caf8df2001-01-14 05:05:51 +00001422
Georg Brandl845c4032008-01-21 14:16:46 +00001423 if (PyType_Ready(&mmap_object_type) < 0)
1424 return;
Tim Peters2caf8df2001-01-14 05:05:51 +00001425
Georg Brandl845c4032008-01-21 14:16:46 +00001426 module = Py_InitModule("mmap", NULL);
Neal Norwitz1ac754f2006-01-19 06:09:39 +00001427 if (module == NULL)
1428 return;
Tim Peters8f9cc292006-02-17 00:00:20 +00001429 dict = PyModule_GetDict(module);
Neal Norwitze9ac0bb2006-08-13 18:11:27 +00001430 if (!dict)
1431 return;
Facundo Batistae1396882008-02-17 18:59:29 +00001432 mmap_module_error = PyErr_NewException("mmap.error",
1433 PyExc_EnvironmentError , NULL);
1434 if (mmap_module_error == NULL)
1435 return;
Tim Peters8f9cc292006-02-17 00:00:20 +00001436 PyDict_SetItemString(dict, "error", mmap_module_error);
Georg Brandl845c4032008-01-21 14:16:46 +00001437 PyDict_SetItemString(dict, "mmap", (PyObject*) &mmap_object_type);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001438#ifdef PROT_EXEC
Neal Norwitze9ac0bb2006-08-13 18:11:27 +00001439 setint(dict, "PROT_EXEC", PROT_EXEC);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001440#endif
1441#ifdef PROT_READ
Neal Norwitze9ac0bb2006-08-13 18:11:27 +00001442 setint(dict, "PROT_READ", PROT_READ);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001443#endif
1444#ifdef PROT_WRITE
Neal Norwitze9ac0bb2006-08-13 18:11:27 +00001445 setint(dict, "PROT_WRITE", PROT_WRITE);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001446#endif
1447
1448#ifdef MAP_SHARED
Neal Norwitze9ac0bb2006-08-13 18:11:27 +00001449 setint(dict, "MAP_SHARED", MAP_SHARED);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001450#endif
1451#ifdef MAP_PRIVATE
Neal Norwitze9ac0bb2006-08-13 18:11:27 +00001452 setint(dict, "MAP_PRIVATE", MAP_PRIVATE);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001453#endif
1454#ifdef MAP_DENYWRITE
Neal Norwitze9ac0bb2006-08-13 18:11:27 +00001455 setint(dict, "MAP_DENYWRITE", MAP_DENYWRITE);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001456#endif
1457#ifdef MAP_EXECUTABLE
Neal Norwitze9ac0bb2006-08-13 18:11:27 +00001458 setint(dict, "MAP_EXECUTABLE", MAP_EXECUTABLE);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001459#endif
Neal Norwitz0e6bc8c2006-02-05 05:45:43 +00001460#ifdef MAP_ANONYMOUS
Neal Norwitze9ac0bb2006-08-13 18:11:27 +00001461 setint(dict, "MAP_ANON", MAP_ANONYMOUS);
1462 setint(dict, "MAP_ANONYMOUS", MAP_ANONYMOUS);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001463#endif
1464
Neal Norwitze9ac0bb2006-08-13 18:11:27 +00001465 setint(dict, "PAGESIZE", (long)my_getpagesize());
Andrew M. Kuchling961fe172000-06-03 19:41:42 +00001466
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001467 setint(dict, "ALLOCATIONGRANULARITY", (long)my_getallocationgranularity());
1468
Neal Norwitze9ac0bb2006-08-13 18:11:27 +00001469 setint(dict, "ACCESS_READ", ACCESS_READ);
1470 setint(dict, "ACCESS_WRITE", ACCESS_WRITE);
1471 setint(dict, "ACCESS_COPY", ACCESS_COPY);
Tim Peters5ebfd362001-11-13 23:11:19 +00001472}