blob: 051a71572cef8c7dcbd076a9b269d8ab6c8d3413 [file] [log] [blame]
Guido van Rossum09fdf072000-03-31 01:17:07 +00001/*
2 / Author: Sam Rushing <rushing@nightmare.com>
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +00003 / Hacked for Unix by A.M. Kuchling <amk1@bigfoot.com>
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 /
15 / The latest version of mmapfile is maintained by Sam at
16 / ftp://squirl.nightmare.com/pub/python/python-ext.
17*/
18
Guido van Rossum09fdf072000-03-31 01:17:07 +000019#include <Python.h>
20
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +000021#ifndef MS_WIN32
22#define UNIX
23#endif
24
25#ifdef MS_WIN32
26#include <windows.h>
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +000027#if _MSC_VER < 1200
28#define INT_PTR unsigned long
29#endif
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +000030#endif
31
32#ifdef UNIX
33#include <unistd.h>
34#include <sys/mman.h>
Andrew M. Kuchling7b9fb922000-06-17 22:41:22 +000035#include <sys/stat.h>
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +000036#endif
37
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +000038#include <string.h>
39#include <sys/types.h>
40
41static PyObject *mmap_module_error;
42
43typedef struct {
Guido van Rossum09fdf072000-03-31 01:17:07 +000044 PyObject_HEAD
45 char * data;
46 size_t size;
47 size_t pos;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +000048
49#ifdef MS_WIN32
Guido van Rossum09fdf072000-03-31 01:17:07 +000050 HANDLE map_handle;
Andrew M. Kuchling70d27422000-06-18 04:45:14 +000051 INT_PTR file_handle;
Guido van Rossum09fdf072000-03-31 01:17:07 +000052 char * tagname;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +000053#endif
54
55#ifdef UNIX
Andrew M. Kuchling7b9fb922000-06-17 22:41:22 +000056 int fd;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +000057#endif
58} mmap_object;
59
60static void
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +000061mmap_object_dealloc(mmap_object *m_obj)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +000062{
63#ifdef MS_WIN32
Mark Hammond2cbed002000-07-30 02:22:43 +000064 if (m_obj->data != NULL)
65 UnmapViewOfFile (m_obj->data);
66 if (m_obj->map_handle != INVALID_HANDLE_VALUE)
67 CloseHandle (m_obj->map_handle);
68 if ((HANDLE)m_obj->file_handle != INVALID_HANDLE_VALUE)
69 CloseHandle ((HANDLE)m_obj->file_handle);
70 if (m_obj->tagname)
71 PyMem_Free(m_obj->tagname);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +000072#endif /* MS_WIN32 */
73
74#ifdef UNIX
Guido van Rossum09fdf072000-03-31 01:17:07 +000075 if (m_obj->data!=NULL) {
Andrew M. Kuchling9bc5f332000-06-18 04:25:08 +000076 msync(m_obj->data, m_obj->size, MS_SYNC);
Guido van Rossum09fdf072000-03-31 01:17:07 +000077 munmap(m_obj->data, m_obj->size);
78 }
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +000079#endif /* UNIX */
80
Guido van Rossumb18618d2000-05-03 23:44:39 +000081 PyObject_Del(m_obj);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +000082}
83
84static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +000085mmap_close_method(mmap_object *self, PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +000086{
Andrew M. Kuchling841b9fb2000-06-03 20:43:43 +000087 if (!PyArg_ParseTuple(args, ":close"))
Andrew M. Kuchling961fe172000-06-03 19:41:42 +000088 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +000089#ifdef MS_WIN32
Guido van Rossum09fdf072000-03-31 01:17:07 +000090 UnmapViewOfFile (self->data);
91 CloseHandle (self->map_handle);
92 CloseHandle ((HANDLE)self->file_handle);
93 self->map_handle = (HANDLE) NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +000094#endif /* MS_WIN32 */
95
96#ifdef UNIX
Guido van Rossum09fdf072000-03-31 01:17:07 +000097 munmap(self->data, self->size);
98 self->data = NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +000099#endif
100
Guido van Rossum09fdf072000-03-31 01:17:07 +0000101 Py_INCREF (Py_None);
102 return (Py_None);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000103}
104
105#ifdef MS_WIN32
Guido van Rossum09fdf072000-03-31 01:17:07 +0000106#define CHECK_VALID(err) \
107do { \
108 if (!self->map_handle) { \
109 PyErr_SetString (PyExc_ValueError, "mmap closed or invalid"); \
110 return err; \
111 } \
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000112} while (0)
113#endif /* MS_WIN32 */
114
115#ifdef UNIX
Guido van Rossum09fdf072000-03-31 01:17:07 +0000116#define CHECK_VALID(err) \
117do { \
118 if (self->data == NULL) { \
119 PyErr_SetString (PyExc_ValueError, "mmap closed or invalid"); \
120 return err; \
121 } \
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000122} while (0)
123#endif /* UNIX */
124
125static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000126mmap_read_byte_method(mmap_object *self,
127 PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000128{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000129 char value;
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000130 char *where;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000131 CHECK_VALID(NULL);
Andrew M. Kuchling841b9fb2000-06-03 20:43:43 +0000132 if (!PyArg_ParseTuple(args, ":read_byte"))
Andrew M. Kuchling961fe172000-06-03 19:41:42 +0000133 return NULL;
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000134 if (self->pos < self->size) {
Guido van Rossum36d4f8b2000-04-10 21:34:37 +0000135 where = self->data + self->pos;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000136 value = (char) *(where);
137 self->pos += 1;
138 return Py_BuildValue("c", (char) *(where));
139 } else {
140 PyErr_SetString (PyExc_ValueError, "read byte out of range");
141 return NULL;
142 }
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000143}
144
145static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000146mmap_read_line_method(mmap_object *self,
147 PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000148{
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000149 char *start = self->data+self->pos;
150 char *eof = self->data+self->size;
151 char *eol;
152 PyObject *result;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000153
Guido van Rossum09fdf072000-03-31 01:17:07 +0000154 CHECK_VALID(NULL);
Andrew M. Kuchling841b9fb2000-06-03 20:43:43 +0000155 if (!PyArg_ParseTuple(args, ":readline"))
Andrew M. Kuchling961fe172000-06-03 19:41:42 +0000156 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000157
Fred Drake56a87a02000-04-04 18:17:35 +0000158 eol = memchr(start, '\n', self->size - self->pos);
159 if (!eol)
160 eol = eof;
161 else
162 ++eol; /* we're interested in the position after the
163 newline. */
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000164 result = PyString_FromStringAndSize(start, (eol - start));
Guido van Rossum09fdf072000-03-31 01:17:07 +0000165 self->pos += (eol - start);
166 return (result);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000167}
168
169static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000170mmap_read_method(mmap_object *self,
171 PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000172{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000173 long num_bytes;
174 PyObject *result;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000175
Guido van Rossum09fdf072000-03-31 01:17:07 +0000176 CHECK_VALID(NULL);
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000177 if (!PyArg_ParseTuple(args, "l:read", &num_bytes))
Guido van Rossum09fdf072000-03-31 01:17:07 +0000178 return(NULL);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000179
Guido van Rossum09fdf072000-03-31 01:17:07 +0000180 /* silently 'adjust' out-of-range requests */
181 if ((self->pos + num_bytes) > self->size) {
182 num_bytes -= (self->pos+num_bytes) - self->size;
183 }
184 result = Py_BuildValue("s#", self->data+self->pos, num_bytes);
185 self->pos += num_bytes;
186 return (result);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000187}
188
189static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000190mmap_find_method(mmap_object *self,
191 PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000192{
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000193 int start = self->pos;
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000194 char *needle;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000195 int len;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000196
Guido van Rossum09fdf072000-03-31 01:17:07 +0000197 CHECK_VALID(NULL);
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000198 if (!PyArg_ParseTuple (args, "s#|i:find", &needle, &len, &start)) {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000199 return NULL;
200 } else {
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000201 char *p = self->data+self->pos;
202 char *e = self->data+self->size;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000203 while (p < e) {
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000204 char *s = p;
205 char *n = needle;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000206 while ((s<e) && (*n) && !(*s-*n)) {
207 s++, n++;
208 }
209 if (!*n) {
210 return Py_BuildValue (
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000211 "i",
212 (int) (p - (self->data + start)));
Guido van Rossum09fdf072000-03-31 01:17:07 +0000213 }
214 p++;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000215 }
Guido van Rossum09fdf072000-03-31 01:17:07 +0000216 return Py_BuildValue ("l", (long) -1);
217 }
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000218}
219
220static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000221mmap_write_method(mmap_object *self,
222 PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000223{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000224 long length;
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000225 char *data;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000226
Guido van Rossum09fdf072000-03-31 01:17:07 +0000227 CHECK_VALID(NULL);
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000228 if (!PyArg_ParseTuple (args, "s#:write", &data, &length))
Guido van Rossum09fdf072000-03-31 01:17:07 +0000229 return(NULL);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000230
Guido van Rossum09fdf072000-03-31 01:17:07 +0000231 if ((self->pos + length) > self->size) {
232 PyErr_SetString (PyExc_ValueError, "data out of range");
233 return NULL;
234 }
235 memcpy (self->data+self->pos, data, length);
236 self->pos = self->pos+length;
237 Py_INCREF (Py_None);
238 return (Py_None);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000239}
240
241static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000242mmap_write_byte_method(mmap_object *self,
243 PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000244{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000245 char value;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000246
Guido van Rossum09fdf072000-03-31 01:17:07 +0000247 CHECK_VALID(NULL);
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000248 if (!PyArg_ParseTuple (args, "c:write_byte", &value))
Guido van Rossum09fdf072000-03-31 01:17:07 +0000249 return(NULL);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000250
Guido van Rossum09fdf072000-03-31 01:17:07 +0000251 *(self->data+self->pos) = value;
252 self->pos += 1;
253 Py_INCREF (Py_None);
254 return (Py_None);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000255}
256
257static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000258mmap_size_method(mmap_object *self,
259 PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000260{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000261 CHECK_VALID(NULL);
Andrew M. Kuchling841b9fb2000-06-03 20:43:43 +0000262 if (!PyArg_ParseTuple(args, ":size"))
Andrew M. Kuchling961fe172000-06-03 19:41:42 +0000263 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000264
265#ifdef MS_WIN32
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000266 if (self->file_handle != (INT_PTR) -1) {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000267 return (Py_BuildValue (
Fredrik Lundh5cccf502000-07-09 13:16:13 +0000268 "l", (long)
Guido van Rossum09fdf072000-03-31 01:17:07 +0000269 GetFileSize ((HANDLE)self->file_handle, NULL)));
270 } else {
Fredrik Lundh5cccf502000-07-09 13:16:13 +0000271 return (Py_BuildValue ("l", (long) self->size) );
Guido van Rossum09fdf072000-03-31 01:17:07 +0000272 }
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000273#endif /* MS_WIN32 */
274
275#ifdef UNIX
Andrew M. Kuchling7b9fb922000-06-17 22:41:22 +0000276 {
277 struct stat buf;
278 if (-1 == fstat(self->fd, &buf)) {
279 PyErr_SetFromErrno(mmap_module_error);
280 return NULL;
281 }
Fredrik Lundh5cccf502000-07-09 13:16:13 +0000282 return (Py_BuildValue ("l", (long) buf.st_size) );
Andrew M. Kuchling7b9fb922000-06-17 22:41:22 +0000283 }
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000284#endif /* UNIX */
285}
286
287/* This assumes that you want the entire file mapped,
288 / and when recreating the map will make the new file
289 / have the new size
290 /
291 / Is this really necessary? This could easily be done
292 / from python by just closing and re-opening with the
293 / new size?
294 */
295
296static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000297mmap_resize_method(mmap_object *self,
298 PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000299{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000300 unsigned long new_size;
301 CHECK_VALID(NULL);
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000302 if (!PyArg_ParseTuple (args, "l:resize", &new_size)) {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000303 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000304#ifdef MS_WIN32
Guido van Rossum09fdf072000-03-31 01:17:07 +0000305 } else {
306 DWORD dwErrCode = 0;
307 /* First, unmap the file view */
308 UnmapViewOfFile (self->data);
309 /* Close the mapping object */
310 CloseHandle ((HANDLE)self->map_handle);
311 /* Move to the desired EOF position */
312 SetFilePointer ((HANDLE)self->file_handle,
313 new_size, NULL, FILE_BEGIN);
314 /* Change the size of the file */
315 SetEndOfFile ((HANDLE)self->file_handle);
316 /* Create another mapping object and remap the file view */
317 self->map_handle = CreateFileMapping (
318 (HANDLE) self->file_handle,
319 NULL,
320 PAGE_READWRITE,
321 0,
322 new_size,
323 self->tagname);
324 if (self->map_handle != NULL) {
325 self->data = (char *) MapViewOfFile (self->map_handle,
326 FILE_MAP_WRITE,
327 0,
328 0,
329 0);
330 if (self->data != NULL) {
331 self->size = new_size;
332 Py_INCREF (Py_None);
333 return Py_None;
334 } else {
335 dwErrCode = GetLastError();
336 }
337 } else {
338 dwErrCode = GetLastError();
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000339 }
Guido van Rossum09fdf072000-03-31 01:17:07 +0000340 PyErr_SetFromWindowsErr(dwErrCode);
341 return (NULL);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000342#endif /* MS_WIN32 */
343
344#ifdef UNIX
Andrew M. Kuchling6fef30e2000-06-18 14:51:21 +0000345#ifndef HAVE_MREMAP
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000346} else {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000347 PyErr_SetString(PyExc_SystemError,
348 "mmap: resizing not available--no mremap()");
349 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000350#else
351} else {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000352 void *newmap;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000353
Andrew M. Kuchling6fef30e2000-06-18 14:51:21 +0000354#ifdef MREMAP_MAYMOVE
Guido van Rossum09fdf072000-03-31 01:17:07 +0000355 newmap = mremap(self->data, self->size, new_size, MREMAP_MAYMOVE);
Andrew M. Kuchling6fef30e2000-06-18 14:51:21 +0000356#else
357 newmap = mremap(self->data, self->size, new_size, 0);
358#endif
Guido van Rossum09fdf072000-03-31 01:17:07 +0000359 if (newmap == (void *)-1)
360 {
361 PyErr_SetFromErrno(mmap_module_error);
362 return NULL;
363 }
364 self->data = newmap;
365 self->size = new_size;
366 Py_INCREF(Py_None);
367 return Py_None;
Andrew M. Kuchling6fef30e2000-06-18 14:51:21 +0000368#endif /* HAVE_MREMAP */
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000369#endif /* UNIX */
370}
371}
372
373static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000374mmap_tell_method(mmap_object *self, PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000375{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000376 CHECK_VALID(NULL);
Andrew M. Kuchling841b9fb2000-06-03 20:43:43 +0000377 if (!PyArg_ParseTuple(args, ":tell"))
Andrew M. Kuchling961fe172000-06-03 19:41:42 +0000378 return NULL;
Fredrik Lundh5cccf502000-07-09 13:16:13 +0000379 return (Py_BuildValue ("l", (long) self->pos) );
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000380}
381
382static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000383mmap_flush_method(mmap_object *self, PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000384{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000385 size_t offset = 0;
386 size_t size = self->size;
387 CHECK_VALID(NULL);
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000388 if (!PyArg_ParseTuple (args, "|ll:flush", &offset, &size)) {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000389 return NULL;
390 } else if ((offset + size) > self->size) {
391 PyErr_SetString (PyExc_ValueError,
392 "flush values out of range");
393 return NULL;
394 } else {
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000395#ifdef MS_WIN32
Fredrik Lundh5cccf502000-07-09 13:16:13 +0000396 return (Py_BuildValue("l", (long)
397 FlushViewOfFile(self->data+offset, size)));
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000398#endif /* MS_WIN32 */
399#ifdef UNIX
Guido van Rossum09fdf072000-03-31 01:17:07 +0000400 /* XXX semantics of return value? */
401 /* XXX flags for msync? */
402 if (-1 == msync(self->data + offset, size,
Andrew M. Kuchling9bc5f332000-06-18 04:25:08 +0000403 MS_SYNC))
Guido van Rossum09fdf072000-03-31 01:17:07 +0000404 {
405 PyErr_SetFromErrno(mmap_module_error);
406 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000407 }
Fredrik Lundh5cccf502000-07-09 13:16:13 +0000408 return Py_BuildValue ("l", (long) 0);
Guido van Rossum09fdf072000-03-31 01:17:07 +0000409#endif /* UNIX */
410 }
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000411}
412
413static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000414mmap_seek_method(mmap_object *self, PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000415{
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000416 int dist;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000417 int how=0;
418 CHECK_VALID(NULL);
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000419 if (!PyArg_ParseTuple (args, "i|i:seek", &dist, &how)) {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000420 return(NULL);
421 } else {
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000422 size_t where;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000423 switch (how) {
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000424 case 0: /* relative to start */
425 if (dist < 0)
426 goto onoutofrange;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000427 where = dist;
428 break;
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000429 case 1: /* relative to current position */
430 if ((int)self->pos + dist < 0)
431 goto onoutofrange;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000432 where = self->pos + dist;
433 break;
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000434 case 2: /* relative to end */
435 if ((int)self->size + dist < 0)
436 goto onoutofrange;
437 where = self->size + dist;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000438 break;
439 default:
440 PyErr_SetString (PyExc_ValueError,
441 "unknown seek type");
442 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000443 }
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000444 if (where > self->size)
445 goto onoutofrange;
446 self->pos = where;
447 Py_INCREF (Py_None);
448 return (Py_None);
Guido van Rossum09fdf072000-03-31 01:17:07 +0000449 }
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000450
451onoutofrange:
452 PyErr_SetString (PyExc_ValueError, "seek out of range");
453 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000454}
455
456static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000457mmap_move_method(mmap_object *self, PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000458{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000459 unsigned long dest, src, count;
460 CHECK_VALID(NULL);
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000461 if (!PyArg_ParseTuple (args, "iii:move", &dest, &src, &count)) {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000462 return NULL;
463 } else {
464 /* bounds check the values */
465 if (/* end of source after end of data?? */
466 ((src+count) > self->size)
467 /* dest will fit? */
468 || (dest+count > self->size)) {
469 PyErr_SetString (PyExc_ValueError,
470 "source or destination out of range");
471 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000472 } else {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000473 memmove (self->data+dest, self->data+src, count);
474 Py_INCREF (Py_None);
475 return Py_None;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000476 }
Guido van Rossum09fdf072000-03-31 01:17:07 +0000477 }
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000478}
479
480static struct PyMethodDef mmap_object_methods[] = {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000481 {"close", (PyCFunction) mmap_close_method, 1},
482 {"find", (PyCFunction) mmap_find_method, 1},
483 {"flush", (PyCFunction) mmap_flush_method, 1},
484 {"move", (PyCFunction) mmap_move_method, 1},
485 {"read", (PyCFunction) mmap_read_method, 1},
486 {"read_byte", (PyCFunction) mmap_read_byte_method, 1},
487 {"readline", (PyCFunction) mmap_read_line_method, 1},
488 {"resize", (PyCFunction) mmap_resize_method, 1},
489 {"seek", (PyCFunction) mmap_seek_method, 1},
490 {"size", (PyCFunction) mmap_size_method, 1},
491 {"tell", (PyCFunction) mmap_tell_method, 1},
492 {"write", (PyCFunction) mmap_write_method, 1},
493 {"write_byte", (PyCFunction) mmap_write_byte_method, 1},
494 {NULL, NULL} /* sentinel */
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000495};
496
497/* Functions for treating an mmap'ed file as a buffer */
498
499static int
Andrew M. Kuchling961fe172000-06-03 19:41:42 +0000500mmap_buffer_getreadbuf(mmap_object *self, int index, const void **ptr)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000501{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000502 CHECK_VALID(-1);
503 if ( index != 0 ) {
504 PyErr_SetString(PyExc_SystemError,
505 "Accessing non-existent mmap segment");
506 return -1;
507 }
508 *ptr = self->data;
509 return self->size;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000510}
511
512static int
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000513mmap_buffer_getwritebuf(mmap_object *self, int index, const void **ptr)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000514{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000515 CHECK_VALID(-1);
516 if ( index != 0 ) {
517 PyErr_SetString(PyExc_SystemError,
518 "Accessing non-existent mmap segment");
519 return -1;
520 }
521 *ptr = self->data;
522 return self->size;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000523}
524
525static int
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000526mmap_buffer_getsegcount(mmap_object *self, int *lenp)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000527{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000528 CHECK_VALID(-1);
529 if (lenp)
530 *lenp = self->size;
531 return 1;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000532}
533
534static int
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000535mmap_buffer_getcharbuffer(mmap_object *self, int index, const void **ptr)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000536{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000537 if ( index != 0 ) {
538 PyErr_SetString(PyExc_SystemError,
539 "accessing non-existent buffer segment");
540 return -1;
541 }
542 *ptr = (const char *)self->data;
543 return self->size;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000544}
545
546static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000547mmap_object_getattr(mmap_object *self, char *name)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000548{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000549 return Py_FindMethod (mmap_object_methods, (PyObject *)self, name);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000550}
551
552static int
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000553mmap_length(mmap_object *self)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000554{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000555 CHECK_VALID(-1);
556 return self->size;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000557}
558
559static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000560mmap_item(mmap_object *self, int i)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000561{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000562 CHECK_VALID(NULL);
Guido van Rossumce8e1dc2000-07-01 00:51:51 +0000563 if (i < 0 || (size_t)i >= self->size) {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000564 PyErr_SetString(PyExc_IndexError, "mmap index out of range");
565 return NULL;
566 }
567 return PyString_FromStringAndSize(self->data + i, 1);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000568}
569
570static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000571mmap_slice(mmap_object *self, int ilow, int ihigh)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000572{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000573 CHECK_VALID(NULL);
574 if (ilow < 0)
575 ilow = 0;
Guido van Rossumce8e1dc2000-07-01 00:51:51 +0000576 else if ((size_t)ilow > self->size)
Guido van Rossum09fdf072000-03-31 01:17:07 +0000577 ilow = self->size;
578 if (ihigh < 0)
579 ihigh = 0;
580 if (ihigh < ilow)
581 ihigh = ilow;
Guido van Rossumce8e1dc2000-07-01 00:51:51 +0000582 else if ((size_t)ihigh > self->size)
Guido van Rossum09fdf072000-03-31 01:17:07 +0000583 ihigh = self->size;
584
585 return PyString_FromStringAndSize(self->data + ilow, ihigh-ilow);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000586}
587
588static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000589mmap_concat(mmap_object *self, PyObject *bb)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000590{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000591 CHECK_VALID(NULL);
592 PyErr_SetString(PyExc_SystemError,
593 "mmaps don't support concatenation");
594 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000595}
596
597static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000598mmap_repeat(mmap_object *self, int n)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000599{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000600 CHECK_VALID(NULL);
601 PyErr_SetString(PyExc_SystemError,
602 "mmaps don't support repeat operation");
603 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000604}
605
606static int
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000607mmap_ass_slice(mmap_object *self, int ilow, int ihigh, PyObject *v)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000608{
Guido van Rossum36d4f8b2000-04-10 21:34:37 +0000609 const char *buf;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000610
Guido van Rossum09fdf072000-03-31 01:17:07 +0000611 CHECK_VALID(-1);
612 if (ilow < 0)
613 ilow = 0;
Guido van Rossumce8e1dc2000-07-01 00:51:51 +0000614 else if ((size_t)ilow > self->size)
Guido van Rossum09fdf072000-03-31 01:17:07 +0000615 ilow = self->size;
616 if (ihigh < 0)
617 ihigh = 0;
618 if (ihigh < ilow)
619 ihigh = ilow;
Guido van Rossumce8e1dc2000-07-01 00:51:51 +0000620 else if ((size_t)ihigh > self->size)
Guido van Rossum09fdf072000-03-31 01:17:07 +0000621 ihigh = self->size;
622
623 if (! (PyString_Check(v)) ) {
624 PyErr_SetString(PyExc_IndexError,
625 "mmap slice assignment must be a string");
626 return -1;
627 }
628 if ( PyString_Size(v) != (ihigh - ilow) ) {
629 PyErr_SetString(PyExc_IndexError,
630 "mmap slice assignment is wrong size");
631 return -1;
632 }
633 buf = PyString_AsString(v);
634 memcpy(self->data + ilow, buf, ihigh-ilow);
635 return 0;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000636}
637
638static int
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000639mmap_ass_item(mmap_object *self, int i, PyObject *v)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000640{
Guido van Rossum36d4f8b2000-04-10 21:34:37 +0000641 const char *buf;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000642
Guido van Rossum09fdf072000-03-31 01:17:07 +0000643 CHECK_VALID(-1);
Guido van Rossumce8e1dc2000-07-01 00:51:51 +0000644 if (i < 0 || (size_t)i >= self->size) {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000645 PyErr_SetString(PyExc_IndexError, "mmap index out of range");
646 return -1;
647 }
648 if (! (PyString_Check(v) && PyString_Size(v)==1) ) {
649 PyErr_SetString(PyExc_IndexError,
650 "mmap assignment must be single-character string");
651 return -1;
652 }
653 buf = PyString_AsString(v);
654 self->data[i] = buf[0];
655 return 0;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000656}
657
658static PySequenceMethods mmap_as_sequence = {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000659 (inquiry)mmap_length, /*sq_length*/
660 (binaryfunc)mmap_concat, /*sq_concat*/
661 (intargfunc)mmap_repeat, /*sq_repeat*/
662 (intargfunc)mmap_item, /*sq_item*/
663 (intintargfunc)mmap_slice, /*sq_slice*/
664 (intobjargproc)mmap_ass_item, /*sq_ass_item*/
665 (intintobjargproc)mmap_ass_slice, /*sq_ass_slice*/
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000666};
667
668static PyBufferProcs mmap_as_buffer = {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000669 (getreadbufferproc)mmap_buffer_getreadbuf,
670 (getwritebufferproc)mmap_buffer_getwritebuf,
671 (getsegcountproc)mmap_buffer_getsegcount,
672 (getcharbufferproc)mmap_buffer_getcharbuffer,
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000673};
674
675static PyTypeObject mmap_object_type = {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000676 PyObject_HEAD_INIT(0) /* patched in module init */
677 0, /* ob_size */
678 "mmap", /* tp_name */
679 sizeof(mmap_object), /* tp_size */
680 0, /* tp_itemsize */
681 /* methods */
682 (destructor) mmap_object_dealloc, /* tp_dealloc */
683 0, /* tp_print */
684 (getattrfunc) mmap_object_getattr, /* tp_getattr */
685 0, /* tp_setattr */
686 0, /* tp_compare */
687 0, /* tp_repr */
688 0, /* tp_as_number */
689 &mmap_as_sequence, /*tp_as_sequence*/
690 0, /*tp_as_mapping*/
691 0, /*tp_hash*/
692 0, /*tp_call*/
693 0, /*tp_str*/
694 0, /*tp_getattro*/
695 0, /*tp_setattro*/
696 &mmap_as_buffer, /*tp_as_buffer*/
697 Py_TPFLAGS_HAVE_GETCHARBUFFER, /*tp_flags*/
698 0, /*tp_doc*/
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000699};
700
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000701
702/* extract the map size from the given PyObject
703
704 The map size is restricted to [0, INT_MAX] because this is the current
705 Python limitation on object sizes. Although the mmap object *could* handle
706 a larger map size, there is no point because all the useful operations
707 (len(), slicing(), sequence indexing) are limited by a C int.
708
Thomas Wouters7e474022000-07-16 12:04:32 +0000709 Returns -1 on error, with an appropriate Python exception raised. On
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000710 success, the map size is returned. */
711static int
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000712_GetMapSize(PyObject *o)
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000713{
714 if (PyInt_Check(o)) {
715 long i = PyInt_AsLong(o);
716 if (PyErr_Occurred())
717 return -1;
718 if (i < 0)
719 goto onnegoverflow;
720 if (i > INT_MAX)
721 goto onposoverflow;
722 return (int)i;
723 }
724 else if (PyLong_Check(o)) {
725 long i = PyLong_AsLong(o);
726 if (PyErr_Occurred()) {
727 /* yes negative overflow is mistaken for positive overflow
728 but not worth the trouble to check sign of 'i' */
729 if (PyErr_ExceptionMatches(PyExc_OverflowError))
730 goto onposoverflow;
731 else
732 return -1;
733 }
734 if (i < 0)
735 goto onnegoverflow;
736 if (i > INT_MAX)
737 goto onposoverflow;
738 return (int)i;
739 }
740 else {
741 PyErr_SetString(PyExc_TypeError,
742 "map size must be an integral value");
743 return -1;
744 }
745
746onnegoverflow:
747 PyErr_SetString(PyExc_OverflowError,
748 "memory mapped size must be positive");
749 return -1;
750
751onposoverflow:
752 PyErr_SetString(PyExc_OverflowError,
753 "memory mapped size is too large (limited by C int)");
754 return -1;
755}
756
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000757#ifdef UNIX
758static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000759new_mmap_object(PyObject *self, PyObject *args, PyObject *kwdict)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000760{
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000761 mmap_object *m_obj;
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000762 PyObject *map_size_obj = NULL;
763 int map_size;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000764 int fd, flags = MAP_SHARED, prot = PROT_WRITE | PROT_READ;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000765 char *keywords[] = {"file", "size", "flags", "prot", NULL};
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000766
Guido van Rossum09fdf072000-03-31 01:17:07 +0000767 if (!PyArg_ParseTupleAndKeywords(args, kwdict,
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000768 "iO|ii", keywords,
769 &fd, &map_size_obj, &flags, &prot)
Guido van Rossum09fdf072000-03-31 01:17:07 +0000770 )
771 return NULL;
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000772 map_size = _GetMapSize(map_size_obj);
773 if (map_size < 0)
774 return NULL;
775
Guido van Rossumb18618d2000-05-03 23:44:39 +0000776 m_obj = PyObject_New (mmap_object, &mmap_object_type);
Guido van Rossum09fdf072000-03-31 01:17:07 +0000777 if (m_obj == NULL) {return NULL;}
778 m_obj->size = (size_t) map_size;
779 m_obj->pos = (size_t) 0;
Andrew M. Kuchling7b9fb922000-06-17 22:41:22 +0000780 m_obj->fd = fd;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000781 m_obj->data = mmap(NULL, map_size,
782 prot, flags,
783 fd, 0);
784 if (m_obj->data == (void *)-1)
785 {
786 Py_DECREF(m_obj);
787 PyErr_SetFromErrno(mmap_module_error);
788 return NULL;
789 }
790 return (PyObject *)m_obj;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000791}
792#endif /* UNIX */
793
794#ifdef MS_WIN32
795static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000796new_mmap_object(PyObject *self, PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000797{
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000798 mmap_object *m_obj;
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000799 PyObject *map_size_obj = NULL;
800 int map_size;
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000801 char *tagname = "";
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000802
Guido van Rossum09fdf072000-03-31 01:17:07 +0000803 DWORD dwErr = 0;
804 int fileno;
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000805 INT_PTR fh = 0;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000806
Guido van Rossum09fdf072000-03-31 01:17:07 +0000807 /* Patch the object type */
808 mmap_object_type.ob_type = &PyType_Type;
809
810 if (!PyArg_ParseTuple(args,
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000811 "iO|z",
Guido van Rossum09fdf072000-03-31 01:17:07 +0000812 &fileno,
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000813 &map_size_obj,
Guido van Rossum09fdf072000-03-31 01:17:07 +0000814 &tagname)
815 )
816 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000817
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000818 map_size = _GetMapSize(map_size_obj);
819 if (map_size < 0)
820 return NULL;
821
Guido van Rossum09fdf072000-03-31 01:17:07 +0000822 /* if an actual filename has been specified */
823 if (fileno != 0) {
824 fh = _get_osfhandle(fileno);
825 if (fh==-1) {
826 PyErr_SetFromErrno(mmap_module_error);
827 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000828 }
Fred Drake1ef4e2d2000-04-05 14:15:31 +0000829 /* Win9x appears to need us seeked to zero */
830 fseek(&_iob[fileno], 0, SEEK_SET);
Guido van Rossum09fdf072000-03-31 01:17:07 +0000831 }
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000832
Guido van Rossumb18618d2000-05-03 23:44:39 +0000833 m_obj = PyObject_New (mmap_object, &mmap_object_type);
Mark Hammond2cbed002000-07-30 02:22:43 +0000834 if (m_obj==NULL)
835 return NULL;
836 /* Set every field to an invalid marker, so we can safely
837 destruct the object in the face of failure */
838 m_obj->data = NULL;
839 m_obj->file_handle = (INT_PTR)INVALID_HANDLE_VALUE;
840 m_obj->map_handle = INVALID_HANDLE_VALUE;
841 m_obj->tagname = NULL;
842
Guido van Rossum09fdf072000-03-31 01:17:07 +0000843 if (fh) {
Mark Hammond2cbed002000-07-30 02:22:43 +0000844 /* It is necessary to duplicate the handle, so the
845 Python code can close it on us */
846 if (!DuplicateHandle(
847 GetCurrentProcess(), /* source process handle */
848 (HANDLE)fh, /* handle to be duplicated */
849 GetCurrentProcess(), /* target proc handle */
850 (LPHANDLE)&m_obj->file_handle, /* result */
851 0, /* access - ignored due to options value */
852 FALSE, /* inherited by child processes? */
853 DUPLICATE_SAME_ACCESS)) { /* options */
854 dwErr = GetLastError();
855 Py_DECREF(m_obj);
856 PyErr_SetFromWindowsErr(dwErr);
857 return NULL;
858 }
Guido van Rossum09fdf072000-03-31 01:17:07 +0000859 if (!map_size) {
860 m_obj->size = GetFileSize ((HANDLE)fh, NULL);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000861 } else {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000862 m_obj->size = map_size;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000863 }
Guido van Rossum09fdf072000-03-31 01:17:07 +0000864 }
865 else {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000866 m_obj->size = map_size;
867 }
868
869 /* set the initial position */
870 m_obj->pos = (size_t) 0;
871
Mark Hammond2cbed002000-07-30 02:22:43 +0000872 /* set the tag name */
873 if (tagname != NULL) {
874 m_obj->tagname = PyMem_Malloc(strlen(tagname)+1);
875 if (m_obj->tagname == NULL) {
876 PyErr_NoMemory();
877 Py_DECREF(m_obj);
878 return NULL;
879 }
880 strcpy(m_obj->tagname, tagname);
881 }
882 else
883 m_obj->tagname = NULL;
884
Guido van Rossum09fdf072000-03-31 01:17:07 +0000885 m_obj->map_handle = CreateFileMapping ((HANDLE) m_obj->file_handle,
886 NULL,
887 PAGE_READWRITE,
888 0,
889 m_obj->size,
890 tagname);
891 if (m_obj->map_handle != NULL) {
892 m_obj->data = (char *) MapViewOfFile (m_obj->map_handle,
893 FILE_MAP_WRITE,
894 0,
895 0,
896 0);
897 if (m_obj->data != NULL) {
898 return ((PyObject *) m_obj);
899 } else {
900 dwErr = GetLastError();
901 }
902 } else {
903 dwErr = GetLastError();
904 }
Mark Hammond2cbed002000-07-30 02:22:43 +0000905 Py_DECREF(m_obj);
Guido van Rossum09fdf072000-03-31 01:17:07 +0000906 PyErr_SetFromWindowsErr(dwErr);
907 return (NULL);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000908}
909#endif /* MS_WIN32 */
910
911/* List of functions exported by this module */
912static struct PyMethodDef mmap_functions[] = {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000913 {"mmap", (PyCFunction) new_mmap_object,
914 METH_VARARGS|METH_KEYWORDS},
915 {NULL, NULL} /* Sentinel */
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000916};
917
918#ifdef MS_WIN32
Guido van Rossum09fdf072000-03-31 01:17:07 +0000919__declspec(dllexport) void
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000920#endif /* MS_WIN32 */
921#ifdef UNIX
922extern void
923#endif
924
925initmmap(void)
926{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000927 PyObject *dict, *module;
928 module = Py_InitModule ("mmap", mmap_functions);
929 dict = PyModule_GetDict (module);
930 mmap_module_error = PyExc_EnvironmentError;
931 Py_INCREF(mmap_module_error);
932 PyDict_SetItemString (dict, "error", mmap_module_error);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000933#ifdef PROT_EXEC
Guido van Rossum09fdf072000-03-31 01:17:07 +0000934 PyDict_SetItemString (dict, "PROT_EXEC", PyInt_FromLong(PROT_EXEC) );
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000935#endif
936#ifdef PROT_READ
Guido van Rossum09fdf072000-03-31 01:17:07 +0000937 PyDict_SetItemString (dict, "PROT_READ", PyInt_FromLong(PROT_READ) );
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000938#endif
939#ifdef PROT_WRITE
Guido van Rossum09fdf072000-03-31 01:17:07 +0000940 PyDict_SetItemString (dict, "PROT_WRITE", PyInt_FromLong(PROT_WRITE) );
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000941#endif
942
943#ifdef MAP_SHARED
Guido van Rossum09fdf072000-03-31 01:17:07 +0000944 PyDict_SetItemString (dict, "MAP_SHARED", PyInt_FromLong(MAP_SHARED) );
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000945#endif
946#ifdef MAP_PRIVATE
Guido van Rossum09fdf072000-03-31 01:17:07 +0000947 PyDict_SetItemString (dict, "MAP_PRIVATE",
948 PyInt_FromLong(MAP_PRIVATE) );
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000949#endif
950#ifdef MAP_DENYWRITE
Guido van Rossum09fdf072000-03-31 01:17:07 +0000951 PyDict_SetItemString (dict, "MAP_DENYWRITE",
952 PyInt_FromLong(MAP_DENYWRITE) );
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000953#endif
954#ifdef MAP_EXECUTABLE
Guido van Rossum09fdf072000-03-31 01:17:07 +0000955 PyDict_SetItemString (dict, "MAP_EXECUTABLE",
956 PyInt_FromLong(MAP_EXECUTABLE) );
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000957#endif
958#ifdef MAP_ANON
Guido van Rossum09fdf072000-03-31 01:17:07 +0000959 PyDict_SetItemString (dict, "MAP_ANON", PyInt_FromLong(MAP_ANON) );
960 PyDict_SetItemString (dict, "MAP_ANONYMOUS",
961 PyInt_FromLong(MAP_ANON) );
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000962#endif
963
964#ifdef UNIX
Guido van Rossum09fdf072000-03-31 01:17:07 +0000965 PyDict_SetItemString (dict, "PAGESIZE",
966 PyInt_FromLong( (long)getpagesize() ) );
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000967#endif
Guido van Rossum09fdf072000-03-31 01:17:07 +0000968#ifdef MS_WIN32
969 {
970 SYSTEM_INFO si;
971 GetSystemInfo(&si);
972 PyDict_SetItemString (dict, "PAGESIZE",
973 PyInt_FromLong( si.dwPageSize ) );
974 }
975#endif /* MS_WIN32 */
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000976
977}
Andrew M. Kuchling961fe172000-06-03 19:41:42 +0000978