111
111
mmap_object_dealloc(mmap_object *m_obj)
113
113
#ifdef MS_WINDOWS
114
if (m_obj->data != NULL)
115
UnmapViewOfFile (m_obj->data);
116
if (m_obj->map_handle != NULL)
117
CloseHandle (m_obj->map_handle);
118
if (m_obj->file_handle != INVALID_HANDLE_VALUE)
119
CloseHandle (m_obj->file_handle);
121
PyMem_Free(m_obj->tagname);
114
if (m_obj->data != NULL)
115
UnmapViewOfFile (m_obj->data);
116
if (m_obj->map_handle != NULL)
117
CloseHandle (m_obj->map_handle);
118
if (m_obj->file_handle != INVALID_HANDLE_VALUE)
119
CloseHandle (m_obj->file_handle);
121
PyMem_Free(m_obj->tagname);
122
122
#endif /* MS_WINDOWS */
126
(void) close(m_obj->fd);
127
if (m_obj->data!=NULL) {
128
msync(m_obj->data, m_obj->size, MS_SYNC);
129
munmap(m_obj->data, m_obj->size);
126
(void) close(m_obj->fd);
127
if (m_obj->data!=NULL) {
128
msync(m_obj->data, m_obj->size, MS_SYNC);
129
munmap(m_obj->data, m_obj->size);
131
131
#endif /* UNIX */
133
Py_TYPE(m_obj)->tp_free((PyObject*)m_obj);
133
Py_TYPE(m_obj)->tp_free((PyObject*)m_obj);
136
136
static PyObject *
137
137
mmap_close_method(mmap_object *self, PyObject *unused)
139
if (self->exports > 0) {
140
PyErr_SetString(PyExc_BufferError, "cannot close "\
141
"exported pointers exist");
139
if (self->exports > 0) {
140
PyErr_SetString(PyExc_BufferError, "cannot close "\
141
"exported pointers exist");
144
144
#ifdef MS_WINDOWS
145
/* For each resource we maintain, we need to check
146
the value is valid, and if so, free the resource
147
and set the member value to an invalid value so
148
the dealloc does not attempt to resource clearing
150
TODO - should we check for errors in the close operations???
152
if (self->data != NULL) {
153
UnmapViewOfFile(self->data);
156
if (self->map_handle != NULL) {
157
CloseHandle(self->map_handle);
158
self->map_handle = NULL;
160
if (self->file_handle != INVALID_HANDLE_VALUE) {
161
CloseHandle(self->file_handle);
162
self->file_handle = INVALID_HANDLE_VALUE;
145
/* For each resource we maintain, we need to check
146
the value is valid, and if so, free the resource
147
and set the member value to an invalid value so
148
the dealloc does not attempt to resource clearing
150
TODO - should we check for errors in the close operations???
152
if (self->data != NULL) {
153
UnmapViewOfFile(self->data);
156
if (self->map_handle != NULL) {
157
CloseHandle(self->map_handle);
158
self->map_handle = NULL;
160
if (self->file_handle != INVALID_HANDLE_VALUE) {
161
CloseHandle(self->file_handle);
162
self->file_handle = INVALID_HANDLE_VALUE;
164
164
#endif /* MS_WINDOWS */
168
(void) close(self->fd);
170
if (self->data != NULL) {
171
munmap(self->data, self->size);
168
(void) close(self->fd);
170
if (self->data != NULL) {
171
munmap(self->data, self->size);
180
180
#ifdef MS_WINDOWS
181
#define CHECK_VALID(err) \
183
if (self->map_handle == NULL) { \
184
PyErr_SetString(PyExc_ValueError, "mmap closed or invalid"); \
181
#define CHECK_VALID(err) \
183
if (self->map_handle == NULL) { \
184
PyErr_SetString(PyExc_ValueError, "mmap closed or invalid"); \
188
188
#endif /* MS_WINDOWS */
191
#define CHECK_VALID(err) \
193
if (self->data == NULL) { \
194
PyErr_SetString(PyExc_ValueError, "mmap closed or invalid"); \
191
#define CHECK_VALID(err) \
193
if (self->data == NULL) { \
194
PyErr_SetString(PyExc_ValueError, "mmap closed or invalid"); \
198
198
#endif /* UNIX */
200
200
static PyObject *
201
201
mmap_read_byte_method(mmap_object *self,
205
if (self->pos < self->size) {
206
char value = self->data[self->pos];
208
return Py_BuildValue("b", value);
210
PyErr_SetString(PyExc_ValueError, "read byte out of range");
205
if (self->pos < self->size) {
206
char value = self->data[self->pos];
208
return Py_BuildValue("b", value);
210
PyErr_SetString(PyExc_ValueError, "read byte out of range");
215
215
static PyObject *
216
216
mmap_read_line_method(mmap_object *self,
219
char *start = self->data+self->pos;
220
char *eof = self->data+self->size;
226
eol = memchr(start, '\n', self->size - self->pos);
230
++eol; /* we're interested in the position after the
232
result = PyBytes_FromStringAndSize(start, (eol - start));
233
self->pos += (eol - start);
219
char *start = self->data+self->pos;
220
char *eof = self->data+self->size;
226
eol = memchr(start, '\n', self->size - self->pos);
230
++eol; /* we're interested in the position after the
232
result = PyBytes_FromStringAndSize(start, (eol - start));
233
self->pos += (eol - start);
237
237
static PyObject *
238
238
mmap_read_method(mmap_object *self,
241
Py_ssize_t num_bytes, n;
245
if (!PyArg_ParseTuple(args, "n:read", &num_bytes))
248
/* silently 'adjust' out-of-range requests */
249
assert(self->size >= self->pos);
250
n = self->size - self->pos;
251
/* The difference can overflow, only if self->size is greater than
252
* PY_SSIZE_T_MAX. But then the operation cannot possibly succeed,
253
* because the mapped area and the returned string each need more
254
* than half of the addressable memory. So we clip the size, and let
255
* the code below raise MemoryError.
259
if (num_bytes < 0 || num_bytes > n) {
262
result = PyBytes_FromStringAndSize(self->data+self->pos, num_bytes);
263
self->pos += num_bytes;
241
Py_ssize_t num_bytes, n;
245
if (!PyArg_ParseTuple(args, "n:read", &num_bytes))
248
/* silently 'adjust' out-of-range requests */
249
assert(self->size >= self->pos);
250
n = self->size - self->pos;
251
/* The difference can overflow, only if self->size is greater than
252
* PY_SSIZE_T_MAX. But then the operation cannot possibly succeed,
253
* because the mapped area and the returned string each need more
254
* than half of the addressable memory. So we clip the size, and let
255
* the code below raise MemoryError.
259
if (num_bytes < 0 || num_bytes > n) {
262
result = PyBytes_FromStringAndSize(self->data+self->pos, num_bytes);
263
self->pos += num_bytes;
267
267
static PyObject *
268
268
mmap_gfind(mmap_object *self,
272
Py_ssize_t start = self->pos;
273
Py_ssize_t end = self->size;
278
if (!PyArg_ParseTuple(args, reverse ? "y#|nn:rfind" : "y#|nn:find",
279
&needle, &len, &start, &end)) {
282
const char *p, *start_p, *end_p;
283
int sign = reverse ? -1 : 1;
289
else if ((size_t)start > self->size)
296
else if ((size_t)end > self->size)
299
start_p = self->data + start;
300
end_p = self->data + end;
302
for (p = (reverse ? end_p - len : start_p);
303
(p >= start_p) && (p + len <= end_p); p += sign) {
305
for (i = 0; i < len && needle[i] == p[i]; ++i)
308
return PyLong_FromSsize_t(p - self->data);
311
return PyLong_FromLong(-1);
272
Py_ssize_t start = self->pos;
273
Py_ssize_t end = self->size;
278
if (!PyArg_ParseTuple(args, reverse ? "y#|nn:rfind" : "y#|nn:find",
279
&needle, &len, &start, &end)) {
282
const char *p, *start_p, *end_p;
283
int sign = reverse ? -1 : 1;
289
else if ((size_t)start > self->size)
296
else if ((size_t)end > self->size)
299
start_p = self->data + start;
300
end_p = self->data + end;
302
for (p = (reverse ? end_p - len : start_p);
303
(p >= start_p) && (p + len <= end_p); p += sign) {
305
for (i = 0; i < len && needle[i] == p[i]; ++i)
308
return PyLong_FromSsize_t(p - self->data);
311
return PyLong_FromLong(-1);
315
315
static PyObject *
316
316
mmap_find_method(mmap_object *self,
319
return mmap_gfind(self, args, 0);
319
return mmap_gfind(self, args, 0);
322
322
static PyObject *
323
323
mmap_rfind_method(mmap_object *self,
326
return mmap_gfind(self, args, 1);
326
return mmap_gfind(self, args, 1);
330
330
is_writable(mmap_object *self)
332
if (self->access != ACCESS_READ)
334
PyErr_Format(PyExc_TypeError, "mmap can't modify a readonly memory map.");
332
if (self->access != ACCESS_READ)
334
PyErr_Format(PyExc_TypeError, "mmap can't modify a readonly memory map.");
339
339
is_resizeable(mmap_object *self)
341
if (self->exports > 0) {
342
PyErr_SetString(PyExc_BufferError,
343
"mmap can't resize with extant buffers exported.");
346
if ((self->access == ACCESS_WRITE) || (self->access == ACCESS_DEFAULT))
348
PyErr_Format(PyExc_TypeError,
349
"mmap can't resize a readonly or copy-on-write memory map.");
341
if (self->exports > 0) {
342
PyErr_SetString(PyExc_BufferError,
343
"mmap can't resize with extant buffers exported.");
346
if ((self->access == ACCESS_WRITE) || (self->access == ACCESS_DEFAULT))
348
PyErr_Format(PyExc_TypeError,
349
"mmap can't resize a readonly or copy-on-write memory map.");
354
354
static PyObject *
355
355
mmap_write_method(mmap_object *self,
362
if (!PyArg_ParseTuple(args, "y#:write", &data, &length))
365
if (!is_writable(self))
368
if ((self->pos + length) > self->size) {
369
PyErr_SetString(PyExc_ValueError, "data out of range");
372
memcpy(self->data+self->pos, data, length);
373
self->pos = self->pos+length;
362
if (!PyArg_ParseTuple(args, "y#:write", &data, &length))
365
if (!is_writable(self))
368
if ((self->pos + length) > self->size) {
369
PyErr_SetString(PyExc_ValueError, "data out of range");
372
memcpy(self->data+self->pos, data, length);
373
self->pos = self->pos+length;
378
378
static PyObject *
379
379
mmap_write_byte_method(mmap_object *self,
385
if (!PyArg_ParseTuple(args, "b:write_byte", &value))
388
if (!is_writable(self))
391
if (self->pos < self->size) {
392
*(self->data+self->pos) = value;
398
PyErr_SetString(PyExc_ValueError, "write byte out of range");
385
if (!PyArg_ParseTuple(args, "b:write_byte", &value))
388
if (!is_writable(self))
391
if (self->pos < self->size) {
392
*(self->data+self->pos) = value;
398
PyErr_SetString(PyExc_ValueError, "write byte out of range");
403
403
static PyObject *
404
404
mmap_size_method(mmap_object *self,
409
409
#ifdef MS_WINDOWS
410
if (self->file_handle != INVALID_HANDLE_VALUE) {
413
low = GetFileSize(self->file_handle, &high);
414
if (low == INVALID_FILE_SIZE) {
415
/* It might be that the function appears to have failed,
416
when indeed its size equals INVALID_FILE_SIZE */
417
DWORD error = GetLastError();
418
if (error != NO_ERROR)
419
return PyErr_SetFromWindowsErr(error);
421
if (!high && low < LONG_MAX)
422
return PyLong_FromLong((long)low);
423
size = (((PY_LONG_LONG)high)<<32) + low;
424
return PyLong_FromLongLong(size);
426
return PyLong_FromSsize_t(self->size);
410
if (self->file_handle != INVALID_HANDLE_VALUE) {
413
low = GetFileSize(self->file_handle, &high);
414
if (low == INVALID_FILE_SIZE) {
415
/* It might be that the function appears to have failed,
416
when indeed its size equals INVALID_FILE_SIZE */
417
DWORD error = GetLastError();
418
if (error != NO_ERROR)
419
return PyErr_SetFromWindowsErr(error);
421
if (!high && low < LONG_MAX)
422
return PyLong_FromLong((long)low);
423
size = (((PY_LONG_LONG)high)<<32) + low;
424
return PyLong_FromLongLong(size);
426
return PyLong_FromSsize_t(self->size);
428
428
#endif /* MS_WINDOWS */
433
if (-1 == fstat(self->fd, &buf)) {
434
PyErr_SetFromErrno(mmap_module_error);
437
return PyLong_FromSsize_t(buf.st_size);
433
if (-1 == fstat(self->fd, &buf)) {
434
PyErr_SetFromErrno(mmap_module_error);
437
return PyLong_FromSsize_t(buf.st_size);
439
439
#endif /* UNIX */
451
451
static PyObject *
452
452
mmap_resize_method(mmap_object *self,
457
if (!PyArg_ParseTuple(args, "n:resize", &new_size) ||
458
!is_resizeable(self)) {
457
if (!PyArg_ParseTuple(args, "n:resize", &new_size) ||
458
!is_resizeable(self)) {
460
460
#ifdef MS_WINDOWS
463
DWORD off_hi, off_lo, newSizeLow, newSizeHigh;
464
/* First, unmap the file view */
465
UnmapViewOfFile(self->data);
467
/* Close the mapping object */
468
CloseHandle(self->map_handle);
469
self->map_handle = NULL;
470
/* Move to the desired EOF position */
463
DWORD off_hi, off_lo, newSizeLow, newSizeHigh;
464
/* First, unmap the file view */
465
UnmapViewOfFile(self->data);
467
/* Close the mapping object */
468
CloseHandle(self->map_handle);
469
self->map_handle = NULL;
470
/* Move to the desired EOF position */
471
471
#if SIZEOF_SIZE_T > 4
472
newSizeHigh = (DWORD)((self->offset + new_size) >> 32);
473
newSizeLow = (DWORD)((self->offset + new_size) & 0xFFFFFFFF);
474
off_hi = (DWORD)(self->offset >> 32);
475
off_lo = (DWORD)(self->offset & 0xFFFFFFFF);
472
newSizeHigh = (DWORD)((self->offset + new_size) >> 32);
473
newSizeLow = (DWORD)((self->offset + new_size) & 0xFFFFFFFF);
474
off_hi = (DWORD)(self->offset >> 32);
475
off_lo = (DWORD)(self->offset & 0xFFFFFFFF);
478
newSizeLow = (DWORD)(self->offset + new_size);
480
off_lo = (DWORD)self->offset;
478
newSizeLow = (DWORD)(self->offset + new_size);
480
off_lo = (DWORD)self->offset;
482
SetFilePointer(self->file_handle,
483
newSizeLow, &newSizeHigh, FILE_BEGIN);
484
/* Change the size of the file */
485
SetEndOfFile(self->file_handle);
486
/* Create another mapping object and remap the file view */
487
self->map_handle = CreateFileMapping(
494
if (self->map_handle != NULL) {
495
self->data = (char *) MapViewOfFile(self->map_handle,
500
if (self->data != NULL) {
501
self->size = new_size;
505
dwErrCode = GetLastError();
506
CloseHandle(self->map_handle);
507
self->map_handle = NULL;
510
dwErrCode = GetLastError();
512
PyErr_SetFromWindowsErr(dwErrCode);
482
SetFilePointer(self->file_handle,
483
newSizeLow, &newSizeHigh, FILE_BEGIN);
484
/* Change the size of the file */
485
SetEndOfFile(self->file_handle);
486
/* Create another mapping object and remap the file view */
487
self->map_handle = CreateFileMapping(
494
if (self->map_handle != NULL) {
495
self->data = (char *) MapViewOfFile(self->map_handle,
500
if (self->data != NULL) {
501
self->size = new_size;
505
dwErrCode = GetLastError();
506
CloseHandle(self->map_handle);
507
self->map_handle = NULL;
510
dwErrCode = GetLastError();
512
PyErr_SetFromWindowsErr(dwErrCode);
514
514
#endif /* MS_WINDOWS */
517
517
#ifndef HAVE_MREMAP
519
PyErr_SetString(PyExc_SystemError,
520
"mmap: resizing not available--no mremap()");
519
PyErr_SetString(PyExc_SystemError,
520
"mmap: resizing not available--no mremap()");
526
if (ftruncate(self->fd, self->offset + new_size) == -1) {
527
PyErr_SetFromErrno(mmap_module_error);
526
if (ftruncate(self->fd, self->offset + new_size) == -1) {
527
PyErr_SetFromErrno(mmap_module_error);
531
531
#ifdef MREMAP_MAYMOVE
532
newmap = mremap(self->data, self->size, new_size, MREMAP_MAYMOVE);
532
newmap = mremap(self->data, self->size, new_size, MREMAP_MAYMOVE);
534
#if defined(__NetBSD__)
535
newmap = mremap(self->data, self->size, self->data, new_size, 0);
537
newmap = mremap(self->data, self->size, new_size, 0);
538
#endif /* __NetBSD__ */
534
#if defined(__NetBSD__)
535
newmap = mremap(self->data, self->size, self->data, new_size, 0);
537
newmap = mremap(self->data, self->size, new_size, 0);
538
#endif /* __NetBSD__ */
540
if (newmap == (void *)-1)
542
PyErr_SetFromErrno(mmap_module_error);
546
self->size = new_size;
540
if (newmap == (void *)-1)
542
PyErr_SetFromErrno(mmap_module_error);
546
self->size = new_size;
549
549
#endif /* HAVE_MREMAP */
550
550
#endif /* UNIX */
554
554
static PyObject *
555
555
mmap_tell_method(mmap_object *self, PyObject *unused)
558
return PyLong_FromSize_t(self->pos);
558
return PyLong_FromSize_t(self->pos);
561
561
static PyObject *
562
562
mmap_flush_method(mmap_object *self, PyObject *args)
564
Py_ssize_t offset = 0;
565
Py_ssize_t size = self->size;
567
if (!PyArg_ParseTuple(args, "|nn:flush", &offset, &size))
569
if ((size_t)(offset + size) > self->size) {
570
PyErr_SetString(PyExc_ValueError, "flush values out of range");
564
Py_ssize_t offset = 0;
565
Py_ssize_t size = self->size;
567
if (!PyArg_ParseTuple(args, "|nn:flush", &offset, &size))
569
if ((size_t)(offset + size) > self->size) {
570
PyErr_SetString(PyExc_ValueError, "flush values out of range");
573
573
#ifdef MS_WINDOWS
574
return PyLong_FromLong((long) FlushViewOfFile(self->data+offset, size));
574
return PyLong_FromLong((long) FlushViewOfFile(self->data+offset, size));
575
575
#elif defined(UNIX)
576
/* XXX semantics of return value? */
577
/* XXX flags for msync? */
578
if (-1 == msync(self->data + offset, size, MS_SYNC)) {
579
PyErr_SetFromErrno(mmap_module_error);
582
return PyLong_FromLong(0);
576
/* XXX semantics of return value? */
577
/* XXX flags for msync? */
578
if (-1 == msync(self->data + offset, size, MS_SYNC)) {
579
PyErr_SetFromErrno(mmap_module_error);
582
return PyLong_FromLong(0);
584
PyErr_SetString(PyExc_ValueError, "flush not supported on this system");
584
PyErr_SetString(PyExc_ValueError, "flush not supported on this system");
589
589
static PyObject *
590
590
mmap_seek_method(mmap_object *self, PyObject *args)
595
if (!PyArg_ParseTuple(args, "n|i:seek", &dist, &how))
600
case 0: /* relative to start */
605
case 1: /* relative to current position */
606
if ((Py_ssize_t)self->pos + dist < 0)
608
where = self->pos + dist;
610
case 2: /* relative to end */
611
if ((Py_ssize_t)self->size + dist < 0)
613
where = self->size + dist;
616
PyErr_SetString(PyExc_ValueError, "unknown seek type");
619
if (where > self->size)
595
if (!PyArg_ParseTuple(args, "n|i:seek", &dist, &how))
600
case 0: /* relative to start */
605
case 1: /* relative to current position */
606
if ((Py_ssize_t)self->pos + dist < 0)
608
where = self->pos + dist;
610
case 2: /* relative to end */
611
if ((Py_ssize_t)self->size + dist < 0)
613
where = self->size + dist;
616
PyErr_SetString(PyExc_ValueError, "unknown seek type");
619
if (where > self->size)
627
PyErr_SetString(PyExc_ValueError, "seek out of range");
627
PyErr_SetString(PyExc_ValueError, "seek out of range");
631
631
static PyObject *
632
632
mmap_move_method(mmap_object *self, PyObject *args)
634
unsigned long dest, src, cnt;
636
if (!PyArg_ParseTuple(args, "kkk:move", &dest, &src, &cnt) ||
637
!is_writable(self)) {
640
/* bounds check the values */
641
if (cnt < 0 || (cnt + dest) < cnt || (cnt + src) < cnt ||
642
src < 0 || src > self->size || (src + cnt) > self->size ||
643
dest < 0 || dest > self->size || (dest + cnt) > self->size) {
644
PyErr_SetString(PyExc_ValueError,
645
"source, destination, or count out of range");
648
memmove(self->data+dest, self->data+src, cnt);
634
unsigned long dest, src, cnt;
636
if (!PyArg_ParseTuple(args, "kkk:move", &dest, &src, &cnt) ||
637
!is_writable(self)) {
640
/* bounds check the values */
641
if (cnt < 0 || (cnt + dest) < cnt || (cnt + src) < cnt ||
642
src < 0 || src > self->size || (src + cnt) > self->size ||
643
dest < 0 || dest > self->size || (dest + cnt) > self->size) {
644
PyErr_SetString(PyExc_ValueError,
645
"source, destination, or count out of range");
648
memmove(self->data+dest, self->data+src, cnt);
654
654
static struct PyMethodDef mmap_object_methods[] = {
655
{"close", (PyCFunction) mmap_close_method, METH_NOARGS},
656
{"find", (PyCFunction) mmap_find_method, METH_VARARGS},
657
{"rfind", (PyCFunction) mmap_rfind_method, METH_VARARGS},
658
{"flush", (PyCFunction) mmap_flush_method, METH_VARARGS},
659
{"move", (PyCFunction) mmap_move_method, METH_VARARGS},
660
{"read", (PyCFunction) mmap_read_method, METH_VARARGS},
661
{"read_byte", (PyCFunction) mmap_read_byte_method, METH_NOARGS},
662
{"readline", (PyCFunction) mmap_read_line_method, METH_NOARGS},
663
{"resize", (PyCFunction) mmap_resize_method, METH_VARARGS},
664
{"seek", (PyCFunction) mmap_seek_method, METH_VARARGS},
665
{"size", (PyCFunction) mmap_size_method, METH_NOARGS},
666
{"tell", (PyCFunction) mmap_tell_method, METH_NOARGS},
667
{"write", (PyCFunction) mmap_write_method, METH_VARARGS},
668
{"write_byte", (PyCFunction) mmap_write_byte_method, METH_VARARGS},
669
{NULL, NULL} /* sentinel */
655
{"close", (PyCFunction) mmap_close_method, METH_NOARGS},
656
{"find", (PyCFunction) mmap_find_method, METH_VARARGS},
657
{"rfind", (PyCFunction) mmap_rfind_method, METH_VARARGS},
658
{"flush", (PyCFunction) mmap_flush_method, METH_VARARGS},
659
{"move", (PyCFunction) mmap_move_method, METH_VARARGS},
660
{"read", (PyCFunction) mmap_read_method, METH_VARARGS},
661
{"read_byte", (PyCFunction) mmap_read_byte_method, METH_NOARGS},
662
{"readline", (PyCFunction) mmap_read_line_method, METH_NOARGS},
663
{"resize", (PyCFunction) mmap_resize_method, METH_VARARGS},
664
{"seek", (PyCFunction) mmap_seek_method, METH_VARARGS},
665
{"size", (PyCFunction) mmap_size_method, METH_NOARGS},
666
{"tell", (PyCFunction) mmap_tell_method, METH_NOARGS},
667
{"write", (PyCFunction) mmap_write_method, METH_VARARGS},
668
{"write_byte", (PyCFunction) mmap_write_byte_method, METH_VARARGS},
669
{NULL, NULL} /* sentinel */
672
672
/* Functions for treating an mmap'ed file as a buffer */
675
675
mmap_buffer_getbuf(mmap_object *self, Py_buffer *view, int flags)
678
if (PyBuffer_FillInfo(view, (PyObject*)self, self->data, self->size,
679
(self->access == ACCESS_READ), flags) < 0)
678
if (PyBuffer_FillInfo(view, (PyObject*)self, self->data, self->size,
679
(self->access == ACCESS_READ), flags) < 0)
686
686
mmap_buffer_releasebuf(mmap_object *self, Py_buffer *view)
691
691
static Py_ssize_t
692
692
mmap_length(mmap_object *self)
698
698
static PyObject *
699
699
mmap_item(mmap_object *self, Py_ssize_t i)
702
if (i < 0 || (size_t)i >= self->size) {
703
PyErr_SetString(PyExc_IndexError, "mmap index out of range");
706
return PyBytes_FromStringAndSize(self->data + i, 1);
702
if (i < 0 || (size_t)i >= self->size) {
703
PyErr_SetString(PyExc_IndexError, "mmap index out of range");
706
return PyBytes_FromStringAndSize(self->data + i, 1);
709
709
static PyObject *
710
710
mmap_subscript(mmap_object *self, PyObject *item)
713
if (PyIndex_Check(item)) {
714
Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
715
if (i == -1 && PyErr_Occurred())
719
if (i < 0 || (size_t)i >= self->size) {
720
PyErr_SetString(PyExc_IndexError,
721
"mmap index out of range");
724
return PyLong_FromLong(Py_CHARMASK(self->data[i]));
726
else if (PySlice_Check(item)) {
727
Py_ssize_t start, stop, step, slicelen;
729
if (PySlice_GetIndicesEx((PySliceObject *)item, self->size,
730
&start, &stop, &step, &slicelen) < 0) {
735
return PyBytes_FromStringAndSize("", 0);
737
return PyBytes_FromStringAndSize(self->data + start,
740
char *result_buf = (char *)PyMem_Malloc(slicelen);
744
if (result_buf == NULL)
745
return PyErr_NoMemory();
746
for (cur = start, i = 0; i < slicelen;
748
result_buf[i] = self->data[cur];
750
result = PyBytes_FromStringAndSize(result_buf,
752
PyMem_Free(result_buf);
757
PyErr_SetString(PyExc_TypeError,
758
"mmap indices must be integers");
713
if (PyIndex_Check(item)) {
714
Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
715
if (i == -1 && PyErr_Occurred())
719
if (i < 0 || (size_t)i >= self->size) {
720
PyErr_SetString(PyExc_IndexError,
721
"mmap index out of range");
724
return PyLong_FromLong(Py_CHARMASK(self->data[i]));
726
else if (PySlice_Check(item)) {
727
Py_ssize_t start, stop, step, slicelen;
729
if (PySlice_GetIndicesEx((PySliceObject *)item, self->size,
730
&start, &stop, &step, &slicelen) < 0) {
735
return PyBytes_FromStringAndSize("", 0);
737
return PyBytes_FromStringAndSize(self->data + start,
740
char *result_buf = (char *)PyMem_Malloc(slicelen);
744
if (result_buf == NULL)
745
return PyErr_NoMemory();
746
for (cur = start, i = 0; i < slicelen;
748
result_buf[i] = self->data[cur];
750
result = PyBytes_FromStringAndSize(result_buf,
752
PyMem_Free(result_buf);
757
PyErr_SetString(PyExc_TypeError,
758
"mmap indices must be integers");
763
763
static PyObject *
764
764
mmap_concat(mmap_object *self, PyObject *bb)
767
PyErr_SetString(PyExc_SystemError,
768
"mmaps don't support concatenation");
767
PyErr_SetString(PyExc_SystemError,
768
"mmaps don't support concatenation");
772
772
static PyObject *
773
773
mmap_repeat(mmap_object *self, Py_ssize_t n)
776
PyErr_SetString(PyExc_SystemError,
777
"mmaps don't support repeat operation");
776
PyErr_SetString(PyExc_SystemError,
777
"mmaps don't support repeat operation");
782
782
mmap_ass_item(mmap_object *self, Py_ssize_t i, PyObject *v)
787
if (i < 0 || (size_t)i >= self->size) {
788
PyErr_SetString(PyExc_IndexError, "mmap index out of range");
792
PyErr_SetString(PyExc_TypeError,
793
"mmap object doesn't support item deletion");
796
if (! (PyBytes_Check(v) && PyBytes_Size(v)==1) ) {
797
PyErr_SetString(PyExc_IndexError,
798
"mmap assignment must be length-1 bytes()");
801
if (!is_writable(self))
803
buf = PyBytes_AsString(v);
804
self->data[i] = buf[0];
787
if (i < 0 || (size_t)i >= self->size) {
788
PyErr_SetString(PyExc_IndexError, "mmap index out of range");
792
PyErr_SetString(PyExc_TypeError,
793
"mmap object doesn't support item deletion");
796
if (! (PyBytes_Check(v) && PyBytes_Size(v)==1) ) {
797
PyErr_SetString(PyExc_IndexError,
798
"mmap assignment must be length-1 bytes()");
801
if (!is_writable(self))
803
buf = PyBytes_AsString(v);
804
self->data[i] = buf[0];
809
809
mmap_ass_subscript(mmap_object *self, PyObject *item, PyObject *value)
813
if (!is_writable(self))
816
if (PyIndex_Check(item)) {
817
Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
820
if (i == -1 && PyErr_Occurred())
824
if (i < 0 || (size_t)i >= self->size) {
825
PyErr_SetString(PyExc_IndexError,
826
"mmap index out of range");
830
PyErr_SetString(PyExc_TypeError,
831
"mmap doesn't support item deletion");
834
if (!PyIndex_Check(value)) {
835
PyErr_SetString(PyExc_TypeError,
836
"mmap item value must be an int");
839
v = PyNumber_AsSsize_t(value, PyExc_TypeError);
840
if (v == -1 && PyErr_Occurred())
842
if (v < 0 || v > 255) {
843
PyErr_SetString(PyExc_ValueError,
844
"mmap item value must be "
851
else if (PySlice_Check(item)) {
852
Py_ssize_t start, stop, step, slicelen;
855
if (PySlice_GetIndicesEx((PySliceObject *)item,
856
self->size, &start, &stop,
857
&step, &slicelen) < 0) {
861
PyErr_SetString(PyExc_TypeError,
862
"mmap object doesn't support slice deletion");
865
if (PyObject_GetBuffer(value, &vbuf, PyBUF_SIMPLE) < 0)
867
if (vbuf.len != slicelen) {
868
PyErr_SetString(PyExc_IndexError,
869
"mmap slice assignment is wrong size");
870
PyBuffer_Release(&vbuf);
876
else if (step == 1) {
877
memcpy(self->data + start, vbuf.buf, slicelen);
882
for (cur = start, i = 0;
886
self->data[cur] = ((char *)vbuf.buf)[i];
889
PyBuffer_Release(&vbuf);
893
PyErr_SetString(PyExc_TypeError,
894
"mmap indices must be integer");
813
if (!is_writable(self))
816
if (PyIndex_Check(item)) {
817
Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
820
if (i == -1 && PyErr_Occurred())
824
if (i < 0 || (size_t)i >= self->size) {
825
PyErr_SetString(PyExc_IndexError,
826
"mmap index out of range");
830
PyErr_SetString(PyExc_TypeError,
831
"mmap doesn't support item deletion");
834
if (!PyIndex_Check(value)) {
835
PyErr_SetString(PyExc_TypeError,
836
"mmap item value must be an int");
839
v = PyNumber_AsSsize_t(value, PyExc_TypeError);
840
if (v == -1 && PyErr_Occurred())
842
if (v < 0 || v > 255) {
843
PyErr_SetString(PyExc_ValueError,
844
"mmap item value must be "
851
else if (PySlice_Check(item)) {
852
Py_ssize_t start, stop, step, slicelen;
855
if (PySlice_GetIndicesEx((PySliceObject *)item,
856
self->size, &start, &stop,
857
&step, &slicelen) < 0) {
861
PyErr_SetString(PyExc_TypeError,
862
"mmap object doesn't support slice deletion");
865
if (PyObject_GetBuffer(value, &vbuf, PyBUF_SIMPLE) < 0)
867
if (vbuf.len != slicelen) {
868
PyErr_SetString(PyExc_IndexError,
869
"mmap slice assignment is wrong size");
870
PyBuffer_Release(&vbuf);
876
else if (step == 1) {
877
memcpy(self->data + start, vbuf.buf, slicelen);
882
for (cur = start, i = 0;
886
self->data[cur] = ((char *)vbuf.buf)[i];
889
PyBuffer_Release(&vbuf);
893
PyErr_SetString(PyExc_TypeError,
894
"mmap indices must be integer");
899
899
static PySequenceMethods mmap_as_sequence = {
900
(lenfunc)mmap_length, /*sq_length*/
901
(binaryfunc)mmap_concat, /*sq_concat*/
902
(ssizeargfunc)mmap_repeat, /*sq_repeat*/
903
(ssizeargfunc)mmap_item, /*sq_item*/
905
(ssizeobjargproc)mmap_ass_item, /*sq_ass_item*/
900
(lenfunc)mmap_length, /*sq_length*/
901
(binaryfunc)mmap_concat, /*sq_concat*/
902
(ssizeargfunc)mmap_repeat, /*sq_repeat*/
903
(ssizeargfunc)mmap_item, /*sq_item*/
905
(ssizeobjargproc)mmap_ass_item, /*sq_ass_item*/
909
909
static PyMappingMethods mmap_as_mapping = {
910
(lenfunc)mmap_length,
911
(binaryfunc)mmap_subscript,
912
(objobjargproc)mmap_ass_subscript,
910
(lenfunc)mmap_length,
911
(binaryfunc)mmap_subscript,
912
(objobjargproc)mmap_ass_subscript,
915
915
static PyBufferProcs mmap_as_buffer = {
916
(getbufferproc)mmap_buffer_getbuf,
917
(releasebufferproc)mmap_buffer_releasebuf,
916
(getbufferproc)mmap_buffer_getbuf,
917
(releasebufferproc)mmap_buffer_releasebuf,
920
920
static PyObject *
1019
1019
new_mmap_object(PyTypeObject *type, PyObject *args, PyObject *kwdict)
1021
1021
#ifdef HAVE_FSTAT
1025
PyObject *map_size_obj = NULL, *offset_obj = NULL;
1026
Py_ssize_t map_size, offset;
1027
int fd, flags = MAP_SHARED, prot = PROT_WRITE | PROT_READ;
1029
int access = (int)ACCESS_DEFAULT;
1030
static char *keywords[] = {"fileno", "length",
1032
"access", "offset", NULL};
1034
if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iO|iiiO", keywords,
1035
&fd, &map_size_obj, &flags, &prot,
1036
&access, &offset_obj))
1038
map_size = _GetMapSize(map_size_obj, "size");
1041
offset = _GetMapSize(offset_obj, "offset");
1045
if ((access != (int)ACCESS_DEFAULT) &&
1046
((flags != MAP_SHARED) || (prot != (PROT_WRITE | PROT_READ))))
1047
return PyErr_Format(PyExc_ValueError,
1048
"mmap can't specify both access and flags, prot.");
1049
switch ((access_mode)access) {
1056
prot = PROT_READ | PROT_WRITE;
1059
flags = MAP_PRIVATE;
1060
prot = PROT_READ | PROT_WRITE;
1062
case ACCESS_DEFAULT:
1063
/* use the specified or default values of flags and prot */
1066
return PyErr_Format(PyExc_ValueError,
1067
"mmap invalid access parameter.");
1025
PyObject *map_size_obj = NULL, *offset_obj = NULL;
1026
Py_ssize_t map_size, offset;
1027
int fd, flags = MAP_SHARED, prot = PROT_WRITE | PROT_READ;
1029
int access = (int)ACCESS_DEFAULT;
1030
static char *keywords[] = {"fileno", "length",
1032
"access", "offset", NULL};
1034
if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iO|iiiO", keywords,
1035
&fd, &map_size_obj, &flags, &prot,
1036
&access, &offset_obj))
1038
map_size = _GetMapSize(map_size_obj, "size");
1041
offset = _GetMapSize(offset_obj, "offset");
1045
if ((access != (int)ACCESS_DEFAULT) &&
1046
((flags != MAP_SHARED) || (prot != (PROT_WRITE | PROT_READ))))
1047
return PyErr_Format(PyExc_ValueError,
1048
"mmap can't specify both access and flags, prot.");
1049
switch ((access_mode)access) {
1056
prot = PROT_READ | PROT_WRITE;
1059
flags = MAP_PRIVATE;
1060
prot = PROT_READ | PROT_WRITE;
1062
case ACCESS_DEFAULT:
1063
/* use the specified or default values of flags and prot */
1066
return PyErr_Format(PyExc_ValueError,
1067
"mmap invalid access parameter.");
1070
1070
if (prot == PROT_READ) {
1071
access = ACCESS_READ;
1071
access = ACCESS_READ;
1074
1074
#ifdef HAVE_FSTAT
1076
/* on OpenVMS we must ensure that all bytes are written to the file */
1076
/* on OpenVMS we must ensure that all bytes are written to the file */
1081
if (fd != -1 && fstat(fd, &st) == 0 && S_ISREG(st.st_mode)) {
1082
if (map_size == 0) {
1083
map_size = st.st_size;
1084
} else if ((size_t)offset + (size_t)map_size > st.st_size) {
1085
PyErr_SetString(PyExc_ValueError,
1086
"mmap length is greater than file size");
1081
if (fd != -1 && fstat(fd, &st) == 0 && S_ISREG(st.st_mode)) {
1082
if (map_size == 0) {
1083
map_size = st.st_size;
1084
} else if ((size_t)offset + (size_t)map_size > st.st_size) {
1085
PyErr_SetString(PyExc_ValueError,
1086
"mmap length is greater than file size");
1091
m_obj = (mmap_object *)type->tp_alloc(type, 0);
1092
if (m_obj == NULL) {return NULL;}
1094
m_obj->size = (size_t) map_size;
1095
m_obj->pos = (size_t) 0;
1097
m_obj->offset = offset;
1100
/* Assume the caller wants to map anonymous memory.
1101
This is the same behaviour as Windows. mmap.mmap(-1, size)
1102
on both Windows and Unix map anonymous memory.
1091
m_obj = (mmap_object *)type->tp_alloc(type, 0);
1092
if (m_obj == NULL) {return NULL;}
1094
m_obj->size = (size_t) map_size;
1095
m_obj->pos = (size_t) 0;
1097
m_obj->offset = offset;
1100
/* Assume the caller wants to map anonymous memory.
1101
This is the same behaviour as Windows. mmap.mmap(-1, size)
1102
on both Windows and Unix map anonymous memory.
1104
1104
#ifdef MAP_ANONYMOUS
1105
/* BSD way to map anonymous memory */
1106
flags |= MAP_ANONYMOUS;
1105
/* BSD way to map anonymous memory */
1106
flags |= MAP_ANONYMOUS;
1108
/* SVR4 method to map anonymous memory is to open /dev/zero */
1109
fd = devzero = open("/dev/zero", O_RDWR);
1110
if (devzero == -1) {
1112
PyErr_SetFromErrno(mmap_module_error);
1108
/* SVR4 method to map anonymous memory is to open /dev/zero */
1109
fd = devzero = open("/dev/zero", O_RDWR);
1110
if (devzero == -1) {
1112
PyErr_SetFromErrno(mmap_module_error);
1117
m_obj->fd = dup(fd);
1118
if (m_obj->fd == -1) {
1120
PyErr_SetFromErrno(mmap_module_error);
1125
m_obj->data = mmap(NULL, map_size,
1129
if (devzero != -1) {
1133
if (m_obj->data == (char *)-1) {
1136
PyErr_SetFromErrno(mmap_module_error);
1139
m_obj->access = (access_mode)access;
1140
return (PyObject *)m_obj;
1117
m_obj->fd = dup(fd);
1118
if (m_obj->fd == -1) {
1120
PyErr_SetFromErrno(mmap_module_error);
1125
m_obj->data = mmap(NULL, map_size,
1129
if (devzero != -1) {
1133
if (m_obj->data == (char *)-1) {
1136
PyErr_SetFromErrno(mmap_module_error);
1139
m_obj->access = (access_mode)access;
1140
return (PyObject *)m_obj;
1142
1142
#endif /* UNIX */
1145
1145
static PyObject *
1146
1146
new_mmap_object(PyTypeObject *type, PyObject *args, PyObject *kwdict)
1149
PyObject *map_size_obj = NULL, *offset_obj = NULL;
1150
Py_ssize_t map_size, offset;
1151
DWORD off_hi; /* upper 32 bits of offset */
1152
DWORD off_lo; /* lower 32 bits of offset */
1153
DWORD size_hi; /* upper 32 bits of size */
1154
DWORD size_lo; /* lower 32 bits of size */
1159
int access = (access_mode)ACCESS_DEFAULT;
1160
DWORD flProtect, dwDesiredAccess;
1161
static char *keywords[] = { "fileno", "length",
1163
"access", "offset", NULL };
1165
if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iO|ziO", keywords,
1166
&fileno, &map_size_obj,
1167
&tagname, &access, &offset_obj)) {
1171
switch((access_mode)access) {
1173
flProtect = PAGE_READONLY;
1174
dwDesiredAccess = FILE_MAP_READ;
1176
case ACCESS_DEFAULT: case ACCESS_WRITE:
1177
flProtect = PAGE_READWRITE;
1178
dwDesiredAccess = FILE_MAP_WRITE;
1181
flProtect = PAGE_WRITECOPY;
1182
dwDesiredAccess = FILE_MAP_COPY;
1185
return PyErr_Format(PyExc_ValueError,
1186
"mmap invalid access parameter.");
1189
map_size = _GetMapSize(map_size_obj, "size");
1192
offset = _GetMapSize(offset_obj, "offset");
1196
/* assume -1 and 0 both mean invalid filedescriptor
1197
to 'anonymously' map memory.
1198
XXX: fileno == 0 is a valid fd, but was accepted prior to 2.5.
1199
XXX: Should this code be added?
1201
PyErr_WarnEx(PyExc_DeprecationWarning,
1202
"don't use 0 for anonymous memory",
1205
if (fileno != -1 && fileno != 0) {
1206
fh = (HANDLE)_get_osfhandle(fileno);
1207
if (fh==(HANDLE)-1) {
1208
PyErr_SetFromErrno(mmap_module_error);
1211
/* Win9x appears to need us seeked to zero */
1212
lseek(fileno, 0, SEEK_SET);
1215
m_obj = (mmap_object *)type->tp_alloc(type, 0);
1218
/* Set every field to an invalid marker, so we can safely
1219
destruct the object in the face of failure */
1221
m_obj->file_handle = INVALID_HANDLE_VALUE;
1222
m_obj->map_handle = NULL;
1223
m_obj->tagname = NULL;
1224
m_obj->offset = offset;
1227
/* It is necessary to duplicate the handle, so the
1228
Python code can close it on us */
1229
if (!DuplicateHandle(
1230
GetCurrentProcess(), /* source process handle */
1231
fh, /* handle to be duplicated */
1232
GetCurrentProcess(), /* target proc handle */
1233
(LPHANDLE)&m_obj->file_handle, /* result */
1234
0, /* access - ignored due to options value */
1235
FALSE, /* inherited by child processes? */
1236
DUPLICATE_SAME_ACCESS)) { /* options */
1237
dwErr = GetLastError();
1239
PyErr_SetFromWindowsErr(dwErr);
1244
low = GetFileSize(fh, &high);
1245
/* low might just happen to have the value INVALID_FILE_SIZE;
1246
so we need to check the last error also. */
1247
if (low == INVALID_FILE_SIZE &&
1248
(dwErr = GetLastError()) != NO_ERROR) {
1250
return PyErr_SetFromWindowsErr(dwErr);
1253
#if SIZEOF_SIZE_T > 4
1254
m_obj->size = (((size_t)high)<<32) + low;
1257
/* File is too large to map completely */
1258
m_obj->size = (size_t)-1;
1263
m_obj->size = map_size;
1267
m_obj->size = map_size;
1270
/* set the initial position */
1271
m_obj->pos = (size_t) 0;
1274
/* set the tag name */
1275
if (tagname != NULL && *tagname != '\0') {
1276
m_obj->tagname = PyMem_Malloc(strlen(tagname)+1);
1277
if (m_obj->tagname == NULL) {
1282
strcpy(m_obj->tagname, tagname);
1285
m_obj->tagname = NULL;
1287
m_obj->access = (access_mode)access;
1288
/* DWORD is a 4-byte int. If we're on a box where size_t consumes
1289
* more than 4 bytes, we need to break it apart. Else (size_t
1290
* consumes 4 bytes), C doesn't define what happens if we shift
1291
* right by 32, so we need different code.
1293
#if SIZEOF_SIZE_T > 4
1294
size_hi = (DWORD)((offset + m_obj->size) >> 32);
1295
size_lo = (DWORD)((offset + m_obj->size) & 0xFFFFFFFF);
1296
off_hi = (DWORD)(offset >> 32);
1297
off_lo = (DWORD)(offset & 0xFFFFFFFF);
1300
size_lo = (DWORD)(offset + m_obj->size);
1302
off_lo = (DWORD)offset;
1304
/* For files, it would be sufficient to pass 0 as size.
1305
For anonymous maps, we have to pass the size explicitly. */
1306
m_obj->map_handle = CreateFileMapping(m_obj->file_handle,
1312
if (m_obj->map_handle != NULL) {
1313
m_obj->data = (char *) MapViewOfFile(m_obj->map_handle,
1318
if (m_obj->data != NULL)
1319
return (PyObject *)m_obj;
1321
dwErr = GetLastError();
1322
CloseHandle(m_obj->map_handle);
1323
m_obj->map_handle = NULL;
1326
dwErr = GetLastError();
1328
PyErr_SetFromWindowsErr(dwErr);
1149
PyObject *map_size_obj = NULL, *offset_obj = NULL;
1150
Py_ssize_t map_size, offset;
1151
DWORD off_hi; /* upper 32 bits of offset */
1152
DWORD off_lo; /* lower 32 bits of offset */
1153
DWORD size_hi; /* upper 32 bits of size */
1154
DWORD size_lo; /* lower 32 bits of size */
1159
int access = (access_mode)ACCESS_DEFAULT;
1160
DWORD flProtect, dwDesiredAccess;
1161
static char *keywords[] = { "fileno", "length",
1163
"access", "offset", NULL };
1165
if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iO|ziO", keywords,
1166
&fileno, &map_size_obj,
1167
&tagname, &access, &offset_obj)) {
1171
switch((access_mode)access) {
1173
flProtect = PAGE_READONLY;
1174
dwDesiredAccess = FILE_MAP_READ;
1176
case ACCESS_DEFAULT: case ACCESS_WRITE:
1177
flProtect = PAGE_READWRITE;
1178
dwDesiredAccess = FILE_MAP_WRITE;
1181
flProtect = PAGE_WRITECOPY;
1182
dwDesiredAccess = FILE_MAP_COPY;
1185
return PyErr_Format(PyExc_ValueError,
1186
"mmap invalid access parameter.");
1189
map_size = _GetMapSize(map_size_obj, "size");
1192
offset = _GetMapSize(offset_obj, "offset");
1196
/* assume -1 and 0 both mean invalid filedescriptor
1197
to 'anonymously' map memory.
1198
XXX: fileno == 0 is a valid fd, but was accepted prior to 2.5.
1199
XXX: Should this code be added?
1201
PyErr_WarnEx(PyExc_DeprecationWarning,
1202
"don't use 0 for anonymous memory",
1205
if (fileno != -1 && fileno != 0) {
1206
fh = (HANDLE)_get_osfhandle(fileno);
1207
if (fh==(HANDLE)-1) {
1208
PyErr_SetFromErrno(mmap_module_error);
1211
/* Win9x appears to need us seeked to zero */
1212
lseek(fileno, 0, SEEK_SET);
1215
m_obj = (mmap_object *)type->tp_alloc(type, 0);
1218
/* Set every field to an invalid marker, so we can safely
1219
destruct the object in the face of failure */
1221
m_obj->file_handle = INVALID_HANDLE_VALUE;
1222
m_obj->map_handle = NULL;
1223
m_obj->tagname = NULL;
1224
m_obj->offset = offset;
1227
/* It is necessary to duplicate the handle, so the
1228
Python code can close it on us */
1229
if (!DuplicateHandle(
1230
GetCurrentProcess(), /* source process handle */
1231
fh, /* handle to be duplicated */
1232
GetCurrentProcess(), /* target proc handle */
1233
(LPHANDLE)&m_obj->file_handle, /* result */
1234
0, /* access - ignored due to options value */
1235
FALSE, /* inherited by child processes? */
1236
DUPLICATE_SAME_ACCESS)) { /* options */
1237
dwErr = GetLastError();
1239
PyErr_SetFromWindowsErr(dwErr);
1244
low = GetFileSize(fh, &high);
1245
/* low might just happen to have the value INVALID_FILE_SIZE;
1246
so we need to check the last error also. */
1247
if (low == INVALID_FILE_SIZE &&
1248
(dwErr = GetLastError()) != NO_ERROR) {
1250
return PyErr_SetFromWindowsErr(dwErr);
1253
#if SIZEOF_SIZE_T > 4
1254
m_obj->size = (((size_t)high)<<32) + low;
1257
/* File is too large to map completely */
1258
m_obj->size = (size_t)-1;
1263
m_obj->size = map_size;
1267
m_obj->size = map_size;
1270
/* set the initial position */
1271
m_obj->pos = (size_t) 0;
1274
/* set the tag name */
1275
if (tagname != NULL && *tagname != '\0') {
1276
m_obj->tagname = PyMem_Malloc(strlen(tagname)+1);
1277
if (m_obj->tagname == NULL) {
1282
strcpy(m_obj->tagname, tagname);
1285
m_obj->tagname = NULL;
1287
m_obj->access = (access_mode)access;
1288
/* DWORD is a 4-byte int. If we're on a box where size_t consumes
1289
* more than 4 bytes, we need to break it apart. Else (size_t
1290
* consumes 4 bytes), C doesn't define what happens if we shift
1291
* right by 32, so we need different code.
1293
#if SIZEOF_SIZE_T > 4
1294
size_hi = (DWORD)((offset + m_obj->size) >> 32);
1295
size_lo = (DWORD)((offset + m_obj->size) & 0xFFFFFFFF);
1296
off_hi = (DWORD)(offset >> 32);
1297
off_lo = (DWORD)(offset & 0xFFFFFFFF);
1300
size_lo = (DWORD)(offset + m_obj->size);
1302
off_lo = (DWORD)offset;
1304
/* For files, it would be sufficient to pass 0 as size.
1305
For anonymous maps, we have to pass the size explicitly. */
1306
m_obj->map_handle = CreateFileMapping(m_obj->file_handle,
1312
if (m_obj->map_handle != NULL) {
1313
m_obj->data = (char *) MapViewOfFile(m_obj->map_handle,
1318
if (m_obj->data != NULL)
1319
return (PyObject *)m_obj;
1321
dwErr = GetLastError();
1322
CloseHandle(m_obj->map_handle);
1323
m_obj->map_handle = NULL;
1326
dwErr = GetLastError();
1328
PyErr_SetFromWindowsErr(dwErr);
1331
1331
#endif /* MS_WINDOWS */
1334
1334
setint(PyObject *d, const char *name, long value)
1336
PyObject *o = PyLong_FromLong(value);
1337
if (o && PyDict_SetItemString(d, name, o) == 0) {
1336
PyObject *o = PyLong_FromLong(value);
1337
if (o && PyDict_SetItemString(d, name, o) == 0) {
1343
1343
static struct PyModuleDef mmapmodule = {
1344
PyModuleDef_HEAD_INIT,
1344
PyModuleDef_HEAD_INIT,
1356
1356
PyInit_mmap(void)
1358
PyObject *dict, *module;
1360
if (PyType_Ready(&mmap_object_type) < 0)
1363
module = PyModule_Create(&mmapmodule);
1366
dict = PyModule_GetDict(module);
1369
mmap_module_error = PyErr_NewException("mmap.error",
1370
PyExc_EnvironmentError , NULL);
1371
if (mmap_module_error == NULL)
1373
PyDict_SetItemString(dict, "error", mmap_module_error);
1374
PyDict_SetItemString(dict, "mmap", (PyObject*) &mmap_object_type);
1358
PyObject *dict, *module;
1360
if (PyType_Ready(&mmap_object_type) < 0)
1363
module = PyModule_Create(&mmapmodule);
1366
dict = PyModule_GetDict(module);
1369
mmap_module_error = PyErr_NewException("mmap.error",
1370
PyExc_EnvironmentError , NULL);
1371
if (mmap_module_error == NULL)
1373
PyDict_SetItemString(dict, "error", mmap_module_error);
1374
PyDict_SetItemString(dict, "mmap", (PyObject*) &mmap_object_type);
1375
1375
#ifdef PROT_EXEC
1376
setint(dict, "PROT_EXEC", PROT_EXEC);
1376
setint(dict, "PROT_EXEC", PROT_EXEC);
1378
1378
#ifdef PROT_READ
1379
setint(dict, "PROT_READ", PROT_READ);
1379
setint(dict, "PROT_READ", PROT_READ);
1381
1381
#ifdef PROT_WRITE
1382
setint(dict, "PROT_WRITE", PROT_WRITE);
1382
setint(dict, "PROT_WRITE", PROT_WRITE);
1385
1385
#ifdef MAP_SHARED
1386
setint(dict, "MAP_SHARED", MAP_SHARED);
1386
setint(dict, "MAP_SHARED", MAP_SHARED);
1388
1388
#ifdef MAP_PRIVATE
1389
setint(dict, "MAP_PRIVATE", MAP_PRIVATE);
1389
setint(dict, "MAP_PRIVATE", MAP_PRIVATE);
1391
1391
#ifdef MAP_DENYWRITE
1392
setint(dict, "MAP_DENYWRITE", MAP_DENYWRITE);
1392
setint(dict, "MAP_DENYWRITE", MAP_DENYWRITE);
1394
1394
#ifdef MAP_EXECUTABLE
1395
setint(dict, "MAP_EXECUTABLE", MAP_EXECUTABLE);
1395
setint(dict, "MAP_EXECUTABLE", MAP_EXECUTABLE);
1397
1397
#ifdef MAP_ANONYMOUS
1398
setint(dict, "MAP_ANON", MAP_ANONYMOUS);
1399
setint(dict, "MAP_ANONYMOUS", MAP_ANONYMOUS);
1398
setint(dict, "MAP_ANON", MAP_ANONYMOUS);
1399
setint(dict, "MAP_ANONYMOUS", MAP_ANONYMOUS);
1402
setint(dict, "PAGESIZE", (long)my_getpagesize());
1404
setint(dict, "ALLOCATIONGRANULARITY", (long)my_getallocationgranularity());
1406
setint(dict, "ACCESS_READ", ACCESS_READ);
1407
setint(dict, "ACCESS_WRITE", ACCESS_WRITE);
1408
setint(dict, "ACCESS_COPY", ACCESS_COPY);
1402
setint(dict, "PAGESIZE", (long)my_getpagesize());
1404
setint(dict, "ALLOCATIONGRANULARITY", (long)my_getallocationgranularity());
1406
setint(dict, "ACCESS_READ", ACCESS_READ);
1407
setint(dict, "ACCESS_WRITE", ACCESS_WRITE);
1408
setint(dict, "ACCESS_COPY", ACCESS_COPY);