blob: cbb2452906fdfcb6fc4414b81ffa0cec2c6c82d6 [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>
Guido van Rossum4b36e6b2000-09-25 13:16:15 +000035
36#ifndef MS_SYNC
37/* This is missing e.g. on SunOS 4.1.4 */
38#define MS_SYNC 0
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +000039#endif
40
Guido van Rossum4b36e6b2000-09-25 13:16:15 +000041#endif /* UNIX */
42
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +000043#include <string.h>
44#include <sys/types.h>
45
46static PyObject *mmap_module_error;
47
48typedef struct {
Guido van Rossum09fdf072000-03-31 01:17:07 +000049 PyObject_HEAD
50 char * data;
51 size_t size;
52 size_t pos;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +000053
54#ifdef MS_WIN32
Guido van Rossum09fdf072000-03-31 01:17:07 +000055 HANDLE map_handle;
Mark Hammond071864a2000-07-30 02:46:26 +000056 HANDLE file_handle;
Guido van Rossum09fdf072000-03-31 01:17:07 +000057 char * tagname;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +000058#endif
59
60#ifdef UNIX
Andrew M. Kuchling7b9fb922000-06-17 22:41:22 +000061 int fd;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +000062#endif
63} mmap_object;
64
65static void
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +000066mmap_object_dealloc(mmap_object *m_obj)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +000067{
68#ifdef MS_WIN32
Mark Hammond2cbed002000-07-30 02:22:43 +000069 if (m_obj->data != NULL)
70 UnmapViewOfFile (m_obj->data);
71 if (m_obj->map_handle != INVALID_HANDLE_VALUE)
72 CloseHandle (m_obj->map_handle);
Mark Hammond071864a2000-07-30 02:46:26 +000073 if (m_obj->file_handle != INVALID_HANDLE_VALUE)
74 CloseHandle (m_obj->file_handle);
Mark Hammond2cbed002000-07-30 02:22:43 +000075 if (m_obj->tagname)
76 PyMem_Free(m_obj->tagname);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +000077#endif /* MS_WIN32 */
78
79#ifdef UNIX
Guido van Rossum09fdf072000-03-31 01:17:07 +000080 if (m_obj->data!=NULL) {
Andrew M. Kuchling9bc5f332000-06-18 04:25:08 +000081 msync(m_obj->data, m_obj->size, MS_SYNC);
Guido van Rossum09fdf072000-03-31 01:17:07 +000082 munmap(m_obj->data, m_obj->size);
83 }
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +000084#endif /* UNIX */
85
Guido van Rossumb18618d2000-05-03 23:44:39 +000086 PyObject_Del(m_obj);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +000087}
88
89static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +000090mmap_close_method(mmap_object *self, PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +000091{
Andrew M. Kuchling841b9fb2000-06-03 20:43:43 +000092 if (!PyArg_ParseTuple(args, ":close"))
Andrew M. Kuchling961fe172000-06-03 19:41:42 +000093 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +000094#ifdef MS_WIN32
Mark Hammond071864a2000-07-30 02:46:26 +000095 /* For each resource we maintain, we need to check
96 the value is valid, and if so, free the resource
97 and set the member value to an invalid value so
98 the dealloc does not attempt to resource clearing
99 again.
100 TODO - should we check for errors in the close operations???
101 */
102 if (self->data != NULL) {
103 UnmapViewOfFile (self->data);
104 self->data = NULL;
105 }
106 if (self->map_handle != INVALID_HANDLE_VALUE) {
107 CloseHandle (self->map_handle);
108 self->map_handle = INVALID_HANDLE_VALUE;
109 }
110 if (self->file_handle != INVALID_HANDLE_VALUE) {
111 CloseHandle (self->file_handle);
112 self->file_handle = INVALID_HANDLE_VALUE;
113 }
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000114#endif /* MS_WIN32 */
115
116#ifdef UNIX
Guido van Rossum09fdf072000-03-31 01:17:07 +0000117 munmap(self->data, self->size);
118 self->data = NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000119#endif
120
Guido van Rossum09fdf072000-03-31 01:17:07 +0000121 Py_INCREF (Py_None);
122 return (Py_None);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000123}
124
125#ifdef MS_WIN32
Guido van Rossum09fdf072000-03-31 01:17:07 +0000126#define CHECK_VALID(err) \
127do { \
128 if (!self->map_handle) { \
129 PyErr_SetString (PyExc_ValueError, "mmap closed or invalid"); \
130 return err; \
131 } \
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000132} while (0)
133#endif /* MS_WIN32 */
134
135#ifdef UNIX
Guido van Rossum09fdf072000-03-31 01:17:07 +0000136#define CHECK_VALID(err) \
137do { \
138 if (self->data == NULL) { \
139 PyErr_SetString (PyExc_ValueError, "mmap closed or invalid"); \
140 return err; \
141 } \
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000142} while (0)
143#endif /* UNIX */
144
145static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000146mmap_read_byte_method(mmap_object *self,
147 PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000148{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000149 char value;
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000150 char *where;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000151 CHECK_VALID(NULL);
Andrew M. Kuchling841b9fb2000-06-03 20:43:43 +0000152 if (!PyArg_ParseTuple(args, ":read_byte"))
Andrew M. Kuchling961fe172000-06-03 19:41:42 +0000153 return NULL;
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000154 if (self->pos < self->size) {
Guido van Rossum36d4f8b2000-04-10 21:34:37 +0000155 where = self->data + self->pos;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000156 value = (char) *(where);
157 self->pos += 1;
158 return Py_BuildValue("c", (char) *(where));
159 } else {
160 PyErr_SetString (PyExc_ValueError, "read byte out of range");
161 return NULL;
162 }
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000163}
164
165static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000166mmap_read_line_method(mmap_object *self,
167 PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000168{
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000169 char *start = self->data+self->pos;
170 char *eof = self->data+self->size;
171 char *eol;
172 PyObject *result;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000173
Guido van Rossum09fdf072000-03-31 01:17:07 +0000174 CHECK_VALID(NULL);
Andrew M. Kuchling841b9fb2000-06-03 20:43:43 +0000175 if (!PyArg_ParseTuple(args, ":readline"))
Andrew M. Kuchling961fe172000-06-03 19:41:42 +0000176 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000177
Fred Drake56a87a02000-04-04 18:17:35 +0000178 eol = memchr(start, '\n', self->size - self->pos);
179 if (!eol)
180 eol = eof;
181 else
182 ++eol; /* we're interested in the position after the
183 newline. */
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000184 result = PyString_FromStringAndSize(start, (eol - start));
Guido van Rossum09fdf072000-03-31 01:17:07 +0000185 self->pos += (eol - start);
186 return (result);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000187}
188
189static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000190mmap_read_method(mmap_object *self,
191 PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000192{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000193 long num_bytes;
194 PyObject *result;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000195
Guido van Rossum09fdf072000-03-31 01:17:07 +0000196 CHECK_VALID(NULL);
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000197 if (!PyArg_ParseTuple(args, "l:read", &num_bytes))
Guido van Rossum09fdf072000-03-31 01:17:07 +0000198 return(NULL);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000199
Guido van Rossum09fdf072000-03-31 01:17:07 +0000200 /* silently 'adjust' out-of-range requests */
201 if ((self->pos + num_bytes) > self->size) {
202 num_bytes -= (self->pos+num_bytes) - self->size;
203 }
204 result = Py_BuildValue("s#", self->data+self->pos, num_bytes);
205 self->pos += num_bytes;
206 return (result);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000207}
208
209static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000210mmap_find_method(mmap_object *self,
211 PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000212{
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000213 int start = self->pos;
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000214 char *needle;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000215 int len;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000216
Guido van Rossum09fdf072000-03-31 01:17:07 +0000217 CHECK_VALID(NULL);
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000218 if (!PyArg_ParseTuple (args, "s#|i:find", &needle, &len, &start)) {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000219 return NULL;
220 } else {
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000221 char *p = self->data+self->pos;
222 char *e = self->data+self->size;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000223 while (p < e) {
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000224 char *s = p;
225 char *n = needle;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000226 while ((s<e) && (*n) && !(*s-*n)) {
227 s++, n++;
228 }
229 if (!*n) {
230 return Py_BuildValue (
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000231 "i",
232 (int) (p - (self->data + start)));
Guido van Rossum09fdf072000-03-31 01:17:07 +0000233 }
234 p++;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000235 }
Guido van Rossum09fdf072000-03-31 01:17:07 +0000236 return Py_BuildValue ("l", (long) -1);
237 }
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000238}
239
240static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000241mmap_write_method(mmap_object *self,
242 PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000243{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000244 long length;
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000245 char *data;
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, "s#:write", &data, &length))
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 if ((self->pos + length) > self->size) {
252 PyErr_SetString (PyExc_ValueError, "data out of range");
253 return NULL;
254 }
255 memcpy (self->data+self->pos, data, length);
256 self->pos = self->pos+length;
257 Py_INCREF (Py_None);
258 return (Py_None);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000259}
260
261static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000262mmap_write_byte_method(mmap_object *self,
263 PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000264{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000265 char value;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000266
Guido van Rossum09fdf072000-03-31 01:17:07 +0000267 CHECK_VALID(NULL);
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000268 if (!PyArg_ParseTuple (args, "c:write_byte", &value))
Guido van Rossum09fdf072000-03-31 01:17:07 +0000269 return(NULL);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000270
Guido van Rossum09fdf072000-03-31 01:17:07 +0000271 *(self->data+self->pos) = value;
272 self->pos += 1;
273 Py_INCREF (Py_None);
274 return (Py_None);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000275}
276
277static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000278mmap_size_method(mmap_object *self,
279 PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000280{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000281 CHECK_VALID(NULL);
Andrew M. Kuchling841b9fb2000-06-03 20:43:43 +0000282 if (!PyArg_ParseTuple(args, ":size"))
Andrew M. Kuchling961fe172000-06-03 19:41:42 +0000283 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000284
285#ifdef MS_WIN32
Mark Hammond071864a2000-07-30 02:46:26 +0000286 if (self->file_handle != INVALID_HANDLE_VALUE) {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000287 return (Py_BuildValue (
Fredrik Lundh5cccf502000-07-09 13:16:13 +0000288 "l", (long)
Mark Hammond071864a2000-07-30 02:46:26 +0000289 GetFileSize (self->file_handle, NULL)));
Guido van Rossum09fdf072000-03-31 01:17:07 +0000290 } else {
Fredrik Lundh5cccf502000-07-09 13:16:13 +0000291 return (Py_BuildValue ("l", (long) self->size) );
Guido van Rossum09fdf072000-03-31 01:17:07 +0000292 }
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000293#endif /* MS_WIN32 */
294
295#ifdef UNIX
Andrew M. Kuchling7b9fb922000-06-17 22:41:22 +0000296 {
297 struct stat buf;
298 if (-1 == fstat(self->fd, &buf)) {
299 PyErr_SetFromErrno(mmap_module_error);
300 return NULL;
301 }
Fredrik Lundh5cccf502000-07-09 13:16:13 +0000302 return (Py_BuildValue ("l", (long) buf.st_size) );
Andrew M. Kuchling7b9fb922000-06-17 22:41:22 +0000303 }
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000304#endif /* UNIX */
305}
306
307/* This assumes that you want the entire file mapped,
308 / and when recreating the map will make the new file
309 / have the new size
310 /
311 / Is this really necessary? This could easily be done
312 / from python by just closing and re-opening with the
313 / new size?
314 */
315
316static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000317mmap_resize_method(mmap_object *self,
318 PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000319{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000320 unsigned long new_size;
321 CHECK_VALID(NULL);
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000322 if (!PyArg_ParseTuple (args, "l:resize", &new_size)) {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000323 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000324#ifdef MS_WIN32
Guido van Rossum09fdf072000-03-31 01:17:07 +0000325 } else {
326 DWORD dwErrCode = 0;
327 /* First, unmap the file view */
328 UnmapViewOfFile (self->data);
329 /* Close the mapping object */
Mark Hammond071864a2000-07-30 02:46:26 +0000330 CloseHandle (self->map_handle);
Guido van Rossum09fdf072000-03-31 01:17:07 +0000331 /* Move to the desired EOF position */
Mark Hammond071864a2000-07-30 02:46:26 +0000332 SetFilePointer (self->file_handle,
Guido van Rossum09fdf072000-03-31 01:17:07 +0000333 new_size, NULL, FILE_BEGIN);
334 /* Change the size of the file */
Mark Hammond071864a2000-07-30 02:46:26 +0000335 SetEndOfFile (self->file_handle);
Guido van Rossum09fdf072000-03-31 01:17:07 +0000336 /* Create another mapping object and remap the file view */
337 self->map_handle = CreateFileMapping (
Mark Hammond071864a2000-07-30 02:46:26 +0000338 self->file_handle,
Guido van Rossum09fdf072000-03-31 01:17:07 +0000339 NULL,
340 PAGE_READWRITE,
341 0,
342 new_size,
343 self->tagname);
344 if (self->map_handle != NULL) {
345 self->data = (char *) MapViewOfFile (self->map_handle,
346 FILE_MAP_WRITE,
347 0,
348 0,
349 0);
350 if (self->data != NULL) {
351 self->size = new_size;
352 Py_INCREF (Py_None);
353 return Py_None;
354 } else {
355 dwErrCode = GetLastError();
356 }
357 } else {
358 dwErrCode = GetLastError();
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000359 }
Guido van Rossum09fdf072000-03-31 01:17:07 +0000360 PyErr_SetFromWindowsErr(dwErrCode);
361 return (NULL);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000362#endif /* MS_WIN32 */
363
364#ifdef UNIX
Andrew M. Kuchling6fef30e2000-06-18 14:51:21 +0000365#ifndef HAVE_MREMAP
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000366} else {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000367 PyErr_SetString(PyExc_SystemError,
368 "mmap: resizing not available--no mremap()");
369 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000370#else
371} else {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000372 void *newmap;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000373
Andrew M. Kuchling6fef30e2000-06-18 14:51:21 +0000374#ifdef MREMAP_MAYMOVE
Guido van Rossum09fdf072000-03-31 01:17:07 +0000375 newmap = mremap(self->data, self->size, new_size, MREMAP_MAYMOVE);
Andrew M. Kuchling6fef30e2000-06-18 14:51:21 +0000376#else
377 newmap = mremap(self->data, self->size, new_size, 0);
378#endif
Guido van Rossum09fdf072000-03-31 01:17:07 +0000379 if (newmap == (void *)-1)
380 {
381 PyErr_SetFromErrno(mmap_module_error);
382 return NULL;
383 }
384 self->data = newmap;
385 self->size = new_size;
386 Py_INCREF(Py_None);
387 return Py_None;
Andrew M. Kuchling6fef30e2000-06-18 14:51:21 +0000388#endif /* HAVE_MREMAP */
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000389#endif /* UNIX */
390}
391}
392
393static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000394mmap_tell_method(mmap_object *self, PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000395{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000396 CHECK_VALID(NULL);
Andrew M. Kuchling841b9fb2000-06-03 20:43:43 +0000397 if (!PyArg_ParseTuple(args, ":tell"))
Andrew M. Kuchling961fe172000-06-03 19:41:42 +0000398 return NULL;
Fredrik Lundh5cccf502000-07-09 13:16:13 +0000399 return (Py_BuildValue ("l", (long) self->pos) );
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000400}
401
402static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000403mmap_flush_method(mmap_object *self, PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000404{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000405 size_t offset = 0;
406 size_t size = self->size;
407 CHECK_VALID(NULL);
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000408 if (!PyArg_ParseTuple (args, "|ll:flush", &offset, &size)) {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000409 return NULL;
410 } else if ((offset + size) > self->size) {
411 PyErr_SetString (PyExc_ValueError,
412 "flush values out of range");
413 return NULL;
414 } else {
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000415#ifdef MS_WIN32
Fredrik Lundh5cccf502000-07-09 13:16:13 +0000416 return (Py_BuildValue("l", (long)
417 FlushViewOfFile(self->data+offset, size)));
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000418#endif /* MS_WIN32 */
419#ifdef UNIX
Guido van Rossum09fdf072000-03-31 01:17:07 +0000420 /* XXX semantics of return value? */
421 /* XXX flags for msync? */
422 if (-1 == msync(self->data + offset, size,
Andrew M. Kuchling9bc5f332000-06-18 04:25:08 +0000423 MS_SYNC))
Guido van Rossum09fdf072000-03-31 01:17:07 +0000424 {
425 PyErr_SetFromErrno(mmap_module_error);
426 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000427 }
Fredrik Lundh5cccf502000-07-09 13:16:13 +0000428 return Py_BuildValue ("l", (long) 0);
Guido van Rossum09fdf072000-03-31 01:17:07 +0000429#endif /* UNIX */
430 }
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000431}
432
433static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000434mmap_seek_method(mmap_object *self, PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000435{
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000436 int dist;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000437 int how=0;
438 CHECK_VALID(NULL);
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000439 if (!PyArg_ParseTuple (args, "i|i:seek", &dist, &how)) {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000440 return(NULL);
441 } else {
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000442 size_t where;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000443 switch (how) {
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000444 case 0: /* relative to start */
445 if (dist < 0)
446 goto onoutofrange;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000447 where = dist;
448 break;
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000449 case 1: /* relative to current position */
450 if ((int)self->pos + dist < 0)
451 goto onoutofrange;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000452 where = self->pos + dist;
453 break;
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000454 case 2: /* relative to end */
455 if ((int)self->size + dist < 0)
456 goto onoutofrange;
457 where = self->size + dist;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000458 break;
459 default:
460 PyErr_SetString (PyExc_ValueError,
461 "unknown seek type");
462 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000463 }
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000464 if (where > self->size)
465 goto onoutofrange;
466 self->pos = where;
467 Py_INCREF (Py_None);
468 return (Py_None);
Guido van Rossum09fdf072000-03-31 01:17:07 +0000469 }
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000470
471onoutofrange:
472 PyErr_SetString (PyExc_ValueError, "seek out of range");
473 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000474}
475
476static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000477mmap_move_method(mmap_object *self, PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000478{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000479 unsigned long dest, src, count;
480 CHECK_VALID(NULL);
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000481 if (!PyArg_ParseTuple (args, "iii:move", &dest, &src, &count)) {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000482 return NULL;
483 } else {
484 /* bounds check the values */
485 if (/* end of source after end of data?? */
486 ((src+count) > self->size)
487 /* dest will fit? */
488 || (dest+count > self->size)) {
489 PyErr_SetString (PyExc_ValueError,
490 "source or destination out of range");
491 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000492 } else {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000493 memmove (self->data+dest, self->data+src, count);
494 Py_INCREF (Py_None);
495 return Py_None;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000496 }
Guido van Rossum09fdf072000-03-31 01:17:07 +0000497 }
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000498}
499
500static struct PyMethodDef mmap_object_methods[] = {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000501 {"close", (PyCFunction) mmap_close_method, 1},
502 {"find", (PyCFunction) mmap_find_method, 1},
503 {"flush", (PyCFunction) mmap_flush_method, 1},
504 {"move", (PyCFunction) mmap_move_method, 1},
505 {"read", (PyCFunction) mmap_read_method, 1},
506 {"read_byte", (PyCFunction) mmap_read_byte_method, 1},
507 {"readline", (PyCFunction) mmap_read_line_method, 1},
508 {"resize", (PyCFunction) mmap_resize_method, 1},
509 {"seek", (PyCFunction) mmap_seek_method, 1},
510 {"size", (PyCFunction) mmap_size_method, 1},
511 {"tell", (PyCFunction) mmap_tell_method, 1},
512 {"write", (PyCFunction) mmap_write_method, 1},
513 {"write_byte", (PyCFunction) mmap_write_byte_method, 1},
514 {NULL, NULL} /* sentinel */
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000515};
516
517/* Functions for treating an mmap'ed file as a buffer */
518
519static int
Andrew M. Kuchling961fe172000-06-03 19:41:42 +0000520mmap_buffer_getreadbuf(mmap_object *self, int index, const void **ptr)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000521{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000522 CHECK_VALID(-1);
523 if ( index != 0 ) {
524 PyErr_SetString(PyExc_SystemError,
525 "Accessing non-existent mmap segment");
526 return -1;
527 }
528 *ptr = self->data;
529 return self->size;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000530}
531
532static int
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000533mmap_buffer_getwritebuf(mmap_object *self, int index, const void **ptr)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000534{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000535 CHECK_VALID(-1);
536 if ( index != 0 ) {
537 PyErr_SetString(PyExc_SystemError,
538 "Accessing non-existent mmap segment");
539 return -1;
540 }
541 *ptr = self->data;
542 return self->size;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000543}
544
545static int
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000546mmap_buffer_getsegcount(mmap_object *self, int *lenp)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000547{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000548 CHECK_VALID(-1);
549 if (lenp)
550 *lenp = self->size;
551 return 1;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000552}
553
554static int
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000555mmap_buffer_getcharbuffer(mmap_object *self, int index, const void **ptr)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000556{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000557 if ( index != 0 ) {
558 PyErr_SetString(PyExc_SystemError,
559 "accessing non-existent buffer segment");
560 return -1;
561 }
562 *ptr = (const char *)self->data;
563 return self->size;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000564}
565
566static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000567mmap_object_getattr(mmap_object *self, char *name)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000568{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000569 return Py_FindMethod (mmap_object_methods, (PyObject *)self, name);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000570}
571
572static int
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000573mmap_length(mmap_object *self)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000574{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000575 CHECK_VALID(-1);
576 return self->size;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000577}
578
579static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000580mmap_item(mmap_object *self, int i)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000581{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000582 CHECK_VALID(NULL);
Guido van Rossumce8e1dc2000-07-01 00:51:51 +0000583 if (i < 0 || (size_t)i >= self->size) {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000584 PyErr_SetString(PyExc_IndexError, "mmap index out of range");
585 return NULL;
586 }
587 return PyString_FromStringAndSize(self->data + i, 1);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000588}
589
590static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000591mmap_slice(mmap_object *self, int ilow, int ihigh)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000592{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000593 CHECK_VALID(NULL);
594 if (ilow < 0)
595 ilow = 0;
Guido van Rossumce8e1dc2000-07-01 00:51:51 +0000596 else if ((size_t)ilow > self->size)
Guido van Rossum09fdf072000-03-31 01:17:07 +0000597 ilow = self->size;
598 if (ihigh < 0)
599 ihigh = 0;
600 if (ihigh < ilow)
601 ihigh = ilow;
Guido van Rossumce8e1dc2000-07-01 00:51:51 +0000602 else if ((size_t)ihigh > self->size)
Guido van Rossum09fdf072000-03-31 01:17:07 +0000603 ihigh = self->size;
604
605 return PyString_FromStringAndSize(self->data + ilow, ihigh-ilow);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000606}
607
608static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000609mmap_concat(mmap_object *self, PyObject *bb)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000610{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000611 CHECK_VALID(NULL);
612 PyErr_SetString(PyExc_SystemError,
613 "mmaps don't support concatenation");
614 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000615}
616
617static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000618mmap_repeat(mmap_object *self, int n)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000619{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000620 CHECK_VALID(NULL);
621 PyErr_SetString(PyExc_SystemError,
622 "mmaps don't support repeat operation");
623 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000624}
625
626static int
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000627mmap_ass_slice(mmap_object *self, int ilow, int ihigh, PyObject *v)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000628{
Guido van Rossum36d4f8b2000-04-10 21:34:37 +0000629 const char *buf;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000630
Guido van Rossum09fdf072000-03-31 01:17:07 +0000631 CHECK_VALID(-1);
632 if (ilow < 0)
633 ilow = 0;
Guido van Rossumce8e1dc2000-07-01 00:51:51 +0000634 else if ((size_t)ilow > self->size)
Guido van Rossum09fdf072000-03-31 01:17:07 +0000635 ilow = self->size;
636 if (ihigh < 0)
637 ihigh = 0;
638 if (ihigh < ilow)
639 ihigh = ilow;
Guido van Rossumce8e1dc2000-07-01 00:51:51 +0000640 else if ((size_t)ihigh > self->size)
Guido van Rossum09fdf072000-03-31 01:17:07 +0000641 ihigh = self->size;
642
643 if (! (PyString_Check(v)) ) {
644 PyErr_SetString(PyExc_IndexError,
645 "mmap slice assignment must be a string");
646 return -1;
647 }
648 if ( PyString_Size(v) != (ihigh - ilow) ) {
649 PyErr_SetString(PyExc_IndexError,
650 "mmap slice assignment is wrong size");
651 return -1;
652 }
653 buf = PyString_AsString(v);
654 memcpy(self->data + ilow, buf, ihigh-ilow);
655 return 0;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000656}
657
658static int
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000659mmap_ass_item(mmap_object *self, int i, PyObject *v)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000660{
Guido van Rossum36d4f8b2000-04-10 21:34:37 +0000661 const char *buf;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000662
Guido van Rossum09fdf072000-03-31 01:17:07 +0000663 CHECK_VALID(-1);
Guido van Rossumce8e1dc2000-07-01 00:51:51 +0000664 if (i < 0 || (size_t)i >= self->size) {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000665 PyErr_SetString(PyExc_IndexError, "mmap index out of range");
666 return -1;
667 }
668 if (! (PyString_Check(v) && PyString_Size(v)==1) ) {
669 PyErr_SetString(PyExc_IndexError,
670 "mmap assignment must be single-character string");
671 return -1;
672 }
673 buf = PyString_AsString(v);
674 self->data[i] = buf[0];
675 return 0;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000676}
677
678static PySequenceMethods mmap_as_sequence = {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000679 (inquiry)mmap_length, /*sq_length*/
680 (binaryfunc)mmap_concat, /*sq_concat*/
681 (intargfunc)mmap_repeat, /*sq_repeat*/
682 (intargfunc)mmap_item, /*sq_item*/
683 (intintargfunc)mmap_slice, /*sq_slice*/
684 (intobjargproc)mmap_ass_item, /*sq_ass_item*/
685 (intintobjargproc)mmap_ass_slice, /*sq_ass_slice*/
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000686};
687
688static PyBufferProcs mmap_as_buffer = {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000689 (getreadbufferproc)mmap_buffer_getreadbuf,
690 (getwritebufferproc)mmap_buffer_getwritebuf,
691 (getsegcountproc)mmap_buffer_getsegcount,
692 (getcharbufferproc)mmap_buffer_getcharbuffer,
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000693};
694
695static PyTypeObject mmap_object_type = {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000696 PyObject_HEAD_INIT(0) /* patched in module init */
697 0, /* ob_size */
698 "mmap", /* tp_name */
699 sizeof(mmap_object), /* tp_size */
700 0, /* tp_itemsize */
701 /* methods */
702 (destructor) mmap_object_dealloc, /* tp_dealloc */
703 0, /* tp_print */
704 (getattrfunc) mmap_object_getattr, /* tp_getattr */
705 0, /* tp_setattr */
706 0, /* tp_compare */
707 0, /* tp_repr */
708 0, /* tp_as_number */
709 &mmap_as_sequence, /*tp_as_sequence*/
710 0, /*tp_as_mapping*/
711 0, /*tp_hash*/
712 0, /*tp_call*/
713 0, /*tp_str*/
714 0, /*tp_getattro*/
715 0, /*tp_setattro*/
716 &mmap_as_buffer, /*tp_as_buffer*/
717 Py_TPFLAGS_HAVE_GETCHARBUFFER, /*tp_flags*/
718 0, /*tp_doc*/
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000719};
720
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000721
722/* extract the map size from the given PyObject
723
724 The map size is restricted to [0, INT_MAX] because this is the current
725 Python limitation on object sizes. Although the mmap object *could* handle
726 a larger map size, there is no point because all the useful operations
727 (len(), slicing(), sequence indexing) are limited by a C int.
728
Thomas Wouters7e474022000-07-16 12:04:32 +0000729 Returns -1 on error, with an appropriate Python exception raised. On
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000730 success, the map size is returned. */
731static int
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000732_GetMapSize(PyObject *o)
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000733{
734 if (PyInt_Check(o)) {
735 long i = PyInt_AsLong(o);
736 if (PyErr_Occurred())
737 return -1;
738 if (i < 0)
739 goto onnegoverflow;
740 if (i > INT_MAX)
741 goto onposoverflow;
742 return (int)i;
743 }
744 else if (PyLong_Check(o)) {
745 long i = PyLong_AsLong(o);
746 if (PyErr_Occurred()) {
747 /* yes negative overflow is mistaken for positive overflow
748 but not worth the trouble to check sign of 'i' */
749 if (PyErr_ExceptionMatches(PyExc_OverflowError))
750 goto onposoverflow;
751 else
752 return -1;
753 }
754 if (i < 0)
755 goto onnegoverflow;
756 if (i > INT_MAX)
757 goto onposoverflow;
758 return (int)i;
759 }
760 else {
761 PyErr_SetString(PyExc_TypeError,
762 "map size must be an integral value");
763 return -1;
764 }
765
766onnegoverflow:
767 PyErr_SetString(PyExc_OverflowError,
768 "memory mapped size must be positive");
769 return -1;
770
771onposoverflow:
772 PyErr_SetString(PyExc_OverflowError,
773 "memory mapped size is too large (limited by C int)");
774 return -1;
775}
776
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000777#ifdef UNIX
778static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000779new_mmap_object(PyObject *self, PyObject *args, PyObject *kwdict)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000780{
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000781 mmap_object *m_obj;
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000782 PyObject *map_size_obj = NULL;
783 int map_size;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000784 int fd, flags = MAP_SHARED, prot = PROT_WRITE | PROT_READ;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000785 char *keywords[] = {"file", "size", "flags", "prot", NULL};
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000786
Guido van Rossum09fdf072000-03-31 01:17:07 +0000787 if (!PyArg_ParseTupleAndKeywords(args, kwdict,
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000788 "iO|ii", keywords,
789 &fd, &map_size_obj, &flags, &prot)
Guido van Rossum09fdf072000-03-31 01:17:07 +0000790 )
791 return NULL;
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000792 map_size = _GetMapSize(map_size_obj);
793 if (map_size < 0)
794 return NULL;
795
Guido van Rossumb18618d2000-05-03 23:44:39 +0000796 m_obj = PyObject_New (mmap_object, &mmap_object_type);
Guido van Rossum09fdf072000-03-31 01:17:07 +0000797 if (m_obj == NULL) {return NULL;}
798 m_obj->size = (size_t) map_size;
799 m_obj->pos = (size_t) 0;
Andrew M. Kuchling7b9fb922000-06-17 22:41:22 +0000800 m_obj->fd = fd;
Guido van Rossum09fdf072000-03-31 01:17:07 +0000801 m_obj->data = mmap(NULL, map_size,
802 prot, flags,
803 fd, 0);
804 if (m_obj->data == (void *)-1)
805 {
806 Py_DECREF(m_obj);
807 PyErr_SetFromErrno(mmap_module_error);
808 return NULL;
809 }
810 return (PyObject *)m_obj;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000811}
812#endif /* UNIX */
813
814#ifdef MS_WIN32
815static PyObject *
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000816new_mmap_object(PyObject *self, PyObject *args)
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000817{
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000818 mmap_object *m_obj;
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000819 PyObject *map_size_obj = NULL;
820 int map_size;
Fredrik Lundh54cf3dc2000-07-08 22:05:01 +0000821 char *tagname = "";
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000822
Guido van Rossum09fdf072000-03-31 01:17:07 +0000823 DWORD dwErr = 0;
824 int fileno;
Mark Hammond071864a2000-07-30 02:46:26 +0000825 HANDLE fh = 0;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000826
Guido van Rossum09fdf072000-03-31 01:17:07 +0000827 /* Patch the object type */
828 mmap_object_type.ob_type = &PyType_Type;
829
830 if (!PyArg_ParseTuple(args,
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000831 "iO|z",
Guido van Rossum09fdf072000-03-31 01:17:07 +0000832 &fileno,
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000833 &map_size_obj,
Guido van Rossum09fdf072000-03-31 01:17:07 +0000834 &tagname)
835 )
836 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000837
Andrew M. Kuchling70d27422000-06-18 04:45:14 +0000838 map_size = _GetMapSize(map_size_obj);
839 if (map_size < 0)
840 return NULL;
841
Guido van Rossum09fdf072000-03-31 01:17:07 +0000842 /* if an actual filename has been specified */
843 if (fileno != 0) {
Mark Hammond071864a2000-07-30 02:46:26 +0000844 fh = (HANDLE)_get_osfhandle(fileno);
845 if (fh==(HANDLE)-1) {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000846 PyErr_SetFromErrno(mmap_module_error);
847 return NULL;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000848 }
Fred Drake1ef4e2d2000-04-05 14:15:31 +0000849 /* Win9x appears to need us seeked to zero */
850 fseek(&_iob[fileno], 0, SEEK_SET);
Guido van Rossum09fdf072000-03-31 01:17:07 +0000851 }
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000852
Guido van Rossumb18618d2000-05-03 23:44:39 +0000853 m_obj = PyObject_New (mmap_object, &mmap_object_type);
Mark Hammond2cbed002000-07-30 02:22:43 +0000854 if (m_obj==NULL)
855 return NULL;
856 /* Set every field to an invalid marker, so we can safely
857 destruct the object in the face of failure */
858 m_obj->data = NULL;
Mark Hammond071864a2000-07-30 02:46:26 +0000859 m_obj->file_handle = INVALID_HANDLE_VALUE;
Mark Hammond2cbed002000-07-30 02:22:43 +0000860 m_obj->map_handle = INVALID_HANDLE_VALUE;
861 m_obj->tagname = NULL;
862
Guido van Rossum09fdf072000-03-31 01:17:07 +0000863 if (fh) {
Mark Hammond2cbed002000-07-30 02:22:43 +0000864 /* It is necessary to duplicate the handle, so the
865 Python code can close it on us */
866 if (!DuplicateHandle(
867 GetCurrentProcess(), /* source process handle */
Mark Hammond071864a2000-07-30 02:46:26 +0000868 fh, /* handle to be duplicated */
Mark Hammond2cbed002000-07-30 02:22:43 +0000869 GetCurrentProcess(), /* target proc handle */
870 (LPHANDLE)&m_obj->file_handle, /* result */
871 0, /* access - ignored due to options value */
872 FALSE, /* inherited by child processes? */
873 DUPLICATE_SAME_ACCESS)) { /* options */
874 dwErr = GetLastError();
875 Py_DECREF(m_obj);
876 PyErr_SetFromWindowsErr(dwErr);
877 return NULL;
878 }
Guido van Rossum09fdf072000-03-31 01:17:07 +0000879 if (!map_size) {
Mark Hammond071864a2000-07-30 02:46:26 +0000880 m_obj->size = GetFileSize (fh, NULL);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000881 } else {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000882 m_obj->size = map_size;
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000883 }
Guido van Rossum09fdf072000-03-31 01:17:07 +0000884 }
885 else {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000886 m_obj->size = map_size;
887 }
888
889 /* set the initial position */
890 m_obj->pos = (size_t) 0;
891
Mark Hammond2cbed002000-07-30 02:22:43 +0000892 /* set the tag name */
893 if (tagname != NULL) {
894 m_obj->tagname = PyMem_Malloc(strlen(tagname)+1);
895 if (m_obj->tagname == NULL) {
896 PyErr_NoMemory();
897 Py_DECREF(m_obj);
898 return NULL;
899 }
900 strcpy(m_obj->tagname, tagname);
901 }
902 else
903 m_obj->tagname = NULL;
904
Mark Hammond071864a2000-07-30 02:46:26 +0000905 m_obj->map_handle = CreateFileMapping (m_obj->file_handle,
Guido van Rossum09fdf072000-03-31 01:17:07 +0000906 NULL,
907 PAGE_READWRITE,
908 0,
909 m_obj->size,
910 tagname);
911 if (m_obj->map_handle != NULL) {
912 m_obj->data = (char *) MapViewOfFile (m_obj->map_handle,
913 FILE_MAP_WRITE,
914 0,
915 0,
916 0);
917 if (m_obj->data != NULL) {
918 return ((PyObject *) m_obj);
919 } else {
920 dwErr = GetLastError();
921 }
922 } else {
923 dwErr = GetLastError();
924 }
Mark Hammond2cbed002000-07-30 02:22:43 +0000925 Py_DECREF(m_obj);
Guido van Rossum09fdf072000-03-31 01:17:07 +0000926 PyErr_SetFromWindowsErr(dwErr);
927 return (NULL);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000928}
929#endif /* MS_WIN32 */
930
931/* List of functions exported by this module */
932static struct PyMethodDef mmap_functions[] = {
Guido van Rossum09fdf072000-03-31 01:17:07 +0000933 {"mmap", (PyCFunction) new_mmap_object,
934 METH_VARARGS|METH_KEYWORDS},
935 {NULL, NULL} /* Sentinel */
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000936};
937
938#ifdef MS_WIN32
Guido van Rossum09fdf072000-03-31 01:17:07 +0000939__declspec(dllexport) void
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000940#endif /* MS_WIN32 */
941#ifdef UNIX
942extern void
943#endif
944
945initmmap(void)
946{
Guido van Rossum09fdf072000-03-31 01:17:07 +0000947 PyObject *dict, *module;
948 module = Py_InitModule ("mmap", mmap_functions);
949 dict = PyModule_GetDict (module);
950 mmap_module_error = PyExc_EnvironmentError;
951 Py_INCREF(mmap_module_error);
952 PyDict_SetItemString (dict, "error", mmap_module_error);
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000953#ifdef PROT_EXEC
Guido van Rossum09fdf072000-03-31 01:17:07 +0000954 PyDict_SetItemString (dict, "PROT_EXEC", PyInt_FromLong(PROT_EXEC) );
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000955#endif
956#ifdef PROT_READ
Guido van Rossum09fdf072000-03-31 01:17:07 +0000957 PyDict_SetItemString (dict, "PROT_READ", PyInt_FromLong(PROT_READ) );
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000958#endif
959#ifdef PROT_WRITE
Guido van Rossum09fdf072000-03-31 01:17:07 +0000960 PyDict_SetItemString (dict, "PROT_WRITE", PyInt_FromLong(PROT_WRITE) );
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000961#endif
962
963#ifdef MAP_SHARED
Guido van Rossum09fdf072000-03-31 01:17:07 +0000964 PyDict_SetItemString (dict, "MAP_SHARED", PyInt_FromLong(MAP_SHARED) );
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000965#endif
966#ifdef MAP_PRIVATE
Guido van Rossum09fdf072000-03-31 01:17:07 +0000967 PyDict_SetItemString (dict, "MAP_PRIVATE",
968 PyInt_FromLong(MAP_PRIVATE) );
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000969#endif
970#ifdef MAP_DENYWRITE
Guido van Rossum09fdf072000-03-31 01:17:07 +0000971 PyDict_SetItemString (dict, "MAP_DENYWRITE",
972 PyInt_FromLong(MAP_DENYWRITE) );
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000973#endif
974#ifdef MAP_EXECUTABLE
Guido van Rossum09fdf072000-03-31 01:17:07 +0000975 PyDict_SetItemString (dict, "MAP_EXECUTABLE",
976 PyInt_FromLong(MAP_EXECUTABLE) );
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000977#endif
978#ifdef MAP_ANON
Guido van Rossum09fdf072000-03-31 01:17:07 +0000979 PyDict_SetItemString (dict, "MAP_ANON", PyInt_FromLong(MAP_ANON) );
980 PyDict_SetItemString (dict, "MAP_ANONYMOUS",
981 PyInt_FromLong(MAP_ANON) );
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000982#endif
983
984#ifdef UNIX
Guido van Rossum09fdf072000-03-31 01:17:07 +0000985 PyDict_SetItemString (dict, "PAGESIZE",
986 PyInt_FromLong( (long)getpagesize() ) );
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000987#endif
Guido van Rossum09fdf072000-03-31 01:17:07 +0000988#ifdef MS_WIN32
989 {
990 SYSTEM_INFO si;
991 GetSystemInfo(&si);
992 PyDict_SetItemString (dict, "PAGESIZE",
993 PyInt_FromLong( si.dwPageSize ) );
994 }
995#endif /* MS_WIN32 */
Andrew M. Kuchling1ed7d2d2000-03-30 21:14:30 +0000996
997}
Andrew M. Kuchling961fe172000-06-03 19:41:42 +0000998