blob: 43ce0a581e84274dd6348bd12273a0a1eabb472d [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
6 / mmapmodule.cpp -- map a view of a file into memory
7 /
8 / todo: need permission flags, perhaps a 'chsize' analog
9 / not all functions check range yet!!!
10 /
11 /
12 / Note: This module currently only deals with 32-bit file
13 / sizes.
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
Guido van Rossum09fdf072000-03-31 01:17:07 +000021#include <Python.h>
22
Martin v. Löwis6238d2b2002-06-30 15:26:10 +000023#ifndef MS_WINDOWS
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +000024#define UNIX
25#endif
26
Martin v. Löwis6238d2b2002-06-30 15:26:10 +000027#ifdef MS_WINDOWS
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +000028#include <windows.h>
Fred Drake145f96e2000-10-01 17:50:46 +000029static int
30my_getpagesize(void)
31{
Tim Peters5ebfd362001-11-13 23:11:19 +000032 SYSTEM_INFO si;
33 GetSystemInfo(&si);
34 return si.dwPageSize;
Fred Drake145f96e2000-10-01 17:50:46 +000035}
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +000036#endif
37
38#ifdef UNIX
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +000039#include <sys/mman.h>
Andrew M. Kuchling7b9fb922000-06-17 22:41:22 +000040#include <sys/stat.h>
Guido van Rossum4b36e6b2000-09-25 13:16:15 +000041
Fred Drake145f96e2000-10-01 17:50:46 +000042#if defined(HAVE_SYSCONF) && defined(_SC_PAGESIZE)
43static int
44my_getpagesize(void)
45{
Tim Peters5ebfd362001-11-13 23:11:19 +000046 return sysconf(_SC_PAGESIZE);
Fred Drake145f96e2000-10-01 17:50:46 +000047}
48#else
49#define my_getpagesize getpagesize
50#endif
51
Guido van Rossum4b36e6b2000-09-25 13:16:15 +000052#endif /* UNIX */
53
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +000054#include <string.h>
55#include <sys/types.h>
56
Neal Norwitz3eaf2b52006-02-16 08:08:54 +000057/* Prefer MAP_ANONYMOUS since MAP_ANON is deprecated according to man page. */
Neal Norwitz0e6bc8c2006-02-05 05:45:43 +000058#if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)
59# define MAP_ANONYMOUS MAP_ANON
60#endif
61
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +000062static PyObject *mmap_module_error;
63
Tim Peters5ebfd362001-11-13 23:11:19 +000064typedef enum
65{
66 ACCESS_DEFAULT,
67 ACCESS_READ,
68 ACCESS_WRITE,
69 ACCESS_COPY
70} access_mode;
71
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +000072typedef struct {
Guido van Rossum09fdf072000-03-31 01:17:07 +000073 PyObject_HEAD
74 char * data;
75 size_t size;
76 size_t pos;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +000077
Martin v. Löwis6238d2b2002-06-30 15:26:10 +000078#ifdef MS_WINDOWS
Guido van Rossum09fdf072000-03-31 01:17:07 +000079 HANDLE map_handle;
Mark Hammond071864a2000-07-30 02:46:26 +000080 HANDLE file_handle;
Guido van Rossum09fdf072000-03-31 01:17:07 +000081 char * tagname;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +000082#endif
83
84#ifdef UNIX
Andrew M. Kuchling7b9fb922000-06-17 22:41:22 +000085 int fd;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +000086#endif
Tim Peters5ebfd362001-11-13 23:11:19 +000087
88 access_mode access;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +000089} mmap_object;
90
Tim Peters5ebfd362001-11-13 23:11:19 +000091
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +000092static void
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +000093mmap_object_dealloc(mmap_object *m_obj)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +000094{
Martin v. Löwis6238d2b2002-06-30 15:26:10 +000095#ifdef MS_WINDOWS
Mark Hammond2cbed002000-07-30 02:22:43 +000096 if (m_obj->data != NULL)
97 UnmapViewOfFile (m_obj->data);
98 if (m_obj->map_handle != INVALID_HANDLE_VALUE)
99 CloseHandle (m_obj->map_handle);
Mark Hammond071864a2000-07-30 02:46:26 +0000100 if (m_obj->file_handle != INVALID_HANDLE_VALUE)
101 CloseHandle (m_obj->file_handle);
Mark Hammond2cbed002000-07-30 02:22:43 +0000102 if (m_obj->tagname)
103 PyMem_Free(m_obj->tagname);
Martin v. Löwis6238d2b2002-06-30 15:26:10 +0000104#endif /* MS_WINDOWS */
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000105
106#ifdef UNIX
Neal Norwitz6eac2002005-11-02 05:36:37 +0000107 if (m_obj->fd >= 0)
108 (void) close(m_obj->fd);
Guido van Rossum09fdf072000-03-31 01:17:07 +0000109 if (m_obj->data!=NULL) {
Andrew M. Kuchling9bc5f332000-06-18 04:25:08 +0000110 msync(m_obj->data, m_obj->size, MS_SYNC);
Guido van Rossum09fdf072000-03-31 01:17:07 +0000111 munmap(m_obj->data, m_obj->size);
112 }
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000113#endif /* UNIX */
114
Guido van Rossumb18618d2000-05-03 23:44:39 +0000115 PyObject_Del(m_obj);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000116}
117
118static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000119mmap_close_method(mmap_object *self, PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000120{
Andrew M. Kuchling841b9fb2000-06-03 20:43:43 +0000121 if (!PyArg_ParseTuple(args, ":close"))
Andrew M. Kuchling961fe172000-06-03 19:41:42 +0000122 return NULL;
Martin v. Löwis6238d2b2002-06-30 15:26:10 +0000123#ifdef MS_WINDOWS
Mark Hammond071864a2000-07-30 02:46:26 +0000124 /* For each resource we maintain, we need to check
Tim Petersec0a5f02006-02-16 23:47:20 +0000125 the value is valid, and if so, free the resource
Mark Hammond071864a2000-07-30 02:46:26 +0000126 and set the member value to an invalid value so
127 the dealloc does not attempt to resource clearing
128 again.
129 TODO - should we check for errors in the close operations???
130 */
131 if (self->data != NULL) {
132 UnmapViewOfFile (self->data);
133 self->data = NULL;
134 }
135 if (self->map_handle != INVALID_HANDLE_VALUE) {
136 CloseHandle (self->map_handle);
137 self->map_handle = INVALID_HANDLE_VALUE;
138 }
139 if (self->file_handle != INVALID_HANDLE_VALUE) {
140 CloseHandle (self->file_handle);
141 self->file_handle = INVALID_HANDLE_VALUE;
142 }
Martin v. Löwis6238d2b2002-06-30 15:26:10 +0000143#endif /* MS_WINDOWS */
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000144
145#ifdef UNIX
Neal Norwitz6eac2002005-11-02 05:36:37 +0000146 (void) close(self->fd);
147 self->fd = -1;
Neal Norwitze604c022003-01-10 20:52:16 +0000148 if (self->data != NULL) {
149 munmap(self->data, self->size);
150 self->data = NULL;
151 }
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000152#endif
153
Guido van Rossum09fdf072000-03-31 01:17:07 +0000154 Py_INCREF (Py_None);
155 return (Py_None);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000156}
157
Martin v. Löwis6238d2b2002-06-30 15:26:10 +0000158#ifdef MS_WINDOWS
Guido van Rossum09fdf072000-03-31 01:17:07 +0000159#define CHECK_VALID(err) \
160do { \
Guido van Rossum69c2b882003-04-09 19:31:02 +0000161 if (self->map_handle == INVALID_HANDLE_VALUE) { \
Guido van Rossum09fdf072000-03-31 01:17:07 +0000162 PyErr_SetString (PyExc_ValueError, "mmap closed or invalid"); \
163 return err; \
164 } \
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000165} while (0)
Martin v. Löwis6238d2b2002-06-30 15:26:10 +0000166#endif /* MS_WINDOWS */
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000167
168#ifdef UNIX
Guido van Rossum09fdf072000-03-31 01:17:07 +0000169#define CHECK_VALID(err) \
170do { \
171 if (self->data == NULL) { \
172 PyErr_SetString (PyExc_ValueError, "mmap closed or invalid"); \
173 return err; \
174 } \
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000175} while (0)
176#endif /* UNIX */
177
178static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000179mmap_read_byte_method(mmap_object *self,
180 PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000181{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000182 CHECK_VALID(NULL);
Andrew M. Kuchling841b9fb2000-06-03 20:43:43 +0000183 if (!PyArg_ParseTuple(args, ":read_byte"))
Andrew M. Kuchling961fe172000-06-03 19:41:42 +0000184 return NULL;
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000185 if (self->pos < self->size) {
Tim Petersd6283b82001-05-09 18:48:26 +0000186 char value = self->data[self->pos];
Guido van Rossum09fdf072000-03-31 01:17:07 +0000187 self->pos += 1;
Tim Petersd6283b82001-05-09 18:48:26 +0000188 return Py_BuildValue("c", value);
Guido van Rossum09fdf072000-03-31 01:17:07 +0000189 } else {
190 PyErr_SetString (PyExc_ValueError, "read byte out of range");
191 return NULL;
192 }
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000193}
194
195static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000196mmap_read_line_method(mmap_object *self,
Tim Peters5ebfd362001-11-13 23:11:19 +0000197 PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000198{
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000199 char *start = self->data+self->pos;
200 char *eof = self->data+self->size;
201 char *eol;
202 PyObject *result;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000203
Guido van Rossum09fdf072000-03-31 01:17:07 +0000204 CHECK_VALID(NULL);
Andrew M. Kuchling841b9fb2000-06-03 20:43:43 +0000205 if (!PyArg_ParseTuple(args, ":readline"))
Andrew M. Kuchling961fe172000-06-03 19:41:42 +0000206 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000207
Fred Drake56a87a02000-04-04 18:17:35 +0000208 eol = memchr(start, '\n', self->size - self->pos);
209 if (!eol)
210 eol = eof;
211 else
212 ++eol; /* we're interested in the position after the
213 newline. */
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000214 result = PyString_FromStringAndSize(start, (eol - start));
Guido van Rossum09fdf072000-03-31 01:17:07 +0000215 self->pos += (eol - start);
216 return (result);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000217}
218
219static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000220mmap_read_method(mmap_object *self,
221 PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000222{
Martin v. Löwisad0a4622006-02-16 14:30:23 +0000223 Py_ssize_t num_bytes;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000224 PyObject *result;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000225
Guido van Rossum09fdf072000-03-31 01:17:07 +0000226 CHECK_VALID(NULL);
Martin v. Löwisad0a4622006-02-16 14:30:23 +0000227 if (!PyArg_ParseTuple(args, "n:read", &num_bytes))
Guido van Rossum09fdf072000-03-31 01:17:07 +0000228 return(NULL);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000229
Guido van Rossum09fdf072000-03-31 01:17:07 +0000230 /* silently 'adjust' out-of-range requests */
231 if ((self->pos + num_bytes) > self->size) {
232 num_bytes -= (self->pos+num_bytes) - self->size;
233 }
234 result = Py_BuildValue("s#", self->data+self->pos, num_bytes);
Tim Petersec0a5f02006-02-16 23:47:20 +0000235 self->pos += num_bytes;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000236 return (result);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000237}
238
239static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000240mmap_find_method(mmap_object *self,
241 PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000242{
Martin v. Löwisad0a4622006-02-16 14:30:23 +0000243 Py_ssize_t start = self->pos;
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000244 char *needle;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000245 int len;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000246
Guido van Rossum09fdf072000-03-31 01:17:07 +0000247 CHECK_VALID(NULL);
Thomas Woutersdde17652006-02-16 21:10:52 +0000248 if (!PyArg_ParseTuple (args, "s#|n:find", &needle, &len, &start)) {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000249 return NULL;
250 } else {
Greg Stein834f4dd2001-05-14 09:32:26 +0000251 char *p;
252 char *e = self->data + self->size;
253
254 if (start < 0)
Tim Peters5ebfd362001-11-13 23:11:19 +0000255 start += self->size;
Greg Stein834f4dd2001-05-14 09:32:26 +0000256 if (start < 0)
Tim Peters5ebfd362001-11-13 23:11:19 +0000257 start = 0;
Tim Petersd401edd2001-05-14 23:19:12 +0000258 else if ((size_t)start > self->size)
Tim Peters5ebfd362001-11-13 23:11:19 +0000259 start = self->size;
Greg Stein834f4dd2001-05-14 09:32:26 +0000260
Tim Petersc9ffa062002-03-08 05:43:32 +0000261 for (p = self->data + start; p + len <= e; ++p) {
262 int i;
263 for (i = 0; i < len && needle[i] == p[i]; ++i)
264 /* nothing */;
265 if (i == len) {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000266 return Py_BuildValue (
Tim Petersd401edd2001-05-14 23:19:12 +0000267 "l",
268 (long) (p - self->data));
Guido van Rossum09fdf072000-03-31 01:17:07 +0000269 }
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000270 }
Guido van Rossum09fdf072000-03-31 01:17:07 +0000271 return Py_BuildValue ("l", (long) -1);
272 }
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000273}
274
Tim Petersec0a5f02006-02-16 23:47:20 +0000275static int
Tim Peters5ebfd362001-11-13 23:11:19 +0000276is_writeable(mmap_object *self)
277{
278 if (self->access != ACCESS_READ)
Tim Petersec0a5f02006-02-16 23:47:20 +0000279 return 1;
Tim Peters5ebfd362001-11-13 23:11:19 +0000280 PyErr_Format(PyExc_TypeError, "mmap can't modify a readonly memory map.");
281 return 0;
282}
283
Tim Petersec0a5f02006-02-16 23:47:20 +0000284static int
Tim Peters5ebfd362001-11-13 23:11:19 +0000285is_resizeable(mmap_object *self)
286{
287 if ((self->access == ACCESS_WRITE) || (self->access == ACCESS_DEFAULT))
Tim Petersec0a5f02006-02-16 23:47:20 +0000288 return 1;
289 PyErr_Format(PyExc_TypeError,
Tim Peters5ebfd362001-11-13 23:11:19 +0000290 "mmap can't resize a readonly or copy-on-write memory map.");
291 return 0;
292}
293
294
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000295static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000296mmap_write_method(mmap_object *self,
297 PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000298{
Neal Norwitz4d933fe2003-02-07 19:44:56 +0000299 int length;
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000300 char *data;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000301
Guido van Rossum09fdf072000-03-31 01:17:07 +0000302 CHECK_VALID(NULL);
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000303 if (!PyArg_ParseTuple (args, "s#:write", &data, &length))
Guido van Rossum09fdf072000-03-31 01:17:07 +0000304 return(NULL);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000305
Tim Peters5ebfd362001-11-13 23:11:19 +0000306 if (!is_writeable(self))
307 return NULL;
308
Guido van Rossum09fdf072000-03-31 01:17:07 +0000309 if ((self->pos + length) > self->size) {
310 PyErr_SetString (PyExc_ValueError, "data out of range");
311 return NULL;
312 }
313 memcpy (self->data+self->pos, data, length);
314 self->pos = self->pos+length;
315 Py_INCREF (Py_None);
316 return (Py_None);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000317}
318
319static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000320mmap_write_byte_method(mmap_object *self,
321 PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000322{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000323 char value;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000324
Guido van Rossum09fdf072000-03-31 01:17:07 +0000325 CHECK_VALID(NULL);
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000326 if (!PyArg_ParseTuple (args, "c:write_byte", &value))
Guido van Rossum09fdf072000-03-31 01:17:07 +0000327 return(NULL);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000328
Tim Peters5ebfd362001-11-13 23:11:19 +0000329 if (!is_writeable(self))
330 return NULL;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000331 *(self->data+self->pos) = value;
332 self->pos += 1;
333 Py_INCREF (Py_None);
334 return (Py_None);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000335}
Tim Petersec0a5f02006-02-16 23:47:20 +0000336
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000337static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000338mmap_size_method(mmap_object *self,
339 PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000340{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000341 CHECK_VALID(NULL);
Andrew M. Kuchling841b9fb2000-06-03 20:43:43 +0000342 if (!PyArg_ParseTuple(args, ":size"))
Andrew M. Kuchling961fe172000-06-03 19:41:42 +0000343 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000344
Martin v. Löwis6238d2b2002-06-30 15:26:10 +0000345#ifdef MS_WINDOWS
Mark Hammond071864a2000-07-30 02:46:26 +0000346 if (self->file_handle != INVALID_HANDLE_VALUE) {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000347 return (Py_BuildValue (
Fredrik Lundh5cccf502000-07-09 13:16:13 +0000348 "l", (long)
Mark Hammond071864a2000-07-30 02:46:26 +0000349 GetFileSize (self->file_handle, NULL)));
Guido van Rossum09fdf072000-03-31 01:17:07 +0000350 } else {
Fredrik Lundh5cccf502000-07-09 13:16:13 +0000351 return (Py_BuildValue ("l", (long) self->size) );
Guido van Rossum09fdf072000-03-31 01:17:07 +0000352 }
Martin v. Löwis6238d2b2002-06-30 15:26:10 +0000353#endif /* MS_WINDOWS */
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000354
355#ifdef UNIX
Andrew M. Kuchling7b9fb922000-06-17 22:41:22 +0000356 {
357 struct stat buf;
358 if (-1 == fstat(self->fd, &buf)) {
359 PyErr_SetFromErrno(mmap_module_error);
360 return NULL;
361 }
Fredrik Lundh5cccf502000-07-09 13:16:13 +0000362 return (Py_BuildValue ("l", (long) buf.st_size) );
Andrew M. Kuchling7b9fb922000-06-17 22:41:22 +0000363 }
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000364#endif /* UNIX */
365}
366
367/* This assumes that you want the entire file mapped,
368 / and when recreating the map will make the new file
369 / have the new size
370 /
371 / Is this really necessary? This could easily be done
372 / from python by just closing and re-opening with the
373 / new size?
374 */
375
376static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000377mmap_resize_method(mmap_object *self,
378 PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000379{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000380 unsigned long new_size;
381 CHECK_VALID(NULL);
Tim Petersec0a5f02006-02-16 23:47:20 +0000382 if (!PyArg_ParseTuple (args, "k:resize", &new_size) ||
Tim Peters5ebfd362001-11-13 23:11:19 +0000383 !is_resizeable(self)) {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000384 return NULL;
Martin v. Löwis6238d2b2002-06-30 15:26:10 +0000385#ifdef MS_WINDOWS
Tim Petersec0a5f02006-02-16 23:47:20 +0000386 } else {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000387 DWORD dwErrCode = 0;
388 /* First, unmap the file view */
389 UnmapViewOfFile (self->data);
390 /* Close the mapping object */
Mark Hammond071864a2000-07-30 02:46:26 +0000391 CloseHandle (self->map_handle);
Guido van Rossum09fdf072000-03-31 01:17:07 +0000392 /* Move to the desired EOF position */
Mark Hammond071864a2000-07-30 02:46:26 +0000393 SetFilePointer (self->file_handle,
Guido van Rossum09fdf072000-03-31 01:17:07 +0000394 new_size, NULL, FILE_BEGIN);
395 /* Change the size of the file */
Mark Hammond071864a2000-07-30 02:46:26 +0000396 SetEndOfFile (self->file_handle);
Guido van Rossum09fdf072000-03-31 01:17:07 +0000397 /* Create another mapping object and remap the file view */
398 self->map_handle = CreateFileMapping (
Mark Hammond071864a2000-07-30 02:46:26 +0000399 self->file_handle,
Guido van Rossum09fdf072000-03-31 01:17:07 +0000400 NULL,
401 PAGE_READWRITE,
402 0,
403 new_size,
404 self->tagname);
405 if (self->map_handle != NULL) {
406 self->data = (char *) MapViewOfFile (self->map_handle,
407 FILE_MAP_WRITE,
408 0,
409 0,
410 0);
411 if (self->data != NULL) {
412 self->size = new_size;
413 Py_INCREF (Py_None);
414 return Py_None;
415 } else {
416 dwErrCode = GetLastError();
417 }
418 } else {
419 dwErrCode = GetLastError();
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000420 }
Guido van Rossum09fdf072000-03-31 01:17:07 +0000421 PyErr_SetFromWindowsErr(dwErrCode);
422 return (NULL);
Martin v. Löwis6238d2b2002-06-30 15:26:10 +0000423#endif /* MS_WINDOWS */
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000424
425#ifdef UNIX
Tim Petersec0a5f02006-02-16 23:47:20 +0000426#ifndef HAVE_MREMAP
Tim Peters5ebfd362001-11-13 23:11:19 +0000427 } else {
428 PyErr_SetString(PyExc_SystemError,
429 "mmap: resizing not available--no mremap()");
430 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000431#else
Tim Peters5ebfd362001-11-13 23:11:19 +0000432 } else {
Armin Rigo335ffe82005-09-20 19:04:02 +0000433 void *newmap;
434
Georg Brandl38387b82005-08-24 07:17:40 +0000435 if (ftruncate(self->fd, new_size) == -1) {
436 PyErr_SetFromErrno(mmap_module_error);
437 return NULL;
438 }
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000439
Andrew M. Kuchling6fef30e2000-06-18 14:51:21 +0000440#ifdef MREMAP_MAYMOVE
Tim Peters5ebfd362001-11-13 23:11:19 +0000441 newmap = mremap(self->data, self->size, new_size, MREMAP_MAYMOVE);
Andrew M. Kuchling6fef30e2000-06-18 14:51:21 +0000442#else
Tim Peters5ebfd362001-11-13 23:11:19 +0000443 newmap = mremap(self->data, self->size, new_size, 0);
Andrew M. Kuchling6fef30e2000-06-18 14:51:21 +0000444#endif
Tim Petersec0a5f02006-02-16 23:47:20 +0000445 if (newmap == (void *)-1)
Tim Peters5ebfd362001-11-13 23:11:19 +0000446 {
447 PyErr_SetFromErrno(mmap_module_error);
448 return NULL;
449 }
450 self->data = newmap;
451 self->size = new_size;
452 Py_INCREF(Py_None);
453 return Py_None;
Andrew M. Kuchling6fef30e2000-06-18 14:51:21 +0000454#endif /* HAVE_MREMAP */
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000455#endif /* UNIX */
Tim Peters5ebfd362001-11-13 23:11:19 +0000456 }
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000457}
458
459static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000460mmap_tell_method(mmap_object *self, PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000461{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000462 CHECK_VALID(NULL);
Andrew M. Kuchling841b9fb2000-06-03 20:43:43 +0000463 if (!PyArg_ParseTuple(args, ":tell"))
Andrew M. Kuchling961fe172000-06-03 19:41:42 +0000464 return NULL;
Fredrik Lundh5cccf502000-07-09 13:16:13 +0000465 return (Py_BuildValue ("l", (long) self->pos) );
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000466}
467
468static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000469mmap_flush_method(mmap_object *self, PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000470{
Martin v. Löwisad0a4622006-02-16 14:30:23 +0000471 Py_ssize_t offset = 0;
472 Py_ssize_t size = self->size;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000473 CHECK_VALID(NULL);
Martin v. Löwisad0a4622006-02-16 14:30:23 +0000474 if (!PyArg_ParseTuple (args, "|nn:flush", &offset, &size)) {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000475 return NULL;
476 } else if ((offset + size) > self->size) {
477 PyErr_SetString (PyExc_ValueError,
478 "flush values out of range");
479 return NULL;
480 } else {
Martin v. Löwis6238d2b2002-06-30 15:26:10 +0000481#ifdef MS_WINDOWS
Fredrik Lundh5cccf502000-07-09 13:16:13 +0000482 return (Py_BuildValue("l", (long)
483 FlushViewOfFile(self->data+offset, size)));
Martin v. Löwis6238d2b2002-06-30 15:26:10 +0000484#endif /* MS_WINDOWS */
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000485#ifdef UNIX
Guido van Rossum09fdf072000-03-31 01:17:07 +0000486 /* XXX semantics of return value? */
487 /* XXX flags for msync? */
488 if (-1 == msync(self->data + offset, size,
Andrew M. Kuchling9bc5f332000-06-18 04:25:08 +0000489 MS_SYNC))
Guido van Rossum09fdf072000-03-31 01:17:07 +0000490 {
491 PyErr_SetFromErrno(mmap_module_error);
492 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000493 }
Tim Petersec0a5f02006-02-16 23:47:20 +0000494 return Py_BuildValue ("l", (long) 0);
495#endif /* UNIX */
Guido van Rossum09fdf072000-03-31 01:17:07 +0000496 }
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000497}
498
499static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000500mmap_seek_method(mmap_object *self, PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000501{
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000502 int dist;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000503 int how=0;
504 CHECK_VALID(NULL);
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000505 if (!PyArg_ParseTuple (args, "i|i:seek", &dist, &how)) {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000506 return(NULL);
507 } else {
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000508 size_t where;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000509 switch (how) {
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000510 case 0: /* relative to start */
511 if (dist < 0)
512 goto onoutofrange;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000513 where = dist;
514 break;
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000515 case 1: /* relative to current position */
516 if ((int)self->pos + dist < 0)
517 goto onoutofrange;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000518 where = self->pos + dist;
519 break;
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000520 case 2: /* relative to end */
521 if ((int)self->size + dist < 0)
522 goto onoutofrange;
523 where = self->size + dist;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000524 break;
525 default:
526 PyErr_SetString (PyExc_ValueError,
527 "unknown seek type");
528 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000529 }
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000530 if (where > self->size)
531 goto onoutofrange;
532 self->pos = where;
533 Py_INCREF (Py_None);
534 return (Py_None);
Guido van Rossum09fdf072000-03-31 01:17:07 +0000535 }
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000536
Tim Peters5ebfd362001-11-13 23:11:19 +0000537 onoutofrange:
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000538 PyErr_SetString (PyExc_ValueError, "seek out of range");
539 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000540}
541
542static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000543mmap_move_method(mmap_object *self, PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000544{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000545 unsigned long dest, src, count;
546 CHECK_VALID(NULL);
Neal Norwitz8856fb72005-12-18 03:34:22 +0000547 if (!PyArg_ParseTuple (args, "kkk:move", &dest, &src, &count) ||
Tim Peters5ebfd362001-11-13 23:11:19 +0000548 !is_writeable(self)) {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000549 return NULL;
550 } else {
551 /* bounds check the values */
552 if (/* end of source after end of data?? */
553 ((src+count) > self->size)
554 /* dest will fit? */
555 || (dest+count > self->size)) {
556 PyErr_SetString (PyExc_ValueError,
557 "source or destination out of range");
558 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000559 } else {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000560 memmove (self->data+dest, self->data+src, count);
561 Py_INCREF (Py_None);
562 return Py_None;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000563 }
Guido van Rossum09fdf072000-03-31 01:17:07 +0000564 }
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000565}
566
567static struct PyMethodDef mmap_object_methods[] = {
Martin v. Löwis43b936d2002-01-17 23:15:58 +0000568 {"close", (PyCFunction) mmap_close_method, METH_VARARGS},
569 {"find", (PyCFunction) mmap_find_method, METH_VARARGS},
570 {"flush", (PyCFunction) mmap_flush_method, METH_VARARGS},
571 {"move", (PyCFunction) mmap_move_method, METH_VARARGS},
572 {"read", (PyCFunction) mmap_read_method, METH_VARARGS},
573 {"read_byte", (PyCFunction) mmap_read_byte_method, METH_VARARGS},
574 {"readline", (PyCFunction) mmap_read_line_method, METH_VARARGS},
575 {"resize", (PyCFunction) mmap_resize_method, METH_VARARGS},
576 {"seek", (PyCFunction) mmap_seek_method, METH_VARARGS},
577 {"size", (PyCFunction) mmap_size_method, METH_VARARGS},
578 {"tell", (PyCFunction) mmap_tell_method, METH_VARARGS},
579 {"write", (PyCFunction) mmap_write_method, METH_VARARGS},
580 {"write_byte", (PyCFunction) mmap_write_byte_method, METH_VARARGS},
Guido van Rossum09fdf072000-03-31 01:17:07 +0000581 {NULL, NULL} /* sentinel */
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000582};
583
584/* Functions for treating an mmap'ed file as a buffer */
585
Martin v. Löwis18e16552006-02-15 17:27:45 +0000586static Py_ssize_t
587mmap_buffer_getreadbuf(mmap_object *self, Py_ssize_t index, const void **ptr)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000588{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000589 CHECK_VALID(-1);
590 if ( index != 0 ) {
591 PyErr_SetString(PyExc_SystemError,
592 "Accessing non-existent mmap segment");
593 return -1;
594 }
595 *ptr = self->data;
596 return self->size;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000597}
598
Martin v. Löwis18e16552006-02-15 17:27:45 +0000599static Py_ssize_t
600mmap_buffer_getwritebuf(mmap_object *self, Py_ssize_t index, const void **ptr)
Tim Petersec0a5f02006-02-16 23:47:20 +0000601{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000602 CHECK_VALID(-1);
603 if ( index != 0 ) {
604 PyErr_SetString(PyExc_SystemError,
605 "Accessing non-existent mmap segment");
606 return -1;
607 }
Tim Peters5ebfd362001-11-13 23:11:19 +0000608 if (!is_writeable(self))
609 return -1;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000610 *ptr = self->data;
611 return self->size;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000612}
613
Martin v. Löwis18e16552006-02-15 17:27:45 +0000614static Py_ssize_t
615mmap_buffer_getsegcount(mmap_object *self, Py_ssize_t *lenp)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000616{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000617 CHECK_VALID(-1);
Tim Petersec0a5f02006-02-16 23:47:20 +0000618 if (lenp)
Guido van Rossum09fdf072000-03-31 01:17:07 +0000619 *lenp = self->size;
620 return 1;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000621}
622
Martin v. Löwis18e16552006-02-15 17:27:45 +0000623static Py_ssize_t
624mmap_buffer_getcharbuffer(mmap_object *self, Py_ssize_t index, const void **ptr)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000625{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000626 if ( index != 0 ) {
627 PyErr_SetString(PyExc_SystemError,
628 "accessing non-existent buffer segment");
629 return -1;
630 }
631 *ptr = (const char *)self->data;
632 return self->size;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000633}
634
635static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000636mmap_object_getattr(mmap_object *self, char *name)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000637{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000638 return Py_FindMethod (mmap_object_methods, (PyObject *)self, name);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000639}
640
Martin v. Löwis18e16552006-02-15 17:27:45 +0000641static Py_ssize_t
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000642mmap_length(mmap_object *self)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000643{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000644 CHECK_VALID(-1);
645 return self->size;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000646}
647
648static PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000649mmap_item(mmap_object *self, Py_ssize_t i)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000650{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000651 CHECK_VALID(NULL);
Guido van Rossumce8e1dc2000-07-01 00:51:51 +0000652 if (i < 0 || (size_t)i >= self->size) {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000653 PyErr_SetString(PyExc_IndexError, "mmap index out of range");
654 return NULL;
655 }
656 return PyString_FromStringAndSize(self->data + i, 1);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000657}
658
659static PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000660mmap_slice(mmap_object *self, Py_ssize_t ilow, Py_ssize_t ihigh)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000661{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000662 CHECK_VALID(NULL);
663 if (ilow < 0)
664 ilow = 0;
Guido van Rossumce8e1dc2000-07-01 00:51:51 +0000665 else if ((size_t)ilow > self->size)
Guido van Rossum09fdf072000-03-31 01:17:07 +0000666 ilow = self->size;
667 if (ihigh < 0)
668 ihigh = 0;
669 if (ihigh < ilow)
670 ihigh = ilow;
Guido van Rossumce8e1dc2000-07-01 00:51:51 +0000671 else if ((size_t)ihigh > self->size)
Guido van Rossum09fdf072000-03-31 01:17:07 +0000672 ihigh = self->size;
Tim Petersec0a5f02006-02-16 23:47:20 +0000673
Guido van Rossum09fdf072000-03-31 01:17:07 +0000674 return PyString_FromStringAndSize(self->data + ilow, ihigh-ilow);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000675}
676
677static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000678mmap_concat(mmap_object *self, PyObject *bb)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000679{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000680 CHECK_VALID(NULL);
681 PyErr_SetString(PyExc_SystemError,
682 "mmaps don't support concatenation");
683 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000684}
685
686static PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000687mmap_repeat(mmap_object *self, Py_ssize_t n)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000688{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000689 CHECK_VALID(NULL);
690 PyErr_SetString(PyExc_SystemError,
691 "mmaps don't support repeat operation");
692 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000693}
694
695static int
Martin v. Löwis18e16552006-02-15 17:27:45 +0000696mmap_ass_slice(mmap_object *self, Py_ssize_t ilow, Py_ssize_t ihigh, PyObject *v)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000697{
Guido van Rossum36d4f8b2000-04-10 21:34:37 +0000698 const char *buf;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000699
Guido van Rossum09fdf072000-03-31 01:17:07 +0000700 CHECK_VALID(-1);
701 if (ilow < 0)
702 ilow = 0;
Guido van Rossumce8e1dc2000-07-01 00:51:51 +0000703 else if ((size_t)ilow > self->size)
Guido van Rossum09fdf072000-03-31 01:17:07 +0000704 ilow = self->size;
705 if (ihigh < 0)
706 ihigh = 0;
707 if (ihigh < ilow)
708 ihigh = ilow;
Guido van Rossumce8e1dc2000-07-01 00:51:51 +0000709 else if ((size_t)ihigh > self->size)
Guido van Rossum09fdf072000-03-31 01:17:07 +0000710 ihigh = self->size;
Tim Petersec0a5f02006-02-16 23:47:20 +0000711
Thomas Wouters1baac722001-07-16 15:47:36 +0000712 if (v == NULL) {
713 PyErr_SetString(PyExc_TypeError,
Tim Peters5ebfd362001-11-13 23:11:19 +0000714 "mmap object doesn't support slice deletion");
Thomas Wouters1baac722001-07-16 15:47:36 +0000715 return -1;
716 }
Guido van Rossum09fdf072000-03-31 01:17:07 +0000717 if (! (PyString_Check(v)) ) {
Tim Petersec0a5f02006-02-16 23:47:20 +0000718 PyErr_SetString(PyExc_IndexError,
Guido van Rossum09fdf072000-03-31 01:17:07 +0000719 "mmap slice assignment must be a string");
720 return -1;
721 }
722 if ( PyString_Size(v) != (ihigh - ilow) ) {
Tim Petersec0a5f02006-02-16 23:47:20 +0000723 PyErr_SetString(PyExc_IndexError,
Guido van Rossum09fdf072000-03-31 01:17:07 +0000724 "mmap slice assignment is wrong size");
725 return -1;
726 }
Tim Peters5ebfd362001-11-13 23:11:19 +0000727 if (!is_writeable(self))
728 return -1;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000729 buf = PyString_AsString(v);
730 memcpy(self->data + ilow, buf, ihigh-ilow);
731 return 0;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000732}
733
734static int
Martin v. Löwis18e16552006-02-15 17:27:45 +0000735mmap_ass_item(mmap_object *self, Py_ssize_t i, PyObject *v)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000736{
Guido van Rossum36d4f8b2000-04-10 21:34:37 +0000737 const char *buf;
Tim Petersec0a5f02006-02-16 23:47:20 +0000738
Guido van Rossum09fdf072000-03-31 01:17:07 +0000739 CHECK_VALID(-1);
Guido van Rossumce8e1dc2000-07-01 00:51:51 +0000740 if (i < 0 || (size_t)i >= self->size) {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000741 PyErr_SetString(PyExc_IndexError, "mmap index out of range");
742 return -1;
743 }
Thomas Wouters1baac722001-07-16 15:47:36 +0000744 if (v == NULL) {
745 PyErr_SetString(PyExc_TypeError,
Tim Peters5ebfd362001-11-13 23:11:19 +0000746 "mmap object doesn't support item deletion");
Thomas Wouters1baac722001-07-16 15:47:36 +0000747 return -1;
748 }
Guido van Rossum09fdf072000-03-31 01:17:07 +0000749 if (! (PyString_Check(v) && PyString_Size(v)==1) ) {
Tim Petersec0a5f02006-02-16 23:47:20 +0000750 PyErr_SetString(PyExc_IndexError,
Tim Peters5ebfd362001-11-13 23:11:19 +0000751 "mmap assignment must be single-character string");
Guido van Rossum09fdf072000-03-31 01:17:07 +0000752 return -1;
753 }
Tim Peters5ebfd362001-11-13 23:11:19 +0000754 if (!is_writeable(self))
755 return -1;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000756 buf = PyString_AsString(v);
757 self->data[i] = buf[0];
758 return 0;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000759}
760
761static PySequenceMethods mmap_as_sequence = {
Martin v. Löwis18e16552006-02-15 17:27:45 +0000762 (lenfunc)mmap_length, /*sq_length*/
Guido van Rossum09fdf072000-03-31 01:17:07 +0000763 (binaryfunc)mmap_concat, /*sq_concat*/
Martin v. Löwis18e16552006-02-15 17:27:45 +0000764 (ssizeargfunc)mmap_repeat, /*sq_repeat*/
765 (ssizeargfunc)mmap_item, /*sq_item*/
766 (ssizessizeargfunc)mmap_slice, /*sq_slice*/
767 (ssizeobjargproc)mmap_ass_item, /*sq_ass_item*/
768 (ssizessizeobjargproc)mmap_ass_slice, /*sq_ass_slice*/
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000769};
770
771static PyBufferProcs mmap_as_buffer = {
Martin v. Löwis18e16552006-02-15 17:27:45 +0000772 (readbufferproc)mmap_buffer_getreadbuf,
773 (writebufferproc)mmap_buffer_getwritebuf,
774 (segcountproc)mmap_buffer_getsegcount,
775 (charbufferproc)mmap_buffer_getcharbuffer,
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000776};
777
778static PyTypeObject mmap_object_type = {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000779 PyObject_HEAD_INIT(0) /* patched in module init */
780 0, /* ob_size */
Guido van Rossum14648392001-12-08 18:02:58 +0000781 "mmap.mmap", /* tp_name */
Guido van Rossum09fdf072000-03-31 01:17:07 +0000782 sizeof(mmap_object), /* tp_size */
783 0, /* tp_itemsize */
784 /* methods */
785 (destructor) mmap_object_dealloc, /* tp_dealloc */
786 0, /* tp_print */
787 (getattrfunc) mmap_object_getattr, /* tp_getattr */
788 0, /* tp_setattr */
789 0, /* tp_compare */
790 0, /* tp_repr */
791 0, /* tp_as_number */
792 &mmap_as_sequence, /*tp_as_sequence*/
793 0, /*tp_as_mapping*/
794 0, /*tp_hash*/
795 0, /*tp_call*/
796 0, /*tp_str*/
797 0, /*tp_getattro*/
798 0, /*tp_setattro*/
799 &mmap_as_buffer, /*tp_as_buffer*/
800 Py_TPFLAGS_HAVE_GETCHARBUFFER, /*tp_flags*/
801 0, /*tp_doc*/
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000802};
803
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000804
805/* extract the map size from the given PyObject
806
807 The map size is restricted to [0, INT_MAX] because this is the current
808 Python limitation on object sizes. Although the mmap object *could* handle
809 a larger map size, there is no point because all the useful operations
810 (len(), slicing(), sequence indexing) are limited by a C int.
811
Thomas Wouters7e474022000-07-16 12:04:32 +0000812 Returns -1 on error, with an appropriate Python exception raised. On
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000813 success, the map size is returned. */
814static int
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000815_GetMapSize(PyObject *o)
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000816{
817 if (PyInt_Check(o)) {
818 long i = PyInt_AsLong(o);
819 if (PyErr_Occurred())
820 return -1;
821 if (i < 0)
822 goto onnegoverflow;
823 if (i > INT_MAX)
824 goto onposoverflow;
825 return (int)i;
826 }
827 else if (PyLong_Check(o)) {
828 long i = PyLong_AsLong(o);
829 if (PyErr_Occurred()) {
830 /* yes negative overflow is mistaken for positive overflow
831 but not worth the trouble to check sign of 'i' */
832 if (PyErr_ExceptionMatches(PyExc_OverflowError))
833 goto onposoverflow;
834 else
835 return -1;
836 }
837 if (i < 0)
838 goto onnegoverflow;
839 if (i > INT_MAX)
840 goto onposoverflow;
841 return (int)i;
842 }
843 else {
844 PyErr_SetString(PyExc_TypeError,
Tim Peters5ebfd362001-11-13 23:11:19 +0000845 "map size must be an integral value");
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000846 return -1;
847 }
848
Tim Peters5ebfd362001-11-13 23:11:19 +0000849 onnegoverflow:
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000850 PyErr_SetString(PyExc_OverflowError,
Tim Peters5ebfd362001-11-13 23:11:19 +0000851 "memory mapped size must be positive");
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000852 return -1;
853
Tim Peters5ebfd362001-11-13 23:11:19 +0000854 onposoverflow:
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000855 PyErr_SetString(PyExc_OverflowError,
Tim Peters5ebfd362001-11-13 23:11:19 +0000856 "memory mapped size is too large (limited by C int)");
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000857 return -1;
858}
859
Tim Petersec0a5f02006-02-16 23:47:20 +0000860#ifdef UNIX
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000861static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000862new_mmap_object(PyObject *self, PyObject *args, PyObject *kwdict)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000863{
Neal Norwitzb5673922002-09-05 21:48:07 +0000864#ifdef HAVE_FSTAT
865 struct stat st;
866#endif
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000867 mmap_object *m_obj;
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000868 PyObject *map_size_obj = NULL;
869 int map_size;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000870 int fd, flags = MAP_SHARED, prot = PROT_WRITE | PROT_READ;
Neal Norwitz0e6bc8c2006-02-05 05:45:43 +0000871 int devzero = -1;
Neal Norwitz8856fb72005-12-18 03:34:22 +0000872 int access = (int)ACCESS_DEFAULT;
Tim Petersec0a5f02006-02-16 23:47:20 +0000873 static const char *keywords[] = {"fileno", "length",
874 "flags", "prot",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +0000875 "access", NULL};
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000876
Tim Petersec0a5f02006-02-16 23:47:20 +0000877 if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iO|iii", keywords,
Jeremy Hyltonaf68c872005-12-10 18:50:16 +0000878 &fd, &map_size_obj, &flags, &prot,
879 &access))
Guido van Rossum09fdf072000-03-31 01:17:07 +0000880 return NULL;
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000881 map_size = _GetMapSize(map_size_obj);
882 if (map_size < 0)
883 return NULL;
Tim Peters5ebfd362001-11-13 23:11:19 +0000884
Tim Petersec0a5f02006-02-16 23:47:20 +0000885 if ((access != (int)ACCESS_DEFAULT) &&
Neal Norwitzd1cfc8a2006-02-05 03:36:57 +0000886 ((flags != MAP_SHARED) || (prot != (PROT_WRITE | PROT_READ))))
Tim Petersec0a5f02006-02-16 23:47:20 +0000887 return PyErr_Format(PyExc_ValueError,
Tim Peters5ebfd362001-11-13 23:11:19 +0000888 "mmap can't specify both access and flags, prot.");
Neal Norwitzd1cfc8a2006-02-05 03:36:57 +0000889 switch ((access_mode)access) {
Tim Peters5ebfd362001-11-13 23:11:19 +0000890 case ACCESS_READ:
891 flags = MAP_SHARED;
892 prot = PROT_READ;
893 break;
894 case ACCESS_WRITE:
895 flags = MAP_SHARED;
896 prot = PROT_READ | PROT_WRITE;
897 break;
898 case ACCESS_COPY:
899 flags = MAP_PRIVATE;
900 prot = PROT_READ | PROT_WRITE;
901 break;
Tim Petersec0a5f02006-02-16 23:47:20 +0000902 case ACCESS_DEFAULT:
Tim Peters5ebfd362001-11-13 23:11:19 +0000903 /* use the specified or default values of flags and prot */
904 break;
905 default:
Tim Petersec0a5f02006-02-16 23:47:20 +0000906 return PyErr_Format(PyExc_ValueError,
Tim Peters5ebfd362001-11-13 23:11:19 +0000907 "mmap invalid access parameter.");
908 }
Neal Norwitzb5673922002-09-05 21:48:07 +0000909
910#ifdef HAVE_FSTAT
Martin v. Löwisc16f3bd2003-05-03 09:14:54 +0000911# ifdef __VMS
912 /* on OpenVMS we must ensure that all bytes are written to the file */
913 fsync(fd);
914# endif
Martin v. Löwis7fe60c02005-03-03 11:22:44 +0000915 if (fstat(fd, &st) == 0 && S_ISREG(st.st_mode)) {
916 if (map_size == 0) {
917 map_size = (int)st.st_size;
918 } else if ((size_t)map_size > st.st_size) {
Tim Petersec0a5f02006-02-16 23:47:20 +0000919 PyErr_SetString(PyExc_ValueError,
Martin v. Löwis7fe60c02005-03-03 11:22:44 +0000920 "mmap length is greater than file size");
921 return NULL;
922 }
Neal Norwitzb5673922002-09-05 21:48:07 +0000923 }
924#endif
Guido van Rossumb18618d2000-05-03 23:44:39 +0000925 m_obj = PyObject_New (mmap_object, &mmap_object_type);
Guido van Rossum09fdf072000-03-31 01:17:07 +0000926 if (m_obj == NULL) {return NULL;}
Neal Norwitz3b4fff82006-01-11 08:54:45 +0000927 m_obj->data = NULL;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000928 m_obj->size = (size_t) map_size;
929 m_obj->pos = (size_t) 0;
Neal Norwitz0e6bc8c2006-02-05 05:45:43 +0000930 if (fd == -1) {
931 m_obj->fd = -1;
932 /* Assume the caller wants to map anonymous memory.
933 This is the same behaviour as Windows. mmap.mmap(-1, size)
934 on both Windows and Unix map anonymous memory.
935 */
936#ifdef MAP_ANONYMOUS
937 /* BSD way to map anonymous memory */
938 flags |= MAP_ANONYMOUS;
939#else
940 /* SVR4 method to map anonymous memory is to open /dev/zero */
941 fd = devzero = open("/dev/zero", O_RDWR);
942 if (devzero == -1) {
943 Py_DECREF(m_obj);
944 PyErr_SetFromErrno(mmap_module_error);
945 return NULL;
946 }
947#endif
948 } else {
949 m_obj->fd = dup(fd);
950 if (m_obj->fd == -1) {
951 Py_DECREF(m_obj);
952 PyErr_SetFromErrno(mmap_module_error);
953 return NULL;
954 }
Georg Brandl38387b82005-08-24 07:17:40 +0000955 }
Neal Norwitz0e6bc8c2006-02-05 05:45:43 +0000956
Tim Petersec0a5f02006-02-16 23:47:20 +0000957 m_obj->data = mmap(NULL, map_size,
Guido van Rossum09fdf072000-03-31 01:17:07 +0000958 prot, flags,
959 fd, 0);
Neal Norwitz0e6bc8c2006-02-05 05:45:43 +0000960
961 if (devzero != -1) {
962 close(devzero);
963 }
964
Tim Peters5ebfd362001-11-13 23:11:19 +0000965 if (m_obj->data == (char *)-1) {
Andrew M. Kuchling16581c82004-05-19 14:39:08 +0000966 m_obj->data = NULL;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000967 Py_DECREF(m_obj);
968 PyErr_SetFromErrno(mmap_module_error);
969 return NULL;
970 }
Neal Norwitz8856fb72005-12-18 03:34:22 +0000971 m_obj->access = (access_mode)access;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000972 return (PyObject *)m_obj;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000973}
974#endif /* UNIX */
975
Martin v. Löwis6238d2b2002-06-30 15:26:10 +0000976#ifdef MS_WINDOWS
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000977static PyObject *
Tim Peters5ebfd362001-11-13 23:11:19 +0000978new_mmap_object(PyObject *self, PyObject *args, PyObject *kwdict)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000979{
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000980 mmap_object *m_obj;
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000981 PyObject *map_size_obj = NULL;
982 int map_size;
Tim Peterse564e7f2006-02-16 23:46:01 +0000983 DWORD size_hi; /* upper 32 bits of m_obj->size */
984 DWORD size_lo; /* lower 32 bits of m_obj->size */
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000985 char *tagname = "";
Guido van Rossum09fdf072000-03-31 01:17:07 +0000986 DWORD dwErr = 0;
987 int fileno;
Mark Hammond071864a2000-07-30 02:46:26 +0000988 HANDLE fh = 0;
Neal Norwitz8856fb72005-12-18 03:34:22 +0000989 int access = (access_mode)ACCESS_DEFAULT;
Tim Peters5ebfd362001-11-13 23:11:19 +0000990 DWORD flProtect, dwDesiredAccess;
Tim Petersec0a5f02006-02-16 23:47:20 +0000991 static const char *keywords[] = { "fileno", "length",
992 "tagname",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +0000993 "access", NULL };
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000994
Tim Peters5ebfd362001-11-13 23:11:19 +0000995 if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iO|zi", keywords,
Tim Petersec0a5f02006-02-16 23:47:20 +0000996 &fileno, &map_size_obj,
Tim Peters5ebfd362001-11-13 23:11:19 +0000997 &tagname, &access)) {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000998 return NULL;
Tim Peters5ebfd362001-11-13 23:11:19 +0000999 }
1000
Neal Norwitz8856fb72005-12-18 03:34:22 +00001001 switch((access_mode)access) {
Tim Peters5ebfd362001-11-13 23:11:19 +00001002 case ACCESS_READ:
1003 flProtect = PAGE_READONLY;
1004 dwDesiredAccess = FILE_MAP_READ;
1005 break;
1006 case ACCESS_DEFAULT: case ACCESS_WRITE:
1007 flProtect = PAGE_READWRITE;
1008 dwDesiredAccess = FILE_MAP_WRITE;
1009 break;
1010 case ACCESS_COPY:
1011 flProtect = PAGE_WRITECOPY;
1012 dwDesiredAccess = FILE_MAP_COPY;
1013 break;
1014 default:
Tim Petersec0a5f02006-02-16 23:47:20 +00001015 return PyErr_Format(PyExc_ValueError,
Tim Peters5ebfd362001-11-13 23:11:19 +00001016 "mmap invalid access parameter.");
1017 }
1018
Andrew M. Kuchling70d27422000-06-18 04:45:14 +00001019 map_size = _GetMapSize(map_size_obj);
1020 if (map_size < 0)
1021 return NULL;
Tim Petersec0a5f02006-02-16 23:47:20 +00001022
Neal Norwitz0e6bc8c2006-02-05 05:45:43 +00001023 /* assume -1 and 0 both mean invalid filedescriptor
1024 to 'anonymously' map memory.
1025 XXX: fileno == 0 is a valid fd, but was accepted prior to 2.5.
1026 XXX: Should this code be added?
1027 if (fileno == 0)
1028 PyErr_Warn(PyExc_DeprecationWarning,
1029 "don't use 0 for anonymous memory");
1030 */
1031 if (fileno != -1 && fileno != 0) {
Mark Hammond071864a2000-07-30 02:46:26 +00001032 fh = (HANDLE)_get_osfhandle(fileno);
1033 if (fh==(HANDLE)-1) {
Tim Peters5ebfd362001-11-13 23:11:19 +00001034 PyErr_SetFromErrno(mmap_module_error);
1035 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001036 }
Fred Drake1ef4e2d2000-04-05 14:15:31 +00001037 /* Win9x appears to need us seeked to zero */
Guido van Rossum69c2b882003-04-09 19:31:02 +00001038 lseek(fileno, 0, SEEK_SET);
Guido van Rossum09fdf072000-03-31 01:17:07 +00001039 }
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001040
Guido van Rossumb18618d2000-05-03 23:44:39 +00001041 m_obj = PyObject_New (mmap_object, &mmap_object_type);
Mark Hammond2cbed002000-07-30 02:22:43 +00001042 if (m_obj==NULL)
1043 return NULL;
1044 /* Set every field to an invalid marker, so we can safely
1045 destruct the object in the face of failure */
1046 m_obj->data = NULL;
Mark Hammond071864a2000-07-30 02:46:26 +00001047 m_obj->file_handle = INVALID_HANDLE_VALUE;
Mark Hammond2cbed002000-07-30 02:22:43 +00001048 m_obj->map_handle = INVALID_HANDLE_VALUE;
1049 m_obj->tagname = NULL;
1050
Guido van Rossum09fdf072000-03-31 01:17:07 +00001051 if (fh) {
Mark Hammond2cbed002000-07-30 02:22:43 +00001052 /* It is necessary to duplicate the handle, so the
1053 Python code can close it on us */
1054 if (!DuplicateHandle(
Tim Peters5ebfd362001-11-13 23:11:19 +00001055 GetCurrentProcess(), /* source process handle */
1056 fh, /* handle to be duplicated */
1057 GetCurrentProcess(), /* target proc handle */
1058 (LPHANDLE)&m_obj->file_handle, /* result */
1059 0, /* access - ignored due to options value */
1060 FALSE, /* inherited by child processes? */
1061 DUPLICATE_SAME_ACCESS)) { /* options */
Mark Hammond2cbed002000-07-30 02:22:43 +00001062 dwErr = GetLastError();
1063 Py_DECREF(m_obj);
1064 PyErr_SetFromWindowsErr(dwErr);
1065 return NULL;
1066 }
Guido van Rossum09fdf072000-03-31 01:17:07 +00001067 if (!map_size) {
Mark Hammond071864a2000-07-30 02:46:26 +00001068 m_obj->size = GetFileSize (fh, NULL);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001069 } else {
Guido van Rossum09fdf072000-03-31 01:17:07 +00001070 m_obj->size = map_size;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001071 }
Guido van Rossum09fdf072000-03-31 01:17:07 +00001072 }
1073 else {
Guido van Rossum09fdf072000-03-31 01:17:07 +00001074 m_obj->size = map_size;
1075 }
1076
1077 /* set the initial position */
1078 m_obj->pos = (size_t) 0;
1079
Mark Hammond2cbed002000-07-30 02:22:43 +00001080 /* set the tag name */
Tim Peters0d9f9dc2001-01-10 05:42:18 +00001081 if (tagname != NULL && *tagname != '\0') {
Mark Hammond2cbed002000-07-30 02:22:43 +00001082 m_obj->tagname = PyMem_Malloc(strlen(tagname)+1);
1083 if (m_obj->tagname == NULL) {
1084 PyErr_NoMemory();
1085 Py_DECREF(m_obj);
1086 return NULL;
1087 }
1088 strcpy(m_obj->tagname, tagname);
1089 }
1090 else
1091 m_obj->tagname = NULL;
1092
Neal Norwitz8856fb72005-12-18 03:34:22 +00001093 m_obj->access = (access_mode)access;
Tim Peterse564e7f2006-02-16 23:46:01 +00001094 /* DWORD is a 4-byte int. If we're on a box where size_t consumes
1095 * more then 4 bytes, we need to break it apart. Else (size_t
1096 * consumes 4 bytes), C doesn't define what happens if we shift
1097 * right by 32, so we need different code.
1098 */
1099#if SIZEOF_SIZE_T > 4
1100 size_hi = (DWORD)(m_obj->size >> 32);
1101 size_lo = (DWORD)(m_obj->size & 0xFFFFFFFF);
1102#else
1103 size_hi = 0;
1104 size_lo = (DWORD)m_obj->size;
1105#endif
Mark Hammond071864a2000-07-30 02:46:26 +00001106 m_obj->map_handle = CreateFileMapping (m_obj->file_handle,
Guido van Rossum09fdf072000-03-31 01:17:07 +00001107 NULL,
Tim Peters5ebfd362001-11-13 23:11:19 +00001108 flProtect,
Tim Peterse564e7f2006-02-16 23:46:01 +00001109 size_hi,
1110 size_lo,
Tim Peters0d9f9dc2001-01-10 05:42:18 +00001111 m_obj->tagname);
Guido van Rossum09fdf072000-03-31 01:17:07 +00001112 if (m_obj->map_handle != NULL) {
1113 m_obj->data = (char *) MapViewOfFile (m_obj->map_handle,
Tim Peters5ebfd362001-11-13 23:11:19 +00001114 dwDesiredAccess,
Guido van Rossum09fdf072000-03-31 01:17:07 +00001115 0,
1116 0,
1117 0);
1118 if (m_obj->data != NULL) {
1119 return ((PyObject *) m_obj);
1120 } else {
Tim Peters5ebfd362001-11-13 23:11:19 +00001121 dwErr = GetLastError();
Guido van Rossum09fdf072000-03-31 01:17:07 +00001122 }
1123 } else {
1124 dwErr = GetLastError();
1125 }
Mark Hammond2cbed002000-07-30 02:22:43 +00001126 Py_DECREF(m_obj);
Guido van Rossum09fdf072000-03-31 01:17:07 +00001127 PyErr_SetFromWindowsErr(dwErr);
1128 return (NULL);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001129}
Martin v. Löwis6238d2b2002-06-30 15:26:10 +00001130#endif /* MS_WINDOWS */
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001131
1132/* List of functions exported by this module */
1133static struct PyMethodDef mmap_functions[] = {
Tim Petersec0a5f02006-02-16 23:47:20 +00001134 {"mmap", (PyCFunction) new_mmap_object,
Guido van Rossum09fdf072000-03-31 01:17:07 +00001135 METH_VARARGS|METH_KEYWORDS},
1136 {NULL, NULL} /* Sentinel */
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001137};
1138
Mark Hammond62b1ab12002-07-23 06:31:15 +00001139PyMODINIT_FUNC
Tim Peters5ebfd362001-11-13 23:11:19 +00001140 initmmap(void)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001141{
Guido van Rossum09fdf072000-03-31 01:17:07 +00001142 PyObject *dict, *module;
Tim Peters2caf8df2001-01-14 05:05:51 +00001143
1144 /* Patch the object type */
1145 mmap_object_type.ob_type = &PyType_Type;
1146
Guido van Rossum09fdf072000-03-31 01:17:07 +00001147 module = Py_InitModule ("mmap", mmap_functions);
Neal Norwitz1ac754f2006-01-19 06:09:39 +00001148 if (module == NULL)
1149 return;
Guido van Rossum09fdf072000-03-31 01:17:07 +00001150 dict = PyModule_GetDict (module);
1151 mmap_module_error = PyExc_EnvironmentError;
1152 Py_INCREF(mmap_module_error);
1153 PyDict_SetItemString (dict, "error", mmap_module_error);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001154#ifdef PROT_EXEC
Guido van Rossum09fdf072000-03-31 01:17:07 +00001155 PyDict_SetItemString (dict, "PROT_EXEC", PyInt_FromLong(PROT_EXEC) );
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001156#endif
1157#ifdef PROT_READ
Guido van Rossum09fdf072000-03-31 01:17:07 +00001158 PyDict_SetItemString (dict, "PROT_READ", PyInt_FromLong(PROT_READ) );
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001159#endif
1160#ifdef PROT_WRITE
Guido van Rossum09fdf072000-03-31 01:17:07 +00001161 PyDict_SetItemString (dict, "PROT_WRITE", PyInt_FromLong(PROT_WRITE) );
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001162#endif
1163
1164#ifdef MAP_SHARED
Guido van Rossum09fdf072000-03-31 01:17:07 +00001165 PyDict_SetItemString (dict, "MAP_SHARED", PyInt_FromLong(MAP_SHARED) );
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001166#endif
1167#ifdef MAP_PRIVATE
Guido van Rossum09fdf072000-03-31 01:17:07 +00001168 PyDict_SetItemString (dict, "MAP_PRIVATE",
1169 PyInt_FromLong(MAP_PRIVATE) );
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001170#endif
1171#ifdef MAP_DENYWRITE
Guido van Rossum09fdf072000-03-31 01:17:07 +00001172 PyDict_SetItemString (dict, "MAP_DENYWRITE",
1173 PyInt_FromLong(MAP_DENYWRITE) );
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001174#endif
1175#ifdef MAP_EXECUTABLE
Guido van Rossum09fdf072000-03-31 01:17:07 +00001176 PyDict_SetItemString (dict, "MAP_EXECUTABLE",
1177 PyInt_FromLong(MAP_EXECUTABLE) );
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001178#endif
Neal Norwitz0e6bc8c2006-02-05 05:45:43 +00001179#ifdef MAP_ANONYMOUS
1180 PyDict_SetItemString (dict, "MAP_ANON", PyInt_FromLong(MAP_ANONYMOUS) );
Guido van Rossum09fdf072000-03-31 01:17:07 +00001181 PyDict_SetItemString (dict, "MAP_ANONYMOUS",
Neal Norwitz0e6bc8c2006-02-05 05:45:43 +00001182 PyInt_FromLong(MAP_ANONYMOUS) );
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001183#endif
1184
Guido van Rossum09fdf072000-03-31 01:17:07 +00001185 PyDict_SetItemString (dict, "PAGESIZE",
Fred Drake145f96e2000-10-01 17:50:46 +00001186 PyInt_FromLong( (long)my_getpagesize() ) );
Andrew M. Kuchling961fe172000-06-03 19:41:42 +00001187
Tim Petersec0a5f02006-02-16 23:47:20 +00001188 PyDict_SetItemString (dict, "ACCESS_READ",
Tim Peters5ebfd362001-11-13 23:11:19 +00001189 PyInt_FromLong(ACCESS_READ));
Tim Petersec0a5f02006-02-16 23:47:20 +00001190 PyDict_SetItemString (dict, "ACCESS_WRITE",
Tim Peters5ebfd362001-11-13 23:11:19 +00001191 PyInt_FromLong(ACCESS_WRITE));
Tim Petersec0a5f02006-02-16 23:47:20 +00001192 PyDict_SetItemString (dict, "ACCESS_COPY",
Tim Peters5ebfd362001-11-13 23:11:19 +00001193 PyInt_FromLong(ACCESS_COPY));
1194}