blob: 95dcfbe630564a9c52b2b24d85827a727ffcb91e [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 */
615 if (/* end of source after end of data?? */
616 ((src+count) > self->size)
617 /* dest will fit? */
618 || (dest+count > self->size)) {
Tim Peters8f9cc292006-02-17 00:00:20 +0000619 PyErr_SetString(PyExc_ValueError,
620 "source or destination out of range");
Guido van Rossum09fdf072000-03-31 01:17:07 +0000621 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000622 } else {
Tim Peters8f9cc292006-02-17 00:00:20 +0000623 memmove(self->data+dest, self->data+src, count);
624 Py_INCREF(Py_None);
Guido van Rossum09fdf072000-03-31 01:17:07 +0000625 return Py_None;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000626 }
Guido van Rossum09fdf072000-03-31 01:17:07 +0000627 }
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000628}
629
630static struct PyMethodDef mmap_object_methods[] = {
Georg Brandl96a8c392006-05-29 21:04:52 +0000631 {"close", (PyCFunction) mmap_close_method, METH_NOARGS},
Martin v. Löwis43b936d2002-01-17 23:15:58 +0000632 {"find", (PyCFunction) mmap_find_method, METH_VARARGS},
Andrew M. Kuchling5c60bfc2008-01-19 18:18:41 +0000633 {"rfind", (PyCFunction) mmap_rfind_method, METH_VARARGS},
Martin v. Löwis43b936d2002-01-17 23:15:58 +0000634 {"flush", (PyCFunction) mmap_flush_method, METH_VARARGS},
635 {"move", (PyCFunction) mmap_move_method, METH_VARARGS},
636 {"read", (PyCFunction) mmap_read_method, METH_VARARGS},
Georg Brandl96a8c392006-05-29 21:04:52 +0000637 {"read_byte", (PyCFunction) mmap_read_byte_method, METH_NOARGS},
638 {"readline", (PyCFunction) mmap_read_line_method, METH_NOARGS},
Martin v. Löwis43b936d2002-01-17 23:15:58 +0000639 {"resize", (PyCFunction) mmap_resize_method, METH_VARARGS},
640 {"seek", (PyCFunction) mmap_seek_method, METH_VARARGS},
Georg Brandl96a8c392006-05-29 21:04:52 +0000641 {"size", (PyCFunction) mmap_size_method, METH_NOARGS},
642 {"tell", (PyCFunction) mmap_tell_method, METH_NOARGS},
Martin v. Löwis43b936d2002-01-17 23:15:58 +0000643 {"write", (PyCFunction) mmap_write_method, METH_VARARGS},
644 {"write_byte", (PyCFunction) mmap_write_byte_method, METH_VARARGS},
Guido van Rossum09fdf072000-03-31 01:17:07 +0000645 {NULL, NULL} /* sentinel */
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000646};
647
648/* Functions for treating an mmap'ed file as a buffer */
649
Martin v. Löwis18e16552006-02-15 17:27:45 +0000650static Py_ssize_t
651mmap_buffer_getreadbuf(mmap_object *self, Py_ssize_t index, const void **ptr)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000652{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000653 CHECK_VALID(-1);
Tim Peters8f9cc292006-02-17 00:00:20 +0000654 if (index != 0) {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000655 PyErr_SetString(PyExc_SystemError,
656 "Accessing non-existent mmap segment");
657 return -1;
658 }
659 *ptr = self->data;
660 return self->size;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000661}
662
Martin v. Löwis18e16552006-02-15 17:27:45 +0000663static Py_ssize_t
664mmap_buffer_getwritebuf(mmap_object *self, Py_ssize_t index, const void **ptr)
Tim Petersec0a5f02006-02-16 23:47:20 +0000665{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000666 CHECK_VALID(-1);
Tim Peters8f9cc292006-02-17 00:00:20 +0000667 if (index != 0) {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000668 PyErr_SetString(PyExc_SystemError,
669 "Accessing non-existent mmap segment");
670 return -1;
671 }
Tim Peters5ebfd362001-11-13 23:11:19 +0000672 if (!is_writeable(self))
673 return -1;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000674 *ptr = self->data;
675 return self->size;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000676}
677
Martin v. Löwis18e16552006-02-15 17:27:45 +0000678static Py_ssize_t
679mmap_buffer_getsegcount(mmap_object *self, Py_ssize_t *lenp)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000680{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000681 CHECK_VALID(-1);
Tim Petersec0a5f02006-02-16 23:47:20 +0000682 if (lenp)
Guido van Rossum09fdf072000-03-31 01:17:07 +0000683 *lenp = self->size;
684 return 1;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000685}
686
Martin v. Löwis18e16552006-02-15 17:27:45 +0000687static Py_ssize_t
688mmap_buffer_getcharbuffer(mmap_object *self, Py_ssize_t index, const void **ptr)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000689{
Tim Peters8f9cc292006-02-17 00:00:20 +0000690 if (index != 0) {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000691 PyErr_SetString(PyExc_SystemError,
692 "accessing non-existent buffer segment");
693 return -1;
694 }
695 *ptr = (const char *)self->data;
696 return self->size;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000697}
698
Martin v. Löwis18e16552006-02-15 17:27:45 +0000699static Py_ssize_t
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000700mmap_length(mmap_object *self)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000701{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000702 CHECK_VALID(-1);
703 return self->size;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000704}
705
706static PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000707mmap_item(mmap_object *self, Py_ssize_t i)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000708{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000709 CHECK_VALID(NULL);
Guido van Rossumce8e1dc2000-07-01 00:51:51 +0000710 if (i < 0 || (size_t)i >= self->size) {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000711 PyErr_SetString(PyExc_IndexError, "mmap index out of range");
712 return NULL;
713 }
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000714 return PyString_FromStringAndSize(self->data + i, 1);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000715}
716
717static PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000718mmap_slice(mmap_object *self, Py_ssize_t ilow, Py_ssize_t ihigh)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000719{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000720 CHECK_VALID(NULL);
721 if (ilow < 0)
722 ilow = 0;
Guido van Rossumce8e1dc2000-07-01 00:51:51 +0000723 else if ((size_t)ilow > self->size)
Guido van Rossum09fdf072000-03-31 01:17:07 +0000724 ilow = self->size;
725 if (ihigh < 0)
726 ihigh = 0;
727 if (ihigh < ilow)
728 ihigh = ilow;
Guido van Rossumce8e1dc2000-07-01 00:51:51 +0000729 else if ((size_t)ihigh > self->size)
Guido van Rossum09fdf072000-03-31 01:17:07 +0000730 ihigh = self->size;
Tim Petersec0a5f02006-02-16 23:47:20 +0000731
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000732 return PyString_FromStringAndSize(self->data + ilow, ihigh-ilow);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000733}
734
735static PyObject *
Thomas Wouters3ccec682007-08-28 15:28:19 +0000736mmap_subscript(mmap_object *self, PyObject *item)
737{
738 CHECK_VALID(NULL);
739 if (PyIndex_Check(item)) {
740 Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
741 if (i == -1 && PyErr_Occurred())
742 return NULL;
743 if (i < 0)
744 i += self->size;
Hirokazu Yamamoto978bacd2009-02-18 15:11:55 +0000745 if (i < 0 || (size_t)i >= self->size) {
Thomas Wouters3ccec682007-08-28 15:28:19 +0000746 PyErr_SetString(PyExc_IndexError,
747 "mmap index out of range");
748 return NULL;
749 }
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000750 return PyString_FromStringAndSize(self->data + i, 1);
Thomas Wouters3ccec682007-08-28 15:28:19 +0000751 }
752 else if (PySlice_Check(item)) {
753 Py_ssize_t start, stop, step, slicelen;
754
755 if (PySlice_GetIndicesEx((PySliceObject *)item, self->size,
756 &start, &stop, &step, &slicelen) < 0) {
757 return NULL;
758 }
759
760 if (slicelen <= 0)
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000761 return PyString_FromStringAndSize("", 0);
Thomas Wouters3ccec682007-08-28 15:28:19 +0000762 else if (step == 1)
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000763 return PyString_FromStringAndSize(self->data + start,
Thomas Wouters3ccec682007-08-28 15:28:19 +0000764 slicelen);
765 else {
766 char *result_buf = (char *)PyMem_Malloc(slicelen);
767 Py_ssize_t cur, i;
768 PyObject *result;
769
770 if (result_buf == NULL)
771 return PyErr_NoMemory();
772 for (cur = start, i = 0; i < slicelen;
773 cur += step, i++) {
774 result_buf[i] = self->data[cur];
775 }
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000776 result = PyString_FromStringAndSize(result_buf,
Thomas Wouters3ccec682007-08-28 15:28:19 +0000777 slicelen);
778 PyMem_Free(result_buf);
779 return result;
780 }
781 }
782 else {
783 PyErr_SetString(PyExc_TypeError,
784 "mmap indices must be integers");
785 return NULL;
786 }
787}
788
789static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000790mmap_concat(mmap_object *self, PyObject *bb)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000791{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000792 CHECK_VALID(NULL);
793 PyErr_SetString(PyExc_SystemError,
794 "mmaps don't support concatenation");
795 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000796}
797
798static PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000799mmap_repeat(mmap_object *self, Py_ssize_t n)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000800{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000801 CHECK_VALID(NULL);
802 PyErr_SetString(PyExc_SystemError,
803 "mmaps don't support repeat operation");
804 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000805}
806
807static int
Martin v. Löwis18e16552006-02-15 17:27:45 +0000808mmap_ass_slice(mmap_object *self, Py_ssize_t ilow, Py_ssize_t ihigh, PyObject *v)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000809{
Guido van Rossum36d4f8b2000-04-10 21:34:37 +0000810 const char *buf;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000811
Guido van Rossum09fdf072000-03-31 01:17:07 +0000812 CHECK_VALID(-1);
813 if (ilow < 0)
814 ilow = 0;
Guido van Rossumce8e1dc2000-07-01 00:51:51 +0000815 else if ((size_t)ilow > self->size)
Guido van Rossum09fdf072000-03-31 01:17:07 +0000816 ilow = self->size;
817 if (ihigh < 0)
818 ihigh = 0;
819 if (ihigh < ilow)
820 ihigh = ilow;
Guido van Rossumce8e1dc2000-07-01 00:51:51 +0000821 else if ((size_t)ihigh > self->size)
Guido van Rossum09fdf072000-03-31 01:17:07 +0000822 ihigh = self->size;
Tim Petersec0a5f02006-02-16 23:47:20 +0000823
Thomas Wouters1baac722001-07-16 15:47:36 +0000824 if (v == NULL) {
825 PyErr_SetString(PyExc_TypeError,
Tim Peters5ebfd362001-11-13 23:11:19 +0000826 "mmap object doesn't support slice deletion");
Thomas Wouters1baac722001-07-16 15:47:36 +0000827 return -1;
828 }
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000829 if (! (PyString_Check(v)) ) {
Tim Petersec0a5f02006-02-16 23:47:20 +0000830 PyErr_SetString(PyExc_IndexError,
Guido van Rossum09fdf072000-03-31 01:17:07 +0000831 "mmap slice assignment must be a string");
832 return -1;
833 }
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000834 if (PyString_Size(v) != (ihigh - ilow)) {
Tim Petersec0a5f02006-02-16 23:47:20 +0000835 PyErr_SetString(PyExc_IndexError,
Guido van Rossum09fdf072000-03-31 01:17:07 +0000836 "mmap slice assignment is wrong size");
837 return -1;
838 }
Tim Peters5ebfd362001-11-13 23:11:19 +0000839 if (!is_writeable(self))
840 return -1;
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000841 buf = PyString_AsString(v);
Guido van Rossum09fdf072000-03-31 01:17:07 +0000842 memcpy(self->data + ilow, buf, ihigh-ilow);
843 return 0;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000844}
845
846static int
Martin v. Löwis18e16552006-02-15 17:27:45 +0000847mmap_ass_item(mmap_object *self, Py_ssize_t i, PyObject *v)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000848{
Guido van Rossum36d4f8b2000-04-10 21:34:37 +0000849 const char *buf;
Tim Petersec0a5f02006-02-16 23:47:20 +0000850
Guido van Rossum09fdf072000-03-31 01:17:07 +0000851 CHECK_VALID(-1);
Guido van Rossumce8e1dc2000-07-01 00:51:51 +0000852 if (i < 0 || (size_t)i >= self->size) {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000853 PyErr_SetString(PyExc_IndexError, "mmap index out of range");
854 return -1;
855 }
Thomas Wouters1baac722001-07-16 15:47:36 +0000856 if (v == NULL) {
857 PyErr_SetString(PyExc_TypeError,
Tim Peters5ebfd362001-11-13 23:11:19 +0000858 "mmap object doesn't support item deletion");
Thomas Wouters1baac722001-07-16 15:47:36 +0000859 return -1;
860 }
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000861 if (! (PyString_Check(v) && PyString_Size(v)==1) ) {
Tim Petersec0a5f02006-02-16 23:47:20 +0000862 PyErr_SetString(PyExc_IndexError,
Tim Peters5ebfd362001-11-13 23:11:19 +0000863 "mmap assignment must be single-character string");
Guido van Rossum09fdf072000-03-31 01:17:07 +0000864 return -1;
865 }
Tim Peters5ebfd362001-11-13 23:11:19 +0000866 if (!is_writeable(self))
867 return -1;
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000868 buf = PyString_AsString(v);
Guido van Rossum09fdf072000-03-31 01:17:07 +0000869 self->data[i] = buf[0];
870 return 0;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000871}
872
Thomas Wouters3ccec682007-08-28 15:28:19 +0000873static int
874mmap_ass_subscript(mmap_object *self, PyObject *item, PyObject *value)
875{
876 CHECK_VALID(-1);
877
878 if (PyIndex_Check(item)) {
879 Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
880 const char *buf;
881
882 if (i == -1 && PyErr_Occurred())
883 return -1;
884 if (i < 0)
885 i += self->size;
Hirokazu Yamamoto978bacd2009-02-18 15:11:55 +0000886 if (i < 0 || (size_t)i >= self->size) {
Thomas Wouters3ccec682007-08-28 15:28:19 +0000887 PyErr_SetString(PyExc_IndexError,
888 "mmap index out of range");
889 return -1;
890 }
891 if (value == NULL) {
892 PyErr_SetString(PyExc_TypeError,
893 "mmap object doesn't support item deletion");
894 return -1;
895 }
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000896 if (!PyString_Check(value) || PyString_Size(value) != 1) {
Thomas Wouters3ccec682007-08-28 15:28:19 +0000897 PyErr_SetString(PyExc_IndexError,
898 "mmap assignment must be single-character string");
899 return -1;
900 }
901 if (!is_writeable(self))
902 return -1;
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000903 buf = PyString_AsString(value);
Thomas Wouters3ccec682007-08-28 15:28:19 +0000904 self->data[i] = buf[0];
905 return 0;
906 }
907 else if (PySlice_Check(item)) {
908 Py_ssize_t start, stop, step, slicelen;
909
910 if (PySlice_GetIndicesEx((PySliceObject *)item,
911 self->size, &start, &stop,
912 &step, &slicelen) < 0) {
913 return -1;
914 }
915 if (value == NULL) {
916 PyErr_SetString(PyExc_TypeError,
917 "mmap object doesn't support slice deletion");
918 return -1;
919 }
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000920 if (!PyString_Check(value)) {
Thomas Wouters3ccec682007-08-28 15:28:19 +0000921 PyErr_SetString(PyExc_IndexError,
922 "mmap slice assignment must be a string");
923 return -1;
924 }
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000925 if (PyString_Size(value) != slicelen) {
Thomas Wouters3ccec682007-08-28 15:28:19 +0000926 PyErr_SetString(PyExc_IndexError,
927 "mmap slice assignment is wrong size");
928 return -1;
929 }
930 if (!is_writeable(self))
931 return -1;
932
933 if (slicelen == 0)
934 return 0;
935 else if (step == 1) {
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000936 const char *buf = PyString_AsString(value);
Thomas Wouters3ccec682007-08-28 15:28:19 +0000937
938 if (buf == NULL)
939 return -1;
940 memcpy(self->data + start, buf, slicelen);
941 return 0;
942 }
943 else {
944 Py_ssize_t cur, i;
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000945 const char *buf = PyString_AsString(value);
Thomas Wouters3ccec682007-08-28 15:28:19 +0000946
947 if (buf == NULL)
948 return -1;
949 for (cur = start, i = 0; i < slicelen;
950 cur += step, i++) {
951 self->data[cur] = buf[i];
952 }
953 return 0;
954 }
955 }
956 else {
957 PyErr_SetString(PyExc_TypeError,
958 "mmap indices must be integer");
959 return -1;
960 }
961}
962
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000963static PySequenceMethods mmap_as_sequence = {
Martin v. Löwis18e16552006-02-15 17:27:45 +0000964 (lenfunc)mmap_length, /*sq_length*/
Guido van Rossum09fdf072000-03-31 01:17:07 +0000965 (binaryfunc)mmap_concat, /*sq_concat*/
Martin v. Löwis18e16552006-02-15 17:27:45 +0000966 (ssizeargfunc)mmap_repeat, /*sq_repeat*/
967 (ssizeargfunc)mmap_item, /*sq_item*/
968 (ssizessizeargfunc)mmap_slice, /*sq_slice*/
969 (ssizeobjargproc)mmap_ass_item, /*sq_ass_item*/
970 (ssizessizeobjargproc)mmap_ass_slice, /*sq_ass_slice*/
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000971};
972
Thomas Wouters3ccec682007-08-28 15:28:19 +0000973static PyMappingMethods mmap_as_mapping = {
974 (lenfunc)mmap_length,
975 (binaryfunc)mmap_subscript,
976 (objobjargproc)mmap_ass_subscript,
977};
978
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000979static PyBufferProcs mmap_as_buffer = {
Martin v. Löwis18e16552006-02-15 17:27:45 +0000980 (readbufferproc)mmap_buffer_getreadbuf,
981 (writebufferproc)mmap_buffer_getwritebuf,
982 (segcountproc)mmap_buffer_getsegcount,
983 (charbufferproc)mmap_buffer_getcharbuffer,
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000984};
985
Georg Brandl845c4032008-01-21 14:16:46 +0000986static PyObject *
987new_mmap_object(PyTypeObject *type, PyObject *args, PyObject *kwdict);
988
Georg Brandlef928022008-01-20 14:50:05 +0000989PyDoc_STRVAR(mmap_doc,
990"Windows: mmap(fileno, length[, tagname[, access[, offset]]])\n\
991\n\
992Maps length bytes from the file specified by the file handle fileno,\n\
993and returns a mmap object. If length is larger than the current size\n\
994of the file, the file is extended to contain length bytes. If length\n\
995is 0, the maximum length of the map is the current size of the file,\n\
996except that if the file is empty Windows raises an exception (you cannot\n\
997create an empty mapping on Windows).\n\
998\n\
999Unix: mmap(fileno, length[, flags[, prot[, access[, offset]]]])\n\
1000\n\
1001Maps length bytes from the file specified by the file descriptor fileno,\n\
1002and returns a mmap object. If length is 0, the maximum length of the map\n\
1003will be the current size of the file when mmap is called.\n\
1004flags specifies the nature of the mapping. MAP_PRIVATE creates a\n\
1005private copy-on-write mapping, so changes to the contents of the mmap\n\
Thomas Heller66260992008-08-19 17:47:13 +00001006object will be private to this process, and MAP_SHARED creates a mapping\n\
Georg Brandlef928022008-01-20 14:50:05 +00001007that's shared with all other processes mapping the same areas of the file.\n\
1008The default value is MAP_SHARED.\n\
1009\n\
1010To map anonymous memory, pass -1 as the fileno (both versions).");
1011
1012
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001013static PyTypeObject mmap_object_type = {
Georg Brandl845c4032008-01-21 14:16:46 +00001014 PyVarObject_HEAD_INIT(NULL, 0)
Guido van Rossum14648392001-12-08 18:02:58 +00001015 "mmap.mmap", /* tp_name */
Guido van Rossum09fdf072000-03-31 01:17:07 +00001016 sizeof(mmap_object), /* tp_size */
1017 0, /* tp_itemsize */
1018 /* methods */
1019 (destructor) mmap_object_dealloc, /* tp_dealloc */
1020 0, /* tp_print */
Georg Brandlef928022008-01-20 14:50:05 +00001021 0, /* tp_getattr */
Guido van Rossum09fdf072000-03-31 01:17:07 +00001022 0, /* tp_setattr */
1023 0, /* tp_compare */
1024 0, /* tp_repr */
1025 0, /* tp_as_number */
1026 &mmap_as_sequence, /*tp_as_sequence*/
Thomas Wouters3ccec682007-08-28 15:28:19 +00001027 &mmap_as_mapping, /*tp_as_mapping*/
Guido van Rossum09fdf072000-03-31 01:17:07 +00001028 0, /*tp_hash*/
1029 0, /*tp_call*/
1030 0, /*tp_str*/
Georg Brandlef928022008-01-20 14:50:05 +00001031 PyObject_GenericGetAttr, /*tp_getattro*/
Guido van Rossum09fdf072000-03-31 01:17:07 +00001032 0, /*tp_setattro*/
1033 &mmap_as_buffer, /*tp_as_buffer*/
Georg Brandl845c4032008-01-21 14:16:46 +00001034 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GETCHARBUFFER, /*tp_flags*/
Georg Brandlef928022008-01-20 14:50:05 +00001035 mmap_doc, /*tp_doc*/
1036 0, /* tp_traverse */
1037 0, /* tp_clear */
1038 0, /* tp_richcompare */
1039 0, /* tp_weaklistoffset */
Georg Brandl845c4032008-01-21 14:16:46 +00001040 0, /* tp_iter */
1041 0, /* tp_iternext */
Georg Brandlef928022008-01-20 14:50:05 +00001042 mmap_object_methods, /* tp_methods */
Georg Brandl845c4032008-01-21 14:16:46 +00001043 0, /* tp_members */
1044 0, /* tp_getset */
1045 0, /* tp_base */
1046 0, /* tp_dict */
1047 0, /* tp_descr_get */
1048 0, /* tp_descr_set */
1049 0, /* tp_dictoffset */
1050 0, /* tp_init */
1051 PyType_GenericAlloc, /* tp_alloc */
1052 new_mmap_object, /* tp_new */
1053 PyObject_Del, /* tp_free */
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001054};
1055
Andrew M. Kuchling70d27422000-06-18 04:45:14 +00001056
1057/* extract the map size from the given PyObject
1058
Thomas Wouters7e474022000-07-16 12:04:32 +00001059 Returns -1 on error, with an appropriate Python exception raised. On
Andrew M. Kuchling70d27422000-06-18 04:45:14 +00001060 success, the map size is returned. */
Martin v. Löwiscfe7e092006-02-17 06:59:14 +00001061static Py_ssize_t
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001062_GetMapSize(PyObject *o, const char* param)
Andrew M. Kuchling70d27422000-06-18 04:45:14 +00001063{
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001064 if (o == NULL)
1065 return 0;
Neal Norwitz8a87f5d2006-08-12 17:03:09 +00001066 if (PyIndex_Check(o)) {
1067 Py_ssize_t i = PyNumber_AsSsize_t(o, PyExc_OverflowError);
Guido van Rossum38fff8c2006-03-07 18:50:55 +00001068 if (i==-1 && PyErr_Occurred())
Andrew M. Kuchling70d27422000-06-18 04:45:14 +00001069 return -1;
Neal Norwitz8a87f5d2006-08-12 17:03:09 +00001070 if (i < 0) {
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001071 PyErr_Format(PyExc_OverflowError,
1072 "memory mapped %s must be positive",
1073 param);
Neal Norwitz8a87f5d2006-08-12 17:03:09 +00001074 return -1;
1075 }
Martin v. Löwiscfe7e092006-02-17 06:59:14 +00001076 return i;
Andrew M. Kuchling70d27422000-06-18 04:45:14 +00001077 }
Andrew M. Kuchling70d27422000-06-18 04:45:14 +00001078
Neal Norwitz8a87f5d2006-08-12 17:03:09 +00001079 PyErr_SetString(PyExc_TypeError, "map size must be an integral value");
Andrew M. Kuchling70d27422000-06-18 04:45:14 +00001080 return -1;
1081}
1082
Tim Petersec0a5f02006-02-16 23:47:20 +00001083#ifdef UNIX
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001084static PyObject *
Georg Brandl845c4032008-01-21 14:16:46 +00001085new_mmap_object(PyTypeObject *type, PyObject *args, PyObject *kwdict)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001086{
Neal Norwitzb5673922002-09-05 21:48:07 +00001087#ifdef HAVE_FSTAT
1088 struct stat st;
1089#endif
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +00001090 mmap_object *m_obj;
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001091 PyObject *map_size_obj = NULL, *offset_obj = NULL;
1092 Py_ssize_t map_size, offset;
Guido van Rossum09fdf072000-03-31 01:17:07 +00001093 int fd, flags = MAP_SHARED, prot = PROT_WRITE | PROT_READ;
Neal Norwitz0e6bc8c2006-02-05 05:45:43 +00001094 int devzero = -1;
Neal Norwitz8856fb72005-12-18 03:34:22 +00001095 int access = (int)ACCESS_DEFAULT;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001096 static char *keywords[] = {"fileno", "length",
Tim Petersec0a5f02006-02-16 23:47:20 +00001097 "flags", "prot",
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001098 "access", "offset", NULL};
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001099
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001100 if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iO|iiiO", keywords,
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001101 &fd, &map_size_obj, &flags, &prot,
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001102 &access, &offset_obj))
Guido van Rossum09fdf072000-03-31 01:17:07 +00001103 return NULL;
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001104 map_size = _GetMapSize(map_size_obj, "size");
Andrew M. Kuchling70d27422000-06-18 04:45:14 +00001105 if (map_size < 0)
1106 return NULL;
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001107 offset = _GetMapSize(offset_obj, "offset");
1108 if (offset < 0)
1109 return NULL;
Tim Peters5ebfd362001-11-13 23:11:19 +00001110
Tim Petersec0a5f02006-02-16 23:47:20 +00001111 if ((access != (int)ACCESS_DEFAULT) &&
Neal Norwitzd1cfc8a2006-02-05 03:36:57 +00001112 ((flags != MAP_SHARED) || (prot != (PROT_WRITE | PROT_READ))))
Tim Petersec0a5f02006-02-16 23:47:20 +00001113 return PyErr_Format(PyExc_ValueError,
Tim Peters5ebfd362001-11-13 23:11:19 +00001114 "mmap can't specify both access and flags, prot.");
Neal Norwitzd1cfc8a2006-02-05 03:36:57 +00001115 switch ((access_mode)access) {
Tim Peters5ebfd362001-11-13 23:11:19 +00001116 case ACCESS_READ:
1117 flags = MAP_SHARED;
1118 prot = PROT_READ;
1119 break;
1120 case ACCESS_WRITE:
1121 flags = MAP_SHARED;
1122 prot = PROT_READ | PROT_WRITE;
1123 break;
1124 case ACCESS_COPY:
1125 flags = MAP_PRIVATE;
1126 prot = PROT_READ | PROT_WRITE;
1127 break;
Tim Petersec0a5f02006-02-16 23:47:20 +00001128 case ACCESS_DEFAULT:
Tim Peters5ebfd362001-11-13 23:11:19 +00001129 /* use the specified or default values of flags and prot */
1130 break;
1131 default:
Tim Petersec0a5f02006-02-16 23:47:20 +00001132 return PyErr_Format(PyExc_ValueError,
Tim Peters5ebfd362001-11-13 23:11:19 +00001133 "mmap invalid access parameter.");
1134 }
Neal Norwitzb5673922002-09-05 21:48:07 +00001135
Christian Heimes7adfad82008-02-15 08:20:11 +00001136 if (prot == PROT_READ) {
1137 access = ACCESS_READ;
1138 }
1139
Neal Norwitzb5673922002-09-05 21:48:07 +00001140#ifdef HAVE_FSTAT
Martin v. Löwisc16f3bd2003-05-03 09:14:54 +00001141# ifdef __VMS
1142 /* on OpenVMS we must ensure that all bytes are written to the file */
Andrew M. Kuchling7c22ccc2008-01-10 13:37:12 +00001143 if (fd != -1) {
1144 fsync(fd);
1145 }
Martin v. Löwisc16f3bd2003-05-03 09:14:54 +00001146# endif
Andrew M. Kuchling7c22ccc2008-01-10 13:37:12 +00001147 if (fd != -1 && fstat(fd, &st) == 0 && S_ISREG(st.st_mode)) {
Martin v. Löwis7fe60c02005-03-03 11:22:44 +00001148 if (map_size == 0) {
Martin v. Löwiscfe7e092006-02-17 06:59:14 +00001149 map_size = st.st_size;
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001150 } else if ((size_t)offset + (size_t)map_size > st.st_size) {
Tim Petersec0a5f02006-02-16 23:47:20 +00001151 PyErr_SetString(PyExc_ValueError,
Martin v. Löwis7fe60c02005-03-03 11:22:44 +00001152 "mmap length is greater than file size");
1153 return NULL;
1154 }
Neal Norwitzb5673922002-09-05 21:48:07 +00001155 }
1156#endif
Georg Brandl845c4032008-01-21 14:16:46 +00001157 m_obj = (mmap_object *)type->tp_alloc(type, 0);
Guido van Rossum09fdf072000-03-31 01:17:07 +00001158 if (m_obj == NULL) {return NULL;}
Neal Norwitz3b4fff82006-01-11 08:54:45 +00001159 m_obj->data = NULL;
Guido van Rossum09fdf072000-03-31 01:17:07 +00001160 m_obj->size = (size_t) map_size;
1161 m_obj->pos = (size_t) 0;
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001162 m_obj->offset = offset;
Neal Norwitz0e6bc8c2006-02-05 05:45:43 +00001163 if (fd == -1) {
1164 m_obj->fd = -1;
1165 /* Assume the caller wants to map anonymous memory.
1166 This is the same behaviour as Windows. mmap.mmap(-1, size)
1167 on both Windows and Unix map anonymous memory.
1168 */
1169#ifdef MAP_ANONYMOUS
1170 /* BSD way to map anonymous memory */
1171 flags |= MAP_ANONYMOUS;
1172#else
1173 /* SVR4 method to map anonymous memory is to open /dev/zero */
1174 fd = devzero = open("/dev/zero", O_RDWR);
1175 if (devzero == -1) {
1176 Py_DECREF(m_obj);
1177 PyErr_SetFromErrno(mmap_module_error);
1178 return NULL;
1179 }
1180#endif
1181 } else {
1182 m_obj->fd = dup(fd);
1183 if (m_obj->fd == -1) {
1184 Py_DECREF(m_obj);
1185 PyErr_SetFromErrno(mmap_module_error);
1186 return NULL;
1187 }
Georg Brandl38387b82005-08-24 07:17:40 +00001188 }
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001189
Tim Petersec0a5f02006-02-16 23:47:20 +00001190 m_obj->data = mmap(NULL, map_size,
Guido van Rossum09fdf072000-03-31 01:17:07 +00001191 prot, flags,
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001192 fd, offset);
Neal Norwitz0e6bc8c2006-02-05 05:45:43 +00001193
1194 if (devzero != -1) {
1195 close(devzero);
1196 }
1197
Tim Peters5ebfd362001-11-13 23:11:19 +00001198 if (m_obj->data == (char *)-1) {
Andrew M. Kuchling16581c82004-05-19 14:39:08 +00001199 m_obj->data = NULL;
Guido van Rossum09fdf072000-03-31 01:17:07 +00001200 Py_DECREF(m_obj);
1201 PyErr_SetFromErrno(mmap_module_error);
1202 return NULL;
1203 }
Neal Norwitz8856fb72005-12-18 03:34:22 +00001204 m_obj->access = (access_mode)access;
Guido van Rossum09fdf072000-03-31 01:17:07 +00001205 return (PyObject *)m_obj;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001206}
1207#endif /* UNIX */
1208
Martin v. Löwis6238d2b2002-06-30 15:26:10 +00001209#ifdef MS_WINDOWS
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001210static PyObject *
Georg Brandl845c4032008-01-21 14:16:46 +00001211new_mmap_object(PyTypeObject *type, PyObject *args, PyObject *kwdict)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001212{
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +00001213 mmap_object *m_obj;
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001214 PyObject *map_size_obj = NULL, *offset_obj = NULL;
1215 Py_ssize_t map_size, offset;
1216 DWORD off_hi; /* upper 32 bits of offset */
1217 DWORD off_lo; /* lower 32 bits of offset */
1218 DWORD size_hi; /* upper 32 bits of size */
1219 DWORD size_lo; /* lower 32 bits of size */
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +00001220 char *tagname = "";
Guido van Rossum09fdf072000-03-31 01:17:07 +00001221 DWORD dwErr = 0;
1222 int fileno;
Mark Hammond071864a2000-07-30 02:46:26 +00001223 HANDLE fh = 0;
Neal Norwitz8856fb72005-12-18 03:34:22 +00001224 int access = (access_mode)ACCESS_DEFAULT;
Tim Peters5ebfd362001-11-13 23:11:19 +00001225 DWORD flProtect, dwDesiredAccess;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001226 static char *keywords[] = { "fileno", "length",
Tim Petersec0a5f02006-02-16 23:47:20 +00001227 "tagname",
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001228 "access", "offset", NULL };
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001229
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001230 if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iO|ziO", keywords,
Tim Petersec0a5f02006-02-16 23:47:20 +00001231 &fileno, &map_size_obj,
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001232 &tagname, &access, &offset_obj)) {
Guido van Rossum09fdf072000-03-31 01:17:07 +00001233 return NULL;
Tim Peters5ebfd362001-11-13 23:11:19 +00001234 }
1235
Neal Norwitz8856fb72005-12-18 03:34:22 +00001236 switch((access_mode)access) {
Tim Peters5ebfd362001-11-13 23:11:19 +00001237 case ACCESS_READ:
1238 flProtect = PAGE_READONLY;
1239 dwDesiredAccess = FILE_MAP_READ;
1240 break;
1241 case ACCESS_DEFAULT: case ACCESS_WRITE:
1242 flProtect = PAGE_READWRITE;
1243 dwDesiredAccess = FILE_MAP_WRITE;
1244 break;
1245 case ACCESS_COPY:
1246 flProtect = PAGE_WRITECOPY;
1247 dwDesiredAccess = FILE_MAP_COPY;
1248 break;
1249 default:
Tim Petersec0a5f02006-02-16 23:47:20 +00001250 return PyErr_Format(PyExc_ValueError,
Tim Peters5ebfd362001-11-13 23:11:19 +00001251 "mmap invalid access parameter.");
1252 }
1253
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001254 map_size = _GetMapSize(map_size_obj, "size");
Andrew M. Kuchling70d27422000-06-18 04:45:14 +00001255 if (map_size < 0)
1256 return NULL;
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001257 offset = _GetMapSize(offset_obj, "offset");
1258 if (offset < 0)
1259 return NULL;
Tim Petersec0a5f02006-02-16 23:47:20 +00001260
Neal Norwitz0e6bc8c2006-02-05 05:45:43 +00001261 /* assume -1 and 0 both mean invalid filedescriptor
1262 to 'anonymously' map memory.
1263 XXX: fileno == 0 is a valid fd, but was accepted prior to 2.5.
1264 XXX: Should this code be added?
1265 if (fileno == 0)
1266 PyErr_Warn(PyExc_DeprecationWarning,
1267 "don't use 0 for anonymous memory");
1268 */
1269 if (fileno != -1 && fileno != 0) {
Mark Hammond071864a2000-07-30 02:46:26 +00001270 fh = (HANDLE)_get_osfhandle(fileno);
1271 if (fh==(HANDLE)-1) {
Tim Peters5ebfd362001-11-13 23:11:19 +00001272 PyErr_SetFromErrno(mmap_module_error);
1273 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001274 }
Fred Drake1ef4e2d2000-04-05 14:15:31 +00001275 /* Win9x appears to need us seeked to zero */
Guido van Rossum69c2b882003-04-09 19:31:02 +00001276 lseek(fileno, 0, SEEK_SET);
Guido van Rossum09fdf072000-03-31 01:17:07 +00001277 }
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001278
Georg Brandl845c4032008-01-21 14:16:46 +00001279 m_obj = (mmap_object *)type->tp_alloc(type, 0);
Tim Peters8f9cc292006-02-17 00:00:20 +00001280 if (m_obj == NULL)
Mark Hammond2cbed002000-07-30 02:22:43 +00001281 return NULL;
1282 /* Set every field to an invalid marker, so we can safely
1283 destruct the object in the face of failure */
1284 m_obj->data = NULL;
Mark Hammond071864a2000-07-30 02:46:26 +00001285 m_obj->file_handle = INVALID_HANDLE_VALUE;
Hirokazu Yamamotoec5294f2009-03-05 14:30:13 +00001286 m_obj->map_handle = NULL;
Mark Hammond2cbed002000-07-30 02:22:43 +00001287 m_obj->tagname = NULL;
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001288 m_obj->offset = offset;
Mark Hammond2cbed002000-07-30 02:22:43 +00001289
Guido van Rossum09fdf072000-03-31 01:17:07 +00001290 if (fh) {
Mark Hammond2cbed002000-07-30 02:22:43 +00001291 /* It is necessary to duplicate the handle, so the
1292 Python code can close it on us */
1293 if (!DuplicateHandle(
Tim Peters5ebfd362001-11-13 23:11:19 +00001294 GetCurrentProcess(), /* source process handle */
1295 fh, /* handle to be duplicated */
1296 GetCurrentProcess(), /* target proc handle */
1297 (LPHANDLE)&m_obj->file_handle, /* result */
1298 0, /* access - ignored due to options value */
1299 FALSE, /* inherited by child processes? */
1300 DUPLICATE_SAME_ACCESS)) { /* options */
Mark Hammond2cbed002000-07-30 02:22:43 +00001301 dwErr = GetLastError();
1302 Py_DECREF(m_obj);
1303 PyErr_SetFromWindowsErr(dwErr);
1304 return NULL;
1305 }
Guido van Rossum09fdf072000-03-31 01:17:07 +00001306 if (!map_size) {
Martin v. Löwis15186072006-02-18 12:38:35 +00001307 DWORD low,high;
1308 low = GetFileSize(fh, &high);
1309 /* low might just happen to have the value INVALID_FILE_SIZE;
1310 so we need to check the last error also. */
1311 if (low == INVALID_FILE_SIZE &&
1312 (dwErr = GetLastError()) != NO_ERROR) {
1313 Py_DECREF(m_obj);
1314 return PyErr_SetFromWindowsErr(dwErr);
1315 }
1316
1317#if SIZEOF_SIZE_T > 4
1318 m_obj->size = (((size_t)high)<<32) + low;
1319#else
1320 if (high)
1321 /* File is too large to map completely */
1322 m_obj->size = (size_t)-1;
1323 else
1324 m_obj->size = low;
1325#endif
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001326 } else {
Guido van Rossum09fdf072000-03-31 01:17:07 +00001327 m_obj->size = map_size;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001328 }
Guido van Rossum09fdf072000-03-31 01:17:07 +00001329 }
1330 else {
Guido van Rossum09fdf072000-03-31 01:17:07 +00001331 m_obj->size = map_size;
1332 }
1333
1334 /* set the initial position */
1335 m_obj->pos = (size_t) 0;
1336
Mark Hammond2cbed002000-07-30 02:22:43 +00001337 /* set the tag name */
Tim Peters0d9f9dc2001-01-10 05:42:18 +00001338 if (tagname != NULL && *tagname != '\0') {
Mark Hammond2cbed002000-07-30 02:22:43 +00001339 m_obj->tagname = PyMem_Malloc(strlen(tagname)+1);
1340 if (m_obj->tagname == NULL) {
1341 PyErr_NoMemory();
1342 Py_DECREF(m_obj);
1343 return NULL;
1344 }
1345 strcpy(m_obj->tagname, tagname);
1346 }
1347 else
1348 m_obj->tagname = NULL;
1349
Neal Norwitz8856fb72005-12-18 03:34:22 +00001350 m_obj->access = (access_mode)access;
Tim Peterse564e7f2006-02-16 23:46:01 +00001351 /* DWORD is a 4-byte int. If we're on a box where size_t consumes
Thomas Wouters2c98a7b2006-02-17 09:59:00 +00001352 * more than 4 bytes, we need to break it apart. Else (size_t
Tim Peterse564e7f2006-02-16 23:46:01 +00001353 * consumes 4 bytes), C doesn't define what happens if we shift
1354 * right by 32, so we need different code.
1355 */
1356#if SIZEOF_SIZE_T > 4
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001357 size_hi = (DWORD)((offset + m_obj->size) >> 32);
1358 size_lo = (DWORD)((offset + m_obj->size) & 0xFFFFFFFF);
1359 off_hi = (DWORD)(offset >> 32);
1360 off_lo = (DWORD)(offset & 0xFFFFFFFF);
Tim Peterse564e7f2006-02-16 23:46:01 +00001361#else
1362 size_hi = 0;
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001363 size_lo = (DWORD)(offset + m_obj->size);
1364 off_hi = 0;
1365 off_lo = (DWORD)offset;
Tim Peterse564e7f2006-02-16 23:46:01 +00001366#endif
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001367 /* For files, it would be sufficient to pass 0 as size.
1368 For anonymous maps, we have to pass the size explicitly. */
Tim Peters8f9cc292006-02-17 00:00:20 +00001369 m_obj->map_handle = CreateFileMapping(m_obj->file_handle,
1370 NULL,
1371 flProtect,
1372 size_hi,
1373 size_lo,
1374 m_obj->tagname);
Guido van Rossum09fdf072000-03-31 01:17:07 +00001375 if (m_obj->map_handle != NULL) {
Tim Peters8f9cc292006-02-17 00:00:20 +00001376 m_obj->data = (char *) MapViewOfFile(m_obj->map_handle,
1377 dwDesiredAccess,
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001378 off_hi,
1379 off_lo,
Hirokazu Yamamoto4b27e962009-02-28 12:42:16 +00001380 m_obj->size);
Tim Peters23721ee2006-02-16 23:50:16 +00001381 if (m_obj->data != NULL)
1382 return (PyObject *)m_obj;
Hirokazu Yamamotoec5294f2009-03-05 14:30:13 +00001383 else {
Tim Peters5ebfd362001-11-13 23:11:19 +00001384 dwErr = GetLastError();
Hirokazu Yamamotoec5294f2009-03-05 14:30:13 +00001385 CloseHandle(m_obj->map_handle);
1386 m_obj->map_handle = NULL;
1387 }
Tim Peters23721ee2006-02-16 23:50:16 +00001388 } else
Guido van Rossum09fdf072000-03-31 01:17:07 +00001389 dwErr = GetLastError();
Mark Hammond2cbed002000-07-30 02:22:43 +00001390 Py_DECREF(m_obj);
Guido van Rossum09fdf072000-03-31 01:17:07 +00001391 PyErr_SetFromWindowsErr(dwErr);
Tim Peters23721ee2006-02-16 23:50:16 +00001392 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001393}
Martin v. Löwis6238d2b2002-06-30 15:26:10 +00001394#endif /* MS_WINDOWS */
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001395
Neal Norwitze9ac0bb2006-08-13 18:11:27 +00001396static void
1397setint(PyObject *d, const char *name, long value)
1398{
1399 PyObject *o = PyInt_FromLong(value);
Neal Norwitz5ed49972006-08-13 18:41:15 +00001400 if (o && PyDict_SetItemString(d, name, o) == 0) {
Neal Norwitze9ac0bb2006-08-13 18:11:27 +00001401 Py_DECREF(o);
Neal Norwitz5ed49972006-08-13 18:41:15 +00001402 }
Neal Norwitze9ac0bb2006-08-13 18:11:27 +00001403}
1404
Mark Hammond62b1ab12002-07-23 06:31:15 +00001405PyMODINIT_FUNC
Georg Brandl845c4032008-01-21 14:16:46 +00001406initmmap(void)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001407{
Guido van Rossum09fdf072000-03-31 01:17:07 +00001408 PyObject *dict, *module;
Tim Peters2caf8df2001-01-14 05:05:51 +00001409
Georg Brandl845c4032008-01-21 14:16:46 +00001410 if (PyType_Ready(&mmap_object_type) < 0)
1411 return;
Tim Peters2caf8df2001-01-14 05:05:51 +00001412
Georg Brandl845c4032008-01-21 14:16:46 +00001413 module = Py_InitModule("mmap", NULL);
Neal Norwitz1ac754f2006-01-19 06:09:39 +00001414 if (module == NULL)
1415 return;
Tim Peters8f9cc292006-02-17 00:00:20 +00001416 dict = PyModule_GetDict(module);
Neal Norwitze9ac0bb2006-08-13 18:11:27 +00001417 if (!dict)
1418 return;
Facundo Batistae1396882008-02-17 18:59:29 +00001419 mmap_module_error = PyErr_NewException("mmap.error",
1420 PyExc_EnvironmentError , NULL);
1421 if (mmap_module_error == NULL)
1422 return;
Tim Peters8f9cc292006-02-17 00:00:20 +00001423 PyDict_SetItemString(dict, "error", mmap_module_error);
Georg Brandl845c4032008-01-21 14:16:46 +00001424 PyDict_SetItemString(dict, "mmap", (PyObject*) &mmap_object_type);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001425#ifdef PROT_EXEC
Neal Norwitze9ac0bb2006-08-13 18:11:27 +00001426 setint(dict, "PROT_EXEC", PROT_EXEC);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001427#endif
1428#ifdef PROT_READ
Neal Norwitze9ac0bb2006-08-13 18:11:27 +00001429 setint(dict, "PROT_READ", PROT_READ);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001430#endif
1431#ifdef PROT_WRITE
Neal Norwitze9ac0bb2006-08-13 18:11:27 +00001432 setint(dict, "PROT_WRITE", PROT_WRITE);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001433#endif
1434
1435#ifdef MAP_SHARED
Neal Norwitze9ac0bb2006-08-13 18:11:27 +00001436 setint(dict, "MAP_SHARED", MAP_SHARED);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001437#endif
1438#ifdef MAP_PRIVATE
Neal Norwitze9ac0bb2006-08-13 18:11:27 +00001439 setint(dict, "MAP_PRIVATE", MAP_PRIVATE);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001440#endif
1441#ifdef MAP_DENYWRITE
Neal Norwitze9ac0bb2006-08-13 18:11:27 +00001442 setint(dict, "MAP_DENYWRITE", MAP_DENYWRITE);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001443#endif
1444#ifdef MAP_EXECUTABLE
Neal Norwitze9ac0bb2006-08-13 18:11:27 +00001445 setint(dict, "MAP_EXECUTABLE", MAP_EXECUTABLE);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001446#endif
Neal Norwitz0e6bc8c2006-02-05 05:45:43 +00001447#ifdef MAP_ANONYMOUS
Neal Norwitze9ac0bb2006-08-13 18:11:27 +00001448 setint(dict, "MAP_ANON", MAP_ANONYMOUS);
1449 setint(dict, "MAP_ANONYMOUS", MAP_ANONYMOUS);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001450#endif
1451
Neal Norwitze9ac0bb2006-08-13 18:11:27 +00001452 setint(dict, "PAGESIZE", (long)my_getpagesize());
Andrew M. Kuchling961fe172000-06-03 19:41:42 +00001453
Travis E. Oliphant8feafab2007-10-23 02:40:56 +00001454 setint(dict, "ALLOCATIONGRANULARITY", (long)my_getallocationgranularity());
1455
Neal Norwitze9ac0bb2006-08-13 18:11:27 +00001456 setint(dict, "ACCESS_READ", ACCESS_READ);
1457 setint(dict, "ACCESS_WRITE", ACCESS_WRITE);
1458 setint(dict, "ACCESS_COPY", ACCESS_COPY);
Tim Peters5ebfd362001-11-13 23:11:19 +00001459}