blob: e1970cbb53be36d3b3eda6713d17acfb4ad260d9 [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{
Martin v. Löwisad0a4622006-02-16 14:30:23 +0000235 Py_ssize_t num_bytes;
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 */
Neal Norwitze7d8be82008-07-31 17:17:14 +0000243 if (num_bytes > self->size - self->pos) {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000244 num_bytes -= (self->pos+num_bytes) - self->size;
245 }
246 result = Py_BuildValue("s#", self->data+self->pos, num_bytes);
Tim Petersec0a5f02006-02-16 23:47:20 +0000247 self->pos += num_bytes;
Tim Peters23721ee2006-02-16 23:50:16 +0000248 return result;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000249}
250
251static PyObject *
Andrew M. Kuchling5c60bfc2008-01-19 18:18:41 +0000252mmap_gfind(mmap_object *self,
253 PyObject *args,
254 int reverse)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000255{
Martin v. Löwisad0a4622006-02-16 14:30:23 +0000256 Py_ssize_t start = self->pos;
Neal Norwitz739a3c42008-01-26 20:24:36 +0000257 Py_ssize_t end = self->size;
258 const char *needle;
Martin v. Löwiscfe7e092006-02-17 06:59:14 +0000259 Py_ssize_t len;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000260
Guido van Rossum09fdf072000-03-31 01:17:07 +0000261 CHECK_VALID(NULL);
Andrew M. Kuchling5c60bfc2008-01-19 18:18:41 +0000262 if (!PyArg_ParseTuple(args, reverse ? "s#|nn:rfind" : "s#|nn:find",
263 &needle, &len, &start, &end)) {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000264 return NULL;
265 } else {
Neal Norwitz739a3c42008-01-26 20:24:36 +0000266 const char *p, *start_p, *end_p;
Neal Norwitze1027f92008-01-27 07:37:38 +0000267 int sign = reverse ? -1 : 1;
Greg Stein834f4dd2001-05-14 09:32:26 +0000268
269 if (start < 0)
Tim Peters5ebfd362001-11-13 23:11:19 +0000270 start += self->size;
Greg Stein834f4dd2001-05-14 09:32:26 +0000271 if (start < 0)
Tim Peters5ebfd362001-11-13 23:11:19 +0000272 start = 0;
Tim Petersd401edd2001-05-14 23:19:12 +0000273 else if ((size_t)start > self->size)
Tim Peters5ebfd362001-11-13 23:11:19 +0000274 start = self->size;
Greg Stein834f4dd2001-05-14 09:32:26 +0000275
Andrew M. Kuchling5c60bfc2008-01-19 18:18:41 +0000276 if (end < 0)
277 end += self->size;
278 if (end < 0)
279 end = 0;
280 else if ((size_t)end > self->size)
281 end = self->size;
282
Neal Norwitz739a3c42008-01-26 20:24:36 +0000283 start_p = self->data + start;
284 end_p = self->data + end;
Andrew M. Kuchling5c60bfc2008-01-19 18:18:41 +0000285
Neal Norwitz739a3c42008-01-26 20:24:36 +0000286 for (p = (reverse ? end_p - len : start_p);
287 (p >= start_p) && (p + len <= end_p); p += sign) {
Martin v. Löwiscfe7e092006-02-17 06:59:14 +0000288 Py_ssize_t i;
Tim Petersc9ffa062002-03-08 05:43:32 +0000289 for (i = 0; i < len && needle[i] == p[i]; ++i)
290 /* nothing */;
291 if (i == len) {
Martin v. Löwiscfe7e092006-02-17 06:59:14 +0000292 return PyInt_FromSsize_t(p - self->data);
Guido van Rossum09fdf072000-03-31 01:17:07 +0000293 }
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000294 }
Martin v. Löwiscfe7e092006-02-17 06:59:14 +0000295 return PyInt_FromLong(-1);
Guido van Rossum09fdf072000-03-31 01:17:07 +0000296 }
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000297}
298
Andrew M. Kuchling5c60bfc2008-01-19 18:18:41 +0000299static PyObject *
300mmap_find_method(mmap_object *self,
301 PyObject *args)
302{
303 return mmap_gfind(self, args, 0);
304}
305
306static PyObject *
307mmap_rfind_method(mmap_object *self,
308 PyObject *args)
309{
310 return mmap_gfind(self, args, 1);
311}
312
Tim Petersec0a5f02006-02-16 23:47:20 +0000313static int
Tim Peters5ebfd362001-11-13 23:11:19 +0000314is_writeable(mmap_object *self)
315{
316 if (self->access != ACCESS_READ)
Tim Petersec0a5f02006-02-16 23:47:20 +0000317 return 1;
Tim Peters5ebfd362001-11-13 23:11:19 +0000318 PyErr_Format(PyExc_TypeError, "mmap can't modify a readonly memory map.");
319 return 0;
320}
321
Tim Petersec0a5f02006-02-16 23:47:20 +0000322static int
Tim Peters5ebfd362001-11-13 23:11:19 +0000323is_resizeable(mmap_object *self)
324{
325 if ((self->access == ACCESS_WRITE) || (self->access == ACCESS_DEFAULT))
Tim Petersec0a5f02006-02-16 23:47:20 +0000326 return 1;
327 PyErr_Format(PyExc_TypeError,
Tim Peters5ebfd362001-11-13 23:11:19 +0000328 "mmap can't resize a readonly or copy-on-write memory map.");
329 return 0;
330}
331
332
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000333static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000334mmap_write_method(mmap_object *self,
335 PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000336{
Martin v. Löwiscfe7e092006-02-17 06:59:14 +0000337 Py_ssize_t length;
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000338 char *data;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000339
Guido van Rossum09fdf072000-03-31 01:17:07 +0000340 CHECK_VALID(NULL);
Tim Peters8f9cc292006-02-17 00:00:20 +0000341 if (!PyArg_ParseTuple(args, "s#:write", &data, &length))
Guido van Rossum09fdf072000-03-31 01:17:07 +0000342 return(NULL);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000343
Tim Peters5ebfd362001-11-13 23:11:19 +0000344 if (!is_writeable(self))
345 return NULL;
346
Guido van Rossum09fdf072000-03-31 01:17:07 +0000347 if ((self->pos + length) > self->size) {
Tim Peters8f9cc292006-02-17 00:00:20 +0000348 PyErr_SetString(PyExc_ValueError, "data out of range");
Guido van Rossum09fdf072000-03-31 01:17:07 +0000349 return NULL;
350 }
Tim Peters8f9cc292006-02-17 00:00:20 +0000351 memcpy(self->data+self->pos, data, length);
Guido van Rossum09fdf072000-03-31 01:17:07 +0000352 self->pos = self->pos+length;
Tim Peters8f9cc292006-02-17 00:00:20 +0000353 Py_INCREF(Py_None);
Tim Peters23721ee2006-02-16 23:50:16 +0000354 return Py_None;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000355}
356
357static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000358mmap_write_byte_method(mmap_object *self,
359 PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000360{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000361 char value;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000362
Guido van Rossum09fdf072000-03-31 01:17:07 +0000363 CHECK_VALID(NULL);
Tim Peters8f9cc292006-02-17 00:00:20 +0000364 if (!PyArg_ParseTuple(args, "c:write_byte", &value))
Guido van Rossum09fdf072000-03-31 01:17:07 +0000365 return(NULL);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000366
Tim Peters5ebfd362001-11-13 23:11:19 +0000367 if (!is_writeable(self))
368 return NULL;
Hirokazu Yamamotof2dc8852009-02-28 10:31:54 +0000369
370 if (self->pos < self->size) {
371 *(self->data+self->pos) = value;
372 self->pos += 1;
373 Py_INCREF(Py_None);
374 return Py_None;
375 }
376 else {
377 PyErr_SetString(PyExc_ValueError, "write byte out of range");
378 return NULL;
379 }
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000380}
Tim Petersec0a5f02006-02-16 23:47:20 +0000381
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000382static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000383mmap_size_method(mmap_object *self,
Georg Brandl96a8c392006-05-29 21:04:52 +0000384 PyObject *unused)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000385{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000386 CHECK_VALID(NULL);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000387
Martin v. Löwis6238d2b2002-06-30 15:26:10 +0000388#ifdef MS_WINDOWS
Mark Hammond071864a2000-07-30 02:46:26 +0000389 if (self->file_handle != INVALID_HANDLE_VALUE) {
Martin v. Löwis15186072006-02-18 12:38:35 +0000390 DWORD low,high;
391 PY_LONG_LONG size;
392 low = GetFileSize(self->file_handle, &high);
393 if (low == INVALID_FILE_SIZE) {
394 /* It might be that the function appears to have failed,
395 when indeed its size equals INVALID_FILE_SIZE */
396 DWORD error = GetLastError();
397 if (error != NO_ERROR)
398 return PyErr_SetFromWindowsErr(error);
399 }
400 if (!high && low < LONG_MAX)
401 return PyInt_FromLong((long)low);
402 size = (((PY_LONG_LONG)high)<<32) + low;
403 return PyLong_FromLongLong(size);
Guido van Rossum09fdf072000-03-31 01:17:07 +0000404 } else {
Martin v. Löwis15186072006-02-18 12:38:35 +0000405 return PyInt_FromSsize_t(self->size);
Guido van Rossum09fdf072000-03-31 01:17:07 +0000406 }
Martin v. Löwis6238d2b2002-06-30 15:26:10 +0000407#endif /* MS_WINDOWS */
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000408
409#ifdef UNIX
Andrew M. Kuchling7b9fb922000-06-17 22:41:22 +0000410 {
411 struct stat buf;
412 if (-1 == fstat(self->fd, &buf)) {
413 PyErr_SetFromErrno(mmap_module_error);
414 return NULL;
415 }
Martin v. Löwis15186072006-02-18 12:38:35 +0000416 return PyInt_FromSsize_t(buf.st_size);
Andrew M. Kuchling7b9fb922000-06-17 22:41:22 +0000417 }
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000418#endif /* UNIX */
419}
420
421/* This assumes that you want the entire file mapped,
422 / and when recreating the map will make the new file
423 / have the new size
424 /
425 / Is this really necessary? This could easily be done
426 / from python by just closing and re-opening with the
427 / new size?
428 */
429
430static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000431mmap_resize_method(mmap_object *self,
432 PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000433{
Martin v. Löwiscfe7e092006-02-17 06:59:14 +0000434 Py_ssize_t new_size;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000435 CHECK_VALID(NULL);
Martin v. Löwiscfe7e092006-02-17 06:59:14 +0000436 if (!PyArg_ParseTuple(args, "n:resize", &new_size) ||
Tim Peters5ebfd362001-11-13 23:11:19 +0000437 !is_resizeable(self)) {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000438 return NULL;
Martin v. Löwis6238d2b2002-06-30 15:26:10 +0000439#ifdef MS_WINDOWS
Tim Petersec0a5f02006-02-16 23:47:20 +0000440 } else {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000441 DWORD dwErrCode = 0;
Travis E. Oliphant8feafab2007-10-23 02:40:56 +0000442 DWORD off_hi, off_lo, newSizeLow, newSizeHigh;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000443 /* First, unmap the file view */
Tim Peters8f9cc292006-02-17 00:00:20 +0000444 UnmapViewOfFile(self->data);
Hirokazu Yamamoto264fc122009-03-05 14:21:12 +0000445 self->data = NULL;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000446 /* Close the mapping object */
Tim Peters8f9cc292006-02-17 00:00:20 +0000447 CloseHandle(self->map_handle);
Hirokazu Yamamoto264fc122009-03-05 14:21:12 +0000448 self->map_handle = NULL;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000449 /* Move to the desired EOF position */
Martin v. Löwis15186072006-02-18 12:38:35 +0000450#if SIZEOF_SIZE_T > 4
Travis E. Oliphant8feafab2007-10-23 02:40:56 +0000451 newSizeHigh = (DWORD)((self->offset + new_size) >> 32);
452 newSizeLow = (DWORD)((self->offset + new_size) & 0xFFFFFFFF);
453 off_hi = (DWORD)(self->offset >> 32);
454 off_lo = (DWORD)(self->offset & 0xFFFFFFFF);
Martin v. Löwis15186072006-02-18 12:38:35 +0000455#else
456 newSizeHigh = 0;
Hirokazu Yamamoto17a837e2009-02-17 13:17:26 +0000457 newSizeLow = (DWORD)(self->offset + new_size);
Travis E. Oliphant8feafab2007-10-23 02:40:56 +0000458 off_hi = 0;
459 off_lo = (DWORD)self->offset;
Martin v. Löwis15186072006-02-18 12:38:35 +0000460#endif
Tim Peters8f9cc292006-02-17 00:00:20 +0000461 SetFilePointer(self->file_handle,
Martin v. Löwis15186072006-02-18 12:38:35 +0000462 newSizeLow, &newSizeHigh, FILE_BEGIN);
Guido van Rossum09fdf072000-03-31 01:17:07 +0000463 /* Change the size of the file */
Tim Peters8f9cc292006-02-17 00:00:20 +0000464 SetEndOfFile(self->file_handle);
Guido van Rossum09fdf072000-03-31 01:17:07 +0000465 /* Create another mapping object and remap the file view */
Tim Peters8f9cc292006-02-17 00:00:20 +0000466 self->map_handle = CreateFileMapping(
Mark Hammond071864a2000-07-30 02:46:26 +0000467 self->file_handle,
Guido van Rossum09fdf072000-03-31 01:17:07 +0000468 NULL,
469 PAGE_READWRITE,
Travis E. Oliphant8feafab2007-10-23 02:40:56 +0000470 0,
471 0,
Guido van Rossum09fdf072000-03-31 01:17:07 +0000472 self->tagname);
473 if (self->map_handle != NULL) {
Tim Peters8f9cc292006-02-17 00:00:20 +0000474 self->data = (char *) MapViewOfFile(self->map_handle,
475 FILE_MAP_WRITE,
Travis E. Oliphant8feafab2007-10-23 02:40:56 +0000476 off_hi,
477 off_lo,
478 new_size);
Guido van Rossum09fdf072000-03-31 01:17:07 +0000479 if (self->data != NULL) {
480 self->size = new_size;
Tim Peters8f9cc292006-02-17 00:00:20 +0000481 Py_INCREF(Py_None);
Guido van Rossum09fdf072000-03-31 01:17:07 +0000482 return Py_None;
483 } else {
484 dwErrCode = GetLastError();
Hirokazu Yamamoto264fc122009-03-05 14:21:12 +0000485 CloseHandle(self->map_handle);
486 self->map_handle = NULL;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000487 }
488 } else {
489 dwErrCode = GetLastError();
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000490 }
Guido van Rossum09fdf072000-03-31 01:17:07 +0000491 PyErr_SetFromWindowsErr(dwErrCode);
Tim Peters23721ee2006-02-16 23:50:16 +0000492 return NULL;
Martin v. Löwis6238d2b2002-06-30 15:26:10 +0000493#endif /* MS_WINDOWS */
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000494
495#ifdef UNIX
Tim Petersec0a5f02006-02-16 23:47:20 +0000496#ifndef HAVE_MREMAP
Tim Peters5ebfd362001-11-13 23:11:19 +0000497 } else {
498 PyErr_SetString(PyExc_SystemError,
499 "mmap: resizing not available--no mremap()");
500 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000501#else
Tim Peters5ebfd362001-11-13 23:11:19 +0000502 } else {
Armin Rigo335ffe82005-09-20 19:04:02 +0000503 void *newmap;
504
Hirokazu Yamamoto17a837e2009-02-17 13:17:26 +0000505 if (ftruncate(self->fd, self->offset + new_size) == -1) {
Georg Brandl38387b82005-08-24 07:17:40 +0000506 PyErr_SetFromErrno(mmap_module_error);
507 return NULL;
508 }
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000509
Andrew M. Kuchling6fef30e2000-06-18 14:51:21 +0000510#ifdef MREMAP_MAYMOVE
Tim Peters5ebfd362001-11-13 23:11:19 +0000511 newmap = mremap(self->data, self->size, new_size, MREMAP_MAYMOVE);
Andrew M. Kuchling6fef30e2000-06-18 14:51:21 +0000512#else
Jesse Noller40a61642009-03-31 18:12:35 +0000513 #if defined(__NetBSD__)
514 newmap = mremap(self->data, self->size, self->data, new_size, 0);
515 #else
516 newmap = mremap(self->data, self->size, new_size, 0);
517 #endif /* __NetBSD__ */
Andrew M. Kuchling6fef30e2000-06-18 14:51:21 +0000518#endif
Tim Petersec0a5f02006-02-16 23:47:20 +0000519 if (newmap == (void *)-1)
Tim Peters5ebfd362001-11-13 23:11:19 +0000520 {
521 PyErr_SetFromErrno(mmap_module_error);
522 return NULL;
523 }
524 self->data = newmap;
525 self->size = new_size;
526 Py_INCREF(Py_None);
527 return Py_None;
Andrew M. Kuchling6fef30e2000-06-18 14:51:21 +0000528#endif /* HAVE_MREMAP */
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000529#endif /* UNIX */
Tim Peters5ebfd362001-11-13 23:11:19 +0000530 }
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000531}
532
533static PyObject *
Georg Brandl96a8c392006-05-29 21:04:52 +0000534mmap_tell_method(mmap_object *self, PyObject *unused)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000535{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000536 CHECK_VALID(NULL);
Neal Norwitz670f8752006-08-22 13:56:56 +0000537 return PyInt_FromSize_t(self->pos);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000538}
539
540static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000541mmap_flush_method(mmap_object *self, PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000542{
Martin v. Löwisad0a4622006-02-16 14:30:23 +0000543 Py_ssize_t offset = 0;
544 Py_ssize_t size = self->size;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000545 CHECK_VALID(NULL);
Tim Petersf2882952006-02-17 01:07:39 +0000546 if (!PyArg_ParseTuple(args, "|nn:flush", &offset, &size))
Guido van Rossum09fdf072000-03-31 01:17:07 +0000547 return NULL;
Tim Petersf2882952006-02-17 01:07:39 +0000548 if ((size_t)(offset + size) > self->size) {
Tim Peters8f9cc292006-02-17 00:00:20 +0000549 PyErr_SetString(PyExc_ValueError, "flush values out of range");
Guido van Rossum09fdf072000-03-31 01:17:07 +0000550 return NULL;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000551 }
Neal Norwitz448654f2008-01-27 07:36:03 +0000552#ifdef MS_WINDOWS
553 return PyInt_FromLong((long) FlushViewOfFile(self->data+offset, size));
554#elif defined(UNIX)
555 /* XXX semantics of return value? */
556 /* XXX flags for msync? */
557 if (-1 == msync(self->data + offset, size, MS_SYNC)) {
558 PyErr_SetFromErrno(mmap_module_error);
559 return NULL;
560 }
561 return PyInt_FromLong(0);
562#else
563 PyErr_SetString(PyExc_ValueError, "flush not supported on this system");
564 return NULL;
565#endif
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000566}
567
568static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000569mmap_seek_method(mmap_object *self, PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000570{
Martin v. Löwiscfe7e092006-02-17 06:59:14 +0000571 Py_ssize_t dist;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000572 int how=0;
573 CHECK_VALID(NULL);
Martin v. Löwiscfe7e092006-02-17 06:59:14 +0000574 if (!PyArg_ParseTuple(args, "n|i:seek", &dist, &how))
Tim Peters8f9cc292006-02-17 00:00:20 +0000575 return NULL;
576 else {
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000577 size_t where;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000578 switch (how) {
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000579 case 0: /* relative to start */
580 if (dist < 0)
581 goto onoutofrange;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000582 where = dist;
583 break;
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000584 case 1: /* relative to current position */
Martin v. Löwiscfe7e092006-02-17 06:59:14 +0000585 if ((Py_ssize_t)self->pos + dist < 0)
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000586 goto onoutofrange;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000587 where = self->pos + dist;
588 break;
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000589 case 2: /* relative to end */
Martin v. Löwiscfe7e092006-02-17 06:59:14 +0000590 if ((Py_ssize_t)self->size + dist < 0)
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000591 goto onoutofrange;
592 where = self->size + dist;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000593 break;
594 default:
Tim Peters8f9cc292006-02-17 00:00:20 +0000595 PyErr_SetString(PyExc_ValueError, "unknown seek type");
Guido van Rossum09fdf072000-03-31 01:17:07 +0000596 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000597 }
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000598 if (where > self->size)
599 goto onoutofrange;
600 self->pos = where;
Tim Peters8f9cc292006-02-17 00:00:20 +0000601 Py_INCREF(Py_None);
Tim Peters23721ee2006-02-16 23:50:16 +0000602 return Py_None;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000603 }
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000604
Tim Peters5ebfd362001-11-13 23:11:19 +0000605 onoutofrange:
Tim Peters8f9cc292006-02-17 00:00:20 +0000606 PyErr_SetString(PyExc_ValueError, "seek out of range");
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000607 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000608}
609
610static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000611mmap_move_method(mmap_object *self, PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000612{
Jack Diederich2ecd3c32009-04-01 20:26:13 +0000613 unsigned long dest, src, cnt;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000614 CHECK_VALID(NULL);
Jack Diederich2ecd3c32009-04-01 20:26:13 +0000615 if (!PyArg_ParseTuple(args, "kkk:move", &dest, &src, &cnt) ||
Tim Peters5ebfd362001-11-13 23:11:19 +0000616 !is_writeable(self)) {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000617 return NULL;
618 } else {
619 /* bounds check the values */
Jack Diederich2ecd3c32009-04-01 20:26:13 +0000620 if (cnt < 0 || (cnt + dest) < cnt || (cnt + src) < cnt ||
621 src < 0 || src > self->size || (src + cnt) > self->size ||
622 dest < 0 || dest > self->size || (dest + cnt) > self->size) {
Tim Peters8f9cc292006-02-17 00:00:20 +0000623 PyErr_SetString(PyExc_ValueError,
Jack Diederich2ecd3c32009-04-01 20:26:13 +0000624 "source, destination, or count out of range");
Guido van Rossum09fdf072000-03-31 01:17:07 +0000625 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000626 }
Jack Diederich2ecd3c32009-04-01 20:26:13 +0000627 memmove(self->data+dest, self->data+src, cnt);
628 Py_INCREF(Py_None);
629 return Py_None;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000630 }
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000631}
632
633static struct PyMethodDef mmap_object_methods[] = {
Georg Brandl96a8c392006-05-29 21:04:52 +0000634 {"close", (PyCFunction) mmap_close_method, METH_NOARGS},
Martin v. Löwis43b936d2002-01-17 23:15:58 +0000635 {"find", (PyCFunction) mmap_find_method, METH_VARARGS},
Andrew M. Kuchling5c60bfc2008-01-19 18:18:41 +0000636 {"rfind", (PyCFunction) mmap_rfind_method, METH_VARARGS},
Martin v. Löwis43b936d2002-01-17 23:15:58 +0000637 {"flush", (PyCFunction) mmap_flush_method, METH_VARARGS},
638 {"move", (PyCFunction) mmap_move_method, METH_VARARGS},
639 {"read", (PyCFunction) mmap_read_method, METH_VARARGS},
Georg Brandl96a8c392006-05-29 21:04:52 +0000640 {"read_byte", (PyCFunction) mmap_read_byte_method, METH_NOARGS},
641 {"readline", (PyCFunction) mmap_read_line_method, METH_NOARGS},
Martin v. Löwis43b936d2002-01-17 23:15:58 +0000642 {"resize", (PyCFunction) mmap_resize_method, METH_VARARGS},
643 {"seek", (PyCFunction) mmap_seek_method, METH_VARARGS},
Georg Brandl96a8c392006-05-29 21:04:52 +0000644 {"size", (PyCFunction) mmap_size_method, METH_NOARGS},
645 {"tell", (PyCFunction) mmap_tell_method, METH_NOARGS},
Martin v. Löwis43b936d2002-01-17 23:15:58 +0000646 {"write", (PyCFunction) mmap_write_method, METH_VARARGS},
647 {"write_byte", (PyCFunction) mmap_write_byte_method, METH_VARARGS},
Guido van Rossum09fdf072000-03-31 01:17:07 +0000648 {NULL, NULL} /* sentinel */
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000649};
650
651/* Functions for treating an mmap'ed file as a buffer */
652
Martin v. Löwis18e16552006-02-15 17:27:45 +0000653static Py_ssize_t
654mmap_buffer_getreadbuf(mmap_object *self, Py_ssize_t index, const void **ptr)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000655{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000656 CHECK_VALID(-1);
Tim Peters8f9cc292006-02-17 00:00:20 +0000657 if (index != 0) {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000658 PyErr_SetString(PyExc_SystemError,
659 "Accessing non-existent mmap segment");
660 return -1;
661 }
662 *ptr = self->data;
663 return self->size;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000664}
665
Martin v. Löwis18e16552006-02-15 17:27:45 +0000666static Py_ssize_t
667mmap_buffer_getwritebuf(mmap_object *self, Py_ssize_t index, const void **ptr)
Tim Petersec0a5f02006-02-16 23:47:20 +0000668{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000669 CHECK_VALID(-1);
Tim Peters8f9cc292006-02-17 00:00:20 +0000670 if (index != 0) {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000671 PyErr_SetString(PyExc_SystemError,
672 "Accessing non-existent mmap segment");
673 return -1;
674 }
Tim Peters5ebfd362001-11-13 23:11:19 +0000675 if (!is_writeable(self))
676 return -1;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000677 *ptr = self->data;
678 return self->size;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000679}
680
Martin v. Löwis18e16552006-02-15 17:27:45 +0000681static Py_ssize_t
682mmap_buffer_getsegcount(mmap_object *self, Py_ssize_t *lenp)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000683{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000684 CHECK_VALID(-1);
Tim Petersec0a5f02006-02-16 23:47:20 +0000685 if (lenp)
Guido van Rossum09fdf072000-03-31 01:17:07 +0000686 *lenp = self->size;
687 return 1;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000688}
689
Martin v. Löwis18e16552006-02-15 17:27:45 +0000690static Py_ssize_t
691mmap_buffer_getcharbuffer(mmap_object *self, Py_ssize_t index, const void **ptr)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000692{
Tim Peters8f9cc292006-02-17 00:00:20 +0000693 if (index != 0) {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000694 PyErr_SetString(PyExc_SystemError,
695 "accessing non-existent buffer segment");
696 return -1;
697 }
698 *ptr = (const char *)self->data;
699 return self->size;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000700}
701
Martin v. Löwis18e16552006-02-15 17:27:45 +0000702static Py_ssize_t
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000703mmap_length(mmap_object *self)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000704{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000705 CHECK_VALID(-1);
706 return self->size;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000707}
708
709static PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000710mmap_item(mmap_object *self, Py_ssize_t i)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000711{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000712 CHECK_VALID(NULL);
Guido van Rossumce8e1dc2000-07-01 00:51:51 +0000713 if (i < 0 || (size_t)i >= self->size) {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000714 PyErr_SetString(PyExc_IndexError, "mmap index out of range");
715 return NULL;
716 }
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000717 return PyString_FromStringAndSize(self->data + i, 1);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000718}
719
720static PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000721mmap_slice(mmap_object *self, Py_ssize_t ilow, Py_ssize_t ihigh)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000722{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000723 CHECK_VALID(NULL);
724 if (ilow < 0)
725 ilow = 0;
Guido van Rossumce8e1dc2000-07-01 00:51:51 +0000726 else if ((size_t)ilow > self->size)
Guido van Rossum09fdf072000-03-31 01:17:07 +0000727 ilow = self->size;
728 if (ihigh < 0)
729 ihigh = 0;
730 if (ihigh < ilow)
731 ihigh = ilow;
Guido van Rossumce8e1dc2000-07-01 00:51:51 +0000732 else if ((size_t)ihigh > self->size)
Guido van Rossum09fdf072000-03-31 01:17:07 +0000733 ihigh = self->size;
Tim Petersec0a5f02006-02-16 23:47:20 +0000734
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000735 return PyString_FromStringAndSize(self->data + ilow, ihigh-ilow);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000736}
737
738static PyObject *
Thomas Wouters3ccec682007-08-28 15:28:19 +0000739mmap_subscript(mmap_object *self, PyObject *item)
740{
741 CHECK_VALID(NULL);
742 if (PyIndex_Check(item)) {
743 Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
744 if (i == -1 && PyErr_Occurred())
745 return NULL;
746 if (i < 0)
747 i += self->size;
Hirokazu Yamamotof6bbd0e2009-02-17 10:12:10 +0000748 if (i < 0 || (size_t)i >= self->size) {
Thomas Wouters3ccec682007-08-28 15:28:19 +0000749 PyErr_SetString(PyExc_IndexError,
750 "mmap index out of range");
751 return NULL;
752 }
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000753 return PyString_FromStringAndSize(self->data + i, 1);
Thomas Wouters3ccec682007-08-28 15:28:19 +0000754 }
755 else if (PySlice_Check(item)) {
756 Py_ssize_t start, stop, step, slicelen;
757
758 if (PySlice_GetIndicesEx((PySliceObject *)item, self->size,
759 &start, &stop, &step, &slicelen) < 0) {
760 return NULL;
761 }
762
763 if (slicelen <= 0)
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000764 return PyString_FromStringAndSize("", 0);
Thomas Wouters3ccec682007-08-28 15:28:19 +0000765 else if (step == 1)
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000766 return PyString_FromStringAndSize(self->data + start,
Thomas Wouters3ccec682007-08-28 15:28:19 +0000767 slicelen);
768 else {
769 char *result_buf = (char *)PyMem_Malloc(slicelen);
770 Py_ssize_t cur, i;
771 PyObject *result;
772
773 if (result_buf == NULL)
774 return PyErr_NoMemory();
775 for (cur = start, i = 0; i < slicelen;
776 cur += step, i++) {
777 result_buf[i] = self->data[cur];
778 }
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000779 result = PyString_FromStringAndSize(result_buf,
Thomas Wouters3ccec682007-08-28 15:28:19 +0000780 slicelen);
781 PyMem_Free(result_buf);
782 return result;
783 }
784 }
785 else {
786 PyErr_SetString(PyExc_TypeError,
787 "mmap indices must be integers");
788 return NULL;
789 }
790}
791
792static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000793mmap_concat(mmap_object *self, PyObject *bb)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000794{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000795 CHECK_VALID(NULL);
796 PyErr_SetString(PyExc_SystemError,
797 "mmaps don't support concatenation");
798 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000799}
800
801static PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000802mmap_repeat(mmap_object *self, Py_ssize_t n)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000803{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000804 CHECK_VALID(NULL);
805 PyErr_SetString(PyExc_SystemError,
806 "mmaps don't support repeat operation");
807 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000808}
809
810static int
Martin v. Löwis18e16552006-02-15 17:27:45 +0000811mmap_ass_slice(mmap_object *self, Py_ssize_t ilow, Py_ssize_t ihigh, PyObject *v)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000812{
Guido van Rossum36d4f8b2000-04-10 21:34:37 +0000813 const char *buf;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000814
Guido van Rossum09fdf072000-03-31 01:17:07 +0000815 CHECK_VALID(-1);
816 if (ilow < 0)
817 ilow = 0;
Guido van Rossumce8e1dc2000-07-01 00:51:51 +0000818 else if ((size_t)ilow > self->size)
Guido van Rossum09fdf072000-03-31 01:17:07 +0000819 ilow = self->size;
820 if (ihigh < 0)
821 ihigh = 0;
822 if (ihigh < ilow)
823 ihigh = ilow;
Guido van Rossumce8e1dc2000-07-01 00:51:51 +0000824 else if ((size_t)ihigh > self->size)
Guido van Rossum09fdf072000-03-31 01:17:07 +0000825 ihigh = self->size;
Tim Petersec0a5f02006-02-16 23:47:20 +0000826
Thomas Wouters1baac722001-07-16 15:47:36 +0000827 if (v == NULL) {
828 PyErr_SetString(PyExc_TypeError,
Tim Peters5ebfd362001-11-13 23:11:19 +0000829 "mmap object doesn't support slice deletion");
Thomas Wouters1baac722001-07-16 15:47:36 +0000830 return -1;
831 }
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000832 if (! (PyString_Check(v)) ) {
Tim Petersec0a5f02006-02-16 23:47:20 +0000833 PyErr_SetString(PyExc_IndexError,
Guido van Rossum09fdf072000-03-31 01:17:07 +0000834 "mmap slice assignment must be a string");
835 return -1;
836 }
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000837 if (PyString_Size(v) != (ihigh - ilow)) {
Tim Petersec0a5f02006-02-16 23:47:20 +0000838 PyErr_SetString(PyExc_IndexError,
Guido van Rossum09fdf072000-03-31 01:17:07 +0000839 "mmap slice assignment is wrong size");
840 return -1;
841 }
Tim Peters5ebfd362001-11-13 23:11:19 +0000842 if (!is_writeable(self))
843 return -1;
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000844 buf = PyString_AsString(v);
Guido van Rossum09fdf072000-03-31 01:17:07 +0000845 memcpy(self->data + ilow, buf, ihigh-ilow);
846 return 0;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000847}
848
849static int
Martin v. Löwis18e16552006-02-15 17:27:45 +0000850mmap_ass_item(mmap_object *self, Py_ssize_t i, PyObject *v)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000851{
Guido van Rossum36d4f8b2000-04-10 21:34:37 +0000852 const char *buf;
Tim Petersec0a5f02006-02-16 23:47:20 +0000853
Guido van Rossum09fdf072000-03-31 01:17:07 +0000854 CHECK_VALID(-1);
Guido van Rossumce8e1dc2000-07-01 00:51:51 +0000855 if (i < 0 || (size_t)i >= self->size) {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000856 PyErr_SetString(PyExc_IndexError, "mmap index out of range");
857 return -1;
858 }
Thomas Wouters1baac722001-07-16 15:47:36 +0000859 if (v == NULL) {
860 PyErr_SetString(PyExc_TypeError,
Tim Peters5ebfd362001-11-13 23:11:19 +0000861 "mmap object doesn't support item deletion");
Thomas Wouters1baac722001-07-16 15:47:36 +0000862 return -1;
863 }
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000864 if (! (PyString_Check(v) && PyString_Size(v)==1) ) {
Tim Petersec0a5f02006-02-16 23:47:20 +0000865 PyErr_SetString(PyExc_IndexError,
Tim Peters5ebfd362001-11-13 23:11:19 +0000866 "mmap assignment must be single-character string");
Guido van Rossum09fdf072000-03-31 01:17:07 +0000867 return -1;
868 }
Tim Peters5ebfd362001-11-13 23:11:19 +0000869 if (!is_writeable(self))
870 return -1;
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000871 buf = PyString_AsString(v);
Guido van Rossum09fdf072000-03-31 01:17:07 +0000872 self->data[i] = buf[0];
873 return 0;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000874}
875
Thomas Wouters3ccec682007-08-28 15:28:19 +0000876static int
877mmap_ass_subscript(mmap_object *self, PyObject *item, PyObject *value)
878{
879 CHECK_VALID(-1);
880
881 if (PyIndex_Check(item)) {
882 Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
883 const char *buf;
884
885 if (i == -1 && PyErr_Occurred())
886 return -1;
887 if (i < 0)
888 i += self->size;
Hirokazu Yamamotof6bbd0e2009-02-17 10:12:10 +0000889 if (i < 0 || (size_t)i >= self->size) {
Thomas Wouters3ccec682007-08-28 15:28:19 +0000890 PyErr_SetString(PyExc_IndexError,
891 "mmap index out of range");
892 return -1;
893 }
894 if (value == NULL) {
895 PyErr_SetString(PyExc_TypeError,
896 "mmap object doesn't support item deletion");
897 return -1;
898 }
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000899 if (!PyString_Check(value) || PyString_Size(value) != 1) {
Thomas Wouters3ccec682007-08-28 15:28:19 +0000900 PyErr_SetString(PyExc_IndexError,
901 "mmap assignment must be single-character string");
902 return -1;
903 }
904 if (!is_writeable(self))
905 return -1;
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000906 buf = PyString_AsString(value);
Thomas Wouters3ccec682007-08-28 15:28:19 +0000907 self->data[i] = buf[0];
908 return 0;
909 }
910 else if (PySlice_Check(item)) {
911 Py_ssize_t start, stop, step, slicelen;
912
913 if (PySlice_GetIndicesEx((PySliceObject *)item,
914 self->size, &start, &stop,
915 &step, &slicelen) < 0) {
916 return -1;
917 }
918 if (value == NULL) {
919 PyErr_SetString(PyExc_TypeError,
920 "mmap object doesn't support slice deletion");
921 return -1;
922 }
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000923 if (!PyString_Check(value)) {
Thomas Wouters3ccec682007-08-28 15:28:19 +0000924 PyErr_SetString(PyExc_IndexError,
925 "mmap slice assignment must be a string");
926 return -1;
927 }
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000928 if (PyString_Size(value) != slicelen) {
Thomas Wouters3ccec682007-08-28 15:28:19 +0000929 PyErr_SetString(PyExc_IndexError,
930 "mmap slice assignment is wrong size");
931 return -1;
932 }
933 if (!is_writeable(self))
934 return -1;
935
936 if (slicelen == 0)
937 return 0;
938 else if (step == 1) {
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000939 const char *buf = PyString_AsString(value);
Thomas Wouters3ccec682007-08-28 15:28:19 +0000940
941 if (buf == NULL)
942 return -1;
943 memcpy(self->data + start, buf, slicelen);
944 return 0;
945 }
946 else {
947 Py_ssize_t cur, i;
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000948 const char *buf = PyString_AsString(value);
Thomas Wouters3ccec682007-08-28 15:28:19 +0000949
950 if (buf == NULL)
951 return -1;
952 for (cur = start, i = 0; i < slicelen;
953 cur += step, i++) {
954 self->data[cur] = buf[i];
955 }
956 return 0;
957 }
958 }
959 else {
960 PyErr_SetString(PyExc_TypeError,
961 "mmap indices must be integer");
962 return -1;
963 }
964}
965
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000966static PySequenceMethods mmap_as_sequence = {
Martin v. Löwis18e16552006-02-15 17:27:45 +0000967 (lenfunc)mmap_length, /*sq_length*/
Guido van Rossum09fdf072000-03-31 01:17:07 +0000968 (binaryfunc)mmap_concat, /*sq_concat*/
Martin v. Löwis18e16552006-02-15 17:27:45 +0000969 (ssizeargfunc)mmap_repeat, /*sq_repeat*/
970 (ssizeargfunc)mmap_item, /*sq_item*/
971 (ssizessizeargfunc)mmap_slice, /*sq_slice*/
972 (ssizeobjargproc)mmap_ass_item, /*sq_ass_item*/
973 (ssizessizeobjargproc)mmap_ass_slice, /*sq_ass_slice*/
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000974};
975
Thomas Wouters3ccec682007-08-28 15:28:19 +0000976static PyMappingMethods mmap_as_mapping = {
977 (lenfunc)mmap_length,
978 (binaryfunc)mmap_subscript,
979 (objobjargproc)mmap_ass_subscript,
980};
981
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000982static PyBufferProcs mmap_as_buffer = {
Martin v. Löwis18e16552006-02-15 17:27:45 +0000983 (readbufferproc)mmap_buffer_getreadbuf,
984 (writebufferproc)mmap_buffer_getwritebuf,
985 (segcountproc)mmap_buffer_getsegcount,
986 (charbufferproc)mmap_buffer_getcharbuffer,
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000987};
988
Georg Brandl845c4032008-01-21 14:16:46 +0000989static PyObject *
990new_mmap_object(PyTypeObject *type, PyObject *args, PyObject *kwdict);
991
Georg Brandlef928022008-01-20 14:50:05 +0000992PyDoc_STRVAR(mmap_doc,
993"Windows: mmap(fileno, length[, tagname[, access[, offset]]])\n\
994\n\
995Maps length bytes from the file specified by the file handle fileno,\n\
996and returns a mmap object. If length is larger than the current size\n\
997of the file, the file is extended to contain length bytes. If length\n\
998is 0, the maximum length of the map is the current size of the file,\n\
999except that if the file is empty Windows raises an exception (you cannot\n\
1000create an empty mapping on Windows).\n\
1001\n\
1002Unix: mmap(fileno, length[, flags[, prot[, access[, offset]]]])\n\
1003\n\
1004Maps length bytes from the file specified by the file descriptor fileno,\n\
1005and returns a mmap object. If length is 0, the maximum length of the map\n\
1006will be the current size of the file when mmap is called.\n\
1007flags specifies the nature of the mapping. MAP_PRIVATE creates a\n\
1008private copy-on-write mapping, so changes to the contents of the mmap\n\
Thomas Heller66260992008-08-19 17:47:13 +00001009object will be private to this process, and MAP_SHARED creates a mapping\n\
Georg Brandlef928022008-01-20 14:50:05 +00001010that's shared with all other processes mapping the same areas of the file.\n\
1011The default value is MAP_SHARED.\n\
1012\n\
1013To map anonymous memory, pass -1 as the fileno (both versions).");
1014
1015
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001016static PyTypeObject mmap_object_type = {
Georg Brandl845c4032008-01-21 14:16:46 +00001017 PyVarObject_HEAD_INIT(NULL, 0)
Guido van Rossum14648392001-12-08 18:02:58 +00001018 "mmap.mmap", /* tp_name */
Guido van Rossum09fdf072000-03-31 01:17:07 +00001019 sizeof(mmap_object), /* tp_size */
1020 0, /* tp_itemsize */
1021 /* methods */
1022 (destructor) mmap_object_dealloc, /* tp_dealloc */
1023 0, /* tp_print */
Georg Brandlef928022008-01-20 14:50:05 +00001024 0, /* tp_getattr */
Guido van Rossum09fdf072000-03-31 01:17:07 +00001025 0, /* tp_setattr */
1026 0, /* tp_compare */
1027 0, /* tp_repr */
1028 0, /* tp_as_number */
1029 &mmap_as_sequence, /*tp_as_sequence*/
Thomas Wouters3ccec682007-08-28 15:28:19 +00001030 &mmap_as_mapping, /*tp_as_mapping*/
Guido van Rossum09fdf072000-03-31 01:17:07 +00001031 0, /*tp_hash*/
1032 0, /*tp_call*/
1033 0, /*tp_str*/
Georg Brandlef928022008-01-20 14:50:05 +00001034 PyObject_GenericGetAttr, /*tp_getattro*/
Guido van Rossum09fdf072000-03-31 01:17:07 +00001035 0, /*tp_setattro*/
1036 &mmap_as_buffer, /*tp_as_buffer*/
Georg Brandl845c4032008-01-21 14:16:46 +00001037 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GETCHARBUFFER, /*tp_flags*/
Georg Brandlef928022008-01-20 14:50:05 +00001038 mmap_doc, /*tp_doc*/
1039 0, /* tp_traverse */
1040 0, /* tp_clear */
1041 0, /* tp_richcompare */
1042 0, /* tp_weaklistoffset */
Georg Brandl845c4032008-01-21 14:16:46 +00001043 0, /* tp_iter */
1044 0, /* tp_iternext */
Georg Brandlef928022008-01-20 14:50:05 +00001045 mmap_object_methods, /* tp_methods */
Georg Brandl845c4032008-01-21 14:16:46 +00001046 0, /* tp_members */
1047 0, /* tp_getset */
1048 0, /* tp_base */
1049 0, /* tp_dict */
1050 0, /* tp_descr_get */
1051 0, /* tp_descr_set */
1052 0, /* tp_dictoffset */
1053 0, /* tp_init */
1054 PyType_GenericAlloc, /* tp_alloc */
1055 new_mmap_object, /* tp_new */
1056 PyObject_Del, /* tp_free */
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001057};
1058
Andrew M. Kuchling70d27422000-06-18 04:45:14 +00001059
1060/* extract the map size from the given PyObject
1061
Thomas Wouters7e474022000-07-16 12:04:32 +00001062 Returns -1 on error, with an appropriate Python exception raised. On
Andrew M. Kuchling70d27422000-06-18 04:45:14 +00001063 success, the map size is returned. */
Martin v. Löwiscfe7e092006-02-17 06:59:14 +00001064static Py_ssize_t
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001065_GetMapSize(PyObject *o, const char* param)
Andrew M. Kuchling70d27422000-06-18 04:45:14 +00001066{
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001067 if (o == NULL)
1068 return 0;
Neal Norwitz8a87f5d2006-08-12 17:03:09 +00001069 if (PyIndex_Check(o)) {
1070 Py_ssize_t i = PyNumber_AsSsize_t(o, PyExc_OverflowError);
Guido van Rossum38fff8c2006-03-07 18:50:55 +00001071 if (i==-1 && PyErr_Occurred())
Andrew M. Kuchling70d27422000-06-18 04:45:14 +00001072 return -1;
Neal Norwitz8a87f5d2006-08-12 17:03:09 +00001073 if (i < 0) {
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001074 PyErr_Format(PyExc_OverflowError,
1075 "memory mapped %s must be positive",
1076 param);
Neal Norwitz8a87f5d2006-08-12 17:03:09 +00001077 return -1;
1078 }
Martin v. Löwiscfe7e092006-02-17 06:59:14 +00001079 return i;
Andrew M. Kuchling70d27422000-06-18 04:45:14 +00001080 }
Andrew M. Kuchling70d27422000-06-18 04:45:14 +00001081
Neal Norwitz8a87f5d2006-08-12 17:03:09 +00001082 PyErr_SetString(PyExc_TypeError, "map size must be an integral value");
Andrew M. Kuchling70d27422000-06-18 04:45:14 +00001083 return -1;
1084}
1085
Tim Petersec0a5f02006-02-16 23:47:20 +00001086#ifdef UNIX
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001087static PyObject *
Georg Brandl845c4032008-01-21 14:16:46 +00001088new_mmap_object(PyTypeObject *type, PyObject *args, PyObject *kwdict)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001089{
Neal Norwitzb5673922002-09-05 21:48:07 +00001090#ifdef HAVE_FSTAT
1091 struct stat st;
1092#endif
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +00001093 mmap_object *m_obj;
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001094 PyObject *map_size_obj = NULL, *offset_obj = NULL;
1095 Py_ssize_t map_size, offset;
Guido van Rossum09fdf072000-03-31 01:17:07 +00001096 int fd, flags = MAP_SHARED, prot = PROT_WRITE | PROT_READ;
Neal Norwitz0e6bc8c2006-02-05 05:45:43 +00001097 int devzero = -1;
Neal Norwitz8856fb72005-12-18 03:34:22 +00001098 int access = (int)ACCESS_DEFAULT;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001099 static char *keywords[] = {"fileno", "length",
Tim Petersec0a5f02006-02-16 23:47:20 +00001100 "flags", "prot",
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001101 "access", "offset", NULL};
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001102
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001103 if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iO|iiiO", keywords,
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001104 &fd, &map_size_obj, &flags, &prot,
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001105 &access, &offset_obj))
Guido van Rossum09fdf072000-03-31 01:17:07 +00001106 return NULL;
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001107 map_size = _GetMapSize(map_size_obj, "size");
Andrew M. Kuchling70d27422000-06-18 04:45:14 +00001108 if (map_size < 0)
1109 return NULL;
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001110 offset = _GetMapSize(offset_obj, "offset");
1111 if (offset < 0)
1112 return NULL;
Tim Peters5ebfd362001-11-13 23:11:19 +00001113
Tim Petersec0a5f02006-02-16 23:47:20 +00001114 if ((access != (int)ACCESS_DEFAULT) &&
Neal Norwitzd1cfc8a2006-02-05 03:36:57 +00001115 ((flags != MAP_SHARED) || (prot != (PROT_WRITE | PROT_READ))))
Tim Petersec0a5f02006-02-16 23:47:20 +00001116 return PyErr_Format(PyExc_ValueError,
Tim Peters5ebfd362001-11-13 23:11:19 +00001117 "mmap can't specify both access and flags, prot.");
Neal Norwitzd1cfc8a2006-02-05 03:36:57 +00001118 switch ((access_mode)access) {
Tim Peters5ebfd362001-11-13 23:11:19 +00001119 case ACCESS_READ:
1120 flags = MAP_SHARED;
1121 prot = PROT_READ;
1122 break;
1123 case ACCESS_WRITE:
1124 flags = MAP_SHARED;
1125 prot = PROT_READ | PROT_WRITE;
1126 break;
1127 case ACCESS_COPY:
1128 flags = MAP_PRIVATE;
1129 prot = PROT_READ | PROT_WRITE;
1130 break;
Tim Petersec0a5f02006-02-16 23:47:20 +00001131 case ACCESS_DEFAULT:
Tim Peters5ebfd362001-11-13 23:11:19 +00001132 /* use the specified or default values of flags and prot */
1133 break;
1134 default:
Tim Petersec0a5f02006-02-16 23:47:20 +00001135 return PyErr_Format(PyExc_ValueError,
Tim Peters5ebfd362001-11-13 23:11:19 +00001136 "mmap invalid access parameter.");
1137 }
Neal Norwitzb5673922002-09-05 21:48:07 +00001138
Christian Heimes7adfad82008-02-15 08:20:11 +00001139 if (prot == PROT_READ) {
1140 access = ACCESS_READ;
1141 }
1142
Neal Norwitzb5673922002-09-05 21:48:07 +00001143#ifdef HAVE_FSTAT
Martin v. Löwisc16f3bd2003-05-03 09:14:54 +00001144# ifdef __VMS
1145 /* on OpenVMS we must ensure that all bytes are written to the file */
Andrew M. Kuchling7c22ccc2008-01-10 13:37:12 +00001146 if (fd != -1) {
1147 fsync(fd);
1148 }
Martin v. Löwisc16f3bd2003-05-03 09:14:54 +00001149# endif
Andrew M. Kuchling7c22ccc2008-01-10 13:37:12 +00001150 if (fd != -1 && fstat(fd, &st) == 0 && S_ISREG(st.st_mode)) {
Martin v. Löwis7fe60c02005-03-03 11:22:44 +00001151 if (map_size == 0) {
Martin v. Löwiscfe7e092006-02-17 06:59:14 +00001152 map_size = st.st_size;
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001153 } else if ((size_t)offset + (size_t)map_size > st.st_size) {
Tim Petersec0a5f02006-02-16 23:47:20 +00001154 PyErr_SetString(PyExc_ValueError,
Martin v. Löwis7fe60c02005-03-03 11:22:44 +00001155 "mmap length is greater than file size");
1156 return NULL;
1157 }
Neal Norwitzb5673922002-09-05 21:48:07 +00001158 }
1159#endif
Georg Brandl845c4032008-01-21 14:16:46 +00001160 m_obj = (mmap_object *)type->tp_alloc(type, 0);
Guido van Rossum09fdf072000-03-31 01:17:07 +00001161 if (m_obj == NULL) {return NULL;}
Neal Norwitz3b4fff82006-01-11 08:54:45 +00001162 m_obj->data = NULL;
Guido van Rossum09fdf072000-03-31 01:17:07 +00001163 m_obj->size = (size_t) map_size;
1164 m_obj->pos = (size_t) 0;
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001165 m_obj->offset = offset;
Neal Norwitz0e6bc8c2006-02-05 05:45:43 +00001166 if (fd == -1) {
1167 m_obj->fd = -1;
1168 /* Assume the caller wants to map anonymous memory.
1169 This is the same behaviour as Windows. mmap.mmap(-1, size)
1170 on both Windows and Unix map anonymous memory.
1171 */
1172#ifdef MAP_ANONYMOUS
1173 /* BSD way to map anonymous memory */
1174 flags |= MAP_ANONYMOUS;
1175#else
1176 /* SVR4 method to map anonymous memory is to open /dev/zero */
1177 fd = devzero = open("/dev/zero", O_RDWR);
1178 if (devzero == -1) {
1179 Py_DECREF(m_obj);
1180 PyErr_SetFromErrno(mmap_module_error);
1181 return NULL;
1182 }
1183#endif
1184 } else {
1185 m_obj->fd = dup(fd);
1186 if (m_obj->fd == -1) {
1187 Py_DECREF(m_obj);
1188 PyErr_SetFromErrno(mmap_module_error);
1189 return NULL;
1190 }
Georg Brandl38387b82005-08-24 07:17:40 +00001191 }
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001192
Tim Petersec0a5f02006-02-16 23:47:20 +00001193 m_obj->data = mmap(NULL, map_size,
Guido van Rossum09fdf072000-03-31 01:17:07 +00001194 prot, flags,
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001195 fd, offset);
Neal Norwitz0e6bc8c2006-02-05 05:45:43 +00001196
1197 if (devzero != -1) {
1198 close(devzero);
1199 }
1200
Tim Peters5ebfd362001-11-13 23:11:19 +00001201 if (m_obj->data == (char *)-1) {
Andrew M. Kuchling16581c82004-05-19 14:39:08 +00001202 m_obj->data = NULL;
Guido van Rossum09fdf072000-03-31 01:17:07 +00001203 Py_DECREF(m_obj);
1204 PyErr_SetFromErrno(mmap_module_error);
1205 return NULL;
1206 }
Neal Norwitz8856fb72005-12-18 03:34:22 +00001207 m_obj->access = (access_mode)access;
Guido van Rossum09fdf072000-03-31 01:17:07 +00001208 return (PyObject *)m_obj;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001209}
1210#endif /* UNIX */
1211
Martin v. Löwis6238d2b2002-06-30 15:26:10 +00001212#ifdef MS_WINDOWS
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001213static PyObject *
Georg Brandl845c4032008-01-21 14:16:46 +00001214new_mmap_object(PyTypeObject *type, PyObject *args, PyObject *kwdict)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001215{
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +00001216 mmap_object *m_obj;
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001217 PyObject *map_size_obj = NULL, *offset_obj = NULL;
1218 Py_ssize_t map_size, offset;
1219 DWORD off_hi; /* upper 32 bits of offset */
1220 DWORD off_lo; /* lower 32 bits of offset */
1221 DWORD size_hi; /* upper 32 bits of size */
1222 DWORD size_lo; /* lower 32 bits of size */
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +00001223 char *tagname = "";
Guido van Rossum09fdf072000-03-31 01:17:07 +00001224 DWORD dwErr = 0;
1225 int fileno;
Mark Hammond071864a2000-07-30 02:46:26 +00001226 HANDLE fh = 0;
Neal Norwitz8856fb72005-12-18 03:34:22 +00001227 int access = (access_mode)ACCESS_DEFAULT;
Tim Peters5ebfd362001-11-13 23:11:19 +00001228 DWORD flProtect, dwDesiredAccess;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001229 static char *keywords[] = { "fileno", "length",
Tim Petersec0a5f02006-02-16 23:47:20 +00001230 "tagname",
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001231 "access", "offset", NULL };
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001232
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001233 if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iO|ziO", keywords,
Tim Petersec0a5f02006-02-16 23:47:20 +00001234 &fileno, &map_size_obj,
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001235 &tagname, &access, &offset_obj)) {
Guido van Rossum09fdf072000-03-31 01:17:07 +00001236 return NULL;
Tim Peters5ebfd362001-11-13 23:11:19 +00001237 }
1238
Neal Norwitz8856fb72005-12-18 03:34:22 +00001239 switch((access_mode)access) {
Tim Peters5ebfd362001-11-13 23:11:19 +00001240 case ACCESS_READ:
1241 flProtect = PAGE_READONLY;
1242 dwDesiredAccess = FILE_MAP_READ;
1243 break;
1244 case ACCESS_DEFAULT: case ACCESS_WRITE:
1245 flProtect = PAGE_READWRITE;
1246 dwDesiredAccess = FILE_MAP_WRITE;
1247 break;
1248 case ACCESS_COPY:
1249 flProtect = PAGE_WRITECOPY;
1250 dwDesiredAccess = FILE_MAP_COPY;
1251 break;
1252 default:
Tim Petersec0a5f02006-02-16 23:47:20 +00001253 return PyErr_Format(PyExc_ValueError,
Tim Peters5ebfd362001-11-13 23:11:19 +00001254 "mmap invalid access parameter.");
1255 }
1256
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001257 map_size = _GetMapSize(map_size_obj, "size");
Andrew M. Kuchling70d27422000-06-18 04:45:14 +00001258 if (map_size < 0)
1259 return NULL;
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001260 offset = _GetMapSize(offset_obj, "offset");
1261 if (offset < 0)
1262 return NULL;
Tim Petersec0a5f02006-02-16 23:47:20 +00001263
Neal Norwitz0e6bc8c2006-02-05 05:45:43 +00001264 /* assume -1 and 0 both mean invalid filedescriptor
1265 to 'anonymously' map memory.
1266 XXX: fileno == 0 is a valid fd, but was accepted prior to 2.5.
1267 XXX: Should this code be added?
1268 if (fileno == 0)
1269 PyErr_Warn(PyExc_DeprecationWarning,
1270 "don't use 0 for anonymous memory");
1271 */
1272 if (fileno != -1 && fileno != 0) {
Mark Hammond071864a2000-07-30 02:46:26 +00001273 fh = (HANDLE)_get_osfhandle(fileno);
1274 if (fh==(HANDLE)-1) {
Tim Peters5ebfd362001-11-13 23:11:19 +00001275 PyErr_SetFromErrno(mmap_module_error);
1276 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001277 }
Fred Drake1ef4e2d2000-04-05 14:15:31 +00001278 /* Win9x appears to need us seeked to zero */
Guido van Rossum69c2b882003-04-09 19:31:02 +00001279 lseek(fileno, 0, SEEK_SET);
Guido van Rossum09fdf072000-03-31 01:17:07 +00001280 }
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001281
Georg Brandl845c4032008-01-21 14:16:46 +00001282 m_obj = (mmap_object *)type->tp_alloc(type, 0);
Tim Peters8f9cc292006-02-17 00:00:20 +00001283 if (m_obj == NULL)
Mark Hammond2cbed002000-07-30 02:22:43 +00001284 return NULL;
1285 /* Set every field to an invalid marker, so we can safely
1286 destruct the object in the face of failure */
1287 m_obj->data = NULL;
Mark Hammond071864a2000-07-30 02:46:26 +00001288 m_obj->file_handle = INVALID_HANDLE_VALUE;
Hirokazu Yamamoto264fc122009-03-05 14:21:12 +00001289 m_obj->map_handle = NULL;
Mark Hammond2cbed002000-07-30 02:22:43 +00001290 m_obj->tagname = NULL;
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001291 m_obj->offset = offset;
Mark Hammond2cbed002000-07-30 02:22:43 +00001292
Guido van Rossum09fdf072000-03-31 01:17:07 +00001293 if (fh) {
Mark Hammond2cbed002000-07-30 02:22:43 +00001294 /* It is necessary to duplicate the handle, so the
1295 Python code can close it on us */
1296 if (!DuplicateHandle(
Tim Peters5ebfd362001-11-13 23:11:19 +00001297 GetCurrentProcess(), /* source process handle */
1298 fh, /* handle to be duplicated */
1299 GetCurrentProcess(), /* target proc handle */
1300 (LPHANDLE)&m_obj->file_handle, /* result */
1301 0, /* access - ignored due to options value */
1302 FALSE, /* inherited by child processes? */
1303 DUPLICATE_SAME_ACCESS)) { /* options */
Mark Hammond2cbed002000-07-30 02:22:43 +00001304 dwErr = GetLastError();
1305 Py_DECREF(m_obj);
1306 PyErr_SetFromWindowsErr(dwErr);
1307 return NULL;
1308 }
Guido van Rossum09fdf072000-03-31 01:17:07 +00001309 if (!map_size) {
Martin v. Löwis15186072006-02-18 12:38:35 +00001310 DWORD low,high;
1311 low = GetFileSize(fh, &high);
1312 /* low might just happen to have the value INVALID_FILE_SIZE;
1313 so we need to check the last error also. */
1314 if (low == INVALID_FILE_SIZE &&
1315 (dwErr = GetLastError()) != NO_ERROR) {
1316 Py_DECREF(m_obj);
1317 return PyErr_SetFromWindowsErr(dwErr);
1318 }
1319
1320#if SIZEOF_SIZE_T > 4
1321 m_obj->size = (((size_t)high)<<32) + low;
1322#else
1323 if (high)
1324 /* File is too large to map completely */
1325 m_obj->size = (size_t)-1;
1326 else
1327 m_obj->size = low;
1328#endif
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001329 } else {
Guido van Rossum09fdf072000-03-31 01:17:07 +00001330 m_obj->size = map_size;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001331 }
Guido van Rossum09fdf072000-03-31 01:17:07 +00001332 }
1333 else {
Guido van Rossum09fdf072000-03-31 01:17:07 +00001334 m_obj->size = map_size;
1335 }
1336
1337 /* set the initial position */
1338 m_obj->pos = (size_t) 0;
1339
Mark Hammond2cbed002000-07-30 02:22:43 +00001340 /* set the tag name */
Tim Peters0d9f9dc2001-01-10 05:42:18 +00001341 if (tagname != NULL && *tagname != '\0') {
Mark Hammond2cbed002000-07-30 02:22:43 +00001342 m_obj->tagname = PyMem_Malloc(strlen(tagname)+1);
1343 if (m_obj->tagname == NULL) {
1344 PyErr_NoMemory();
1345 Py_DECREF(m_obj);
1346 return NULL;
1347 }
1348 strcpy(m_obj->tagname, tagname);
1349 }
1350 else
1351 m_obj->tagname = NULL;
1352
Neal Norwitz8856fb72005-12-18 03:34:22 +00001353 m_obj->access = (access_mode)access;
Tim Peterse564e7f2006-02-16 23:46:01 +00001354 /* DWORD is a 4-byte int. If we're on a box where size_t consumes
Thomas Wouters2c98a7b2006-02-17 09:59:00 +00001355 * more than 4 bytes, we need to break it apart. Else (size_t
Tim Peterse564e7f2006-02-16 23:46:01 +00001356 * consumes 4 bytes), C doesn't define what happens if we shift
1357 * right by 32, so we need different code.
1358 */
1359#if SIZEOF_SIZE_T > 4
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001360 size_hi = (DWORD)((offset + m_obj->size) >> 32);
1361 size_lo = (DWORD)((offset + m_obj->size) & 0xFFFFFFFF);
1362 off_hi = (DWORD)(offset >> 32);
1363 off_lo = (DWORD)(offset & 0xFFFFFFFF);
Tim Peterse564e7f2006-02-16 23:46:01 +00001364#else
1365 size_hi = 0;
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001366 size_lo = (DWORD)(offset + m_obj->size);
1367 off_hi = 0;
1368 off_lo = (DWORD)offset;
Tim Peterse564e7f2006-02-16 23:46:01 +00001369#endif
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001370 /* For files, it would be sufficient to pass 0 as size.
1371 For anonymous maps, we have to pass the size explicitly. */
Tim Peters8f9cc292006-02-17 00:00:20 +00001372 m_obj->map_handle = CreateFileMapping(m_obj->file_handle,
1373 NULL,
1374 flProtect,
1375 size_hi,
1376 size_lo,
1377 m_obj->tagname);
Guido van Rossum09fdf072000-03-31 01:17:07 +00001378 if (m_obj->map_handle != NULL) {
Tim Peters8f9cc292006-02-17 00:00:20 +00001379 m_obj->data = (char *) MapViewOfFile(m_obj->map_handle,
1380 dwDesiredAccess,
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001381 off_hi,
1382 off_lo,
Hirokazu Yamamotob0e10c72009-02-28 12:13:07 +00001383 m_obj->size);
Tim Peters23721ee2006-02-16 23:50:16 +00001384 if (m_obj->data != NULL)
1385 return (PyObject *)m_obj;
Hirokazu Yamamoto264fc122009-03-05 14:21:12 +00001386 else {
Tim Peters5ebfd362001-11-13 23:11:19 +00001387 dwErr = GetLastError();
Hirokazu Yamamoto264fc122009-03-05 14:21:12 +00001388 CloseHandle(m_obj->map_handle);
1389 m_obj->map_handle = NULL;
1390 }
Tim Peters23721ee2006-02-16 23:50:16 +00001391 } else
Guido van Rossum09fdf072000-03-31 01:17:07 +00001392 dwErr = GetLastError();
Mark Hammond2cbed002000-07-30 02:22:43 +00001393 Py_DECREF(m_obj);
Guido van Rossum09fdf072000-03-31 01:17:07 +00001394 PyErr_SetFromWindowsErr(dwErr);
Tim Peters23721ee2006-02-16 23:50:16 +00001395 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001396}
Martin v. Löwis6238d2b2002-06-30 15:26:10 +00001397#endif /* MS_WINDOWS */
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001398
Neal Norwitze9ac0bb2006-08-13 18:11:27 +00001399static void
1400setint(PyObject *d, const char *name, long value)
1401{
1402 PyObject *o = PyInt_FromLong(value);
Neal Norwitz5ed49972006-08-13 18:41:15 +00001403 if (o && PyDict_SetItemString(d, name, o) == 0) {
Neal Norwitze9ac0bb2006-08-13 18:11:27 +00001404 Py_DECREF(o);
Neal Norwitz5ed49972006-08-13 18:41:15 +00001405 }
Neal Norwitze9ac0bb2006-08-13 18:11:27 +00001406}
1407
Mark Hammond62b1ab12002-07-23 06:31:15 +00001408PyMODINIT_FUNC
Georg Brandl845c4032008-01-21 14:16:46 +00001409initmmap(void)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001410{
Guido van Rossum09fdf072000-03-31 01:17:07 +00001411 PyObject *dict, *module;
Tim Peters2caf8df2001-01-14 05:05:51 +00001412
Georg Brandl845c4032008-01-21 14:16:46 +00001413 if (PyType_Ready(&mmap_object_type) < 0)
1414 return;
Tim Peters2caf8df2001-01-14 05:05:51 +00001415
Georg Brandl845c4032008-01-21 14:16:46 +00001416 module = Py_InitModule("mmap", NULL);
Neal Norwitz1ac754f2006-01-19 06:09:39 +00001417 if (module == NULL)
1418 return;
Tim Peters8f9cc292006-02-17 00:00:20 +00001419 dict = PyModule_GetDict(module);
Neal Norwitze9ac0bb2006-08-13 18:11:27 +00001420 if (!dict)
1421 return;
Facundo Batistae1396882008-02-17 18:59:29 +00001422 mmap_module_error = PyErr_NewException("mmap.error",
1423 PyExc_EnvironmentError , NULL);
1424 if (mmap_module_error == NULL)
1425 return;
Tim Peters8f9cc292006-02-17 00:00:20 +00001426 PyDict_SetItemString(dict, "error", mmap_module_error);
Georg Brandl845c4032008-01-21 14:16:46 +00001427 PyDict_SetItemString(dict, "mmap", (PyObject*) &mmap_object_type);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001428#ifdef PROT_EXEC
Neal Norwitze9ac0bb2006-08-13 18:11:27 +00001429 setint(dict, "PROT_EXEC", PROT_EXEC);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001430#endif
1431#ifdef PROT_READ
Neal Norwitze9ac0bb2006-08-13 18:11:27 +00001432 setint(dict, "PROT_READ", PROT_READ);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001433#endif
1434#ifdef PROT_WRITE
Neal Norwitze9ac0bb2006-08-13 18:11:27 +00001435 setint(dict, "PROT_WRITE", PROT_WRITE);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001436#endif
1437
1438#ifdef MAP_SHARED
Neal Norwitze9ac0bb2006-08-13 18:11:27 +00001439 setint(dict, "MAP_SHARED", MAP_SHARED);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001440#endif
1441#ifdef MAP_PRIVATE
Neal Norwitze9ac0bb2006-08-13 18:11:27 +00001442 setint(dict, "MAP_PRIVATE", MAP_PRIVATE);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001443#endif
1444#ifdef MAP_DENYWRITE
Neal Norwitze9ac0bb2006-08-13 18:11:27 +00001445 setint(dict, "MAP_DENYWRITE", MAP_DENYWRITE);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001446#endif
1447#ifdef MAP_EXECUTABLE
Neal Norwitze9ac0bb2006-08-13 18:11:27 +00001448 setint(dict, "MAP_EXECUTABLE", MAP_EXECUTABLE);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001449#endif
Neal Norwitz0e6bc8c2006-02-05 05:45:43 +00001450#ifdef MAP_ANONYMOUS
Neal Norwitze9ac0bb2006-08-13 18:11:27 +00001451 setint(dict, "MAP_ANON", MAP_ANONYMOUS);
1452 setint(dict, "MAP_ANONYMOUS", MAP_ANONYMOUS);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001453#endif
1454
Neal Norwitze9ac0bb2006-08-13 18:11:27 +00001455 setint(dict, "PAGESIZE", (long)my_getpagesize());
Andrew M. Kuchling961fe172000-06-03 19:41:42 +00001456
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001457 setint(dict, "ALLOCATIONGRANULARITY", (long)my_getallocationgranularity());
1458
Neal Norwitze9ac0bb2006-08-13 18:11:27 +00001459 setint(dict, "ACCESS_READ", ACCESS_READ);
1460 setint(dict, "ACCESS_WRITE", ACCESS_WRITE);
1461 setint(dict, "ACCESS_COPY", ACCESS_COPY);
Tim Peters5ebfd362001-11-13 23:11:19 +00001462}