blob: d191c1e6fb122ed47e6113834052508f06db3913 [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 Yamamotoec5294f2009-03-05 14:30:13 +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 Yamamotoec5294f2009-03-05 14:30:13 +0000150 if (self->map_handle != NULL) {
Tim Peters8f9cc292006-02-17 00:00:20 +0000151 CloseHandle(self->map_handle);
Hirokazu Yamamotoec5294f2009-03-05 14:30:13 +0000152 self->map_handle = NULL;
Mark Hammond071864a2000-07-30 02:46:26 +0000153 }
154 if (self->file_handle != INVALID_HANDLE_VALUE) {
Tim Peters8f9cc292006-02-17 00:00:20 +0000155 CloseHandle(self->file_handle);
Mark Hammond071864a2000-07-30 02:46:26 +0000156 self->file_handle = INVALID_HANDLE_VALUE;
157 }
Martin v. Löwis6238d2b2002-06-30 15:26:10 +0000158#endif /* MS_WINDOWS */
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000159
160#ifdef UNIX
Neal Norwitz6eac2002005-11-02 05:36:37 +0000161 (void) close(self->fd);
162 self->fd = -1;
Neal Norwitze604c022003-01-10 20:52:16 +0000163 if (self->data != NULL) {
164 munmap(self->data, self->size);
165 self->data = NULL;
166 }
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000167#endif
168
Tim Peters8f9cc292006-02-17 00:00:20 +0000169 Py_INCREF(Py_None);
Tim Peters23721ee2006-02-16 23:50:16 +0000170 return Py_None;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000171}
172
Martin v. Löwis6238d2b2002-06-30 15:26:10 +0000173#ifdef MS_WINDOWS
Guido van Rossum09fdf072000-03-31 01:17:07 +0000174#define CHECK_VALID(err) \
175do { \
Hirokazu Yamamotoec5294f2009-03-05 14:30:13 +0000176 if (self->map_handle == NULL) { \
Tim Peters8f9cc292006-02-17 00:00:20 +0000177 PyErr_SetString(PyExc_ValueError, "mmap closed or invalid"); \
Guido van Rossum09fdf072000-03-31 01:17:07 +0000178 return err; \
179 } \
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000180} while (0)
Martin v. Löwis6238d2b2002-06-30 15:26:10 +0000181#endif /* MS_WINDOWS */
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000182
183#ifdef UNIX
Guido van Rossum09fdf072000-03-31 01:17:07 +0000184#define CHECK_VALID(err) \
185do { \
186 if (self->data == NULL) { \
Tim Peters8f9cc292006-02-17 00:00:20 +0000187 PyErr_SetString(PyExc_ValueError, "mmap closed or invalid"); \
Guido van Rossum09fdf072000-03-31 01:17:07 +0000188 return err; \
189 } \
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000190} while (0)
191#endif /* UNIX */
192
193static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000194mmap_read_byte_method(mmap_object *self,
Georg Brandl96a8c392006-05-29 21:04:52 +0000195 PyObject *unused)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000196{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000197 CHECK_VALID(NULL);
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000198 if (self->pos < self->size) {
Tim Petersd6283b82001-05-09 18:48:26 +0000199 char value = self->data[self->pos];
Guido van Rossum09fdf072000-03-31 01:17:07 +0000200 self->pos += 1;
Tim Petersd6283b82001-05-09 18:48:26 +0000201 return Py_BuildValue("c", value);
Guido van Rossum09fdf072000-03-31 01:17:07 +0000202 } else {
Tim Peters8f9cc292006-02-17 00:00:20 +0000203 PyErr_SetString(PyExc_ValueError, "read byte out of range");
Guido van Rossum09fdf072000-03-31 01:17:07 +0000204 return NULL;
205 }
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000206}
207
208static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000209mmap_read_line_method(mmap_object *self,
Georg Brandl96a8c392006-05-29 21:04:52 +0000210 PyObject *unused)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000211{
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000212 char *start = self->data+self->pos;
213 char *eof = self->data+self->size;
214 char *eol;
215 PyObject *result;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000216
Guido van Rossum09fdf072000-03-31 01:17:07 +0000217 CHECK_VALID(NULL);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000218
Fred Drake56a87a02000-04-04 18:17:35 +0000219 eol = memchr(start, '\n', self->size - self->pos);
220 if (!eol)
221 eol = eof;
222 else
223 ++eol; /* we're interested in the position after the
224 newline. */
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000225 result = PyString_FromStringAndSize(start, (eol - start));
Guido van Rossum09fdf072000-03-31 01:17:07 +0000226 self->pos += (eol - start);
Tim Peters23721ee2006-02-16 23:50:16 +0000227 return result;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000228}
229
230static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000231mmap_read_method(mmap_object *self,
232 PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000233{
Martin v. Löwisad0a4622006-02-16 14:30:23 +0000234 Py_ssize_t num_bytes;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000235 PyObject *result;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000236
Guido van Rossum09fdf072000-03-31 01:17:07 +0000237 CHECK_VALID(NULL);
Martin v. Löwisad0a4622006-02-16 14:30:23 +0000238 if (!PyArg_ParseTuple(args, "n:read", &num_bytes))
Guido van Rossum09fdf072000-03-31 01:17:07 +0000239 return(NULL);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000240
Guido van Rossum09fdf072000-03-31 01:17:07 +0000241 /* silently 'adjust' out-of-range requests */
Neal Norwitze7d8be82008-07-31 17:17:14 +0000242 if (num_bytes > self->size - self->pos) {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000243 num_bytes -= (self->pos+num_bytes) - self->size;
244 }
245 result = Py_BuildValue("s#", self->data+self->pos, num_bytes);
Tim Petersec0a5f02006-02-16 23:47:20 +0000246 self->pos += num_bytes;
Tim Peters23721ee2006-02-16 23:50:16 +0000247 return result;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000248}
249
250static PyObject *
Andrew M. Kuchling5c60bfc2008-01-19 18:18:41 +0000251mmap_gfind(mmap_object *self,
252 PyObject *args,
253 int reverse)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000254{
Martin v. Löwisad0a4622006-02-16 14:30:23 +0000255 Py_ssize_t start = self->pos;
Neal Norwitz739a3c42008-01-26 20:24:36 +0000256 Py_ssize_t end = self->size;
257 const char *needle;
Martin v. Löwiscfe7e092006-02-17 06:59:14 +0000258 Py_ssize_t len;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000259
Guido van Rossum09fdf072000-03-31 01:17:07 +0000260 CHECK_VALID(NULL);
Andrew M. Kuchling5c60bfc2008-01-19 18:18:41 +0000261 if (!PyArg_ParseTuple(args, reverse ? "s#|nn:rfind" : "s#|nn:find",
262 &needle, &len, &start, &end)) {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000263 return NULL;
264 } else {
Neal Norwitz739a3c42008-01-26 20:24:36 +0000265 const char *p, *start_p, *end_p;
Neal Norwitze1027f92008-01-27 07:37:38 +0000266 int sign = reverse ? -1 : 1;
Greg Stein834f4dd2001-05-14 09:32:26 +0000267
268 if (start < 0)
Tim Peters5ebfd362001-11-13 23:11:19 +0000269 start += self->size;
Greg Stein834f4dd2001-05-14 09:32:26 +0000270 if (start < 0)
Tim Peters5ebfd362001-11-13 23:11:19 +0000271 start = 0;
Tim Petersd401edd2001-05-14 23:19:12 +0000272 else if ((size_t)start > self->size)
Tim Peters5ebfd362001-11-13 23:11:19 +0000273 start = self->size;
Greg Stein834f4dd2001-05-14 09:32:26 +0000274
Andrew M. Kuchling5c60bfc2008-01-19 18:18:41 +0000275 if (end < 0)
276 end += self->size;
277 if (end < 0)
278 end = 0;
279 else if ((size_t)end > self->size)
280 end = self->size;
281
Neal Norwitz739a3c42008-01-26 20:24:36 +0000282 start_p = self->data + start;
283 end_p = self->data + end;
Andrew M. Kuchling5c60bfc2008-01-19 18:18:41 +0000284
Neal Norwitz739a3c42008-01-26 20:24:36 +0000285 for (p = (reverse ? end_p - len : start_p);
286 (p >= start_p) && (p + len <= end_p); p += sign) {
Martin v. Löwiscfe7e092006-02-17 06:59:14 +0000287 Py_ssize_t i;
Tim Petersc9ffa062002-03-08 05:43:32 +0000288 for (i = 0; i < len && needle[i] == p[i]; ++i)
289 /* nothing */;
290 if (i == len) {
Martin v. Löwiscfe7e092006-02-17 06:59:14 +0000291 return PyInt_FromSsize_t(p - self->data);
Guido van Rossum09fdf072000-03-31 01:17:07 +0000292 }
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000293 }
Martin v. Löwiscfe7e092006-02-17 06:59:14 +0000294 return PyInt_FromLong(-1);
Guido van Rossum09fdf072000-03-31 01:17:07 +0000295 }
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000296}
297
Andrew M. Kuchling5c60bfc2008-01-19 18:18:41 +0000298static PyObject *
299mmap_find_method(mmap_object *self,
300 PyObject *args)
301{
302 return mmap_gfind(self, args, 0);
303}
304
305static PyObject *
306mmap_rfind_method(mmap_object *self,
307 PyObject *args)
308{
309 return mmap_gfind(self, args, 1);
310}
311
Tim Petersec0a5f02006-02-16 23:47:20 +0000312static int
Tim Peters5ebfd362001-11-13 23:11:19 +0000313is_writeable(mmap_object *self)
314{
315 if (self->access != ACCESS_READ)
Tim Petersec0a5f02006-02-16 23:47:20 +0000316 return 1;
Tim Peters5ebfd362001-11-13 23:11:19 +0000317 PyErr_Format(PyExc_TypeError, "mmap can't modify a readonly memory map.");
318 return 0;
319}
320
Tim Petersec0a5f02006-02-16 23:47:20 +0000321static int
Tim Peters5ebfd362001-11-13 23:11:19 +0000322is_resizeable(mmap_object *self)
323{
324 if ((self->access == ACCESS_WRITE) || (self->access == ACCESS_DEFAULT))
Tim Petersec0a5f02006-02-16 23:47:20 +0000325 return 1;
326 PyErr_Format(PyExc_TypeError,
Tim Peters5ebfd362001-11-13 23:11:19 +0000327 "mmap can't resize a readonly or copy-on-write memory map.");
328 return 0;
329}
330
331
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000332static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000333mmap_write_method(mmap_object *self,
334 PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000335{
Martin v. Löwiscfe7e092006-02-17 06:59:14 +0000336 Py_ssize_t length;
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000337 char *data;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000338
Guido van Rossum09fdf072000-03-31 01:17:07 +0000339 CHECK_VALID(NULL);
Tim Peters8f9cc292006-02-17 00:00:20 +0000340 if (!PyArg_ParseTuple(args, "s#:write", &data, &length))
Guido van Rossum09fdf072000-03-31 01:17:07 +0000341 return(NULL);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000342
Tim Peters5ebfd362001-11-13 23:11:19 +0000343 if (!is_writeable(self))
344 return NULL;
345
Guido van Rossum09fdf072000-03-31 01:17:07 +0000346 if ((self->pos + length) > self->size) {
Tim Peters8f9cc292006-02-17 00:00:20 +0000347 PyErr_SetString(PyExc_ValueError, "data out of range");
Guido van Rossum09fdf072000-03-31 01:17:07 +0000348 return NULL;
349 }
Tim Peters8f9cc292006-02-17 00:00:20 +0000350 memcpy(self->data+self->pos, data, length);
Guido van Rossum09fdf072000-03-31 01:17:07 +0000351 self->pos = self->pos+length;
Tim Peters8f9cc292006-02-17 00:00:20 +0000352 Py_INCREF(Py_None);
Tim Peters23721ee2006-02-16 23:50:16 +0000353 return Py_None;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000354}
355
356static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000357mmap_write_byte_method(mmap_object *self,
358 PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000359{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000360 char value;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000361
Guido van Rossum09fdf072000-03-31 01:17:07 +0000362 CHECK_VALID(NULL);
Tim Peters8f9cc292006-02-17 00:00:20 +0000363 if (!PyArg_ParseTuple(args, "c:write_byte", &value))
Guido van Rossum09fdf072000-03-31 01:17:07 +0000364 return(NULL);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000365
Tim Peters5ebfd362001-11-13 23:11:19 +0000366 if (!is_writeable(self))
367 return NULL;
Hirokazu Yamamotoe363fa02009-02-28 11:39:45 +0000368
369 if (self->pos < self->size) {
370 *(self->data+self->pos) = value;
371 self->pos += 1;
372 Py_INCREF(Py_None);
373 return Py_None;
374 }
375 else {
376 PyErr_SetString(PyExc_ValueError, "write byte out of range");
377 return NULL;
378 }
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000379}
Tim Petersec0a5f02006-02-16 23:47:20 +0000380
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000381static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000382mmap_size_method(mmap_object *self,
Georg Brandl96a8c392006-05-29 21:04:52 +0000383 PyObject *unused)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000384{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000385 CHECK_VALID(NULL);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000386
Martin v. Löwis6238d2b2002-06-30 15:26:10 +0000387#ifdef MS_WINDOWS
Mark Hammond071864a2000-07-30 02:46:26 +0000388 if (self->file_handle != INVALID_HANDLE_VALUE) {
Martin v. Löwis15186072006-02-18 12:38:35 +0000389 DWORD low,high;
390 PY_LONG_LONG size;
391 low = GetFileSize(self->file_handle, &high);
392 if (low == INVALID_FILE_SIZE) {
393 /* It might be that the function appears to have failed,
394 when indeed its size equals INVALID_FILE_SIZE */
395 DWORD error = GetLastError();
396 if (error != NO_ERROR)
397 return PyErr_SetFromWindowsErr(error);
398 }
399 if (!high && low < LONG_MAX)
400 return PyInt_FromLong((long)low);
401 size = (((PY_LONG_LONG)high)<<32) + low;
402 return PyLong_FromLongLong(size);
Guido van Rossum09fdf072000-03-31 01:17:07 +0000403 } else {
Martin v. Löwis15186072006-02-18 12:38:35 +0000404 return PyInt_FromSsize_t(self->size);
Guido van Rossum09fdf072000-03-31 01:17:07 +0000405 }
Martin v. Löwis6238d2b2002-06-30 15:26:10 +0000406#endif /* MS_WINDOWS */
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000407
408#ifdef UNIX
Andrew M. Kuchling7b9fb922000-06-17 22:41:22 +0000409 {
410 struct stat buf;
411 if (-1 == fstat(self->fd, &buf)) {
412 PyErr_SetFromErrno(mmap_module_error);
413 return NULL;
414 }
Martin v. Löwis15186072006-02-18 12:38:35 +0000415 return PyInt_FromSsize_t(buf.st_size);
Andrew M. Kuchling7b9fb922000-06-17 22:41:22 +0000416 }
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000417#endif /* UNIX */
418}
419
420/* This assumes that you want the entire file mapped,
421 / and when recreating the map will make the new file
422 / have the new size
423 /
424 / Is this really necessary? This could easily be done
425 / from python by just closing and re-opening with the
426 / new size?
427 */
428
429static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000430mmap_resize_method(mmap_object *self,
431 PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000432{
Martin v. Löwiscfe7e092006-02-17 06:59:14 +0000433 Py_ssize_t new_size;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000434 CHECK_VALID(NULL);
Martin v. Löwiscfe7e092006-02-17 06:59:14 +0000435 if (!PyArg_ParseTuple(args, "n:resize", &new_size) ||
Tim Peters5ebfd362001-11-13 23:11:19 +0000436 !is_resizeable(self)) {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000437 return NULL;
Martin v. Löwis6238d2b2002-06-30 15:26:10 +0000438#ifdef MS_WINDOWS
Tim Petersec0a5f02006-02-16 23:47:20 +0000439 } else {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000440 DWORD dwErrCode = 0;
Travis E. Oliphant8feafab2007-10-23 02:40:56 +0000441 DWORD off_hi, off_lo, newSizeLow, newSizeHigh;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000442 /* First, unmap the file view */
Tim Peters8f9cc292006-02-17 00:00:20 +0000443 UnmapViewOfFile(self->data);
Hirokazu Yamamotoec5294f2009-03-05 14:30:13 +0000444 self->data = NULL;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000445 /* Close the mapping object */
Tim Peters8f9cc292006-02-17 00:00:20 +0000446 CloseHandle(self->map_handle);
Hirokazu Yamamotoec5294f2009-03-05 14:30:13 +0000447 self->map_handle = NULL;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000448 /* Move to the desired EOF position */
Martin v. Löwis15186072006-02-18 12:38:35 +0000449#if SIZEOF_SIZE_T > 4
Travis E. Oliphant8feafab2007-10-23 02:40:56 +0000450 newSizeHigh = (DWORD)((self->offset + new_size) >> 32);
451 newSizeLow = (DWORD)((self->offset + new_size) & 0xFFFFFFFF);
452 off_hi = (DWORD)(self->offset >> 32);
453 off_lo = (DWORD)(self->offset & 0xFFFFFFFF);
Martin v. Löwis15186072006-02-18 12:38:35 +0000454#else
455 newSizeHigh = 0;
Hirokazu Yamamoto978bacd2009-02-18 15:11:55 +0000456 newSizeLow = (DWORD)(self->offset + new_size);
Travis E. Oliphant8feafab2007-10-23 02:40:56 +0000457 off_hi = 0;
458 off_lo = (DWORD)self->offset;
Martin v. Löwis15186072006-02-18 12:38:35 +0000459#endif
Tim Peters8f9cc292006-02-17 00:00:20 +0000460 SetFilePointer(self->file_handle,
Martin v. Löwis15186072006-02-18 12:38:35 +0000461 newSizeLow, &newSizeHigh, FILE_BEGIN);
Guido van Rossum09fdf072000-03-31 01:17:07 +0000462 /* Change the size of the file */
Tim Peters8f9cc292006-02-17 00:00:20 +0000463 SetEndOfFile(self->file_handle);
Guido van Rossum09fdf072000-03-31 01:17:07 +0000464 /* Create another mapping object and remap the file view */
Tim Peters8f9cc292006-02-17 00:00:20 +0000465 self->map_handle = CreateFileMapping(
Mark Hammond071864a2000-07-30 02:46:26 +0000466 self->file_handle,
Guido van Rossum09fdf072000-03-31 01:17:07 +0000467 NULL,
468 PAGE_READWRITE,
Travis E. Oliphant8feafab2007-10-23 02:40:56 +0000469 0,
470 0,
Guido van Rossum09fdf072000-03-31 01:17:07 +0000471 self->tagname);
472 if (self->map_handle != NULL) {
Tim Peters8f9cc292006-02-17 00:00:20 +0000473 self->data = (char *) MapViewOfFile(self->map_handle,
474 FILE_MAP_WRITE,
Travis E. Oliphant8feafab2007-10-23 02:40:56 +0000475 off_hi,
476 off_lo,
477 new_size);
Guido van Rossum09fdf072000-03-31 01:17:07 +0000478 if (self->data != NULL) {
479 self->size = new_size;
Tim Peters8f9cc292006-02-17 00:00:20 +0000480 Py_INCREF(Py_None);
Guido van Rossum09fdf072000-03-31 01:17:07 +0000481 return Py_None;
482 } else {
483 dwErrCode = GetLastError();
Hirokazu Yamamotoec5294f2009-03-05 14:30:13 +0000484 CloseHandle(self->map_handle);
485 self->map_handle = NULL;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000486 }
487 } else {
488 dwErrCode = GetLastError();
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000489 }
Guido van Rossum09fdf072000-03-31 01:17:07 +0000490 PyErr_SetFromWindowsErr(dwErrCode);
Tim Peters23721ee2006-02-16 23:50:16 +0000491 return NULL;
Martin v. Löwis6238d2b2002-06-30 15:26:10 +0000492#endif /* MS_WINDOWS */
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000493
494#ifdef UNIX
Tim Petersec0a5f02006-02-16 23:47:20 +0000495#ifndef HAVE_MREMAP
Tim Peters5ebfd362001-11-13 23:11:19 +0000496 } else {
497 PyErr_SetString(PyExc_SystemError,
498 "mmap: resizing not available--no mremap()");
499 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000500#else
Tim Peters5ebfd362001-11-13 23:11:19 +0000501 } else {
Armin Rigo335ffe82005-09-20 19:04:02 +0000502 void *newmap;
503
Hirokazu Yamamoto978bacd2009-02-18 15:11:55 +0000504 if (ftruncate(self->fd, self->offset + new_size) == -1) {
Georg Brandl38387b82005-08-24 07:17:40 +0000505 PyErr_SetFromErrno(mmap_module_error);
506 return NULL;
507 }
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000508
Andrew M. Kuchling6fef30e2000-06-18 14:51:21 +0000509#ifdef MREMAP_MAYMOVE
Tim Peters5ebfd362001-11-13 23:11:19 +0000510 newmap = mremap(self->data, self->size, new_size, MREMAP_MAYMOVE);
Andrew M. Kuchling6fef30e2000-06-18 14:51:21 +0000511#else
Tim Peters5ebfd362001-11-13 23:11:19 +0000512 newmap = mremap(self->data, self->size, new_size, 0);
Andrew M. Kuchling6fef30e2000-06-18 14:51:21 +0000513#endif
Tim Petersec0a5f02006-02-16 23:47:20 +0000514 if (newmap == (void *)-1)
Tim Peters5ebfd362001-11-13 23:11:19 +0000515 {
516 PyErr_SetFromErrno(mmap_module_error);
517 return NULL;
518 }
519 self->data = newmap;
520 self->size = new_size;
521 Py_INCREF(Py_None);
522 return Py_None;
Andrew M. Kuchling6fef30e2000-06-18 14:51:21 +0000523#endif /* HAVE_MREMAP */
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000524#endif /* UNIX */
Tim Peters5ebfd362001-11-13 23:11:19 +0000525 }
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000526}
527
528static PyObject *
Georg Brandl96a8c392006-05-29 21:04:52 +0000529mmap_tell_method(mmap_object *self, PyObject *unused)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000530{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000531 CHECK_VALID(NULL);
Neal Norwitz670f8752006-08-22 13:56:56 +0000532 return PyInt_FromSize_t(self->pos);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000533}
534
535static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000536mmap_flush_method(mmap_object *self, PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000537{
Martin v. Löwisad0a4622006-02-16 14:30:23 +0000538 Py_ssize_t offset = 0;
539 Py_ssize_t size = self->size;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000540 CHECK_VALID(NULL);
Tim Petersf2882952006-02-17 01:07:39 +0000541 if (!PyArg_ParseTuple(args, "|nn:flush", &offset, &size))
Guido van Rossum09fdf072000-03-31 01:17:07 +0000542 return NULL;
Tim Petersf2882952006-02-17 01:07:39 +0000543 if ((size_t)(offset + size) > self->size) {
Tim Peters8f9cc292006-02-17 00:00:20 +0000544 PyErr_SetString(PyExc_ValueError, "flush values out of range");
Guido van Rossum09fdf072000-03-31 01:17:07 +0000545 return NULL;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000546 }
Neal Norwitz448654f2008-01-27 07:36:03 +0000547#ifdef MS_WINDOWS
548 return PyInt_FromLong((long) FlushViewOfFile(self->data+offset, size));
549#elif defined(UNIX)
550 /* XXX semantics of return value? */
551 /* XXX flags for msync? */
552 if (-1 == msync(self->data + offset, size, MS_SYNC)) {
553 PyErr_SetFromErrno(mmap_module_error);
554 return NULL;
555 }
556 return PyInt_FromLong(0);
557#else
558 PyErr_SetString(PyExc_ValueError, "flush not supported on this system");
559 return NULL;
560#endif
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000561}
562
563static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000564mmap_seek_method(mmap_object *self, PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000565{
Martin v. Löwiscfe7e092006-02-17 06:59:14 +0000566 Py_ssize_t dist;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000567 int how=0;
568 CHECK_VALID(NULL);
Martin v. Löwiscfe7e092006-02-17 06:59:14 +0000569 if (!PyArg_ParseTuple(args, "n|i:seek", &dist, &how))
Tim Peters8f9cc292006-02-17 00:00:20 +0000570 return NULL;
571 else {
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000572 size_t where;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000573 switch (how) {
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000574 case 0: /* relative to start */
575 if (dist < 0)
576 goto onoutofrange;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000577 where = dist;
578 break;
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000579 case 1: /* relative to current position */
Martin v. Löwiscfe7e092006-02-17 06:59:14 +0000580 if ((Py_ssize_t)self->pos + dist < 0)
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000581 goto onoutofrange;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000582 where = self->pos + dist;
583 break;
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000584 case 2: /* relative to end */
Martin v. Löwiscfe7e092006-02-17 06:59:14 +0000585 if ((Py_ssize_t)self->size + dist < 0)
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000586 goto onoutofrange;
587 where = self->size + dist;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000588 break;
589 default:
Tim Peters8f9cc292006-02-17 00:00:20 +0000590 PyErr_SetString(PyExc_ValueError, "unknown seek type");
Guido van Rossum09fdf072000-03-31 01:17:07 +0000591 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000592 }
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000593 if (where > self->size)
594 goto onoutofrange;
595 self->pos = where;
Tim Peters8f9cc292006-02-17 00:00:20 +0000596 Py_INCREF(Py_None);
Tim Peters23721ee2006-02-16 23:50:16 +0000597 return Py_None;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000598 }
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000599
Tim Peters5ebfd362001-11-13 23:11:19 +0000600 onoutofrange:
Tim Peters8f9cc292006-02-17 00:00:20 +0000601 PyErr_SetString(PyExc_ValueError, "seek out of range");
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000602 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000603}
604
605static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000606mmap_move_method(mmap_object *self, PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000607{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000608 unsigned long dest, src, count;
609 CHECK_VALID(NULL);
Tim Peters8f9cc292006-02-17 00:00:20 +0000610 if (!PyArg_ParseTuple(args, "kkk:move", &dest, &src, &count) ||
Tim Peters5ebfd362001-11-13 23:11:19 +0000611 !is_writeable(self)) {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000612 return NULL;
613 } else {
614 /* bounds check the values */
Hirokazu Yamamoto60098042009-03-31 13:22:01 +0000615 unsigned long pos = src > dest ? src : dest;
616 if (self->size >= pos && count > self->size - pos) {
Tim Peters8f9cc292006-02-17 00:00:20 +0000617 PyErr_SetString(PyExc_ValueError,
618 "source or destination out of range");
Guido van Rossum09fdf072000-03-31 01:17:07 +0000619 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000620 } else {
Tim Peters8f9cc292006-02-17 00:00:20 +0000621 memmove(self->data+dest, self->data+src, count);
622 Py_INCREF(Py_None);
Guido van Rossum09fdf072000-03-31 01:17:07 +0000623 return Py_None;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000624 }
Guido van Rossum09fdf072000-03-31 01:17:07 +0000625 }
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000626}
627
628static struct PyMethodDef mmap_object_methods[] = {
Georg Brandl96a8c392006-05-29 21:04:52 +0000629 {"close", (PyCFunction) mmap_close_method, METH_NOARGS},
Martin v. Löwis43b936d2002-01-17 23:15:58 +0000630 {"find", (PyCFunction) mmap_find_method, METH_VARARGS},
Andrew M. Kuchling5c60bfc2008-01-19 18:18:41 +0000631 {"rfind", (PyCFunction) mmap_rfind_method, METH_VARARGS},
Martin v. Löwis43b936d2002-01-17 23:15:58 +0000632 {"flush", (PyCFunction) mmap_flush_method, METH_VARARGS},
633 {"move", (PyCFunction) mmap_move_method, METH_VARARGS},
634 {"read", (PyCFunction) mmap_read_method, METH_VARARGS},
Georg Brandl96a8c392006-05-29 21:04:52 +0000635 {"read_byte", (PyCFunction) mmap_read_byte_method, METH_NOARGS},
636 {"readline", (PyCFunction) mmap_read_line_method, METH_NOARGS},
Martin v. Löwis43b936d2002-01-17 23:15:58 +0000637 {"resize", (PyCFunction) mmap_resize_method, METH_VARARGS},
638 {"seek", (PyCFunction) mmap_seek_method, METH_VARARGS},
Georg Brandl96a8c392006-05-29 21:04:52 +0000639 {"size", (PyCFunction) mmap_size_method, METH_NOARGS},
640 {"tell", (PyCFunction) mmap_tell_method, METH_NOARGS},
Martin v. Löwis43b936d2002-01-17 23:15:58 +0000641 {"write", (PyCFunction) mmap_write_method, METH_VARARGS},
642 {"write_byte", (PyCFunction) mmap_write_byte_method, METH_VARARGS},
Guido van Rossum09fdf072000-03-31 01:17:07 +0000643 {NULL, NULL} /* sentinel */
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000644};
645
646/* Functions for treating an mmap'ed file as a buffer */
647
Martin v. Löwis18e16552006-02-15 17:27:45 +0000648static Py_ssize_t
649mmap_buffer_getreadbuf(mmap_object *self, Py_ssize_t index, const void **ptr)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000650{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000651 CHECK_VALID(-1);
Tim Peters8f9cc292006-02-17 00:00:20 +0000652 if (index != 0) {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000653 PyErr_SetString(PyExc_SystemError,
654 "Accessing non-existent mmap segment");
655 return -1;
656 }
657 *ptr = self->data;
658 return self->size;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000659}
660
Martin v. Löwis18e16552006-02-15 17:27:45 +0000661static Py_ssize_t
662mmap_buffer_getwritebuf(mmap_object *self, Py_ssize_t index, const void **ptr)
Tim Petersec0a5f02006-02-16 23:47:20 +0000663{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000664 CHECK_VALID(-1);
Tim Peters8f9cc292006-02-17 00:00:20 +0000665 if (index != 0) {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000666 PyErr_SetString(PyExc_SystemError,
667 "Accessing non-existent mmap segment");
668 return -1;
669 }
Tim Peters5ebfd362001-11-13 23:11:19 +0000670 if (!is_writeable(self))
671 return -1;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000672 *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_getsegcount(mmap_object *self, Py_ssize_t *lenp)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000678{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000679 CHECK_VALID(-1);
Tim Petersec0a5f02006-02-16 23:47:20 +0000680 if (lenp)
Guido van Rossum09fdf072000-03-31 01:17:07 +0000681 *lenp = self->size;
682 return 1;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000683}
684
Martin v. Löwis18e16552006-02-15 17:27:45 +0000685static Py_ssize_t
686mmap_buffer_getcharbuffer(mmap_object *self, Py_ssize_t index, const void **ptr)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000687{
Tim Peters8f9cc292006-02-17 00:00:20 +0000688 if (index != 0) {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000689 PyErr_SetString(PyExc_SystemError,
690 "accessing non-existent buffer segment");
691 return -1;
692 }
693 *ptr = (const char *)self->data;
694 return self->size;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000695}
696
Martin v. Löwis18e16552006-02-15 17:27:45 +0000697static Py_ssize_t
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000698mmap_length(mmap_object *self)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000699{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000700 CHECK_VALID(-1);
701 return self->size;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000702}
703
704static PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000705mmap_item(mmap_object *self, Py_ssize_t i)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000706{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000707 CHECK_VALID(NULL);
Guido van Rossumce8e1dc2000-07-01 00:51:51 +0000708 if (i < 0 || (size_t)i >= self->size) {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000709 PyErr_SetString(PyExc_IndexError, "mmap index out of range");
710 return NULL;
711 }
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000712 return PyString_FromStringAndSize(self->data + i, 1);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000713}
714
715static PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000716mmap_slice(mmap_object *self, Py_ssize_t ilow, Py_ssize_t ihigh)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000717{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000718 CHECK_VALID(NULL);
719 if (ilow < 0)
720 ilow = 0;
Guido van Rossumce8e1dc2000-07-01 00:51:51 +0000721 else if ((size_t)ilow > self->size)
Guido van Rossum09fdf072000-03-31 01:17:07 +0000722 ilow = self->size;
723 if (ihigh < 0)
724 ihigh = 0;
725 if (ihigh < ilow)
726 ihigh = ilow;
Guido van Rossumce8e1dc2000-07-01 00:51:51 +0000727 else if ((size_t)ihigh > self->size)
Guido van Rossum09fdf072000-03-31 01:17:07 +0000728 ihigh = self->size;
Tim Petersec0a5f02006-02-16 23:47:20 +0000729
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000730 return PyString_FromStringAndSize(self->data + ilow, ihigh-ilow);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000731}
732
733static PyObject *
Thomas Wouters3ccec682007-08-28 15:28:19 +0000734mmap_subscript(mmap_object *self, PyObject *item)
735{
736 CHECK_VALID(NULL);
737 if (PyIndex_Check(item)) {
738 Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
739 if (i == -1 && PyErr_Occurred())
740 return NULL;
741 if (i < 0)
742 i += self->size;
Hirokazu Yamamoto978bacd2009-02-18 15:11:55 +0000743 if (i < 0 || (size_t)i >= self->size) {
Thomas Wouters3ccec682007-08-28 15:28:19 +0000744 PyErr_SetString(PyExc_IndexError,
745 "mmap index out of range");
746 return NULL;
747 }
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000748 return PyString_FromStringAndSize(self->data + i, 1);
Thomas Wouters3ccec682007-08-28 15:28:19 +0000749 }
750 else if (PySlice_Check(item)) {
751 Py_ssize_t start, stop, step, slicelen;
752
753 if (PySlice_GetIndicesEx((PySliceObject *)item, self->size,
754 &start, &stop, &step, &slicelen) < 0) {
755 return NULL;
756 }
757
758 if (slicelen <= 0)
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000759 return PyString_FromStringAndSize("", 0);
Thomas Wouters3ccec682007-08-28 15:28:19 +0000760 else if (step == 1)
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000761 return PyString_FromStringAndSize(self->data + start,
Thomas Wouters3ccec682007-08-28 15:28:19 +0000762 slicelen);
763 else {
764 char *result_buf = (char *)PyMem_Malloc(slicelen);
765 Py_ssize_t cur, i;
766 PyObject *result;
767
768 if (result_buf == NULL)
769 return PyErr_NoMemory();
770 for (cur = start, i = 0; i < slicelen;
771 cur += step, i++) {
772 result_buf[i] = self->data[cur];
773 }
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000774 result = PyString_FromStringAndSize(result_buf,
Thomas Wouters3ccec682007-08-28 15:28:19 +0000775 slicelen);
776 PyMem_Free(result_buf);
777 return result;
778 }
779 }
780 else {
781 PyErr_SetString(PyExc_TypeError,
782 "mmap indices must be integers");
783 return NULL;
784 }
785}
786
787static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000788mmap_concat(mmap_object *self, PyObject *bb)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000789{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000790 CHECK_VALID(NULL);
791 PyErr_SetString(PyExc_SystemError,
792 "mmaps don't support concatenation");
793 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000794}
795
796static PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000797mmap_repeat(mmap_object *self, Py_ssize_t n)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000798{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000799 CHECK_VALID(NULL);
800 PyErr_SetString(PyExc_SystemError,
801 "mmaps don't support repeat operation");
802 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000803}
804
805static int
Martin v. Löwis18e16552006-02-15 17:27:45 +0000806mmap_ass_slice(mmap_object *self, Py_ssize_t ilow, Py_ssize_t ihigh, PyObject *v)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000807{
Guido van Rossum36d4f8b2000-04-10 21:34:37 +0000808 const char *buf;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000809
Guido van Rossum09fdf072000-03-31 01:17:07 +0000810 CHECK_VALID(-1);
811 if (ilow < 0)
812 ilow = 0;
Guido van Rossumce8e1dc2000-07-01 00:51:51 +0000813 else if ((size_t)ilow > self->size)
Guido van Rossum09fdf072000-03-31 01:17:07 +0000814 ilow = self->size;
815 if (ihigh < 0)
816 ihigh = 0;
817 if (ihigh < ilow)
818 ihigh = ilow;
Guido van Rossumce8e1dc2000-07-01 00:51:51 +0000819 else if ((size_t)ihigh > self->size)
Guido van Rossum09fdf072000-03-31 01:17:07 +0000820 ihigh = self->size;
Tim Petersec0a5f02006-02-16 23:47:20 +0000821
Thomas Wouters1baac722001-07-16 15:47:36 +0000822 if (v == NULL) {
823 PyErr_SetString(PyExc_TypeError,
Tim Peters5ebfd362001-11-13 23:11:19 +0000824 "mmap object doesn't support slice deletion");
Thomas Wouters1baac722001-07-16 15:47:36 +0000825 return -1;
826 }
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000827 if (! (PyString_Check(v)) ) {
Tim Petersec0a5f02006-02-16 23:47:20 +0000828 PyErr_SetString(PyExc_IndexError,
Guido van Rossum09fdf072000-03-31 01:17:07 +0000829 "mmap slice assignment must be a string");
830 return -1;
831 }
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000832 if (PyString_Size(v) != (ihigh - ilow)) {
Tim Petersec0a5f02006-02-16 23:47:20 +0000833 PyErr_SetString(PyExc_IndexError,
Guido van Rossum09fdf072000-03-31 01:17:07 +0000834 "mmap slice assignment is wrong size");
835 return -1;
836 }
Tim Peters5ebfd362001-11-13 23:11:19 +0000837 if (!is_writeable(self))
838 return -1;
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000839 buf = PyString_AsString(v);
Guido van Rossum09fdf072000-03-31 01:17:07 +0000840 memcpy(self->data + ilow, buf, ihigh-ilow);
841 return 0;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000842}
843
844static int
Martin v. Löwis18e16552006-02-15 17:27:45 +0000845mmap_ass_item(mmap_object *self, Py_ssize_t i, PyObject *v)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000846{
Guido van Rossum36d4f8b2000-04-10 21:34:37 +0000847 const char *buf;
Tim Petersec0a5f02006-02-16 23:47:20 +0000848
Guido van Rossum09fdf072000-03-31 01:17:07 +0000849 CHECK_VALID(-1);
Guido van Rossumce8e1dc2000-07-01 00:51:51 +0000850 if (i < 0 || (size_t)i >= self->size) {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000851 PyErr_SetString(PyExc_IndexError, "mmap index out of range");
852 return -1;
853 }
Thomas Wouters1baac722001-07-16 15:47:36 +0000854 if (v == NULL) {
855 PyErr_SetString(PyExc_TypeError,
Tim Peters5ebfd362001-11-13 23:11:19 +0000856 "mmap object doesn't support item deletion");
Thomas Wouters1baac722001-07-16 15:47:36 +0000857 return -1;
858 }
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000859 if (! (PyString_Check(v) && PyString_Size(v)==1) ) {
Tim Petersec0a5f02006-02-16 23:47:20 +0000860 PyErr_SetString(PyExc_IndexError,
Tim Peters5ebfd362001-11-13 23:11:19 +0000861 "mmap assignment must be single-character string");
Guido van Rossum09fdf072000-03-31 01:17:07 +0000862 return -1;
863 }
Tim Peters5ebfd362001-11-13 23:11:19 +0000864 if (!is_writeable(self))
865 return -1;
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000866 buf = PyString_AsString(v);
Guido van Rossum09fdf072000-03-31 01:17:07 +0000867 self->data[i] = buf[0];
868 return 0;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000869}
870
Thomas Wouters3ccec682007-08-28 15:28:19 +0000871static int
872mmap_ass_subscript(mmap_object *self, PyObject *item, PyObject *value)
873{
874 CHECK_VALID(-1);
875
876 if (PyIndex_Check(item)) {
877 Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
878 const char *buf;
879
880 if (i == -1 && PyErr_Occurred())
881 return -1;
882 if (i < 0)
883 i += self->size;
Hirokazu Yamamoto978bacd2009-02-18 15:11:55 +0000884 if (i < 0 || (size_t)i >= self->size) {
Thomas Wouters3ccec682007-08-28 15:28:19 +0000885 PyErr_SetString(PyExc_IndexError,
886 "mmap index out of range");
887 return -1;
888 }
889 if (value == NULL) {
890 PyErr_SetString(PyExc_TypeError,
891 "mmap object doesn't support item deletion");
892 return -1;
893 }
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000894 if (!PyString_Check(value) || PyString_Size(value) != 1) {
Thomas Wouters3ccec682007-08-28 15:28:19 +0000895 PyErr_SetString(PyExc_IndexError,
896 "mmap assignment must be single-character string");
897 return -1;
898 }
899 if (!is_writeable(self))
900 return -1;
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000901 buf = PyString_AsString(value);
Thomas Wouters3ccec682007-08-28 15:28:19 +0000902 self->data[i] = buf[0];
903 return 0;
904 }
905 else if (PySlice_Check(item)) {
906 Py_ssize_t start, stop, step, slicelen;
907
908 if (PySlice_GetIndicesEx((PySliceObject *)item,
909 self->size, &start, &stop,
910 &step, &slicelen) < 0) {
911 return -1;
912 }
913 if (value == NULL) {
914 PyErr_SetString(PyExc_TypeError,
915 "mmap object doesn't support slice deletion");
916 return -1;
917 }
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000918 if (!PyString_Check(value)) {
Thomas Wouters3ccec682007-08-28 15:28:19 +0000919 PyErr_SetString(PyExc_IndexError,
920 "mmap slice assignment must be a string");
921 return -1;
922 }
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000923 if (PyString_Size(value) != slicelen) {
Thomas Wouters3ccec682007-08-28 15:28:19 +0000924 PyErr_SetString(PyExc_IndexError,
925 "mmap slice assignment is wrong size");
926 return -1;
927 }
928 if (!is_writeable(self))
929 return -1;
930
931 if (slicelen == 0)
932 return 0;
933 else if (step == 1) {
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000934 const char *buf = PyString_AsString(value);
Thomas Wouters3ccec682007-08-28 15:28:19 +0000935
936 if (buf == NULL)
937 return -1;
938 memcpy(self->data + start, buf, slicelen);
939 return 0;
940 }
941 else {
942 Py_ssize_t cur, i;
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000943 const char *buf = PyString_AsString(value);
Thomas Wouters3ccec682007-08-28 15:28:19 +0000944
945 if (buf == NULL)
946 return -1;
947 for (cur = start, i = 0; i < slicelen;
948 cur += step, i++) {
949 self->data[cur] = buf[i];
950 }
951 return 0;
952 }
953 }
954 else {
955 PyErr_SetString(PyExc_TypeError,
956 "mmap indices must be integer");
957 return -1;
958 }
959}
960
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000961static PySequenceMethods mmap_as_sequence = {
Martin v. Löwis18e16552006-02-15 17:27:45 +0000962 (lenfunc)mmap_length, /*sq_length*/
Guido van Rossum09fdf072000-03-31 01:17:07 +0000963 (binaryfunc)mmap_concat, /*sq_concat*/
Martin v. Löwis18e16552006-02-15 17:27:45 +0000964 (ssizeargfunc)mmap_repeat, /*sq_repeat*/
965 (ssizeargfunc)mmap_item, /*sq_item*/
966 (ssizessizeargfunc)mmap_slice, /*sq_slice*/
967 (ssizeobjargproc)mmap_ass_item, /*sq_ass_item*/
968 (ssizessizeobjargproc)mmap_ass_slice, /*sq_ass_slice*/
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000969};
970
Thomas Wouters3ccec682007-08-28 15:28:19 +0000971static PyMappingMethods mmap_as_mapping = {
972 (lenfunc)mmap_length,
973 (binaryfunc)mmap_subscript,
974 (objobjargproc)mmap_ass_subscript,
975};
976
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000977static PyBufferProcs mmap_as_buffer = {
Martin v. Löwis18e16552006-02-15 17:27:45 +0000978 (readbufferproc)mmap_buffer_getreadbuf,
979 (writebufferproc)mmap_buffer_getwritebuf,
980 (segcountproc)mmap_buffer_getsegcount,
981 (charbufferproc)mmap_buffer_getcharbuffer,
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000982};
983
Georg Brandl845c4032008-01-21 14:16:46 +0000984static PyObject *
985new_mmap_object(PyTypeObject *type, PyObject *args, PyObject *kwdict);
986
Georg Brandlef928022008-01-20 14:50:05 +0000987PyDoc_STRVAR(mmap_doc,
988"Windows: mmap(fileno, length[, tagname[, access[, offset]]])\n\
989\n\
990Maps length bytes from the file specified by the file handle fileno,\n\
991and returns a mmap object. If length is larger than the current size\n\
992of the file, the file is extended to contain length bytes. If length\n\
993is 0, the maximum length of the map is the current size of the file,\n\
994except that if the file is empty Windows raises an exception (you cannot\n\
995create an empty mapping on Windows).\n\
996\n\
997Unix: mmap(fileno, length[, flags[, prot[, access[, offset]]]])\n\
998\n\
999Maps length bytes from the file specified by the file descriptor fileno,\n\
1000and returns a mmap object. If length is 0, the maximum length of the map\n\
1001will be the current size of the file when mmap is called.\n\
1002flags specifies the nature of the mapping. MAP_PRIVATE creates a\n\
1003private copy-on-write mapping, so changes to the contents of the mmap\n\
Thomas Heller66260992008-08-19 17:47:13 +00001004object will be private to this process, and MAP_SHARED creates a mapping\n\
Georg Brandlef928022008-01-20 14:50:05 +00001005that's shared with all other processes mapping the same areas of the file.\n\
1006The default value is MAP_SHARED.\n\
1007\n\
1008To map anonymous memory, pass -1 as the fileno (both versions).");
1009
1010
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001011static PyTypeObject mmap_object_type = {
Georg Brandl845c4032008-01-21 14:16:46 +00001012 PyVarObject_HEAD_INIT(NULL, 0)
Guido van Rossum14648392001-12-08 18:02:58 +00001013 "mmap.mmap", /* tp_name */
Guido van Rossum09fdf072000-03-31 01:17:07 +00001014 sizeof(mmap_object), /* tp_size */
1015 0, /* tp_itemsize */
1016 /* methods */
1017 (destructor) mmap_object_dealloc, /* tp_dealloc */
1018 0, /* tp_print */
Georg Brandlef928022008-01-20 14:50:05 +00001019 0, /* tp_getattr */
Guido van Rossum09fdf072000-03-31 01:17:07 +00001020 0, /* tp_setattr */
1021 0, /* tp_compare */
1022 0, /* tp_repr */
1023 0, /* tp_as_number */
1024 &mmap_as_sequence, /*tp_as_sequence*/
Thomas Wouters3ccec682007-08-28 15:28:19 +00001025 &mmap_as_mapping, /*tp_as_mapping*/
Guido van Rossum09fdf072000-03-31 01:17:07 +00001026 0, /*tp_hash*/
1027 0, /*tp_call*/
1028 0, /*tp_str*/
Georg Brandlef928022008-01-20 14:50:05 +00001029 PyObject_GenericGetAttr, /*tp_getattro*/
Guido van Rossum09fdf072000-03-31 01:17:07 +00001030 0, /*tp_setattro*/
1031 &mmap_as_buffer, /*tp_as_buffer*/
Georg Brandl845c4032008-01-21 14:16:46 +00001032 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GETCHARBUFFER, /*tp_flags*/
Georg Brandlef928022008-01-20 14:50:05 +00001033 mmap_doc, /*tp_doc*/
1034 0, /* tp_traverse */
1035 0, /* tp_clear */
1036 0, /* tp_richcompare */
1037 0, /* tp_weaklistoffset */
Georg Brandl845c4032008-01-21 14:16:46 +00001038 0, /* tp_iter */
1039 0, /* tp_iternext */
Georg Brandlef928022008-01-20 14:50:05 +00001040 mmap_object_methods, /* tp_methods */
Georg Brandl845c4032008-01-21 14:16:46 +00001041 0, /* tp_members */
1042 0, /* tp_getset */
1043 0, /* tp_base */
1044 0, /* tp_dict */
1045 0, /* tp_descr_get */
1046 0, /* tp_descr_set */
1047 0, /* tp_dictoffset */
1048 0, /* tp_init */
1049 PyType_GenericAlloc, /* tp_alloc */
1050 new_mmap_object, /* tp_new */
1051 PyObject_Del, /* tp_free */
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001052};
1053
Andrew M. Kuchling70d27422000-06-18 04:45:14 +00001054
1055/* extract the map size from the given PyObject
1056
Thomas Wouters7e474022000-07-16 12:04:32 +00001057 Returns -1 on error, with an appropriate Python exception raised. On
Andrew M. Kuchling70d27422000-06-18 04:45:14 +00001058 success, the map size is returned. */
Martin v. Löwiscfe7e092006-02-17 06:59:14 +00001059static Py_ssize_t
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001060_GetMapSize(PyObject *o, const char* param)
Andrew M. Kuchling70d27422000-06-18 04:45:14 +00001061{
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001062 if (o == NULL)
1063 return 0;
Neal Norwitz8a87f5d2006-08-12 17:03:09 +00001064 if (PyIndex_Check(o)) {
1065 Py_ssize_t i = PyNumber_AsSsize_t(o, PyExc_OverflowError);
Guido van Rossum38fff8c2006-03-07 18:50:55 +00001066 if (i==-1 && PyErr_Occurred())
Andrew M. Kuchling70d27422000-06-18 04:45:14 +00001067 return -1;
Neal Norwitz8a87f5d2006-08-12 17:03:09 +00001068 if (i < 0) {
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001069 PyErr_Format(PyExc_OverflowError,
1070 "memory mapped %s must be positive",
1071 param);
Neal Norwitz8a87f5d2006-08-12 17:03:09 +00001072 return -1;
1073 }
Martin v. Löwiscfe7e092006-02-17 06:59:14 +00001074 return i;
Andrew M. Kuchling70d27422000-06-18 04:45:14 +00001075 }
Andrew M. Kuchling70d27422000-06-18 04:45:14 +00001076
Neal Norwitz8a87f5d2006-08-12 17:03:09 +00001077 PyErr_SetString(PyExc_TypeError, "map size must be an integral value");
Andrew M. Kuchling70d27422000-06-18 04:45:14 +00001078 return -1;
1079}
1080
Tim Petersec0a5f02006-02-16 23:47:20 +00001081#ifdef UNIX
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001082static PyObject *
Georg Brandl845c4032008-01-21 14:16:46 +00001083new_mmap_object(PyTypeObject *type, PyObject *args, PyObject *kwdict)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001084{
Neal Norwitzb5673922002-09-05 21:48:07 +00001085#ifdef HAVE_FSTAT
1086 struct stat st;
1087#endif
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +00001088 mmap_object *m_obj;
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001089 PyObject *map_size_obj = NULL, *offset_obj = NULL;
1090 Py_ssize_t map_size, offset;
Guido van Rossum09fdf072000-03-31 01:17:07 +00001091 int fd, flags = MAP_SHARED, prot = PROT_WRITE | PROT_READ;
Neal Norwitz0e6bc8c2006-02-05 05:45:43 +00001092 int devzero = -1;
Neal Norwitz8856fb72005-12-18 03:34:22 +00001093 int access = (int)ACCESS_DEFAULT;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001094 static char *keywords[] = {"fileno", "length",
Tim Petersec0a5f02006-02-16 23:47:20 +00001095 "flags", "prot",
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001096 "access", "offset", NULL};
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001097
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001098 if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iO|iiiO", keywords,
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001099 &fd, &map_size_obj, &flags, &prot,
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001100 &access, &offset_obj))
Guido van Rossum09fdf072000-03-31 01:17:07 +00001101 return NULL;
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001102 map_size = _GetMapSize(map_size_obj, "size");
Andrew M. Kuchling70d27422000-06-18 04:45:14 +00001103 if (map_size < 0)
1104 return NULL;
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001105 offset = _GetMapSize(offset_obj, "offset");
1106 if (offset < 0)
1107 return NULL;
Tim Peters5ebfd362001-11-13 23:11:19 +00001108
Tim Petersec0a5f02006-02-16 23:47:20 +00001109 if ((access != (int)ACCESS_DEFAULT) &&
Neal Norwitzd1cfc8a2006-02-05 03:36:57 +00001110 ((flags != MAP_SHARED) || (prot != (PROT_WRITE | PROT_READ))))
Tim Petersec0a5f02006-02-16 23:47:20 +00001111 return PyErr_Format(PyExc_ValueError,
Tim Peters5ebfd362001-11-13 23:11:19 +00001112 "mmap can't specify both access and flags, prot.");
Neal Norwitzd1cfc8a2006-02-05 03:36:57 +00001113 switch ((access_mode)access) {
Tim Peters5ebfd362001-11-13 23:11:19 +00001114 case ACCESS_READ:
1115 flags = MAP_SHARED;
1116 prot = PROT_READ;
1117 break;
1118 case ACCESS_WRITE:
1119 flags = MAP_SHARED;
1120 prot = PROT_READ | PROT_WRITE;
1121 break;
1122 case ACCESS_COPY:
1123 flags = MAP_PRIVATE;
1124 prot = PROT_READ | PROT_WRITE;
1125 break;
Tim Petersec0a5f02006-02-16 23:47:20 +00001126 case ACCESS_DEFAULT:
Tim Peters5ebfd362001-11-13 23:11:19 +00001127 /* use the specified or default values of flags and prot */
1128 break;
1129 default:
Tim Petersec0a5f02006-02-16 23:47:20 +00001130 return PyErr_Format(PyExc_ValueError,
Tim Peters5ebfd362001-11-13 23:11:19 +00001131 "mmap invalid access parameter.");
1132 }
Neal Norwitzb5673922002-09-05 21:48:07 +00001133
Christian Heimes7adfad82008-02-15 08:20:11 +00001134 if (prot == PROT_READ) {
1135 access = ACCESS_READ;
1136 }
1137
Neal Norwitzb5673922002-09-05 21:48:07 +00001138#ifdef HAVE_FSTAT
Martin v. Löwisc16f3bd2003-05-03 09:14:54 +00001139# ifdef __VMS
1140 /* on OpenVMS we must ensure that all bytes are written to the file */
Andrew M. Kuchling7c22ccc2008-01-10 13:37:12 +00001141 if (fd != -1) {
1142 fsync(fd);
1143 }
Martin v. Löwisc16f3bd2003-05-03 09:14:54 +00001144# endif
Andrew M. Kuchling7c22ccc2008-01-10 13:37:12 +00001145 if (fd != -1 && fstat(fd, &st) == 0 && S_ISREG(st.st_mode)) {
Martin v. Löwis7fe60c02005-03-03 11:22:44 +00001146 if (map_size == 0) {
Martin v. Löwiscfe7e092006-02-17 06:59:14 +00001147 map_size = st.st_size;
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001148 } else if ((size_t)offset + (size_t)map_size > st.st_size) {
Tim Petersec0a5f02006-02-16 23:47:20 +00001149 PyErr_SetString(PyExc_ValueError,
Martin v. Löwis7fe60c02005-03-03 11:22:44 +00001150 "mmap length is greater than file size");
1151 return NULL;
1152 }
Neal Norwitzb5673922002-09-05 21:48:07 +00001153 }
1154#endif
Georg Brandl845c4032008-01-21 14:16:46 +00001155 m_obj = (mmap_object *)type->tp_alloc(type, 0);
Guido van Rossum09fdf072000-03-31 01:17:07 +00001156 if (m_obj == NULL) {return NULL;}
Neal Norwitz3b4fff82006-01-11 08:54:45 +00001157 m_obj->data = NULL;
Guido van Rossum09fdf072000-03-31 01:17:07 +00001158 m_obj->size = (size_t) map_size;
1159 m_obj->pos = (size_t) 0;
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001160 m_obj->offset = offset;
Neal Norwitz0e6bc8c2006-02-05 05:45:43 +00001161 if (fd == -1) {
1162 m_obj->fd = -1;
1163 /* Assume the caller wants to map anonymous memory.
1164 This is the same behaviour as Windows. mmap.mmap(-1, size)
1165 on both Windows and Unix map anonymous memory.
1166 */
1167#ifdef MAP_ANONYMOUS
1168 /* BSD way to map anonymous memory */
1169 flags |= MAP_ANONYMOUS;
1170#else
1171 /* SVR4 method to map anonymous memory is to open /dev/zero */
1172 fd = devzero = open("/dev/zero", O_RDWR);
1173 if (devzero == -1) {
1174 Py_DECREF(m_obj);
1175 PyErr_SetFromErrno(mmap_module_error);
1176 return NULL;
1177 }
1178#endif
1179 } else {
1180 m_obj->fd = dup(fd);
1181 if (m_obj->fd == -1) {
1182 Py_DECREF(m_obj);
1183 PyErr_SetFromErrno(mmap_module_error);
1184 return NULL;
1185 }
Georg Brandl38387b82005-08-24 07:17:40 +00001186 }
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001187
Tim Petersec0a5f02006-02-16 23:47:20 +00001188 m_obj->data = mmap(NULL, map_size,
Guido van Rossum09fdf072000-03-31 01:17:07 +00001189 prot, flags,
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001190 fd, offset);
Neal Norwitz0e6bc8c2006-02-05 05:45:43 +00001191
1192 if (devzero != -1) {
1193 close(devzero);
1194 }
1195
Tim Peters5ebfd362001-11-13 23:11:19 +00001196 if (m_obj->data == (char *)-1) {
Andrew M. Kuchling16581c82004-05-19 14:39:08 +00001197 m_obj->data = NULL;
Guido van Rossum09fdf072000-03-31 01:17:07 +00001198 Py_DECREF(m_obj);
1199 PyErr_SetFromErrno(mmap_module_error);
1200 return NULL;
1201 }
Neal Norwitz8856fb72005-12-18 03:34:22 +00001202 m_obj->access = (access_mode)access;
Guido van Rossum09fdf072000-03-31 01:17:07 +00001203 return (PyObject *)m_obj;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001204}
1205#endif /* UNIX */
1206
Martin v. Löwis6238d2b2002-06-30 15:26:10 +00001207#ifdef MS_WINDOWS
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001208static PyObject *
Georg Brandl845c4032008-01-21 14:16:46 +00001209new_mmap_object(PyTypeObject *type, PyObject *args, PyObject *kwdict)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001210{
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +00001211 mmap_object *m_obj;
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001212 PyObject *map_size_obj = NULL, *offset_obj = NULL;
1213 Py_ssize_t map_size, offset;
1214 DWORD off_hi; /* upper 32 bits of offset */
1215 DWORD off_lo; /* lower 32 bits of offset */
1216 DWORD size_hi; /* upper 32 bits of size */
1217 DWORD size_lo; /* lower 32 bits of size */
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +00001218 char *tagname = "";
Guido van Rossum09fdf072000-03-31 01:17:07 +00001219 DWORD dwErr = 0;
1220 int fileno;
Mark Hammond071864a2000-07-30 02:46:26 +00001221 HANDLE fh = 0;
Neal Norwitz8856fb72005-12-18 03:34:22 +00001222 int access = (access_mode)ACCESS_DEFAULT;
Tim Peters5ebfd362001-11-13 23:11:19 +00001223 DWORD flProtect, dwDesiredAccess;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001224 static char *keywords[] = { "fileno", "length",
Tim Petersec0a5f02006-02-16 23:47:20 +00001225 "tagname",
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001226 "access", "offset", NULL };
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001227
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001228 if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iO|ziO", keywords,
Tim Petersec0a5f02006-02-16 23:47:20 +00001229 &fileno, &map_size_obj,
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001230 &tagname, &access, &offset_obj)) {
Guido van Rossum09fdf072000-03-31 01:17:07 +00001231 return NULL;
Tim Peters5ebfd362001-11-13 23:11:19 +00001232 }
1233
Neal Norwitz8856fb72005-12-18 03:34:22 +00001234 switch((access_mode)access) {
Tim Peters5ebfd362001-11-13 23:11:19 +00001235 case ACCESS_READ:
1236 flProtect = PAGE_READONLY;
1237 dwDesiredAccess = FILE_MAP_READ;
1238 break;
1239 case ACCESS_DEFAULT: case ACCESS_WRITE:
1240 flProtect = PAGE_READWRITE;
1241 dwDesiredAccess = FILE_MAP_WRITE;
1242 break;
1243 case ACCESS_COPY:
1244 flProtect = PAGE_WRITECOPY;
1245 dwDesiredAccess = FILE_MAP_COPY;
1246 break;
1247 default:
Tim Petersec0a5f02006-02-16 23:47:20 +00001248 return PyErr_Format(PyExc_ValueError,
Tim Peters5ebfd362001-11-13 23:11:19 +00001249 "mmap invalid access parameter.");
1250 }
1251
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001252 map_size = _GetMapSize(map_size_obj, "size");
Andrew M. Kuchling70d27422000-06-18 04:45:14 +00001253 if (map_size < 0)
1254 return NULL;
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001255 offset = _GetMapSize(offset_obj, "offset");
1256 if (offset < 0)
1257 return NULL;
Tim Petersec0a5f02006-02-16 23:47:20 +00001258
Neal Norwitz0e6bc8c2006-02-05 05:45:43 +00001259 /* assume -1 and 0 both mean invalid filedescriptor
1260 to 'anonymously' map memory.
1261 XXX: fileno == 0 is a valid fd, but was accepted prior to 2.5.
1262 XXX: Should this code be added?
1263 if (fileno == 0)
1264 PyErr_Warn(PyExc_DeprecationWarning,
1265 "don't use 0 for anonymous memory");
1266 */
1267 if (fileno != -1 && fileno != 0) {
Mark Hammond071864a2000-07-30 02:46:26 +00001268 fh = (HANDLE)_get_osfhandle(fileno);
1269 if (fh==(HANDLE)-1) {
Tim Peters5ebfd362001-11-13 23:11:19 +00001270 PyErr_SetFromErrno(mmap_module_error);
1271 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001272 }
Fred Drake1ef4e2d2000-04-05 14:15:31 +00001273 /* Win9x appears to need us seeked to zero */
Guido van Rossum69c2b882003-04-09 19:31:02 +00001274 lseek(fileno, 0, SEEK_SET);
Guido van Rossum09fdf072000-03-31 01:17:07 +00001275 }
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001276
Georg Brandl845c4032008-01-21 14:16:46 +00001277 m_obj = (mmap_object *)type->tp_alloc(type, 0);
Tim Peters8f9cc292006-02-17 00:00:20 +00001278 if (m_obj == NULL)
Mark Hammond2cbed002000-07-30 02:22:43 +00001279 return NULL;
1280 /* Set every field to an invalid marker, so we can safely
1281 destruct the object in the face of failure */
1282 m_obj->data = NULL;
Mark Hammond071864a2000-07-30 02:46:26 +00001283 m_obj->file_handle = INVALID_HANDLE_VALUE;
Hirokazu Yamamotoec5294f2009-03-05 14:30:13 +00001284 m_obj->map_handle = NULL;
Mark Hammond2cbed002000-07-30 02:22:43 +00001285 m_obj->tagname = NULL;
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001286 m_obj->offset = offset;
Mark Hammond2cbed002000-07-30 02:22:43 +00001287
Guido van Rossum09fdf072000-03-31 01:17:07 +00001288 if (fh) {
Mark Hammond2cbed002000-07-30 02:22:43 +00001289 /* It is necessary to duplicate the handle, so the
1290 Python code can close it on us */
1291 if (!DuplicateHandle(
Tim Peters5ebfd362001-11-13 23:11:19 +00001292 GetCurrentProcess(), /* source process handle */
1293 fh, /* handle to be duplicated */
1294 GetCurrentProcess(), /* target proc handle */
1295 (LPHANDLE)&m_obj->file_handle, /* result */
1296 0, /* access - ignored due to options value */
1297 FALSE, /* inherited by child processes? */
1298 DUPLICATE_SAME_ACCESS)) { /* options */
Mark Hammond2cbed002000-07-30 02:22:43 +00001299 dwErr = GetLastError();
1300 Py_DECREF(m_obj);
1301 PyErr_SetFromWindowsErr(dwErr);
1302 return NULL;
1303 }
Guido van Rossum09fdf072000-03-31 01:17:07 +00001304 if (!map_size) {
Martin v. Löwis15186072006-02-18 12:38:35 +00001305 DWORD low,high;
1306 low = GetFileSize(fh, &high);
1307 /* low might just happen to have the value INVALID_FILE_SIZE;
1308 so we need to check the last error also. */
1309 if (low == INVALID_FILE_SIZE &&
1310 (dwErr = GetLastError()) != NO_ERROR) {
1311 Py_DECREF(m_obj);
1312 return PyErr_SetFromWindowsErr(dwErr);
1313 }
1314
1315#if SIZEOF_SIZE_T > 4
1316 m_obj->size = (((size_t)high)<<32) + low;
1317#else
1318 if (high)
1319 /* File is too large to map completely */
1320 m_obj->size = (size_t)-1;
1321 else
1322 m_obj->size = low;
1323#endif
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001324 } else {
Guido van Rossum09fdf072000-03-31 01:17:07 +00001325 m_obj->size = map_size;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001326 }
Guido van Rossum09fdf072000-03-31 01:17:07 +00001327 }
1328 else {
Guido van Rossum09fdf072000-03-31 01:17:07 +00001329 m_obj->size = map_size;
1330 }
1331
1332 /* set the initial position */
1333 m_obj->pos = (size_t) 0;
1334
Mark Hammond2cbed002000-07-30 02:22:43 +00001335 /* set the tag name */
Tim Peters0d9f9dc2001-01-10 05:42:18 +00001336 if (tagname != NULL && *tagname != '\0') {
Mark Hammond2cbed002000-07-30 02:22:43 +00001337 m_obj->tagname = PyMem_Malloc(strlen(tagname)+1);
1338 if (m_obj->tagname == NULL) {
1339 PyErr_NoMemory();
1340 Py_DECREF(m_obj);
1341 return NULL;
1342 }
1343 strcpy(m_obj->tagname, tagname);
1344 }
1345 else
1346 m_obj->tagname = NULL;
1347
Neal Norwitz8856fb72005-12-18 03:34:22 +00001348 m_obj->access = (access_mode)access;
Tim Peterse564e7f2006-02-16 23:46:01 +00001349 /* DWORD is a 4-byte int. If we're on a box where size_t consumes
Thomas Wouters2c98a7b2006-02-17 09:59:00 +00001350 * more than 4 bytes, we need to break it apart. Else (size_t
Tim Peterse564e7f2006-02-16 23:46:01 +00001351 * consumes 4 bytes), C doesn't define what happens if we shift
1352 * right by 32, so we need different code.
1353 */
1354#if SIZEOF_SIZE_T > 4
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001355 size_hi = (DWORD)((offset + m_obj->size) >> 32);
1356 size_lo = (DWORD)((offset + m_obj->size) & 0xFFFFFFFF);
1357 off_hi = (DWORD)(offset >> 32);
1358 off_lo = (DWORD)(offset & 0xFFFFFFFF);
Tim Peterse564e7f2006-02-16 23:46:01 +00001359#else
1360 size_hi = 0;
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001361 size_lo = (DWORD)(offset + m_obj->size);
1362 off_hi = 0;
1363 off_lo = (DWORD)offset;
Tim Peterse564e7f2006-02-16 23:46:01 +00001364#endif
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001365 /* For files, it would be sufficient to pass 0 as size.
1366 For anonymous maps, we have to pass the size explicitly. */
Tim Peters8f9cc292006-02-17 00:00:20 +00001367 m_obj->map_handle = CreateFileMapping(m_obj->file_handle,
1368 NULL,
1369 flProtect,
1370 size_hi,
1371 size_lo,
1372 m_obj->tagname);
Guido van Rossum09fdf072000-03-31 01:17:07 +00001373 if (m_obj->map_handle != NULL) {
Tim Peters8f9cc292006-02-17 00:00:20 +00001374 m_obj->data = (char *) MapViewOfFile(m_obj->map_handle,
1375 dwDesiredAccess,
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001376 off_hi,
1377 off_lo,
Hirokazu Yamamoto4b27e962009-02-28 12:42:16 +00001378 m_obj->size);
Tim Peters23721ee2006-02-16 23:50:16 +00001379 if (m_obj->data != NULL)
1380 return (PyObject *)m_obj;
Hirokazu Yamamotoec5294f2009-03-05 14:30:13 +00001381 else {
Tim Peters5ebfd362001-11-13 23:11:19 +00001382 dwErr = GetLastError();
Hirokazu Yamamotoec5294f2009-03-05 14:30:13 +00001383 CloseHandle(m_obj->map_handle);
1384 m_obj->map_handle = NULL;
1385 }
Tim Peters23721ee2006-02-16 23:50:16 +00001386 } else
Guido van Rossum09fdf072000-03-31 01:17:07 +00001387 dwErr = GetLastError();
Mark Hammond2cbed002000-07-30 02:22:43 +00001388 Py_DECREF(m_obj);
Guido van Rossum09fdf072000-03-31 01:17:07 +00001389 PyErr_SetFromWindowsErr(dwErr);
Tim Peters23721ee2006-02-16 23:50:16 +00001390 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001391}
Martin v. Löwis6238d2b2002-06-30 15:26:10 +00001392#endif /* MS_WINDOWS */
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001393
Neal Norwitze9ac0bb2006-08-13 18:11:27 +00001394static void
1395setint(PyObject *d, const char *name, long value)
1396{
1397 PyObject *o = PyInt_FromLong(value);
Neal Norwitz5ed49972006-08-13 18:41:15 +00001398 if (o && PyDict_SetItemString(d, name, o) == 0) {
Neal Norwitze9ac0bb2006-08-13 18:11:27 +00001399 Py_DECREF(o);
Neal Norwitz5ed49972006-08-13 18:41:15 +00001400 }
Neal Norwitze9ac0bb2006-08-13 18:11:27 +00001401}
1402
Mark Hammond62b1ab12002-07-23 06:31:15 +00001403PyMODINIT_FUNC
Georg Brandl845c4032008-01-21 14:16:46 +00001404initmmap(void)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001405{
Guido van Rossum09fdf072000-03-31 01:17:07 +00001406 PyObject *dict, *module;
Tim Peters2caf8df2001-01-14 05:05:51 +00001407
Georg Brandl845c4032008-01-21 14:16:46 +00001408 if (PyType_Ready(&mmap_object_type) < 0)
1409 return;
Tim Peters2caf8df2001-01-14 05:05:51 +00001410
Georg Brandl845c4032008-01-21 14:16:46 +00001411 module = Py_InitModule("mmap", NULL);
Neal Norwitz1ac754f2006-01-19 06:09:39 +00001412 if (module == NULL)
1413 return;
Tim Peters8f9cc292006-02-17 00:00:20 +00001414 dict = PyModule_GetDict(module);
Neal Norwitze9ac0bb2006-08-13 18:11:27 +00001415 if (!dict)
1416 return;
Facundo Batistae1396882008-02-17 18:59:29 +00001417 mmap_module_error = PyErr_NewException("mmap.error",
1418 PyExc_EnvironmentError , NULL);
1419 if (mmap_module_error == NULL)
1420 return;
Tim Peters8f9cc292006-02-17 00:00:20 +00001421 PyDict_SetItemString(dict, "error", mmap_module_error);
Georg Brandl845c4032008-01-21 14:16:46 +00001422 PyDict_SetItemString(dict, "mmap", (PyObject*) &mmap_object_type);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001423#ifdef PROT_EXEC
Neal Norwitze9ac0bb2006-08-13 18:11:27 +00001424 setint(dict, "PROT_EXEC", PROT_EXEC);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001425#endif
1426#ifdef PROT_READ
Neal Norwitze9ac0bb2006-08-13 18:11:27 +00001427 setint(dict, "PROT_READ", PROT_READ);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001428#endif
1429#ifdef PROT_WRITE
Neal Norwitze9ac0bb2006-08-13 18:11:27 +00001430 setint(dict, "PROT_WRITE", PROT_WRITE);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001431#endif
1432
1433#ifdef MAP_SHARED
Neal Norwitze9ac0bb2006-08-13 18:11:27 +00001434 setint(dict, "MAP_SHARED", MAP_SHARED);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001435#endif
1436#ifdef MAP_PRIVATE
Neal Norwitze9ac0bb2006-08-13 18:11:27 +00001437 setint(dict, "MAP_PRIVATE", MAP_PRIVATE);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001438#endif
1439#ifdef MAP_DENYWRITE
Neal Norwitze9ac0bb2006-08-13 18:11:27 +00001440 setint(dict, "MAP_DENYWRITE", MAP_DENYWRITE);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001441#endif
1442#ifdef MAP_EXECUTABLE
Neal Norwitze9ac0bb2006-08-13 18:11:27 +00001443 setint(dict, "MAP_EXECUTABLE", MAP_EXECUTABLE);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001444#endif
Neal Norwitz0e6bc8c2006-02-05 05:45:43 +00001445#ifdef MAP_ANONYMOUS
Neal Norwitze9ac0bb2006-08-13 18:11:27 +00001446 setint(dict, "MAP_ANON", MAP_ANONYMOUS);
1447 setint(dict, "MAP_ANONYMOUS", MAP_ANONYMOUS);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001448#endif
1449
Neal Norwitze9ac0bb2006-08-13 18:11:27 +00001450 setint(dict, "PAGESIZE", (long)my_getpagesize());
Andrew M. Kuchling961fe172000-06-03 19:41:42 +00001451
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001452 setint(dict, "ALLOCATIONGRANULARITY", (long)my_getallocationgranularity());
1453
Neal Norwitze9ac0bb2006-08-13 18:11:27 +00001454 setint(dict, "ACCESS_READ", ACCESS_READ);
1455 setint(dict, "ACCESS_WRITE", ACCESS_WRITE);
1456 setint(dict, "ACCESS_COPY", ACCESS_COPY);
Tim Peters5ebfd362001-11-13 23:11:19 +00001457}