blob: c3caa22f5a9ea6eda5bc7f1934bb6637f6b4f1b0 [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
Guido van Rossum09fdf072000-03-31 01:17:07 +000064 UnmapViewOfFile (m_obj->data);
65 CloseHandle (m_obj->map_handle);
66 CloseHandle ((HANDLE)m_obj->file_handle);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +000067#endif /* MS_WIN32 */
68
69#ifdef UNIX
Guido van Rossum09fdf072000-03-31 01:17:07 +000070 if (m_obj->data!=NULL) {
Andrew M. Kuchling9bc5f332000-06-18 04:25:08 +000071 msync(m_obj->data, m_obj->size, MS_SYNC);
Guido van Rossum09fdf072000-03-31 01:17:07 +000072 munmap(m_obj->data, m_obj->size);
73 }
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +000074#endif /* UNIX */
75
Guido van Rossumb18618d2000-05-03 23:44:39 +000076 PyObject_Del(m_obj);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +000077}
78
79static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +000080mmap_close_method(mmap_object *self, PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +000081{
Andrew M. Kuchling841b9fb2000-06-03 20:43:43 +000082 if (!PyArg_ParseTuple(args, ":close"))
Andrew M. Kuchling961fe172000-06-03 19:41:42 +000083 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +000084#ifdef MS_WIN32
Guido van Rossum09fdf072000-03-31 01:17:07 +000085 UnmapViewOfFile (self->data);
86 CloseHandle (self->map_handle);
87 CloseHandle ((HANDLE)self->file_handle);
88 self->map_handle = (HANDLE) NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +000089#endif /* MS_WIN32 */
90
91#ifdef UNIX
Guido van Rossum09fdf072000-03-31 01:17:07 +000092 munmap(self->data, self->size);
93 self->data = NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +000094#endif
95
Guido van Rossum09fdf072000-03-31 01:17:07 +000096 Py_INCREF (Py_None);
97 return (Py_None);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +000098}
99
100#ifdef MS_WIN32
Guido van Rossum09fdf072000-03-31 01:17:07 +0000101#define CHECK_VALID(err) \
102do { \
103 if (!self->map_handle) { \
104 PyErr_SetString (PyExc_ValueError, "mmap closed or invalid"); \
105 return err; \
106 } \
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000107} while (0)
108#endif /* MS_WIN32 */
109
110#ifdef UNIX
Guido van Rossum09fdf072000-03-31 01:17:07 +0000111#define CHECK_VALID(err) \
112do { \
113 if (self->data == NULL) { \
114 PyErr_SetString (PyExc_ValueError, "mmap closed or invalid"); \
115 return err; \
116 } \
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000117} while (0)
118#endif /* UNIX */
119
120static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000121mmap_read_byte_method(mmap_object *self,
122 PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000123{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000124 char value;
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000125 char *where;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000126 CHECK_VALID(NULL);
Andrew M. Kuchling841b9fb2000-06-03 20:43:43 +0000127 if (!PyArg_ParseTuple(args, ":read_byte"))
Andrew M. Kuchling961fe172000-06-03 19:41:42 +0000128 return NULL;
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000129 if (self->pos < self->size) {
Guido van Rossum36d4f8b2000-04-10 21:34:37 +0000130 where = self->data + self->pos;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000131 value = (char) *(where);
132 self->pos += 1;
133 return Py_BuildValue("c", (char) *(where));
134 } else {
135 PyErr_SetString (PyExc_ValueError, "read byte out of range");
136 return NULL;
137 }
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000138}
139
140static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000141mmap_read_line_method(mmap_object *self,
142 PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000143{
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000144 char *start = self->data+self->pos;
145 char *eof = self->data+self->size;
146 char *eol;
147 PyObject *result;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000148
Guido van Rossum09fdf072000-03-31 01:17:07 +0000149 CHECK_VALID(NULL);
Andrew M. Kuchling841b9fb2000-06-03 20:43:43 +0000150 if (!PyArg_ParseTuple(args, ":readline"))
Andrew M. Kuchling961fe172000-06-03 19:41:42 +0000151 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000152
Fred Drake56a87a02000-04-04 18:17:35 +0000153 eol = memchr(start, '\n', self->size - self->pos);
154 if (!eol)
155 eol = eof;
156 else
157 ++eol; /* we're interested in the position after the
158 newline. */
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000159 result = PyString_FromStringAndSize(start, (eol - start));
Guido van Rossum09fdf072000-03-31 01:17:07 +0000160 self->pos += (eol - start);
161 return (result);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000162}
163
164static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000165mmap_read_method(mmap_object *self,
166 PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000167{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000168 long num_bytes;
169 PyObject *result;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000170
Guido van Rossum09fdf072000-03-31 01:17:07 +0000171 CHECK_VALID(NULL);
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000172 if (!PyArg_ParseTuple(args, "l:read", &num_bytes))
Guido van Rossum09fdf072000-03-31 01:17:07 +0000173 return(NULL);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000174
Guido van Rossum09fdf072000-03-31 01:17:07 +0000175 /* silently 'adjust' out-of-range requests */
176 if ((self->pos + num_bytes) > self->size) {
177 num_bytes -= (self->pos+num_bytes) - self->size;
178 }
179 result = Py_BuildValue("s#", self->data+self->pos, num_bytes);
180 self->pos += num_bytes;
181 return (result);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000182}
183
184static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000185mmap_find_method(mmap_object *self,
186 PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000187{
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000188 int start = self->pos;
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000189 char *needle;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000190 int len;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000191
Guido van Rossum09fdf072000-03-31 01:17:07 +0000192 CHECK_VALID(NULL);
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000193 if (!PyArg_ParseTuple (args, "s#|i:find", &needle, &len, &start)) {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000194 return NULL;
195 } else {
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000196 char *p = self->data+self->pos;
197 char *e = self->data+self->size;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000198 while (p < e) {
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000199 char *s = p;
200 char *n = needle;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000201 while ((s<e) && (*n) && !(*s-*n)) {
202 s++, n++;
203 }
204 if (!*n) {
205 return Py_BuildValue (
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000206 "i",
207 (int) (p - (self->data + start)));
Guido van Rossum09fdf072000-03-31 01:17:07 +0000208 }
209 p++;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000210 }
Guido van Rossum09fdf072000-03-31 01:17:07 +0000211 return Py_BuildValue ("l", (long) -1);
212 }
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000213}
214
215static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000216mmap_write_method(mmap_object *self,
217 PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000218{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000219 long length;
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000220 char *data;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000221
Guido van Rossum09fdf072000-03-31 01:17:07 +0000222 CHECK_VALID(NULL);
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000223 if (!PyArg_ParseTuple (args, "s#:write", &data, &length))
Guido van Rossum09fdf072000-03-31 01:17:07 +0000224 return(NULL);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000225
Guido van Rossum09fdf072000-03-31 01:17:07 +0000226 if ((self->pos + length) > self->size) {
227 PyErr_SetString (PyExc_ValueError, "data out of range");
228 return NULL;
229 }
230 memcpy (self->data+self->pos, data, length);
231 self->pos = self->pos+length;
232 Py_INCREF (Py_None);
233 return (Py_None);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000234}
235
236static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000237mmap_write_byte_method(mmap_object *self,
238 PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000239{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000240 char value;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000241
Guido van Rossum09fdf072000-03-31 01:17:07 +0000242 CHECK_VALID(NULL);
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000243 if (!PyArg_ParseTuple (args, "c:write_byte", &value))
Guido van Rossum09fdf072000-03-31 01:17:07 +0000244 return(NULL);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000245
Guido van Rossum09fdf072000-03-31 01:17:07 +0000246 *(self->data+self->pos) = value;
247 self->pos += 1;
248 Py_INCREF (Py_None);
249 return (Py_None);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000250}
251
252static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000253mmap_size_method(mmap_object *self,
254 PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000255{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000256 CHECK_VALID(NULL);
Andrew M. Kuchling841b9fb2000-06-03 20:43:43 +0000257 if (!PyArg_ParseTuple(args, ":size"))
Andrew M. Kuchling961fe172000-06-03 19:41:42 +0000258 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000259
260#ifdef MS_WIN32
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000261 if (self->file_handle != (INT_PTR) -1) {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000262 return (Py_BuildValue (
Fredrik Lundh5cccf502000-07-09 13:16:13 +0000263 "l", (long)
Guido van Rossum09fdf072000-03-31 01:17:07 +0000264 GetFileSize ((HANDLE)self->file_handle, NULL)));
265 } else {
Fredrik Lundh5cccf502000-07-09 13:16:13 +0000266 return (Py_BuildValue ("l", (long) self->size) );
Guido van Rossum09fdf072000-03-31 01:17:07 +0000267 }
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000268#endif /* MS_WIN32 */
269
270#ifdef UNIX
Andrew M. Kuchling7b9fb922000-06-17 22:41:22 +0000271 {
272 struct stat buf;
273 if (-1 == fstat(self->fd, &buf)) {
274 PyErr_SetFromErrno(mmap_module_error);
275 return NULL;
276 }
Fredrik Lundh5cccf502000-07-09 13:16:13 +0000277 return (Py_BuildValue ("l", (long) buf.st_size) );
Andrew M. Kuchling7b9fb922000-06-17 22:41:22 +0000278 }
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000279#endif /* UNIX */
280}
281
282/* This assumes that you want the entire file mapped,
283 / and when recreating the map will make the new file
284 / have the new size
285 /
286 / Is this really necessary? This could easily be done
287 / from python by just closing and re-opening with the
288 / new size?
289 */
290
291static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000292mmap_resize_method(mmap_object *self,
293 PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000294{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000295 unsigned long new_size;
296 CHECK_VALID(NULL);
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000297 if (!PyArg_ParseTuple (args, "l:resize", &new_size)) {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000298 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000299#ifdef MS_WIN32
Guido van Rossum09fdf072000-03-31 01:17:07 +0000300 } else {
301 DWORD dwErrCode = 0;
302 /* First, unmap the file view */
303 UnmapViewOfFile (self->data);
304 /* Close the mapping object */
305 CloseHandle ((HANDLE)self->map_handle);
306 /* Move to the desired EOF position */
307 SetFilePointer ((HANDLE)self->file_handle,
308 new_size, NULL, FILE_BEGIN);
309 /* Change the size of the file */
310 SetEndOfFile ((HANDLE)self->file_handle);
311 /* Create another mapping object and remap the file view */
312 self->map_handle = CreateFileMapping (
313 (HANDLE) self->file_handle,
314 NULL,
315 PAGE_READWRITE,
316 0,
317 new_size,
318 self->tagname);
319 if (self->map_handle != NULL) {
320 self->data = (char *) MapViewOfFile (self->map_handle,
321 FILE_MAP_WRITE,
322 0,
323 0,
324 0);
325 if (self->data != NULL) {
326 self->size = new_size;
327 Py_INCREF (Py_None);
328 return Py_None;
329 } else {
330 dwErrCode = GetLastError();
331 }
332 } else {
333 dwErrCode = GetLastError();
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000334 }
Guido van Rossum09fdf072000-03-31 01:17:07 +0000335 PyErr_SetFromWindowsErr(dwErrCode);
336 return (NULL);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000337#endif /* MS_WIN32 */
338
339#ifdef UNIX
Andrew M. Kuchling6fef30e2000-06-18 14:51:21 +0000340#ifndef HAVE_MREMAP
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000341} else {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000342 PyErr_SetString(PyExc_SystemError,
343 "mmap: resizing not available--no mremap()");
344 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000345#else
346} else {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000347 void *newmap;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000348
Andrew M. Kuchling6fef30e2000-06-18 14:51:21 +0000349#ifdef MREMAP_MAYMOVE
Guido van Rossum09fdf072000-03-31 01:17:07 +0000350 newmap = mremap(self->data, self->size, new_size, MREMAP_MAYMOVE);
Andrew M. Kuchling6fef30e2000-06-18 14:51:21 +0000351#else
352 newmap = mremap(self->data, self->size, new_size, 0);
353#endif
Guido van Rossum09fdf072000-03-31 01:17:07 +0000354 if (newmap == (void *)-1)
355 {
356 PyErr_SetFromErrno(mmap_module_error);
357 return NULL;
358 }
359 self->data = newmap;
360 self->size = new_size;
361 Py_INCREF(Py_None);
362 return Py_None;
Andrew M. Kuchling6fef30e2000-06-18 14:51:21 +0000363#endif /* HAVE_MREMAP */
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000364#endif /* UNIX */
365}
366}
367
368static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000369mmap_tell_method(mmap_object *self, PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000370{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000371 CHECK_VALID(NULL);
Andrew M. Kuchling841b9fb2000-06-03 20:43:43 +0000372 if (!PyArg_ParseTuple(args, ":tell"))
Andrew M. Kuchling961fe172000-06-03 19:41:42 +0000373 return NULL;
Fredrik Lundh5cccf502000-07-09 13:16:13 +0000374 return (Py_BuildValue ("l", (long) self->pos) );
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000375}
376
377static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000378mmap_flush_method(mmap_object *self, PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000379{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000380 size_t offset = 0;
381 size_t size = self->size;
382 CHECK_VALID(NULL);
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000383 if (!PyArg_ParseTuple (args, "|ll:flush", &offset, &size)) {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000384 return NULL;
385 } else if ((offset + size) > self->size) {
386 PyErr_SetString (PyExc_ValueError,
387 "flush values out of range");
388 return NULL;
389 } else {
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000390#ifdef MS_WIN32
Fredrik Lundh5cccf502000-07-09 13:16:13 +0000391 return (Py_BuildValue("l", (long)
392 FlushViewOfFile(self->data+offset, size)));
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000393#endif /* MS_WIN32 */
394#ifdef UNIX
Guido van Rossum09fdf072000-03-31 01:17:07 +0000395 /* XXX semantics of return value? */
396 /* XXX flags for msync? */
397 if (-1 == msync(self->data + offset, size,
Andrew M. Kuchling9bc5f332000-06-18 04:25:08 +0000398 MS_SYNC))
Guido van Rossum09fdf072000-03-31 01:17:07 +0000399 {
400 PyErr_SetFromErrno(mmap_module_error);
401 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000402 }
Fredrik Lundh5cccf502000-07-09 13:16:13 +0000403 return Py_BuildValue ("l", (long) 0);
Guido van Rossum09fdf072000-03-31 01:17:07 +0000404#endif /* UNIX */
405 }
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000406}
407
408static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000409mmap_seek_method(mmap_object *self, PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000410{
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000411 int dist;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000412 int how=0;
413 CHECK_VALID(NULL);
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000414 if (!PyArg_ParseTuple (args, "i|i:seek", &dist, &how)) {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000415 return(NULL);
416 } else {
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000417 size_t where;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000418 switch (how) {
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000419 case 0: /* relative to start */
420 if (dist < 0)
421 goto onoutofrange;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000422 where = dist;
423 break;
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000424 case 1: /* relative to current position */
425 if ((int)self->pos + dist < 0)
426 goto onoutofrange;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000427 where = self->pos + dist;
428 break;
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000429 case 2: /* relative to end */
430 if ((int)self->size + dist < 0)
431 goto onoutofrange;
432 where = self->size + dist;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000433 break;
434 default:
435 PyErr_SetString (PyExc_ValueError,
436 "unknown seek type");
437 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000438 }
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000439 if (where > self->size)
440 goto onoutofrange;
441 self->pos = where;
442 Py_INCREF (Py_None);
443 return (Py_None);
Guido van Rossum09fdf072000-03-31 01:17:07 +0000444 }
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000445
446onoutofrange:
447 PyErr_SetString (PyExc_ValueError, "seek out of range");
448 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000449}
450
451static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000452mmap_move_method(mmap_object *self, PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000453{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000454 unsigned long dest, src, count;
455 CHECK_VALID(NULL);
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000456 if (!PyArg_ParseTuple (args, "iii:move", &dest, &src, &count)) {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000457 return NULL;
458 } else {
459 /* bounds check the values */
460 if (/* end of source after end of data?? */
461 ((src+count) > self->size)
462 /* dest will fit? */
463 || (dest+count > self->size)) {
464 PyErr_SetString (PyExc_ValueError,
465 "source or destination out of range");
466 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000467 } else {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000468 memmove (self->data+dest, self->data+src, count);
469 Py_INCREF (Py_None);
470 return Py_None;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000471 }
Guido van Rossum09fdf072000-03-31 01:17:07 +0000472 }
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000473}
474
475static struct PyMethodDef mmap_object_methods[] = {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000476 {"close", (PyCFunction) mmap_close_method, 1},
477 {"find", (PyCFunction) mmap_find_method, 1},
478 {"flush", (PyCFunction) mmap_flush_method, 1},
479 {"move", (PyCFunction) mmap_move_method, 1},
480 {"read", (PyCFunction) mmap_read_method, 1},
481 {"read_byte", (PyCFunction) mmap_read_byte_method, 1},
482 {"readline", (PyCFunction) mmap_read_line_method, 1},
483 {"resize", (PyCFunction) mmap_resize_method, 1},
484 {"seek", (PyCFunction) mmap_seek_method, 1},
485 {"size", (PyCFunction) mmap_size_method, 1},
486 {"tell", (PyCFunction) mmap_tell_method, 1},
487 {"write", (PyCFunction) mmap_write_method, 1},
488 {"write_byte", (PyCFunction) mmap_write_byte_method, 1},
489 {NULL, NULL} /* sentinel */
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000490};
491
492/* Functions for treating an mmap'ed file as a buffer */
493
494static int
Andrew M. Kuchling961fe172000-06-03 19:41:42 +0000495mmap_buffer_getreadbuf(mmap_object *self, int index, const void **ptr)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000496{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000497 CHECK_VALID(-1);
498 if ( index != 0 ) {
499 PyErr_SetString(PyExc_SystemError,
500 "Accessing non-existent mmap segment");
501 return -1;
502 }
503 *ptr = self->data;
504 return self->size;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000505}
506
507static int
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000508mmap_buffer_getwritebuf(mmap_object *self, int index, const void **ptr)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000509{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000510 CHECK_VALID(-1);
511 if ( index != 0 ) {
512 PyErr_SetString(PyExc_SystemError,
513 "Accessing non-existent mmap segment");
514 return -1;
515 }
516 *ptr = self->data;
517 return self->size;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000518}
519
520static int
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000521mmap_buffer_getsegcount(mmap_object *self, int *lenp)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000522{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000523 CHECK_VALID(-1);
524 if (lenp)
525 *lenp = self->size;
526 return 1;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000527}
528
529static int
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000530mmap_buffer_getcharbuffer(mmap_object *self, int index, const void **ptr)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000531{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000532 if ( index != 0 ) {
533 PyErr_SetString(PyExc_SystemError,
534 "accessing non-existent buffer segment");
535 return -1;
536 }
537 *ptr = (const char *)self->data;
538 return self->size;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000539}
540
541static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000542mmap_object_getattr(mmap_object *self, char *name)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000543{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000544 return Py_FindMethod (mmap_object_methods, (PyObject *)self, name);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000545}
546
547static int
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000548mmap_length(mmap_object *self)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000549{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000550 CHECK_VALID(-1);
551 return self->size;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000552}
553
554static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000555mmap_item(mmap_object *self, int i)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000556{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000557 CHECK_VALID(NULL);
Guido van Rossumce8e1dc2000-07-01 00:51:51 +0000558 if (i < 0 || (size_t)i >= self->size) {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000559 PyErr_SetString(PyExc_IndexError, "mmap index out of range");
560 return NULL;
561 }
562 return PyString_FromStringAndSize(self->data + i, 1);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000563}
564
565static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000566mmap_slice(mmap_object *self, int ilow, int ihigh)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000567{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000568 CHECK_VALID(NULL);
569 if (ilow < 0)
570 ilow = 0;
Guido van Rossumce8e1dc2000-07-01 00:51:51 +0000571 else if ((size_t)ilow > self->size)
Guido van Rossum09fdf072000-03-31 01:17:07 +0000572 ilow = self->size;
573 if (ihigh < 0)
574 ihigh = 0;
575 if (ihigh < ilow)
576 ihigh = ilow;
Guido van Rossumce8e1dc2000-07-01 00:51:51 +0000577 else if ((size_t)ihigh > self->size)
Guido van Rossum09fdf072000-03-31 01:17:07 +0000578 ihigh = self->size;
579
580 return PyString_FromStringAndSize(self->data + ilow, ihigh-ilow);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000581}
582
583static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000584mmap_concat(mmap_object *self, PyObject *bb)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000585{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000586 CHECK_VALID(NULL);
587 PyErr_SetString(PyExc_SystemError,
588 "mmaps don't support concatenation");
589 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000590}
591
592static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000593mmap_repeat(mmap_object *self, int n)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000594{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000595 CHECK_VALID(NULL);
596 PyErr_SetString(PyExc_SystemError,
597 "mmaps don't support repeat operation");
598 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000599}
600
601static int
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000602mmap_ass_slice(mmap_object *self, int ilow, int ihigh, PyObject *v)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000603{
Guido van Rossum36d4f8b2000-04-10 21:34:37 +0000604 const char *buf;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000605
Guido van Rossum09fdf072000-03-31 01:17:07 +0000606 CHECK_VALID(-1);
607 if (ilow < 0)
608 ilow = 0;
Guido van Rossumce8e1dc2000-07-01 00:51:51 +0000609 else if ((size_t)ilow > self->size)
Guido van Rossum09fdf072000-03-31 01:17:07 +0000610 ilow = self->size;
611 if (ihigh < 0)
612 ihigh = 0;
613 if (ihigh < ilow)
614 ihigh = ilow;
Guido van Rossumce8e1dc2000-07-01 00:51:51 +0000615 else if ((size_t)ihigh > self->size)
Guido van Rossum09fdf072000-03-31 01:17:07 +0000616 ihigh = self->size;
617
618 if (! (PyString_Check(v)) ) {
619 PyErr_SetString(PyExc_IndexError,
620 "mmap slice assignment must be a string");
621 return -1;
622 }
623 if ( PyString_Size(v) != (ihigh - ilow) ) {
624 PyErr_SetString(PyExc_IndexError,
625 "mmap slice assignment is wrong size");
626 return -1;
627 }
628 buf = PyString_AsString(v);
629 memcpy(self->data + ilow, buf, ihigh-ilow);
630 return 0;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000631}
632
633static int
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000634mmap_ass_item(mmap_object *self, int i, PyObject *v)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000635{
Guido van Rossum36d4f8b2000-04-10 21:34:37 +0000636 const char *buf;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000637
Guido van Rossum09fdf072000-03-31 01:17:07 +0000638 CHECK_VALID(-1);
Guido van Rossumce8e1dc2000-07-01 00:51:51 +0000639 if (i < 0 || (size_t)i >= self->size) {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000640 PyErr_SetString(PyExc_IndexError, "mmap index out of range");
641 return -1;
642 }
643 if (! (PyString_Check(v) && PyString_Size(v)==1) ) {
644 PyErr_SetString(PyExc_IndexError,
645 "mmap assignment must be single-character string");
646 return -1;
647 }
648 buf = PyString_AsString(v);
649 self->data[i] = buf[0];
650 return 0;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000651}
652
653static PySequenceMethods mmap_as_sequence = {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000654 (inquiry)mmap_length, /*sq_length*/
655 (binaryfunc)mmap_concat, /*sq_concat*/
656 (intargfunc)mmap_repeat, /*sq_repeat*/
657 (intargfunc)mmap_item, /*sq_item*/
658 (intintargfunc)mmap_slice, /*sq_slice*/
659 (intobjargproc)mmap_ass_item, /*sq_ass_item*/
660 (intintobjargproc)mmap_ass_slice, /*sq_ass_slice*/
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000661};
662
663static PyBufferProcs mmap_as_buffer = {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000664 (getreadbufferproc)mmap_buffer_getreadbuf,
665 (getwritebufferproc)mmap_buffer_getwritebuf,
666 (getsegcountproc)mmap_buffer_getsegcount,
667 (getcharbufferproc)mmap_buffer_getcharbuffer,
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000668};
669
670static PyTypeObject mmap_object_type = {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000671 PyObject_HEAD_INIT(0) /* patched in module init */
672 0, /* ob_size */
673 "mmap", /* tp_name */
674 sizeof(mmap_object), /* tp_size */
675 0, /* tp_itemsize */
676 /* methods */
677 (destructor) mmap_object_dealloc, /* tp_dealloc */
678 0, /* tp_print */
679 (getattrfunc) mmap_object_getattr, /* tp_getattr */
680 0, /* tp_setattr */
681 0, /* tp_compare */
682 0, /* tp_repr */
683 0, /* tp_as_number */
684 &mmap_as_sequence, /*tp_as_sequence*/
685 0, /*tp_as_mapping*/
686 0, /*tp_hash*/
687 0, /*tp_call*/
688 0, /*tp_str*/
689 0, /*tp_getattro*/
690 0, /*tp_setattro*/
691 &mmap_as_buffer, /*tp_as_buffer*/
692 Py_TPFLAGS_HAVE_GETCHARBUFFER, /*tp_flags*/
693 0, /*tp_doc*/
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000694};
695
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000696
697/* extract the map size from the given PyObject
698
699 The map size is restricted to [0, INT_MAX] because this is the current
700 Python limitation on object sizes. Although the mmap object *could* handle
701 a larger map size, there is no point because all the useful operations
702 (len(), slicing(), sequence indexing) are limited by a C int.
703
704 Returns -1 on error, with an apprpriate Python exception raised. On
705 success, the map size is returned. */
706static int
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000707_GetMapSize(PyObject *o)
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000708{
709 if (PyInt_Check(o)) {
710 long i = PyInt_AsLong(o);
711 if (PyErr_Occurred())
712 return -1;
713 if (i < 0)
714 goto onnegoverflow;
715 if (i > INT_MAX)
716 goto onposoverflow;
717 return (int)i;
718 }
719 else if (PyLong_Check(o)) {
720 long i = PyLong_AsLong(o);
721 if (PyErr_Occurred()) {
722 /* yes negative overflow is mistaken for positive overflow
723 but not worth the trouble to check sign of 'i' */
724 if (PyErr_ExceptionMatches(PyExc_OverflowError))
725 goto onposoverflow;
726 else
727 return -1;
728 }
729 if (i < 0)
730 goto onnegoverflow;
731 if (i > INT_MAX)
732 goto onposoverflow;
733 return (int)i;
734 }
735 else {
736 PyErr_SetString(PyExc_TypeError,
737 "map size must be an integral value");
738 return -1;
739 }
740
741onnegoverflow:
742 PyErr_SetString(PyExc_OverflowError,
743 "memory mapped size must be positive");
744 return -1;
745
746onposoverflow:
747 PyErr_SetString(PyExc_OverflowError,
748 "memory mapped size is too large (limited by C int)");
749 return -1;
750}
751
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000752#ifdef UNIX
753static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000754new_mmap_object(PyObject *self, PyObject *args, PyObject *kwdict)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000755{
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000756 mmap_object *m_obj;
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000757 PyObject *map_size_obj = NULL;
758 int map_size;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000759 int fd, flags = MAP_SHARED, prot = PROT_WRITE | PROT_READ;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000760 char *keywords[] = {"file", "size", "flags", "prot", NULL};
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000761
Guido van Rossum09fdf072000-03-31 01:17:07 +0000762 if (!PyArg_ParseTupleAndKeywords(args, kwdict,
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000763 "iO|ii", keywords,
764 &fd, &map_size_obj, &flags, &prot)
Guido van Rossum09fdf072000-03-31 01:17:07 +0000765 )
766 return NULL;
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000767 map_size = _GetMapSize(map_size_obj);
768 if (map_size < 0)
769 return NULL;
770
Guido van Rossumb18618d2000-05-03 23:44:39 +0000771 m_obj = PyObject_New (mmap_object, &mmap_object_type);
Guido van Rossum09fdf072000-03-31 01:17:07 +0000772 if (m_obj == NULL) {return NULL;}
773 m_obj->size = (size_t) map_size;
774 m_obj->pos = (size_t) 0;
Andrew M. Kuchling7b9fb922000-06-17 22:41:22 +0000775 m_obj->fd = fd;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000776 m_obj->data = mmap(NULL, map_size,
777 prot, flags,
778 fd, 0);
779 if (m_obj->data == (void *)-1)
780 {
781 Py_DECREF(m_obj);
782 PyErr_SetFromErrno(mmap_module_error);
783 return NULL;
784 }
785 return (PyObject *)m_obj;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000786}
787#endif /* UNIX */
788
789#ifdef MS_WIN32
790static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000791new_mmap_object(PyObject *self, PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000792{
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000793 mmap_object *m_obj;
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000794 PyObject *map_size_obj = NULL;
795 int map_size;
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000796 char *tagname = "";
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000797
Guido van Rossum09fdf072000-03-31 01:17:07 +0000798 DWORD dwErr = 0;
799 int fileno;
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000800 INT_PTR fh = 0;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000801
Guido van Rossum09fdf072000-03-31 01:17:07 +0000802 /* Patch the object type */
803 mmap_object_type.ob_type = &PyType_Type;
804
805 if (!PyArg_ParseTuple(args,
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000806 "iO|z",
Guido van Rossum09fdf072000-03-31 01:17:07 +0000807 &fileno,
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000808 &map_size_obj,
Guido van Rossum09fdf072000-03-31 01:17:07 +0000809 &tagname)
810 )
811 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000812
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000813 map_size = _GetMapSize(map_size_obj);
814 if (map_size < 0)
815 return NULL;
816
Guido van Rossum09fdf072000-03-31 01:17:07 +0000817 /* if an actual filename has been specified */
818 if (fileno != 0) {
819 fh = _get_osfhandle(fileno);
820 if (fh==-1) {
821 PyErr_SetFromErrno(mmap_module_error);
822 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000823 }
Fred Drake1ef4e2d2000-04-05 14:15:31 +0000824 /* Win9x appears to need us seeked to zero */
825 fseek(&_iob[fileno], 0, SEEK_SET);
Guido van Rossum09fdf072000-03-31 01:17:07 +0000826 }
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000827
Guido van Rossumb18618d2000-05-03 23:44:39 +0000828 m_obj = PyObject_New (mmap_object, &mmap_object_type);
Guido van Rossum09fdf072000-03-31 01:17:07 +0000829
830 if (fh) {
831 m_obj->file_handle = fh;
832 if (!map_size) {
833 m_obj->size = GetFileSize ((HANDLE)fh, NULL);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000834 } else {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000835 m_obj->size = map_size;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000836 }
Guido van Rossum09fdf072000-03-31 01:17:07 +0000837 }
838 else {
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000839 m_obj->file_handle = (INT_PTR) -1;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000840 m_obj->size = map_size;
841 }
842
843 /* set the initial position */
844 m_obj->pos = (size_t) 0;
845
846 m_obj->map_handle = CreateFileMapping ((HANDLE) m_obj->file_handle,
847 NULL,
848 PAGE_READWRITE,
849 0,
850 m_obj->size,
851 tagname);
852 if (m_obj->map_handle != NULL) {
853 m_obj->data = (char *) MapViewOfFile (m_obj->map_handle,
854 FILE_MAP_WRITE,
855 0,
856 0,
857 0);
858 if (m_obj->data != NULL) {
859 return ((PyObject *) m_obj);
860 } else {
861 dwErr = GetLastError();
862 }
863 } else {
864 dwErr = GetLastError();
865 }
866 PyErr_SetFromWindowsErr(dwErr);
867 return (NULL);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000868}
869#endif /* MS_WIN32 */
870
871/* List of functions exported by this module */
872static struct PyMethodDef mmap_functions[] = {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000873 {"mmap", (PyCFunction) new_mmap_object,
874 METH_VARARGS|METH_KEYWORDS},
875 {NULL, NULL} /* Sentinel */
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000876};
877
878#ifdef MS_WIN32
Guido van Rossum09fdf072000-03-31 01:17:07 +0000879__declspec(dllexport) void
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000880#endif /* MS_WIN32 */
881#ifdef UNIX
882extern void
883#endif
884
885initmmap(void)
886{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000887 PyObject *dict, *module;
888 module = Py_InitModule ("mmap", mmap_functions);
889 dict = PyModule_GetDict (module);
890 mmap_module_error = PyExc_EnvironmentError;
891 Py_INCREF(mmap_module_error);
892 PyDict_SetItemString (dict, "error", mmap_module_error);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000893#ifdef PROT_EXEC
Guido van Rossum09fdf072000-03-31 01:17:07 +0000894 PyDict_SetItemString (dict, "PROT_EXEC", PyInt_FromLong(PROT_EXEC) );
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000895#endif
896#ifdef PROT_READ
Guido van Rossum09fdf072000-03-31 01:17:07 +0000897 PyDict_SetItemString (dict, "PROT_READ", PyInt_FromLong(PROT_READ) );
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000898#endif
899#ifdef PROT_WRITE
Guido van Rossum09fdf072000-03-31 01:17:07 +0000900 PyDict_SetItemString (dict, "PROT_WRITE", PyInt_FromLong(PROT_WRITE) );
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000901#endif
902
903#ifdef MAP_SHARED
Guido van Rossum09fdf072000-03-31 01:17:07 +0000904 PyDict_SetItemString (dict, "MAP_SHARED", PyInt_FromLong(MAP_SHARED) );
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000905#endif
906#ifdef MAP_PRIVATE
Guido van Rossum09fdf072000-03-31 01:17:07 +0000907 PyDict_SetItemString (dict, "MAP_PRIVATE",
908 PyInt_FromLong(MAP_PRIVATE) );
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000909#endif
910#ifdef MAP_DENYWRITE
Guido van Rossum09fdf072000-03-31 01:17:07 +0000911 PyDict_SetItemString (dict, "MAP_DENYWRITE",
912 PyInt_FromLong(MAP_DENYWRITE) );
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000913#endif
914#ifdef MAP_EXECUTABLE
Guido van Rossum09fdf072000-03-31 01:17:07 +0000915 PyDict_SetItemString (dict, "MAP_EXECUTABLE",
916 PyInt_FromLong(MAP_EXECUTABLE) );
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000917#endif
918#ifdef MAP_ANON
Guido van Rossum09fdf072000-03-31 01:17:07 +0000919 PyDict_SetItemString (dict, "MAP_ANON", PyInt_FromLong(MAP_ANON) );
920 PyDict_SetItemString (dict, "MAP_ANONYMOUS",
921 PyInt_FromLong(MAP_ANON) );
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000922#endif
923
924#ifdef UNIX
Guido van Rossum09fdf072000-03-31 01:17:07 +0000925 PyDict_SetItemString (dict, "PAGESIZE",
926 PyInt_FromLong( (long)getpagesize() ) );
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000927#endif
Guido van Rossum09fdf072000-03-31 01:17:07 +0000928#ifdef MS_WIN32
929 {
930 SYSTEM_INFO si;
931 GetSystemInfo(&si);
932 PyDict_SetItemString (dict, "PAGESIZE",
933 PyInt_FromLong( si.dwPageSize ) );
934 }
935#endif /* MS_WIN32 */
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000936
937}
Andrew M. Kuchling961fe172000-06-03 19:41:42 +0000938