blob: b6b2d85301ad05c3dbe17c6fbb5f597acef585c1 [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 Norwitz0e6bc8c2006-02-05 05:45:43 +000057/* maybe define MAP_ANON in terms of MAP_ANONYMOUS */
58#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
125 the value is valid, and if so, free the resource
126 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{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000223 long num_bytes;
224 PyObject *result;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000225
Guido van Rossum09fdf072000-03-31 01:17:07 +0000226 CHECK_VALID(NULL);
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000227 if (!PyArg_ParseTuple(args, "l: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);
235 self->pos += num_bytes;
236 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{
Tim Petersd401edd2001-05-14 23:19:12 +0000243 long 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);
Tim Petersd401edd2001-05-14 23:19:12 +0000248 if (!PyArg_ParseTuple (args, "s#|l: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 Peters5ebfd362001-11-13 23:11:19 +0000275static int
276is_writeable(mmap_object *self)
277{
278 if (self->access != ACCESS_READ)
279 return 1;
280 PyErr_Format(PyExc_TypeError, "mmap can't modify a readonly memory map.");
281 return 0;
282}
283
284static int
285is_resizeable(mmap_object *self)
286{
287 if ((self->access == ACCESS_WRITE) || (self->access == ACCESS_DEFAULT))
288 return 1;
289 PyErr_Format(PyExc_TypeError,
290 "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 Peters5ebfd362001-11-13 23:11:19 +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);
Neal Norwitz8856fb72005-12-18 03:34:22 +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
Guido van Rossum09fdf072000-03-31 01:17:07 +0000386 } else {
387 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
Andrew M. Kuchling6fef30e2000-06-18 14:51:21 +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 Peters5ebfd362001-11-13 23:11:19 +0000445 if (newmap == (void *)-1)
446 {
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{
Neal Norwitz8856fb72005-12-18 03:34:22 +0000471 unsigned long offset = 0;
472 unsigned long size = self->size;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000473 CHECK_VALID(NULL);
Neal Norwitz8856fb72005-12-18 03:34:22 +0000474 if (!PyArg_ParseTuple (args, "|kk: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 }
Fredrik Lundh5cccf502000-07-09 13:16:13 +0000494 return Py_BuildValue ("l", (long) 0);
Guido van Rossum09fdf072000-03-31 01:17:07 +0000495#endif /* UNIX */
496 }
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
586static int
Andrew M. Kuchling961fe172000-06-03 19:41:42 +0000587mmap_buffer_getreadbuf(mmap_object *self, int 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
599static int
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000600mmap_buffer_getwritebuf(mmap_object *self, int index, const void **ptr)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +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
614static int
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000615mmap_buffer_getsegcount(mmap_object *self, int *lenp)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000616{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000617 CHECK_VALID(-1);
618 if (lenp)
619 *lenp = self->size;
620 return 1;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000621}
622
623static int
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000624mmap_buffer_getcharbuffer(mmap_object *self, int 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
641static int
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 *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000649mmap_item(mmap_object *self, int 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 *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000660mmap_slice(mmap_object *self, int ilow, int 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;
673
674 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 *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000687mmap_repeat(mmap_object *self, int 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
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000696mmap_ass_slice(mmap_object *self, int ilow, int 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;
711
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)) ) {
718 PyErr_SetString(PyExc_IndexError,
719 "mmap slice assignment must be a string");
720 return -1;
721 }
722 if ( PyString_Size(v) != (ihigh - ilow) ) {
723 PyErr_SetString(PyExc_IndexError,
724 "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
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000735mmap_ass_item(mmap_object *self, int i, PyObject *v)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000736{
Guido van Rossum36d4f8b2000-04-10 21:34:37 +0000737 const char *buf;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +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) ) {
750 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 = {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000762 (inquiry)mmap_length, /*sq_length*/
763 (binaryfunc)mmap_concat, /*sq_concat*/
764 (intargfunc)mmap_repeat, /*sq_repeat*/
765 (intargfunc)mmap_item, /*sq_item*/
766 (intintargfunc)mmap_slice, /*sq_slice*/
767 (intobjargproc)mmap_ass_item, /*sq_ass_item*/
768 (intintobjargproc)mmap_ass_slice, /*sq_ass_slice*/
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000769};
770
771static PyBufferProcs mmap_as_buffer = {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000772 (getreadbufferproc)mmap_buffer_getreadbuf,
773 (getwritebufferproc)mmap_buffer_getwritebuf,
774 (getsegcountproc)mmap_buffer_getsegcount,
775 (getcharbufferproc)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
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000860#ifdef UNIX
861static 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;
Jeremy Hyltonaf68c872005-12-10 18:50:16 +0000873 static const char *keywords[] = {"fileno", "length",
874 "flags", "prot",
875 "access", NULL};
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000876
Tim Peters5ebfd362001-11-13 23:11:19 +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
Neal Norwitz8856fb72005-12-18 03:34:22 +0000885 if ((access != (int)ACCESS_DEFAULT) &&
Neal Norwitzd1cfc8a2006-02-05 03:36:57 +0000886 ((flags != MAP_SHARED) || (prot != (PROT_WRITE | PROT_READ))))
Tim Peters5ebfd362001-11-13 23:11:19 +0000887 return PyErr_Format(PyExc_ValueError,
888 "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;
902 case ACCESS_DEFAULT:
903 /* use the specified or default values of flags and prot */
904 break;
905 default:
906 return PyErr_Format(PyExc_ValueError,
907 "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) {
919 PyErr_SetString(PyExc_ValueError,
920 "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
Guido van Rossum09fdf072000-03-31 01:17:07 +0000957 m_obj->data = mmap(NULL, map_size,
958 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;
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000983 char *tagname = "";
Guido van Rossum09fdf072000-03-31 01:17:07 +0000984 DWORD dwErr = 0;
985 int fileno;
Mark Hammond071864a2000-07-30 02:46:26 +0000986 HANDLE fh = 0;
Neal Norwitz8856fb72005-12-18 03:34:22 +0000987 int access = (access_mode)ACCESS_DEFAULT;
Tim Peters5ebfd362001-11-13 23:11:19 +0000988 DWORD flProtect, dwDesiredAccess;
Jeremy Hyltonaf68c872005-12-10 18:50:16 +0000989 static const char *keywords[] = { "fileno", "length",
990 "tagname",
991 "access", NULL };
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000992
Tim Peters5ebfd362001-11-13 23:11:19 +0000993 if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iO|zi", keywords,
994 &fileno, &map_size_obj,
995 &tagname, &access)) {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000996 return NULL;
Tim Peters5ebfd362001-11-13 23:11:19 +0000997 }
998
Neal Norwitz8856fb72005-12-18 03:34:22 +0000999 switch((access_mode)access) {
Tim Peters5ebfd362001-11-13 23:11:19 +00001000 case ACCESS_READ:
1001 flProtect = PAGE_READONLY;
1002 dwDesiredAccess = FILE_MAP_READ;
1003 break;
1004 case ACCESS_DEFAULT: case ACCESS_WRITE:
1005 flProtect = PAGE_READWRITE;
1006 dwDesiredAccess = FILE_MAP_WRITE;
1007 break;
1008 case ACCESS_COPY:
1009 flProtect = PAGE_WRITECOPY;
1010 dwDesiredAccess = FILE_MAP_COPY;
1011 break;
1012 default:
1013 return PyErr_Format(PyExc_ValueError,
1014 "mmap invalid access parameter.");
1015 }
1016
Andrew M. Kuchling70d27422000-06-18 04:45:14 +00001017 map_size = _GetMapSize(map_size_obj);
1018 if (map_size < 0)
1019 return NULL;
1020
Neal Norwitz0e6bc8c2006-02-05 05:45:43 +00001021 /* assume -1 and 0 both mean invalid filedescriptor
1022 to 'anonymously' map memory.
1023 XXX: fileno == 0 is a valid fd, but was accepted prior to 2.5.
1024 XXX: Should this code be added?
1025 if (fileno == 0)
1026 PyErr_Warn(PyExc_DeprecationWarning,
1027 "don't use 0 for anonymous memory");
1028 */
1029 if (fileno != -1 && fileno != 0) {
Mark Hammond071864a2000-07-30 02:46:26 +00001030 fh = (HANDLE)_get_osfhandle(fileno);
1031 if (fh==(HANDLE)-1) {
Tim Peters5ebfd362001-11-13 23:11:19 +00001032 PyErr_SetFromErrno(mmap_module_error);
1033 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001034 }
Fred Drake1ef4e2d2000-04-05 14:15:31 +00001035 /* Win9x appears to need us seeked to zero */
Guido van Rossum69c2b882003-04-09 19:31:02 +00001036 lseek(fileno, 0, SEEK_SET);
Guido van Rossum09fdf072000-03-31 01:17:07 +00001037 }
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001038
Guido van Rossumb18618d2000-05-03 23:44:39 +00001039 m_obj = PyObject_New (mmap_object, &mmap_object_type);
Mark Hammond2cbed002000-07-30 02:22:43 +00001040 if (m_obj==NULL)
1041 return NULL;
1042 /* Set every field to an invalid marker, so we can safely
1043 destruct the object in the face of failure */
1044 m_obj->data = NULL;
Mark Hammond071864a2000-07-30 02:46:26 +00001045 m_obj->file_handle = INVALID_HANDLE_VALUE;
Mark Hammond2cbed002000-07-30 02:22:43 +00001046 m_obj->map_handle = INVALID_HANDLE_VALUE;
1047 m_obj->tagname = NULL;
1048
Guido van Rossum09fdf072000-03-31 01:17:07 +00001049 if (fh) {
Mark Hammond2cbed002000-07-30 02:22:43 +00001050 /* It is necessary to duplicate the handle, so the
1051 Python code can close it on us */
1052 if (!DuplicateHandle(
Tim Peters5ebfd362001-11-13 23:11:19 +00001053 GetCurrentProcess(), /* source process handle */
1054 fh, /* handle to be duplicated */
1055 GetCurrentProcess(), /* target proc handle */
1056 (LPHANDLE)&m_obj->file_handle, /* result */
1057 0, /* access - ignored due to options value */
1058 FALSE, /* inherited by child processes? */
1059 DUPLICATE_SAME_ACCESS)) { /* options */
Mark Hammond2cbed002000-07-30 02:22:43 +00001060 dwErr = GetLastError();
1061 Py_DECREF(m_obj);
1062 PyErr_SetFromWindowsErr(dwErr);
1063 return NULL;
1064 }
Guido van Rossum09fdf072000-03-31 01:17:07 +00001065 if (!map_size) {
Mark Hammond071864a2000-07-30 02:46:26 +00001066 m_obj->size = GetFileSize (fh, NULL);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001067 } else {
Guido van Rossum09fdf072000-03-31 01:17:07 +00001068 m_obj->size = map_size;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001069 }
Guido van Rossum09fdf072000-03-31 01:17:07 +00001070 }
1071 else {
Guido van Rossum09fdf072000-03-31 01:17:07 +00001072 m_obj->size = map_size;
1073 }
1074
1075 /* set the initial position */
1076 m_obj->pos = (size_t) 0;
1077
Mark Hammond2cbed002000-07-30 02:22:43 +00001078 /* set the tag name */
Tim Peters0d9f9dc2001-01-10 05:42:18 +00001079 if (tagname != NULL && *tagname != '\0') {
Mark Hammond2cbed002000-07-30 02:22:43 +00001080 m_obj->tagname = PyMem_Malloc(strlen(tagname)+1);
1081 if (m_obj->tagname == NULL) {
1082 PyErr_NoMemory();
1083 Py_DECREF(m_obj);
1084 return NULL;
1085 }
1086 strcpy(m_obj->tagname, tagname);
1087 }
1088 else
1089 m_obj->tagname = NULL;
1090
Neal Norwitz8856fb72005-12-18 03:34:22 +00001091 m_obj->access = (access_mode)access;
Mark Hammond071864a2000-07-30 02:46:26 +00001092 m_obj->map_handle = CreateFileMapping (m_obj->file_handle,
Guido van Rossum09fdf072000-03-31 01:17:07 +00001093 NULL,
Tim Peters5ebfd362001-11-13 23:11:19 +00001094 flProtect,
Guido van Rossum09fdf072000-03-31 01:17:07 +00001095 0,
1096 m_obj->size,
Tim Peters0d9f9dc2001-01-10 05:42:18 +00001097 m_obj->tagname);
Guido van Rossum09fdf072000-03-31 01:17:07 +00001098 if (m_obj->map_handle != NULL) {
1099 m_obj->data = (char *) MapViewOfFile (m_obj->map_handle,
Tim Peters5ebfd362001-11-13 23:11:19 +00001100 dwDesiredAccess,
Guido van Rossum09fdf072000-03-31 01:17:07 +00001101 0,
1102 0,
1103 0);
1104 if (m_obj->data != NULL) {
1105 return ((PyObject *) m_obj);
1106 } else {
Tim Peters5ebfd362001-11-13 23:11:19 +00001107 dwErr = GetLastError();
Guido van Rossum09fdf072000-03-31 01:17:07 +00001108 }
1109 } else {
1110 dwErr = GetLastError();
1111 }
Mark Hammond2cbed002000-07-30 02:22:43 +00001112 Py_DECREF(m_obj);
Guido van Rossum09fdf072000-03-31 01:17:07 +00001113 PyErr_SetFromWindowsErr(dwErr);
1114 return (NULL);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001115}
Martin v. Löwis6238d2b2002-06-30 15:26:10 +00001116#endif /* MS_WINDOWS */
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001117
1118/* List of functions exported by this module */
1119static struct PyMethodDef mmap_functions[] = {
Guido van Rossum09fdf072000-03-31 01:17:07 +00001120 {"mmap", (PyCFunction) new_mmap_object,
1121 METH_VARARGS|METH_KEYWORDS},
1122 {NULL, NULL} /* Sentinel */
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001123};
1124
Mark Hammond62b1ab12002-07-23 06:31:15 +00001125PyMODINIT_FUNC
Tim Peters5ebfd362001-11-13 23:11:19 +00001126 initmmap(void)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001127{
Guido van Rossum09fdf072000-03-31 01:17:07 +00001128 PyObject *dict, *module;
Tim Peters2caf8df2001-01-14 05:05:51 +00001129
1130 /* Patch the object type */
1131 mmap_object_type.ob_type = &PyType_Type;
1132
Guido van Rossum09fdf072000-03-31 01:17:07 +00001133 module = Py_InitModule ("mmap", mmap_functions);
Neal Norwitz1ac754f2006-01-19 06:09:39 +00001134 if (module == NULL)
1135 return;
Guido van Rossum09fdf072000-03-31 01:17:07 +00001136 dict = PyModule_GetDict (module);
1137 mmap_module_error = PyExc_EnvironmentError;
1138 Py_INCREF(mmap_module_error);
1139 PyDict_SetItemString (dict, "error", mmap_module_error);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001140#ifdef PROT_EXEC
Guido van Rossum09fdf072000-03-31 01:17:07 +00001141 PyDict_SetItemString (dict, "PROT_EXEC", PyInt_FromLong(PROT_EXEC) );
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001142#endif
1143#ifdef PROT_READ
Guido van Rossum09fdf072000-03-31 01:17:07 +00001144 PyDict_SetItemString (dict, "PROT_READ", PyInt_FromLong(PROT_READ) );
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001145#endif
1146#ifdef PROT_WRITE
Guido van Rossum09fdf072000-03-31 01:17:07 +00001147 PyDict_SetItemString (dict, "PROT_WRITE", PyInt_FromLong(PROT_WRITE) );
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001148#endif
1149
1150#ifdef MAP_SHARED
Guido van Rossum09fdf072000-03-31 01:17:07 +00001151 PyDict_SetItemString (dict, "MAP_SHARED", PyInt_FromLong(MAP_SHARED) );
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001152#endif
1153#ifdef MAP_PRIVATE
Guido van Rossum09fdf072000-03-31 01:17:07 +00001154 PyDict_SetItemString (dict, "MAP_PRIVATE",
1155 PyInt_FromLong(MAP_PRIVATE) );
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001156#endif
1157#ifdef MAP_DENYWRITE
Guido van Rossum09fdf072000-03-31 01:17:07 +00001158 PyDict_SetItemString (dict, "MAP_DENYWRITE",
1159 PyInt_FromLong(MAP_DENYWRITE) );
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001160#endif
1161#ifdef MAP_EXECUTABLE
Guido van Rossum09fdf072000-03-31 01:17:07 +00001162 PyDict_SetItemString (dict, "MAP_EXECUTABLE",
1163 PyInt_FromLong(MAP_EXECUTABLE) );
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001164#endif
Neal Norwitz0e6bc8c2006-02-05 05:45:43 +00001165#ifdef MAP_ANONYMOUS
1166 PyDict_SetItemString (dict, "MAP_ANON", PyInt_FromLong(MAP_ANONYMOUS) );
Guido van Rossum09fdf072000-03-31 01:17:07 +00001167 PyDict_SetItemString (dict, "MAP_ANONYMOUS",
Neal Norwitz0e6bc8c2006-02-05 05:45:43 +00001168 PyInt_FromLong(MAP_ANONYMOUS) );
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00001169#endif
1170
Guido van Rossum09fdf072000-03-31 01:17:07 +00001171 PyDict_SetItemString (dict, "PAGESIZE",
Fred Drake145f96e2000-10-01 17:50:46 +00001172 PyInt_FromLong( (long)my_getpagesize() ) );
Andrew M. Kuchling961fe172000-06-03 19:41:42 +00001173
Tim Peters5ebfd362001-11-13 23:11:19 +00001174 PyDict_SetItemString (dict, "ACCESS_READ",
1175 PyInt_FromLong(ACCESS_READ));
1176 PyDict_SetItemString (dict, "ACCESS_WRITE",
1177 PyInt_FromLong(ACCESS_WRITE));
1178 PyDict_SetItemString (dict, "ACCESS_COPY",
1179 PyInt_FromLong(ACCESS_COPY));
1180}