blob: 467f110ead6459f63035b10643fad2759d63ae84 [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 /
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
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +000023#ifndef MS_WIN32
24#define UNIX
25#endif
26
27#ifdef MS_WIN32
28#include <windows.h>
29#endif
30
31#ifdef UNIX
32#include <unistd.h>
33#include <sys/mman.h>
Andrew M. Kuchling7b9fb922000-06-17 22:41:22 +000034#include <sys/stat.h>
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +000035#endif
36
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +000037#include <string.h>
38#include <sys/types.h>
39
40static PyObject *mmap_module_error;
41
42typedef struct {
Guido van Rossum09fdf072000-03-31 01:17:07 +000043 PyObject_HEAD
44 char * data;
45 size_t size;
46 size_t pos;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +000047
48#ifdef MS_WIN32
Guido van Rossum09fdf072000-03-31 01:17:07 +000049 HANDLE map_handle;
Mark Hammond071864a2000-07-30 02:46:26 +000050 HANDLE file_handle;
Guido van Rossum09fdf072000-03-31 01:17:07 +000051 char * tagname;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +000052#endif
53
54#ifdef UNIX
Andrew M. Kuchling7b9fb922000-06-17 22:41:22 +000055 int fd;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +000056#endif
57} mmap_object;
58
59static void
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +000060mmap_object_dealloc(mmap_object *m_obj)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +000061{
62#ifdef MS_WIN32
Mark Hammond2cbed002000-07-30 02:22:43 +000063 if (m_obj->data != NULL)
64 UnmapViewOfFile (m_obj->data);
65 if (m_obj->map_handle != INVALID_HANDLE_VALUE)
66 CloseHandle (m_obj->map_handle);
Mark Hammond071864a2000-07-30 02:46:26 +000067 if (m_obj->file_handle != INVALID_HANDLE_VALUE)
68 CloseHandle (m_obj->file_handle);
Mark Hammond2cbed002000-07-30 02:22:43 +000069 if (m_obj->tagname)
70 PyMem_Free(m_obj->tagname);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +000071#endif /* MS_WIN32 */
72
73#ifdef UNIX
Guido van Rossum09fdf072000-03-31 01:17:07 +000074 if (m_obj->data!=NULL) {
Andrew M. Kuchling9bc5f332000-06-18 04:25:08 +000075 msync(m_obj->data, m_obj->size, MS_SYNC);
Guido van Rossum09fdf072000-03-31 01:17:07 +000076 munmap(m_obj->data, m_obj->size);
77 }
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +000078#endif /* UNIX */
79
Guido van Rossumb18618d2000-05-03 23:44:39 +000080 PyObject_Del(m_obj);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +000081}
82
83static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +000084mmap_close_method(mmap_object *self, PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +000085{
Andrew M. Kuchling841b9fb2000-06-03 20:43:43 +000086 if (!PyArg_ParseTuple(args, ":close"))
Andrew M. Kuchling961fe172000-06-03 19:41:42 +000087 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +000088#ifdef MS_WIN32
Mark Hammond071864a2000-07-30 02:46:26 +000089 /* For each resource we maintain, we need to check
90 the value is valid, and if so, free the resource
91 and set the member value to an invalid value so
92 the dealloc does not attempt to resource clearing
93 again.
94 TODO - should we check for errors in the close operations???
95 */
96 if (self->data != NULL) {
97 UnmapViewOfFile (self->data);
98 self->data = NULL;
99 }
100 if (self->map_handle != INVALID_HANDLE_VALUE) {
101 CloseHandle (self->map_handle);
102 self->map_handle = INVALID_HANDLE_VALUE;
103 }
104 if (self->file_handle != INVALID_HANDLE_VALUE) {
105 CloseHandle (self->file_handle);
106 self->file_handle = INVALID_HANDLE_VALUE;
107 }
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000108#endif /* MS_WIN32 */
109
110#ifdef UNIX
Guido van Rossum09fdf072000-03-31 01:17:07 +0000111 munmap(self->data, self->size);
112 self->data = NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000113#endif
114
Guido van Rossum09fdf072000-03-31 01:17:07 +0000115 Py_INCREF (Py_None);
116 return (Py_None);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000117}
118
119#ifdef MS_WIN32
Guido van Rossum09fdf072000-03-31 01:17:07 +0000120#define CHECK_VALID(err) \
121do { \
122 if (!self->map_handle) { \
123 PyErr_SetString (PyExc_ValueError, "mmap closed or invalid"); \
124 return err; \
125 } \
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000126} while (0)
127#endif /* MS_WIN32 */
128
129#ifdef UNIX
Guido van Rossum09fdf072000-03-31 01:17:07 +0000130#define CHECK_VALID(err) \
131do { \
132 if (self->data == NULL) { \
133 PyErr_SetString (PyExc_ValueError, "mmap closed or invalid"); \
134 return err; \
135 } \
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000136} while (0)
137#endif /* UNIX */
138
139static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000140mmap_read_byte_method(mmap_object *self,
141 PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000142{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000143 char value;
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000144 char *where;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000145 CHECK_VALID(NULL);
Andrew M. Kuchling841b9fb2000-06-03 20:43:43 +0000146 if (!PyArg_ParseTuple(args, ":read_byte"))
Andrew M. Kuchling961fe172000-06-03 19:41:42 +0000147 return NULL;
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000148 if (self->pos < self->size) {
Guido van Rossum36d4f8b2000-04-10 21:34:37 +0000149 where = self->data + self->pos;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000150 value = (char) *(where);
151 self->pos += 1;
152 return Py_BuildValue("c", (char) *(where));
153 } else {
154 PyErr_SetString (PyExc_ValueError, "read byte out of range");
155 return NULL;
156 }
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000157}
158
159static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000160mmap_read_line_method(mmap_object *self,
161 PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000162{
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000163 char *start = self->data+self->pos;
164 char *eof = self->data+self->size;
165 char *eol;
166 PyObject *result;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000167
Guido van Rossum09fdf072000-03-31 01:17:07 +0000168 CHECK_VALID(NULL);
Andrew M. Kuchling841b9fb2000-06-03 20:43:43 +0000169 if (!PyArg_ParseTuple(args, ":readline"))
Andrew M. Kuchling961fe172000-06-03 19:41:42 +0000170 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000171
Fred Drake56a87a02000-04-04 18:17:35 +0000172 eol = memchr(start, '\n', self->size - self->pos);
173 if (!eol)
174 eol = eof;
175 else
176 ++eol; /* we're interested in the position after the
177 newline. */
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000178 result = PyString_FromStringAndSize(start, (eol - start));
Guido van Rossum09fdf072000-03-31 01:17:07 +0000179 self->pos += (eol - start);
180 return (result);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000181}
182
183static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000184mmap_read_method(mmap_object *self,
185 PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000186{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000187 long num_bytes;
188 PyObject *result;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000189
Guido van Rossum09fdf072000-03-31 01:17:07 +0000190 CHECK_VALID(NULL);
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000191 if (!PyArg_ParseTuple(args, "l:read", &num_bytes))
Guido van Rossum09fdf072000-03-31 01:17:07 +0000192 return(NULL);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000193
Guido van Rossum09fdf072000-03-31 01:17:07 +0000194 /* silently 'adjust' out-of-range requests */
195 if ((self->pos + num_bytes) > self->size) {
196 num_bytes -= (self->pos+num_bytes) - self->size;
197 }
198 result = Py_BuildValue("s#", self->data+self->pos, num_bytes);
199 self->pos += num_bytes;
200 return (result);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000201}
202
203static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000204mmap_find_method(mmap_object *self,
205 PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000206{
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000207 int start = self->pos;
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000208 char *needle;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000209 int len;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000210
Guido van Rossum09fdf072000-03-31 01:17:07 +0000211 CHECK_VALID(NULL);
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000212 if (!PyArg_ParseTuple (args, "s#|i:find", &needle, &len, &start)) {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000213 return NULL;
214 } else {
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000215 char *p = self->data+self->pos;
216 char *e = self->data+self->size;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000217 while (p < e) {
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000218 char *s = p;
219 char *n = needle;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000220 while ((s<e) && (*n) && !(*s-*n)) {
221 s++, n++;
222 }
223 if (!*n) {
224 return Py_BuildValue (
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000225 "i",
226 (int) (p - (self->data + start)));
Guido van Rossum09fdf072000-03-31 01:17:07 +0000227 }
228 p++;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000229 }
Guido van Rossum09fdf072000-03-31 01:17:07 +0000230 return Py_BuildValue ("l", (long) -1);
231 }
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000232}
233
234static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000235mmap_write_method(mmap_object *self,
236 PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000237{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000238 long length;
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000239 char *data;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000240
Guido van Rossum09fdf072000-03-31 01:17:07 +0000241 CHECK_VALID(NULL);
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000242 if (!PyArg_ParseTuple (args, "s#:write", &data, &length))
Guido van Rossum09fdf072000-03-31 01:17:07 +0000243 return(NULL);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000244
Guido van Rossum09fdf072000-03-31 01:17:07 +0000245 if ((self->pos + length) > self->size) {
246 PyErr_SetString (PyExc_ValueError, "data out of range");
247 return NULL;
248 }
249 memcpy (self->data+self->pos, data, length);
250 self->pos = self->pos+length;
251 Py_INCREF (Py_None);
252 return (Py_None);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000253}
254
255static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000256mmap_write_byte_method(mmap_object *self,
257 PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000258{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000259 char value;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000260
Guido van Rossum09fdf072000-03-31 01:17:07 +0000261 CHECK_VALID(NULL);
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000262 if (!PyArg_ParseTuple (args, "c:write_byte", &value))
Guido van Rossum09fdf072000-03-31 01:17:07 +0000263 return(NULL);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000264
Guido van Rossum09fdf072000-03-31 01:17:07 +0000265 *(self->data+self->pos) = value;
266 self->pos += 1;
267 Py_INCREF (Py_None);
268 return (Py_None);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000269}
270
271static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000272mmap_size_method(mmap_object *self,
273 PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000274{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000275 CHECK_VALID(NULL);
Andrew M. Kuchling841b9fb2000-06-03 20:43:43 +0000276 if (!PyArg_ParseTuple(args, ":size"))
Andrew M. Kuchling961fe172000-06-03 19:41:42 +0000277 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000278
279#ifdef MS_WIN32
Mark Hammond071864a2000-07-30 02:46:26 +0000280 if (self->file_handle != INVALID_HANDLE_VALUE) {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000281 return (Py_BuildValue (
Fredrik Lundh5cccf502000-07-09 13:16:13 +0000282 "l", (long)
Mark Hammond071864a2000-07-30 02:46:26 +0000283 GetFileSize (self->file_handle, NULL)));
Guido van Rossum09fdf072000-03-31 01:17:07 +0000284 } else {
Fredrik Lundh5cccf502000-07-09 13:16:13 +0000285 return (Py_BuildValue ("l", (long) self->size) );
Guido van Rossum09fdf072000-03-31 01:17:07 +0000286 }
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000287#endif /* MS_WIN32 */
288
289#ifdef UNIX
Andrew M. Kuchling7b9fb922000-06-17 22:41:22 +0000290 {
291 struct stat buf;
292 if (-1 == fstat(self->fd, &buf)) {
293 PyErr_SetFromErrno(mmap_module_error);
294 return NULL;
295 }
Fredrik Lundh5cccf502000-07-09 13:16:13 +0000296 return (Py_BuildValue ("l", (long) buf.st_size) );
Andrew M. Kuchling7b9fb922000-06-17 22:41:22 +0000297 }
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000298#endif /* UNIX */
299}
300
301/* This assumes that you want the entire file mapped,
302 / and when recreating the map will make the new file
303 / have the new size
304 /
305 / Is this really necessary? This could easily be done
306 / from python by just closing and re-opening with the
307 / new size?
308 */
309
310static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000311mmap_resize_method(mmap_object *self,
312 PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000313{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000314 unsigned long new_size;
315 CHECK_VALID(NULL);
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000316 if (!PyArg_ParseTuple (args, "l:resize", &new_size)) {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000317 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000318#ifdef MS_WIN32
Guido van Rossum09fdf072000-03-31 01:17:07 +0000319 } else {
320 DWORD dwErrCode = 0;
321 /* First, unmap the file view */
322 UnmapViewOfFile (self->data);
323 /* Close the mapping object */
Mark Hammond071864a2000-07-30 02:46:26 +0000324 CloseHandle (self->map_handle);
Guido van Rossum09fdf072000-03-31 01:17:07 +0000325 /* Move to the desired EOF position */
Mark Hammond071864a2000-07-30 02:46:26 +0000326 SetFilePointer (self->file_handle,
Guido van Rossum09fdf072000-03-31 01:17:07 +0000327 new_size, NULL, FILE_BEGIN);
328 /* Change the size of the file */
Mark Hammond071864a2000-07-30 02:46:26 +0000329 SetEndOfFile (self->file_handle);
Guido van Rossum09fdf072000-03-31 01:17:07 +0000330 /* Create another mapping object and remap the file view */
331 self->map_handle = CreateFileMapping (
Mark Hammond071864a2000-07-30 02:46:26 +0000332 self->file_handle,
Guido van Rossum09fdf072000-03-31 01:17:07 +0000333 NULL,
334 PAGE_READWRITE,
335 0,
336 new_size,
337 self->tagname);
338 if (self->map_handle != NULL) {
339 self->data = (char *) MapViewOfFile (self->map_handle,
340 FILE_MAP_WRITE,
341 0,
342 0,
343 0);
344 if (self->data != NULL) {
345 self->size = new_size;
346 Py_INCREF (Py_None);
347 return Py_None;
348 } else {
349 dwErrCode = GetLastError();
350 }
351 } else {
352 dwErrCode = GetLastError();
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000353 }
Guido van Rossum09fdf072000-03-31 01:17:07 +0000354 PyErr_SetFromWindowsErr(dwErrCode);
355 return (NULL);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000356#endif /* MS_WIN32 */
357
358#ifdef UNIX
Andrew M. Kuchling6fef30e2000-06-18 14:51:21 +0000359#ifndef HAVE_MREMAP
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000360} else {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000361 PyErr_SetString(PyExc_SystemError,
362 "mmap: resizing not available--no mremap()");
363 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000364#else
365} else {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000366 void *newmap;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000367
Andrew M. Kuchling6fef30e2000-06-18 14:51:21 +0000368#ifdef MREMAP_MAYMOVE
Guido van Rossum09fdf072000-03-31 01:17:07 +0000369 newmap = mremap(self->data, self->size, new_size, MREMAP_MAYMOVE);
Andrew M. Kuchling6fef30e2000-06-18 14:51:21 +0000370#else
371 newmap = mremap(self->data, self->size, new_size, 0);
372#endif
Guido van Rossum09fdf072000-03-31 01:17:07 +0000373 if (newmap == (void *)-1)
374 {
375 PyErr_SetFromErrno(mmap_module_error);
376 return NULL;
377 }
378 self->data = newmap;
379 self->size = new_size;
380 Py_INCREF(Py_None);
381 return Py_None;
Andrew M. Kuchling6fef30e2000-06-18 14:51:21 +0000382#endif /* HAVE_MREMAP */
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000383#endif /* UNIX */
384}
385}
386
387static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000388mmap_tell_method(mmap_object *self, PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000389{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000390 CHECK_VALID(NULL);
Andrew M. Kuchling841b9fb2000-06-03 20:43:43 +0000391 if (!PyArg_ParseTuple(args, ":tell"))
Andrew M. Kuchling961fe172000-06-03 19:41:42 +0000392 return NULL;
Fredrik Lundh5cccf502000-07-09 13:16:13 +0000393 return (Py_BuildValue ("l", (long) self->pos) );
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000394}
395
396static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000397mmap_flush_method(mmap_object *self, PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000398{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000399 size_t offset = 0;
400 size_t size = self->size;
401 CHECK_VALID(NULL);
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000402 if (!PyArg_ParseTuple (args, "|ll:flush", &offset, &size)) {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000403 return NULL;
404 } else if ((offset + size) > self->size) {
405 PyErr_SetString (PyExc_ValueError,
406 "flush values out of range");
407 return NULL;
408 } else {
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000409#ifdef MS_WIN32
Fredrik Lundh5cccf502000-07-09 13:16:13 +0000410 return (Py_BuildValue("l", (long)
411 FlushViewOfFile(self->data+offset, size)));
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000412#endif /* MS_WIN32 */
413#ifdef UNIX
Guido van Rossum09fdf072000-03-31 01:17:07 +0000414 /* XXX semantics of return value? */
415 /* XXX flags for msync? */
416 if (-1 == msync(self->data + offset, size,
Andrew M. Kuchling9bc5f332000-06-18 04:25:08 +0000417 MS_SYNC))
Guido van Rossum09fdf072000-03-31 01:17:07 +0000418 {
419 PyErr_SetFromErrno(mmap_module_error);
420 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000421 }
Fredrik Lundh5cccf502000-07-09 13:16:13 +0000422 return Py_BuildValue ("l", (long) 0);
Guido van Rossum09fdf072000-03-31 01:17:07 +0000423#endif /* UNIX */
424 }
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000425}
426
427static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000428mmap_seek_method(mmap_object *self, PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000429{
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000430 int dist;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000431 int how=0;
432 CHECK_VALID(NULL);
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000433 if (!PyArg_ParseTuple (args, "i|i:seek", &dist, &how)) {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000434 return(NULL);
435 } else {
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000436 size_t where;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000437 switch (how) {
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000438 case 0: /* relative to start */
439 if (dist < 0)
440 goto onoutofrange;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000441 where = dist;
442 break;
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000443 case 1: /* relative to current position */
444 if ((int)self->pos + dist < 0)
445 goto onoutofrange;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000446 where = self->pos + dist;
447 break;
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000448 case 2: /* relative to end */
449 if ((int)self->size + dist < 0)
450 goto onoutofrange;
451 where = self->size + dist;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000452 break;
453 default:
454 PyErr_SetString (PyExc_ValueError,
455 "unknown seek type");
456 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000457 }
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000458 if (where > self->size)
459 goto onoutofrange;
460 self->pos = where;
461 Py_INCREF (Py_None);
462 return (Py_None);
Guido van Rossum09fdf072000-03-31 01:17:07 +0000463 }
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000464
465onoutofrange:
466 PyErr_SetString (PyExc_ValueError, "seek out of range");
467 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000468}
469
470static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000471mmap_move_method(mmap_object *self, PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000472{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000473 unsigned long dest, src, count;
474 CHECK_VALID(NULL);
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000475 if (!PyArg_ParseTuple (args, "iii:move", &dest, &src, &count)) {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000476 return NULL;
477 } else {
478 /* bounds check the values */
479 if (/* end of source after end of data?? */
480 ((src+count) > self->size)
481 /* dest will fit? */
482 || (dest+count > self->size)) {
483 PyErr_SetString (PyExc_ValueError,
484 "source or destination out of range");
485 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000486 } else {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000487 memmove (self->data+dest, self->data+src, count);
488 Py_INCREF (Py_None);
489 return Py_None;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000490 }
Guido van Rossum09fdf072000-03-31 01:17:07 +0000491 }
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000492}
493
494static struct PyMethodDef mmap_object_methods[] = {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000495 {"close", (PyCFunction) mmap_close_method, 1},
496 {"find", (PyCFunction) mmap_find_method, 1},
497 {"flush", (PyCFunction) mmap_flush_method, 1},
498 {"move", (PyCFunction) mmap_move_method, 1},
499 {"read", (PyCFunction) mmap_read_method, 1},
500 {"read_byte", (PyCFunction) mmap_read_byte_method, 1},
501 {"readline", (PyCFunction) mmap_read_line_method, 1},
502 {"resize", (PyCFunction) mmap_resize_method, 1},
503 {"seek", (PyCFunction) mmap_seek_method, 1},
504 {"size", (PyCFunction) mmap_size_method, 1},
505 {"tell", (PyCFunction) mmap_tell_method, 1},
506 {"write", (PyCFunction) mmap_write_method, 1},
507 {"write_byte", (PyCFunction) mmap_write_byte_method, 1},
508 {NULL, NULL} /* sentinel */
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000509};
510
511/* Functions for treating an mmap'ed file as a buffer */
512
513static int
Andrew M. Kuchling961fe172000-06-03 19:41:42 +0000514mmap_buffer_getreadbuf(mmap_object *self, int index, const void **ptr)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000515{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000516 CHECK_VALID(-1);
517 if ( index != 0 ) {
518 PyErr_SetString(PyExc_SystemError,
519 "Accessing non-existent mmap segment");
520 return -1;
521 }
522 *ptr = self->data;
523 return self->size;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000524}
525
526static int
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000527mmap_buffer_getwritebuf(mmap_object *self, int index, const void **ptr)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000528{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000529 CHECK_VALID(-1);
530 if ( index != 0 ) {
531 PyErr_SetString(PyExc_SystemError,
532 "Accessing non-existent mmap segment");
533 return -1;
534 }
535 *ptr = self->data;
536 return self->size;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000537}
538
539static int
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000540mmap_buffer_getsegcount(mmap_object *self, int *lenp)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000541{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000542 CHECK_VALID(-1);
543 if (lenp)
544 *lenp = self->size;
545 return 1;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000546}
547
548static int
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000549mmap_buffer_getcharbuffer(mmap_object *self, int index, const void **ptr)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000550{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000551 if ( index != 0 ) {
552 PyErr_SetString(PyExc_SystemError,
553 "accessing non-existent buffer segment");
554 return -1;
555 }
556 *ptr = (const char *)self->data;
557 return self->size;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000558}
559
560static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000561mmap_object_getattr(mmap_object *self, char *name)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000562{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000563 return Py_FindMethod (mmap_object_methods, (PyObject *)self, name);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000564}
565
566static int
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000567mmap_length(mmap_object *self)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000568{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000569 CHECK_VALID(-1);
570 return self->size;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000571}
572
573static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000574mmap_item(mmap_object *self, int i)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000575{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000576 CHECK_VALID(NULL);
Guido van Rossumce8e1dc2000-07-01 00:51:51 +0000577 if (i < 0 || (size_t)i >= self->size) {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000578 PyErr_SetString(PyExc_IndexError, "mmap index out of range");
579 return NULL;
580 }
581 return PyString_FromStringAndSize(self->data + i, 1);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000582}
583
584static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000585mmap_slice(mmap_object *self, int ilow, int ihigh)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000586{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000587 CHECK_VALID(NULL);
588 if (ilow < 0)
589 ilow = 0;
Guido van Rossumce8e1dc2000-07-01 00:51:51 +0000590 else if ((size_t)ilow > self->size)
Guido van Rossum09fdf072000-03-31 01:17:07 +0000591 ilow = self->size;
592 if (ihigh < 0)
593 ihigh = 0;
594 if (ihigh < ilow)
595 ihigh = ilow;
Guido van Rossumce8e1dc2000-07-01 00:51:51 +0000596 else if ((size_t)ihigh > self->size)
Guido van Rossum09fdf072000-03-31 01:17:07 +0000597 ihigh = self->size;
598
599 return PyString_FromStringAndSize(self->data + ilow, ihigh-ilow);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000600}
601
602static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000603mmap_concat(mmap_object *self, PyObject *bb)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000604{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000605 CHECK_VALID(NULL);
606 PyErr_SetString(PyExc_SystemError,
607 "mmaps don't support concatenation");
608 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000609}
610
611static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000612mmap_repeat(mmap_object *self, int n)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000613{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000614 CHECK_VALID(NULL);
615 PyErr_SetString(PyExc_SystemError,
616 "mmaps don't support repeat operation");
617 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000618}
619
620static int
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000621mmap_ass_slice(mmap_object *self, int ilow, int ihigh, PyObject *v)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000622{
Guido van Rossum36d4f8b2000-04-10 21:34:37 +0000623 const char *buf;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000624
Guido van Rossum09fdf072000-03-31 01:17:07 +0000625 CHECK_VALID(-1);
626 if (ilow < 0)
627 ilow = 0;
Guido van Rossumce8e1dc2000-07-01 00:51:51 +0000628 else if ((size_t)ilow > self->size)
Guido van Rossum09fdf072000-03-31 01:17:07 +0000629 ilow = self->size;
630 if (ihigh < 0)
631 ihigh = 0;
632 if (ihigh < ilow)
633 ihigh = ilow;
Guido van Rossumce8e1dc2000-07-01 00:51:51 +0000634 else if ((size_t)ihigh > self->size)
Guido van Rossum09fdf072000-03-31 01:17:07 +0000635 ihigh = self->size;
636
637 if (! (PyString_Check(v)) ) {
638 PyErr_SetString(PyExc_IndexError,
639 "mmap slice assignment must be a string");
640 return -1;
641 }
642 if ( PyString_Size(v) != (ihigh - ilow) ) {
643 PyErr_SetString(PyExc_IndexError,
644 "mmap slice assignment is wrong size");
645 return -1;
646 }
647 buf = PyString_AsString(v);
648 memcpy(self->data + ilow, buf, ihigh-ilow);
649 return 0;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000650}
651
652static int
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000653mmap_ass_item(mmap_object *self, int i, PyObject *v)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000654{
Guido van Rossum36d4f8b2000-04-10 21:34:37 +0000655 const char *buf;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000656
Guido van Rossum09fdf072000-03-31 01:17:07 +0000657 CHECK_VALID(-1);
Guido van Rossumce8e1dc2000-07-01 00:51:51 +0000658 if (i < 0 || (size_t)i >= self->size) {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000659 PyErr_SetString(PyExc_IndexError, "mmap index out of range");
660 return -1;
661 }
662 if (! (PyString_Check(v) && PyString_Size(v)==1) ) {
663 PyErr_SetString(PyExc_IndexError,
664 "mmap assignment must be single-character string");
665 return -1;
666 }
667 buf = PyString_AsString(v);
668 self->data[i] = buf[0];
669 return 0;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000670}
671
672static PySequenceMethods mmap_as_sequence = {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000673 (inquiry)mmap_length, /*sq_length*/
674 (binaryfunc)mmap_concat, /*sq_concat*/
675 (intargfunc)mmap_repeat, /*sq_repeat*/
676 (intargfunc)mmap_item, /*sq_item*/
677 (intintargfunc)mmap_slice, /*sq_slice*/
678 (intobjargproc)mmap_ass_item, /*sq_ass_item*/
679 (intintobjargproc)mmap_ass_slice, /*sq_ass_slice*/
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000680};
681
682static PyBufferProcs mmap_as_buffer = {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000683 (getreadbufferproc)mmap_buffer_getreadbuf,
684 (getwritebufferproc)mmap_buffer_getwritebuf,
685 (getsegcountproc)mmap_buffer_getsegcount,
686 (getcharbufferproc)mmap_buffer_getcharbuffer,
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000687};
688
689static PyTypeObject mmap_object_type = {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000690 PyObject_HEAD_INIT(0) /* patched in module init */
691 0, /* ob_size */
692 "mmap", /* tp_name */
693 sizeof(mmap_object), /* tp_size */
694 0, /* tp_itemsize */
695 /* methods */
696 (destructor) mmap_object_dealloc, /* tp_dealloc */
697 0, /* tp_print */
698 (getattrfunc) mmap_object_getattr, /* tp_getattr */
699 0, /* tp_setattr */
700 0, /* tp_compare */
701 0, /* tp_repr */
702 0, /* tp_as_number */
703 &mmap_as_sequence, /*tp_as_sequence*/
704 0, /*tp_as_mapping*/
705 0, /*tp_hash*/
706 0, /*tp_call*/
707 0, /*tp_str*/
708 0, /*tp_getattro*/
709 0, /*tp_setattro*/
710 &mmap_as_buffer, /*tp_as_buffer*/
711 Py_TPFLAGS_HAVE_GETCHARBUFFER, /*tp_flags*/
712 0, /*tp_doc*/
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000713};
714
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000715
716/* extract the map size from the given PyObject
717
718 The map size is restricted to [0, INT_MAX] because this is the current
719 Python limitation on object sizes. Although the mmap object *could* handle
720 a larger map size, there is no point because all the useful operations
721 (len(), slicing(), sequence indexing) are limited by a C int.
722
Thomas Wouters7e474022000-07-16 12:04:32 +0000723 Returns -1 on error, with an appropriate Python exception raised. On
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000724 success, the map size is returned. */
725static int
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000726_GetMapSize(PyObject *o)
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000727{
728 if (PyInt_Check(o)) {
729 long i = PyInt_AsLong(o);
730 if (PyErr_Occurred())
731 return -1;
732 if (i < 0)
733 goto onnegoverflow;
734 if (i > INT_MAX)
735 goto onposoverflow;
736 return (int)i;
737 }
738 else if (PyLong_Check(o)) {
739 long i = PyLong_AsLong(o);
740 if (PyErr_Occurred()) {
741 /* yes negative overflow is mistaken for positive overflow
742 but not worth the trouble to check sign of 'i' */
743 if (PyErr_ExceptionMatches(PyExc_OverflowError))
744 goto onposoverflow;
745 else
746 return -1;
747 }
748 if (i < 0)
749 goto onnegoverflow;
750 if (i > INT_MAX)
751 goto onposoverflow;
752 return (int)i;
753 }
754 else {
755 PyErr_SetString(PyExc_TypeError,
756 "map size must be an integral value");
757 return -1;
758 }
759
760onnegoverflow:
761 PyErr_SetString(PyExc_OverflowError,
762 "memory mapped size must be positive");
763 return -1;
764
765onposoverflow:
766 PyErr_SetString(PyExc_OverflowError,
767 "memory mapped size is too large (limited by C int)");
768 return -1;
769}
770
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000771#ifdef UNIX
772static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000773new_mmap_object(PyObject *self, PyObject *args, PyObject *kwdict)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000774{
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000775 mmap_object *m_obj;
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000776 PyObject *map_size_obj = NULL;
777 int map_size;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000778 int fd, flags = MAP_SHARED, prot = PROT_WRITE | PROT_READ;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000779 char *keywords[] = {"file", "size", "flags", "prot", NULL};
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000780
Guido van Rossum09fdf072000-03-31 01:17:07 +0000781 if (!PyArg_ParseTupleAndKeywords(args, kwdict,
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000782 "iO|ii", keywords,
783 &fd, &map_size_obj, &flags, &prot)
Guido van Rossum09fdf072000-03-31 01:17:07 +0000784 )
785 return NULL;
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000786 map_size = _GetMapSize(map_size_obj);
787 if (map_size < 0)
788 return NULL;
789
Guido van Rossumb18618d2000-05-03 23:44:39 +0000790 m_obj = PyObject_New (mmap_object, &mmap_object_type);
Guido van Rossum09fdf072000-03-31 01:17:07 +0000791 if (m_obj == NULL) {return NULL;}
792 m_obj->size = (size_t) map_size;
793 m_obj->pos = (size_t) 0;
Andrew M. Kuchling7b9fb922000-06-17 22:41:22 +0000794 m_obj->fd = fd;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000795 m_obj->data = mmap(NULL, map_size,
796 prot, flags,
797 fd, 0);
798 if (m_obj->data == (void *)-1)
799 {
800 Py_DECREF(m_obj);
801 PyErr_SetFromErrno(mmap_module_error);
802 return NULL;
803 }
804 return (PyObject *)m_obj;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000805}
806#endif /* UNIX */
807
808#ifdef MS_WIN32
809static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000810new_mmap_object(PyObject *self, PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000811{
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000812 mmap_object *m_obj;
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000813 PyObject *map_size_obj = NULL;
814 int map_size;
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000815 char *tagname = "";
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000816
Guido van Rossum09fdf072000-03-31 01:17:07 +0000817 DWORD dwErr = 0;
818 int fileno;
Mark Hammond071864a2000-07-30 02:46:26 +0000819 HANDLE fh = 0;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000820
Guido van Rossum09fdf072000-03-31 01:17:07 +0000821 /* Patch the object type */
822 mmap_object_type.ob_type = &PyType_Type;
823
824 if (!PyArg_ParseTuple(args,
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000825 "iO|z",
Guido van Rossum09fdf072000-03-31 01:17:07 +0000826 &fileno,
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000827 &map_size_obj,
Guido van Rossum09fdf072000-03-31 01:17:07 +0000828 &tagname)
829 )
830 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000831
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000832 map_size = _GetMapSize(map_size_obj);
833 if (map_size < 0)
834 return NULL;
835
Guido van Rossum09fdf072000-03-31 01:17:07 +0000836 /* if an actual filename has been specified */
837 if (fileno != 0) {
Mark Hammond071864a2000-07-30 02:46:26 +0000838 fh = (HANDLE)_get_osfhandle(fileno);
839 if (fh==(HANDLE)-1) {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000840 PyErr_SetFromErrno(mmap_module_error);
841 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000842 }
Fred Drake1ef4e2d2000-04-05 14:15:31 +0000843 /* Win9x appears to need us seeked to zero */
844 fseek(&_iob[fileno], 0, SEEK_SET);
Guido van Rossum09fdf072000-03-31 01:17:07 +0000845 }
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000846
Guido van Rossumb18618d2000-05-03 23:44:39 +0000847 m_obj = PyObject_New (mmap_object, &mmap_object_type);
Mark Hammond2cbed002000-07-30 02:22:43 +0000848 if (m_obj==NULL)
849 return NULL;
850 /* Set every field to an invalid marker, so we can safely
851 destruct the object in the face of failure */
852 m_obj->data = NULL;
Mark Hammond071864a2000-07-30 02:46:26 +0000853 m_obj->file_handle = INVALID_HANDLE_VALUE;
Mark Hammond2cbed002000-07-30 02:22:43 +0000854 m_obj->map_handle = INVALID_HANDLE_VALUE;
855 m_obj->tagname = NULL;
856
Guido van Rossum09fdf072000-03-31 01:17:07 +0000857 if (fh) {
Mark Hammond2cbed002000-07-30 02:22:43 +0000858 /* It is necessary to duplicate the handle, so the
859 Python code can close it on us */
860 if (!DuplicateHandle(
861 GetCurrentProcess(), /* source process handle */
Mark Hammond071864a2000-07-30 02:46:26 +0000862 fh, /* handle to be duplicated */
Mark Hammond2cbed002000-07-30 02:22:43 +0000863 GetCurrentProcess(), /* target proc handle */
864 (LPHANDLE)&m_obj->file_handle, /* result */
865 0, /* access - ignored due to options value */
866 FALSE, /* inherited by child processes? */
867 DUPLICATE_SAME_ACCESS)) { /* options */
868 dwErr = GetLastError();
869 Py_DECREF(m_obj);
870 PyErr_SetFromWindowsErr(dwErr);
871 return NULL;
872 }
Guido van Rossum09fdf072000-03-31 01:17:07 +0000873 if (!map_size) {
Mark Hammond071864a2000-07-30 02:46:26 +0000874 m_obj->size = GetFileSize (fh, NULL);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000875 } else {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000876 m_obj->size = map_size;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000877 }
Guido van Rossum09fdf072000-03-31 01:17:07 +0000878 }
879 else {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000880 m_obj->size = map_size;
881 }
882
883 /* set the initial position */
884 m_obj->pos = (size_t) 0;
885
Mark Hammond2cbed002000-07-30 02:22:43 +0000886 /* set the tag name */
887 if (tagname != NULL) {
888 m_obj->tagname = PyMem_Malloc(strlen(tagname)+1);
889 if (m_obj->tagname == NULL) {
890 PyErr_NoMemory();
891 Py_DECREF(m_obj);
892 return NULL;
893 }
894 strcpy(m_obj->tagname, tagname);
895 }
896 else
897 m_obj->tagname = NULL;
898
Mark Hammond071864a2000-07-30 02:46:26 +0000899 m_obj->map_handle = CreateFileMapping (m_obj->file_handle,
Guido van Rossum09fdf072000-03-31 01:17:07 +0000900 NULL,
901 PAGE_READWRITE,
902 0,
903 m_obj->size,
904 tagname);
905 if (m_obj->map_handle != NULL) {
906 m_obj->data = (char *) MapViewOfFile (m_obj->map_handle,
907 FILE_MAP_WRITE,
908 0,
909 0,
910 0);
911 if (m_obj->data != NULL) {
912 return ((PyObject *) m_obj);
913 } else {
914 dwErr = GetLastError();
915 }
916 } else {
917 dwErr = GetLastError();
918 }
Mark Hammond2cbed002000-07-30 02:22:43 +0000919 Py_DECREF(m_obj);
Guido van Rossum09fdf072000-03-31 01:17:07 +0000920 PyErr_SetFromWindowsErr(dwErr);
921 return (NULL);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000922}
923#endif /* MS_WIN32 */
924
925/* List of functions exported by this module */
926static struct PyMethodDef mmap_functions[] = {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000927 {"mmap", (PyCFunction) new_mmap_object,
928 METH_VARARGS|METH_KEYWORDS},
929 {NULL, NULL} /* Sentinel */
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000930};
931
932#ifdef MS_WIN32
Guido van Rossum09fdf072000-03-31 01:17:07 +0000933__declspec(dllexport) void
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000934#endif /* MS_WIN32 */
935#ifdef UNIX
936extern void
937#endif
938
939initmmap(void)
940{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000941 PyObject *dict, *module;
942 module = Py_InitModule ("mmap", mmap_functions);
943 dict = PyModule_GetDict (module);
944 mmap_module_error = PyExc_EnvironmentError;
945 Py_INCREF(mmap_module_error);
946 PyDict_SetItemString (dict, "error", mmap_module_error);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000947#ifdef PROT_EXEC
Guido van Rossum09fdf072000-03-31 01:17:07 +0000948 PyDict_SetItemString (dict, "PROT_EXEC", PyInt_FromLong(PROT_EXEC) );
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000949#endif
950#ifdef PROT_READ
Guido van Rossum09fdf072000-03-31 01:17:07 +0000951 PyDict_SetItemString (dict, "PROT_READ", PyInt_FromLong(PROT_READ) );
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000952#endif
953#ifdef PROT_WRITE
Guido van Rossum09fdf072000-03-31 01:17:07 +0000954 PyDict_SetItemString (dict, "PROT_WRITE", PyInt_FromLong(PROT_WRITE) );
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000955#endif
956
957#ifdef MAP_SHARED
Guido van Rossum09fdf072000-03-31 01:17:07 +0000958 PyDict_SetItemString (dict, "MAP_SHARED", PyInt_FromLong(MAP_SHARED) );
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000959#endif
960#ifdef MAP_PRIVATE
Guido van Rossum09fdf072000-03-31 01:17:07 +0000961 PyDict_SetItemString (dict, "MAP_PRIVATE",
962 PyInt_FromLong(MAP_PRIVATE) );
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000963#endif
964#ifdef MAP_DENYWRITE
Guido van Rossum09fdf072000-03-31 01:17:07 +0000965 PyDict_SetItemString (dict, "MAP_DENYWRITE",
966 PyInt_FromLong(MAP_DENYWRITE) );
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000967#endif
968#ifdef MAP_EXECUTABLE
Guido van Rossum09fdf072000-03-31 01:17:07 +0000969 PyDict_SetItemString (dict, "MAP_EXECUTABLE",
970 PyInt_FromLong(MAP_EXECUTABLE) );
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000971#endif
972#ifdef MAP_ANON
Guido van Rossum09fdf072000-03-31 01:17:07 +0000973 PyDict_SetItemString (dict, "MAP_ANON", PyInt_FromLong(MAP_ANON) );
974 PyDict_SetItemString (dict, "MAP_ANONYMOUS",
975 PyInt_FromLong(MAP_ANON) );
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000976#endif
977
978#ifdef UNIX
Guido van Rossum09fdf072000-03-31 01:17:07 +0000979 PyDict_SetItemString (dict, "PAGESIZE",
980 PyInt_FromLong( (long)getpagesize() ) );
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000981#endif
Guido van Rossum09fdf072000-03-31 01:17:07 +0000982#ifdef MS_WIN32
983 {
984 SYSTEM_INFO si;
985 GetSystemInfo(&si);
986 PyDict_SetItemString (dict, "PAGESIZE",
987 PyInt_FromLong( si.dwPageSize ) );
988 }
989#endif /* MS_WIN32 */
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000990
991}
Andrew M. Kuchling961fe172000-06-03 19:41:42 +0000992