~ubuntu-branches/ubuntu/natty/python3.1/natty-security

« back to all changes in this revision

Viewing changes to Modules/mmapmodule.c

  • Committer: Bazaar Package Importer
  • Author(s): Matthias Klose
  • Date: 2010-07-06 16:52:42 UTC
  • mfrom: (1.2.1 upstream) (2.1.11 sid)
  • Revision ID: james.westby@ubuntu.com-20100706165242-2xv4i019r3et6c0j
Tags: 3.1.2+20100706-1ubuntu1
* Merge with Debian; remaining changes:
  - Regenerate the control file.
  - Add debian/patches/overwrite-semaphore-check for Lucid buildds.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
2
 /  Author: Sam Rushing <rushing@nightmare.com>
3
3
 /  Hacked for Unix by AMK
4
 
 /  $Id: mmapmodule.c 73685 2009-06-29 15:02:36Z hirokazu.yamamoto $
 
4
 /  $Id: mmapmodule.c 81033 2010-05-09 16:14:21Z antoine.pitrou $
5
5
 
6
6
 / Modified to support mmap with offset - to map a 'window' of a file
7
7
 /   Author:  Yotam Medini  yotamm@mellanox.co.il
30
30
static int
31
31
my_getpagesize(void)
32
32
{
33
 
        SYSTEM_INFO si;
34
 
        GetSystemInfo(&si);
35
 
        return si.dwPageSize;
 
33
    SYSTEM_INFO si;
 
34
    GetSystemInfo(&si);
 
35
    return si.dwPageSize;
36
36
}
37
37
 
38
38
static int
39
39
my_getallocationgranularity (void)
40
40
{
41
41
 
42
 
        SYSTEM_INFO si;
43
 
        GetSystemInfo(&si);
44
 
        return si.dwAllocationGranularity;
 
42
    SYSTEM_INFO si;
 
43
    GetSystemInfo(&si);
 
44
    return si.dwAllocationGranularity;
45
45
}
46
46
 
47
47
#endif
54
54
static int
55
55
my_getpagesize(void)
56
56
{
57
 
        return sysconf(_SC_PAGESIZE);
 
57
    return sysconf(_SC_PAGESIZE);
58
58
}
59
59
 
60
60
#define my_getallocationgranularity my_getpagesize
79
79
 
80
80
typedef enum
81
81
{
82
 
        ACCESS_DEFAULT,
83
 
        ACCESS_READ,
84
 
        ACCESS_WRITE,
85
 
        ACCESS_COPY
 
82
    ACCESS_DEFAULT,
 
83
    ACCESS_READ,
 
84
    ACCESS_WRITE,
 
85
    ACCESS_COPY
86
86
} access_mode;
87
87
 
88
88
typedef struct {
89
 
        PyObject_HEAD
90
 
        char *  data;
91
 
        size_t  size;
92
 
        size_t  pos;    /* relative to offset */
93
 
        size_t  offset; 
94
 
        int     exports;
 
89
    PyObject_HEAD
 
90
    char *      data;
 
91
    size_t      size;
 
92
    size_t      pos;    /* relative to offset */
 
93
    size_t      offset;
 
94
    int     exports;
95
95
 
96
96
#ifdef MS_WINDOWS
97
 
        HANDLE  map_handle;
98
 
        HANDLE  file_handle;
99
 
        char *  tagname;
 
97
    HANDLE      map_handle;
 
98
    HANDLE      file_handle;
 
99
    char *      tagname;
100
100
#endif
101
101
 
102
102
#ifdef UNIX
103
 
        int fd;
 
103
    int fd;
104
104
#endif
105
105
 
106
 
        access_mode access;
 
106
    access_mode access;
107
107
} mmap_object;
108
108
 
109
109
 
111
111
mmap_object_dealloc(mmap_object *m_obj)
112
112
{
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);
120
 
        if (m_obj->tagname)
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);
 
120
    if (m_obj->tagname)
 
121
        PyMem_Free(m_obj->tagname);
122
122
#endif /* MS_WINDOWS */
123
123
 
124
124
#ifdef UNIX
125
 
        if (m_obj->fd >= 0)
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);
130
 
        }
 
125
    if (m_obj->fd >= 0)
 
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);
 
130
    }
131
131
#endif /* UNIX */
132
132
 
133
 
        Py_TYPE(m_obj)->tp_free((PyObject*)m_obj);
 
133
    Py_TYPE(m_obj)->tp_free((PyObject*)m_obj);
134
134
}
135
135
 
136
136
static PyObject *
137
137
mmap_close_method(mmap_object *self, PyObject *unused)
138
138
{
139
 
        if (self->exports > 0) {
140
 
                PyErr_SetString(PyExc_BufferError, "cannot close "\
141
 
                                "exported pointers exist");
142
 
                return NULL;
143
 
        }
 
139
    if (self->exports > 0) {
 
140
        PyErr_SetString(PyExc_BufferError, "cannot close "\
 
141
                        "exported pointers exist");
 
142
        return NULL;
 
143
    }
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
149
 
           again.
150
 
           TODO - should we check for errors in the close operations???
151
 
        */
152
 
        if (self->data != NULL) {
153
 
                UnmapViewOfFile(self->data);
154
 
                self->data = NULL;
155
 
        }
156
 
        if (self->map_handle != NULL) {
157
 
                CloseHandle(self->map_handle);
158
 
                self->map_handle = NULL;
159
 
        }
160
 
        if (self->file_handle != INVALID_HANDLE_VALUE) {
161
 
                CloseHandle(self->file_handle);
162
 
                self->file_handle = INVALID_HANDLE_VALUE;
163
 
        }
 
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
 
149
       again.
 
150
       TODO - should we check for errors in the close operations???
 
151
    */
 
152
    if (self->data != NULL) {
 
153
        UnmapViewOfFile(self->data);
 
154
        self->data = NULL;
 
155
    }
 
156
    if (self->map_handle != NULL) {
 
157
        CloseHandle(self->map_handle);
 
158
        self->map_handle = NULL;
 
159
    }
 
160
    if (self->file_handle != INVALID_HANDLE_VALUE) {
 
161
        CloseHandle(self->file_handle);
 
162
        self->file_handle = INVALID_HANDLE_VALUE;
 
163
    }
164
164
#endif /* MS_WINDOWS */
165
165
 
166
166
#ifdef UNIX
167
 
        if (0 <= self->fd)
168
 
                (void) close(self->fd);
169
 
        self->fd = -1;
170
 
        if (self->data != NULL) {
171
 
                munmap(self->data, self->size);
172
 
                self->data = NULL;
173
 
        }
 
167
    if (0 <= self->fd)
 
168
        (void) close(self->fd);
 
169
    self->fd = -1;
 
170
    if (self->data != NULL) {
 
171
        munmap(self->data, self->size);
 
172
        self->data = NULL;
 
173
    }
174
174
#endif
175
175
 
176
 
        Py_INCREF(Py_None);
177
 
        return Py_None;
 
176
    Py_INCREF(Py_None);
 
177
    return Py_None;
178
178
}
179
179
 
180
180
#ifdef MS_WINDOWS
181
 
#define CHECK_VALID(err)                                                \
182
 
do {                                                                    \
183
 
    if (self->map_handle == NULL) {                                     \
184
 
        PyErr_SetString(PyExc_ValueError, "mmap closed or invalid");    \
185
 
        return err;                                                     \
186
 
    }                                                                   \
 
181
#define CHECK_VALID(err)                                                \
 
182
do {                                                                    \
 
183
    if (self->map_handle == NULL) {                                     \
 
184
    PyErr_SetString(PyExc_ValueError, "mmap closed or invalid");        \
 
185
    return err;                                                         \
 
186
    }                                                                   \
187
187
} while (0)
188
188
#endif /* MS_WINDOWS */
189
189
 
190
190
#ifdef UNIX
191
 
#define CHECK_VALID(err)                                                \
192
 
do {                                                                    \
193
 
    if (self->data == NULL) {                                           \
194
 
        PyErr_SetString(PyExc_ValueError, "mmap closed or invalid");    \
195
 
        return err;                                                     \
196
 
        }                                                               \
 
191
#define CHECK_VALID(err)                                                \
 
192
do {                                                                    \
 
193
    if (self->data == NULL) {                                           \
 
194
    PyErr_SetString(PyExc_ValueError, "mmap closed or invalid");        \
 
195
    return err;                                                         \
 
196
    }                                                                   \
197
197
} while (0)
198
198
#endif /* UNIX */
199
199
 
200
200
static PyObject *
201
201
mmap_read_byte_method(mmap_object *self,
202
 
                      PyObject *unused)
 
202
                      PyObject *unused)
203
203
{
204
 
        CHECK_VALID(NULL);
205
 
        if (self->pos < self->size) {
206
 
                char value = self->data[self->pos];
207
 
                self->pos += 1;
208
 
                return Py_BuildValue("b", value);
209
 
        } else {
210
 
                PyErr_SetString(PyExc_ValueError, "read byte out of range");
211
 
                return NULL;
212
 
        }
 
204
    CHECK_VALID(NULL);
 
205
    if (self->pos < self->size) {
 
206
        char value = self->data[self->pos];
 
207
        self->pos += 1;
 
208
        return Py_BuildValue("b", value);
 
209
    } else {
 
210
        PyErr_SetString(PyExc_ValueError, "read byte out of range");
 
211
        return NULL;
 
212
    }
213
213
}
214
214
 
215
215
static PyObject *
216
216
mmap_read_line_method(mmap_object *self,
217
 
                      PyObject *unused)
 
217
                      PyObject *unused)
218
218
{
219
 
        char *start = self->data+self->pos;
220
 
        char *eof = self->data+self->size;
221
 
        char *eol;
222
 
        PyObject *result;
223
 
 
224
 
        CHECK_VALID(NULL);
225
 
 
226
 
        eol = memchr(start, '\n', self->size - self->pos);
227
 
        if (!eol)
228
 
                eol = eof;
229
 
        else
230
 
                ++eol;          /* we're interested in the position after the
231
 
                                   newline. */
232
 
        result = PyBytes_FromStringAndSize(start, (eol - start));
233
 
        self->pos += (eol - start);
234
 
        return result;
 
219
    char *start = self->data+self->pos;
 
220
    char *eof = self->data+self->size;
 
221
    char *eol;
 
222
    PyObject *result;
 
223
 
 
224
    CHECK_VALID(NULL);
 
225
 
 
226
    eol = memchr(start, '\n', self->size - self->pos);
 
227
    if (!eol)
 
228
        eol = eof;
 
229
    else
 
230
        ++eol;                  /* we're interested in the position after the
 
231
                           newline. */
 
232
    result = PyBytes_FromStringAndSize(start, (eol - start));
 
233
    self->pos += (eol - start);
 
234
    return result;
235
235
}
236
236
 
237
237
static PyObject *
238
238
mmap_read_method(mmap_object *self,
239
 
                 PyObject *args)
 
239
                 PyObject *args)
240
240
{
241
 
        Py_ssize_t num_bytes, n;
242
 
        PyObject *result;
243
 
 
244
 
        CHECK_VALID(NULL);
245
 
        if (!PyArg_ParseTuple(args, "n:read", &num_bytes))
246
 
                return(NULL);
247
 
 
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.
256
 
         */
257
 
        if (n < 0)
258
 
                n = PY_SSIZE_T_MAX;
259
 
        if (num_bytes < 0 || num_bytes > n) {
260
 
                num_bytes = n;
261
 
        }
262
 
        result = PyBytes_FromStringAndSize(self->data+self->pos, num_bytes);
263
 
        self->pos += num_bytes;
264
 
        return result;
 
241
    Py_ssize_t num_bytes, n;
 
242
    PyObject *result;
 
243
 
 
244
    CHECK_VALID(NULL);
 
245
    if (!PyArg_ParseTuple(args, "n:read", &num_bytes))
 
246
        return(NULL);
 
247
 
 
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.
 
256
     */
 
257
    if (n < 0)
 
258
        n = PY_SSIZE_T_MAX;
 
259
    if (num_bytes < 0 || num_bytes > n) {
 
260
        num_bytes = n;
 
261
    }
 
262
    result = PyBytes_FromStringAndSize(self->data+self->pos, num_bytes);
 
263
    self->pos += num_bytes;
 
264
    return result;
265
265
}
266
266
 
267
267
static PyObject *
268
268
mmap_gfind(mmap_object *self,
269
 
           PyObject *args,
270
 
           int reverse)
 
269
           PyObject *args,
 
270
           int reverse)
271
271
{
272
 
        Py_ssize_t start = self->pos;
273
 
        Py_ssize_t end = self->size;
274
 
        const char *needle;
275
 
        Py_ssize_t len;
276
 
 
277
 
        CHECK_VALID(NULL);
278
 
        if (!PyArg_ParseTuple(args, reverse ? "y#|nn:rfind" : "y#|nn:find",
279
 
                              &needle, &len, &start, &end)) {
280
 
                return NULL;
281
 
        } else {
282
 
                const char *p, *start_p, *end_p;
283
 
                int sign = reverse ? -1 : 1;
284
 
 
285
 
                if (start < 0)
286
 
                        start += self->size;
287
 
                if (start < 0)
288
 
                        start = 0;
289
 
                else if ((size_t)start > self->size)
290
 
                        start = self->size;
291
 
 
292
 
                if (end < 0)
293
 
                        end += self->size;
294
 
                if (end < 0)
295
 
                        end = 0;
296
 
                else if ((size_t)end > self->size)
297
 
                        end = self->size;
298
 
 
299
 
                start_p = self->data + start;
300
 
                end_p = self->data + end;
301
 
 
302
 
                for (p = (reverse ? end_p - len : start_p);
303
 
                     (p >= start_p) && (p + len <= end_p); p += sign) {
304
 
                        Py_ssize_t i;
305
 
                        for (i = 0; i < len && needle[i] == p[i]; ++i)
306
 
                                /* nothing */;
307
 
                        if (i == len) {
308
 
                                return PyLong_FromSsize_t(p - self->data);
309
 
                        }
310
 
                }
311
 
                return PyLong_FromLong(-1);
312
 
        }
 
272
    Py_ssize_t start = self->pos;
 
273
    Py_ssize_t end = self->size;
 
274
    const char *needle;
 
275
    Py_ssize_t len;
 
276
 
 
277
    CHECK_VALID(NULL);
 
278
    if (!PyArg_ParseTuple(args, reverse ? "y#|nn:rfind" : "y#|nn:find",
 
279
                          &needle, &len, &start, &end)) {
 
280
        return NULL;
 
281
    } else {
 
282
        const char *p, *start_p, *end_p;
 
283
        int sign = reverse ? -1 : 1;
 
284
 
 
285
        if (start < 0)
 
286
            start += self->size;
 
287
        if (start < 0)
 
288
            start = 0;
 
289
        else if ((size_t)start > self->size)
 
290
            start = self->size;
 
291
 
 
292
        if (end < 0)
 
293
            end += self->size;
 
294
        if (end < 0)
 
295
            end = 0;
 
296
        else if ((size_t)end > self->size)
 
297
            end = self->size;
 
298
 
 
299
        start_p = self->data + start;
 
300
        end_p = self->data + end;
 
301
 
 
302
        for (p = (reverse ? end_p - len : start_p);
 
303
             (p >= start_p) && (p + len <= end_p); p += sign) {
 
304
            Py_ssize_t i;
 
305
            for (i = 0; i < len && needle[i] == p[i]; ++i)
 
306
                /* nothing */;
 
307
            if (i == len) {
 
308
                return PyLong_FromSsize_t(p - self->data);
 
309
            }
 
310
        }
 
311
        return PyLong_FromLong(-1);
 
312
    }
313
313
}
314
314
 
315
315
static PyObject *
316
316
mmap_find_method(mmap_object *self,
317
 
                 PyObject *args)
 
317
                 PyObject *args)
318
318
{
319
 
        return mmap_gfind(self, args, 0);
 
319
    return mmap_gfind(self, args, 0);
320
320
}
321
321
 
322
322
static PyObject *
323
323
mmap_rfind_method(mmap_object *self,
324
 
                 PyObject *args)
 
324
                 PyObject *args)
325
325
{
326
 
        return mmap_gfind(self, args, 1);
 
326
    return mmap_gfind(self, args, 1);
327
327
}
328
328
 
329
329
static int
330
330
is_writable(mmap_object *self)
331
331
{
332
 
        if (self->access != ACCESS_READ)
333
 
                return 1;
334
 
        PyErr_Format(PyExc_TypeError, "mmap can't modify a readonly memory map.");
335
 
        return 0;
 
332
    if (self->access != ACCESS_READ)
 
333
        return 1;
 
334
    PyErr_Format(PyExc_TypeError, "mmap can't modify a readonly memory map.");
 
335
    return 0;
336
336
}
337
337
 
338
338
static int
339
339
is_resizeable(mmap_object *self)
340
340
{
341
 
        if (self->exports > 0) {
342
 
                PyErr_SetString(PyExc_BufferError,
343
 
                                "mmap can't resize with extant buffers exported.");
344
 
                return 0;
345
 
        }
346
 
        if ((self->access == ACCESS_WRITE) || (self->access == ACCESS_DEFAULT))
347
 
                return 1;
348
 
        PyErr_Format(PyExc_TypeError,
349
 
                     "mmap can't resize a readonly or copy-on-write memory map.");
350
 
        return 0;
 
341
    if (self->exports > 0) {
 
342
        PyErr_SetString(PyExc_BufferError,
 
343
                        "mmap can't resize with extant buffers exported.");
 
344
        return 0;
 
345
    }
 
346
    if ((self->access == ACCESS_WRITE) || (self->access == ACCESS_DEFAULT))
 
347
        return 1;
 
348
    PyErr_Format(PyExc_TypeError,
 
349
                 "mmap can't resize a readonly or copy-on-write memory map.");
 
350
    return 0;
351
351
}
352
352
 
353
353
 
354
354
static PyObject *
355
355
mmap_write_method(mmap_object *self,
356
 
                  PyObject *args)
 
356
                  PyObject *args)
357
357
{
358
 
        Py_ssize_t length;
359
 
        char *data;
360
 
 
361
 
        CHECK_VALID(NULL);
362
 
        if (!PyArg_ParseTuple(args, "y#:write", &data, &length))
363
 
                return(NULL);
364
 
 
365
 
        if (!is_writable(self))
366
 
                return NULL;
367
 
 
368
 
        if ((self->pos + length) > self->size) {
369
 
                PyErr_SetString(PyExc_ValueError, "data out of range");
370
 
                return NULL;
371
 
        }
372
 
        memcpy(self->data+self->pos, data, length);
373
 
        self->pos = self->pos+length;
374
 
        Py_INCREF(Py_None);
375
 
        return Py_None;
 
358
    Py_ssize_t length;
 
359
    char *data;
 
360
 
 
361
    CHECK_VALID(NULL);
 
362
    if (!PyArg_ParseTuple(args, "y#:write", &data, &length))
 
363
        return(NULL);
 
364
 
 
365
    if (!is_writable(self))
 
366
        return NULL;
 
367
 
 
368
    if ((self->pos + length) > self->size) {
 
369
        PyErr_SetString(PyExc_ValueError, "data out of range");
 
370
        return NULL;
 
371
    }
 
372
    memcpy(self->data+self->pos, data, length);
 
373
    self->pos = self->pos+length;
 
374
    Py_INCREF(Py_None);
 
375
    return Py_None;
376
376
}
377
377
 
378
378
static PyObject *
379
379
mmap_write_byte_method(mmap_object *self,
380
 
                       PyObject *args)
 
380
                       PyObject *args)
381
381
{
382
 
        char value;
383
 
 
384
 
        CHECK_VALID(NULL);
385
 
        if (!PyArg_ParseTuple(args, "b:write_byte", &value))
386
 
                return(NULL);
387
 
 
388
 
        if (!is_writable(self))
389
 
                return NULL;
390
 
 
391
 
        if (self->pos < self->size) {
392
 
                *(self->data+self->pos) = value;
393
 
                self->pos += 1;
394
 
                Py_INCREF(Py_None);
395
 
                return Py_None;
396
 
        }
397
 
        else {
398
 
                PyErr_SetString(PyExc_ValueError, "write byte out of range");
399
 
                return NULL;
400
 
        }
 
382
    char value;
 
383
 
 
384
    CHECK_VALID(NULL);
 
385
    if (!PyArg_ParseTuple(args, "b:write_byte", &value))
 
386
        return(NULL);
 
387
 
 
388
    if (!is_writable(self))
 
389
        return NULL;
 
390
 
 
391
    if (self->pos < self->size) {
 
392
        *(self->data+self->pos) = value;
 
393
        self->pos += 1;
 
394
        Py_INCREF(Py_None);
 
395
        return Py_None;
 
396
    }
 
397
    else {
 
398
        PyErr_SetString(PyExc_ValueError, "write byte out of range");
 
399
        return NULL;
 
400
    }
401
401
}
402
402
 
403
403
static PyObject *
404
404
mmap_size_method(mmap_object *self,
405
 
                 PyObject *unused)
 
405
                 PyObject *unused)
406
406
{
407
 
        CHECK_VALID(NULL);
 
407
    CHECK_VALID(NULL);
408
408
 
409
409
#ifdef MS_WINDOWS
410
 
        if (self->file_handle != INVALID_HANDLE_VALUE) {
411
 
                DWORD low,high;
412
 
                PY_LONG_LONG size;
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);
420
 
                }
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);
425
 
        } else {
426
 
                return PyLong_FromSsize_t(self->size);
427
 
        }
 
410
    if (self->file_handle != INVALID_HANDLE_VALUE) {
 
411
        DWORD low,high;
 
412
        PY_LONG_LONG size;
 
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);
 
420
        }
 
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);
 
425
    } else {
 
426
        return PyLong_FromSsize_t(self->size);
 
427
    }
428
428
#endif /* MS_WINDOWS */
429
429
 
430
430
#ifdef UNIX
431
 
        {
432
 
                struct stat buf;
433
 
                if (-1 == fstat(self->fd, &buf)) {
434
 
                        PyErr_SetFromErrno(mmap_module_error);
435
 
                        return NULL;
436
 
                }
437
 
                return PyLong_FromSsize_t(buf.st_size);
438
 
        }
 
431
    {
 
432
        struct stat buf;
 
433
        if (-1 == fstat(self->fd, &buf)) {
 
434
            PyErr_SetFromErrno(mmap_module_error);
 
435
            return NULL;
 
436
        }
 
437
        return PyLong_FromSsize_t(buf.st_size);
 
438
    }
439
439
#endif /* UNIX */
440
440
}
441
441
 
450
450
 
451
451
static PyObject *
452
452
mmap_resize_method(mmap_object *self,
453
 
                   PyObject *args)
 
453
                   PyObject *args)
454
454
{
455
 
        Py_ssize_t new_size;
456
 
        CHECK_VALID(NULL);
457
 
        if (!PyArg_ParseTuple(args, "n:resize", &new_size) ||
458
 
            !is_resizeable(self)) {
459
 
                return NULL;
 
455
    Py_ssize_t new_size;
 
456
    CHECK_VALID(NULL);
 
457
    if (!PyArg_ParseTuple(args, "n:resize", &new_size) ||
 
458
        !is_resizeable(self)) {
 
459
        return NULL;
460
460
#ifdef MS_WINDOWS
461
 
        } else {
462
 
                DWORD dwErrCode = 0;
463
 
                DWORD off_hi, off_lo, newSizeLow, newSizeHigh;
464
 
                /* First, unmap the file view */
465
 
                UnmapViewOfFile(self->data);
466
 
                self->data = NULL;
467
 
                /* Close the mapping object */
468
 
                CloseHandle(self->map_handle);
469
 
                self->map_handle = NULL;
470
 
                /* Move to the desired EOF position */
 
461
    } else {
 
462
        DWORD dwErrCode = 0;
 
463
        DWORD off_hi, off_lo, newSizeLow, newSizeHigh;
 
464
        /* First, unmap the file view */
 
465
        UnmapViewOfFile(self->data);
 
466
        self->data = NULL;
 
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);
476
476
#else
477
 
                newSizeHigh = 0;
478
 
                newSizeLow = (DWORD)(self->offset + new_size);
479
 
                off_hi = 0;
480
 
                off_lo = (DWORD)self->offset;
 
477
        newSizeHigh = 0;
 
478
        newSizeLow = (DWORD)(self->offset + new_size);
 
479
        off_hi = 0;
 
480
        off_lo = (DWORD)self->offset;
481
481
#endif
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(
488
 
                        self->file_handle,
489
 
                        NULL,
490
 
                        PAGE_READWRITE,
491
 
                        0,
492
 
                        0,
493
 
                        self->tagname);
494
 
                if (self->map_handle != NULL) {
495
 
                        self->data = (char *) MapViewOfFile(self->map_handle,
496
 
                                                            FILE_MAP_WRITE,
497
 
                                                            off_hi,
498
 
                                                            off_lo,
499
 
                                                            new_size);
500
 
                        if (self->data != NULL) {
501
 
                                self->size = new_size;
502
 
                                Py_INCREF(Py_None);
503
 
                                return Py_None;
504
 
                        } else {
505
 
                                dwErrCode = GetLastError();
506
 
                                CloseHandle(self->map_handle);
507
 
                                self->map_handle = NULL;
508
 
                        }
509
 
                } else {
510
 
                        dwErrCode = GetLastError();
511
 
                }
512
 
                PyErr_SetFromWindowsErr(dwErrCode);
513
 
                return NULL;
 
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(
 
488
            self->file_handle,
 
489
            NULL,
 
490
            PAGE_READWRITE,
 
491
            0,
 
492
            0,
 
493
            self->tagname);
 
494
        if (self->map_handle != NULL) {
 
495
            self->data = (char *) MapViewOfFile(self->map_handle,
 
496
                                                FILE_MAP_WRITE,
 
497
                                                off_hi,
 
498
                                                off_lo,
 
499
                                                new_size);
 
500
            if (self->data != NULL) {
 
501
                self->size = new_size;
 
502
                Py_INCREF(Py_None);
 
503
                return Py_None;
 
504
            } else {
 
505
                dwErrCode = GetLastError();
 
506
                CloseHandle(self->map_handle);
 
507
                self->map_handle = NULL;
 
508
            }
 
509
        } else {
 
510
            dwErrCode = GetLastError();
 
511
        }
 
512
        PyErr_SetFromWindowsErr(dwErrCode);
 
513
        return NULL;
514
514
#endif /* MS_WINDOWS */
515
515
 
516
516
#ifdef UNIX
517
517
#ifndef HAVE_MREMAP
518
 
        } else {
519
 
                PyErr_SetString(PyExc_SystemError,
520
 
                                "mmap: resizing not available--no mremap()");
521
 
                return NULL;
 
518
    } else {
 
519
        PyErr_SetString(PyExc_SystemError,
 
520
                        "mmap: resizing not available--no mremap()");
 
521
        return NULL;
522
522
#else
523
 
        } else {
524
 
                void *newmap;
 
523
    } else {
 
524
        void *newmap;
525
525
 
526
 
                if (ftruncate(self->fd, self->offset + new_size) == -1) {
527
 
                        PyErr_SetFromErrno(mmap_module_error);
528
 
                        return NULL;
529
 
                }
 
526
        if (ftruncate(self->fd, self->offset + new_size) == -1) {
 
527
            PyErr_SetFromErrno(mmap_module_error);
 
528
            return NULL;
 
529
        }
530
530
 
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);
533
533
#else
534
 
                #if defined(__NetBSD__)
535
 
                        newmap = mremap(self->data, self->size, self->data, new_size, 0);
536
 
                #else
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);
 
536
        #else
 
537
            newmap = mremap(self->data, self->size, new_size, 0);
 
538
        #endif /* __NetBSD__ */
539
539
#endif
540
 
                if (newmap == (void *)-1)
541
 
                {
542
 
                        PyErr_SetFromErrno(mmap_module_error);
543
 
                        return NULL;
544
 
                }
545
 
                self->data = newmap;
546
 
                self->size = new_size;
547
 
                Py_INCREF(Py_None);
548
 
                return Py_None;
 
540
        if (newmap == (void *)-1)
 
541
        {
 
542
            PyErr_SetFromErrno(mmap_module_error);
 
543
            return NULL;
 
544
        }
 
545
        self->data = newmap;
 
546
        self->size = new_size;
 
547
        Py_INCREF(Py_None);
 
548
        return Py_None;
549
549
#endif /* HAVE_MREMAP */
550
550
#endif /* UNIX */
551
 
        }
 
551
    }
552
552
}
553
553
 
554
554
static PyObject *
555
555
mmap_tell_method(mmap_object *self, PyObject *unused)
556
556
{
557
 
        CHECK_VALID(NULL);
558
 
        return PyLong_FromSize_t(self->pos);
 
557
    CHECK_VALID(NULL);
 
558
    return PyLong_FromSize_t(self->pos);
559
559
}
560
560
 
561
561
static PyObject *
562
562
mmap_flush_method(mmap_object *self, PyObject *args)
563
563
{
564
 
        Py_ssize_t offset = 0;
565
 
        Py_ssize_t size = self->size;
566
 
        CHECK_VALID(NULL);
567
 
        if (!PyArg_ParseTuple(args, "|nn:flush", &offset, &size))
568
 
                return NULL;
569
 
        if ((size_t)(offset + size) > self->size) {
570
 
                PyErr_SetString(PyExc_ValueError, "flush values out of range");
571
 
                return NULL;
572
 
        }
 
564
    Py_ssize_t offset = 0;
 
565
    Py_ssize_t size = self->size;
 
566
    CHECK_VALID(NULL);
 
567
    if (!PyArg_ParseTuple(args, "|nn:flush", &offset, &size))
 
568
        return NULL;
 
569
    if ((size_t)(offset + size) > self->size) {
 
570
        PyErr_SetString(PyExc_ValueError, "flush values out of range");
 
571
        return NULL;
 
572
    }
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);
580
 
                return NULL;
581
 
        }
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);
 
580
        return NULL;
 
581
    }
 
582
    return PyLong_FromLong(0);
583
583
#else
584
 
        PyErr_SetString(PyExc_ValueError, "flush not supported on this system");
585
 
        return NULL;
 
584
    PyErr_SetString(PyExc_ValueError, "flush not supported on this system");
 
585
    return NULL;
586
586
#endif
587
587
}
588
588
 
589
589
static PyObject *
590
590
mmap_seek_method(mmap_object *self, PyObject *args)
591
591
{
592
 
        Py_ssize_t dist;
593
 
        int how=0;
594
 
        CHECK_VALID(NULL);
595
 
        if (!PyArg_ParseTuple(args, "n|i:seek", &dist, &how))
596
 
                return NULL;
597
 
        else {
598
 
                size_t where;
599
 
                switch (how) {
600
 
                case 0: /* relative to start */
601
 
                        if (dist < 0)
602
 
                                goto onoutofrange;
603
 
                        where = dist;
604
 
                        break;
605
 
                case 1: /* relative to current position */
606
 
                        if ((Py_ssize_t)self->pos + dist < 0)
607
 
                                goto onoutofrange;
608
 
                        where = self->pos + dist;
609
 
                        break;
610
 
                case 2: /* relative to end */
611
 
                        if ((Py_ssize_t)self->size + dist < 0)
612
 
                                goto onoutofrange;
613
 
                        where = self->size + dist;
614
 
                        break;
615
 
                default:
616
 
                        PyErr_SetString(PyExc_ValueError, "unknown seek type");
617
 
                        return NULL;
618
 
                }
619
 
                if (where > self->size)
620
 
                        goto onoutofrange;
621
 
                self->pos = where;
622
 
                Py_INCREF(Py_None);
623
 
                return Py_None;
624
 
        }
 
592
    Py_ssize_t dist;
 
593
    int how=0;
 
594
    CHECK_VALID(NULL);
 
595
    if (!PyArg_ParseTuple(args, "n|i:seek", &dist, &how))
 
596
        return NULL;
 
597
    else {
 
598
        size_t where;
 
599
        switch (how) {
 
600
        case 0: /* relative to start */
 
601
            if (dist < 0)
 
602
                goto onoutofrange;
 
603
            where = dist;
 
604
            break;
 
605
        case 1: /* relative to current position */
 
606
            if ((Py_ssize_t)self->pos + dist < 0)
 
607
                goto onoutofrange;
 
608
            where = self->pos + dist;
 
609
            break;
 
610
        case 2: /* relative to end */
 
611
            if ((Py_ssize_t)self->size + dist < 0)
 
612
                goto onoutofrange;
 
613
            where = self->size + dist;
 
614
            break;
 
615
        default:
 
616
            PyErr_SetString(PyExc_ValueError, "unknown seek type");
 
617
            return NULL;
 
618
        }
 
619
        if (where > self->size)
 
620
            goto onoutofrange;
 
621
        self->pos = where;
 
622
        Py_INCREF(Py_None);
 
623
        return Py_None;
 
624
    }
625
625
 
626
626
  onoutofrange:
627
 
        PyErr_SetString(PyExc_ValueError, "seek out of range");
628
 
        return NULL;
 
627
    PyErr_SetString(PyExc_ValueError, "seek out of range");
 
628
    return NULL;
629
629
}
630
630
 
631
631
static PyObject *
632
632
mmap_move_method(mmap_object *self, PyObject *args)
633
633
{
634
 
        unsigned long dest, src, cnt;
635
 
        CHECK_VALID(NULL);
636
 
        if (!PyArg_ParseTuple(args, "kkk:move", &dest, &src, &cnt) ||
637
 
            !is_writable(self)) {
638
 
                return NULL;
639
 
        } else {
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");
646
 
                        return NULL;
647
 
                }
648
 
                memmove(self->data+dest, self->data+src, cnt);
649
 
                Py_INCREF(Py_None);
650
 
                return Py_None;
651
 
        }
 
634
    unsigned long dest, src, cnt;
 
635
    CHECK_VALID(NULL);
 
636
    if (!PyArg_ParseTuple(args, "kkk:move", &dest, &src, &cnt) ||
 
637
        !is_writable(self)) {
 
638
        return NULL;
 
639
    } else {
 
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");
 
646
            return NULL;
 
647
        }
 
648
        memmove(self->data+dest, self->data+src, cnt);
 
649
        Py_INCREF(Py_None);
 
650
        return Py_None;
 
651
    }
652
652
}
653
653
 
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 */
670
670
};
671
671
 
672
672
/* Functions for treating an mmap'ed file as a buffer */
674
674
static int
675
675
mmap_buffer_getbuf(mmap_object *self, Py_buffer *view, int flags)
676
676
{
677
 
        CHECK_VALID(-1);
678
 
        if (PyBuffer_FillInfo(view, (PyObject*)self, self->data, self->size,
679
 
                              (self->access == ACCESS_READ), flags) < 0)
680
 
                return -1;
681
 
        self->exports++;
682
 
        return 0;
 
677
    CHECK_VALID(-1);
 
678
    if (PyBuffer_FillInfo(view, (PyObject*)self, self->data, self->size,
 
679
                          (self->access == ACCESS_READ), flags) < 0)
 
680
        return -1;
 
681
    self->exports++;
 
682
    return 0;
683
683
}
684
684
 
685
685
static void
686
686
mmap_buffer_releasebuf(mmap_object *self, Py_buffer *view)
687
687
{
688
 
        self->exports--;
 
688
    self->exports--;
689
689
}
690
690
 
691
691
static Py_ssize_t
692
692
mmap_length(mmap_object *self)
693
693
{
694
 
        CHECK_VALID(-1);
695
 
        return self->size;
 
694
    CHECK_VALID(-1);
 
695
    return self->size;
696
696
}
697
697
 
698
698
static PyObject *
699
699
mmap_item(mmap_object *self, Py_ssize_t i)
700
700
{
701
 
        CHECK_VALID(NULL);
702
 
        if (i < 0 || (size_t)i >= self->size) {
703
 
                PyErr_SetString(PyExc_IndexError, "mmap index out of range");
704
 
                return NULL;
705
 
        }
706
 
        return PyBytes_FromStringAndSize(self->data + i, 1);
 
701
    CHECK_VALID(NULL);
 
702
    if (i < 0 || (size_t)i >= self->size) {
 
703
        PyErr_SetString(PyExc_IndexError, "mmap index out of range");
 
704
        return NULL;
 
705
    }
 
706
    return PyBytes_FromStringAndSize(self->data + i, 1);
707
707
}
708
708
 
709
709
static PyObject *
710
710
mmap_subscript(mmap_object *self, PyObject *item)
711
711
{
712
 
        CHECK_VALID(NULL);
713
 
        if (PyIndex_Check(item)) {
714
 
                Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
715
 
                if (i == -1 && PyErr_Occurred())
716
 
                        return NULL;
717
 
                if (i < 0)
718
 
                        i += self->size;
719
 
                if (i < 0 || (size_t)i >= self->size) {
720
 
                        PyErr_SetString(PyExc_IndexError,
721
 
                                "mmap index out of range");
722
 
                        return NULL;
723
 
                }
724
 
                return PyLong_FromLong(Py_CHARMASK(self->data[i]));
725
 
        }
726
 
        else if (PySlice_Check(item)) {
727
 
                Py_ssize_t start, stop, step, slicelen;
728
 
 
729
 
                if (PySlice_GetIndicesEx((PySliceObject *)item, self->size,
730
 
                                 &start, &stop, &step, &slicelen) < 0) {
731
 
                        return NULL;
732
 
                }
733
 
 
734
 
                if (slicelen <= 0)
735
 
                        return PyBytes_FromStringAndSize("", 0);
736
 
                else if (step == 1)
737
 
                        return PyBytes_FromStringAndSize(self->data + start,
738
 
                                                          slicelen);
739
 
                else {
740
 
                        char *result_buf = (char *)PyMem_Malloc(slicelen);
741
 
                        Py_ssize_t cur, i;
742
 
                        PyObject *result;
743
 
 
744
 
                        if (result_buf == NULL)
745
 
                                return PyErr_NoMemory();
746
 
                        for (cur = start, i = 0; i < slicelen;
747
 
                             cur += step, i++) {
748
 
                                result_buf[i] = self->data[cur];
749
 
                        }
750
 
                        result = PyBytes_FromStringAndSize(result_buf,
751
 
                                                            slicelen);
752
 
                        PyMem_Free(result_buf);
753
 
                        return result;
754
 
                }
755
 
        }
756
 
        else {
757
 
                PyErr_SetString(PyExc_TypeError,
758
 
                                "mmap indices must be integers");
759
 
                return NULL;
760
 
        }
 
712
    CHECK_VALID(NULL);
 
713
    if (PyIndex_Check(item)) {
 
714
        Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
 
715
        if (i == -1 && PyErr_Occurred())
 
716
            return NULL;
 
717
        if (i < 0)
 
718
            i += self->size;
 
719
        if (i < 0 || (size_t)i >= self->size) {
 
720
            PyErr_SetString(PyExc_IndexError,
 
721
                "mmap index out of range");
 
722
            return NULL;
 
723
        }
 
724
        return PyLong_FromLong(Py_CHARMASK(self->data[i]));
 
725
    }
 
726
    else if (PySlice_Check(item)) {
 
727
        Py_ssize_t start, stop, step, slicelen;
 
728
 
 
729
        if (PySlice_GetIndicesEx((PySliceObject *)item, self->size,
 
730
                         &start, &stop, &step, &slicelen) < 0) {
 
731
            return NULL;
 
732
        }
 
733
 
 
734
        if (slicelen <= 0)
 
735
            return PyBytes_FromStringAndSize("", 0);
 
736
        else if (step == 1)
 
737
            return PyBytes_FromStringAndSize(self->data + start,
 
738
                                              slicelen);
 
739
        else {
 
740
            char *result_buf = (char *)PyMem_Malloc(slicelen);
 
741
            Py_ssize_t cur, i;
 
742
            PyObject *result;
 
743
 
 
744
            if (result_buf == NULL)
 
745
                return PyErr_NoMemory();
 
746
            for (cur = start, i = 0; i < slicelen;
 
747
                 cur += step, i++) {
 
748
                result_buf[i] = self->data[cur];
 
749
            }
 
750
            result = PyBytes_FromStringAndSize(result_buf,
 
751
                                                slicelen);
 
752
            PyMem_Free(result_buf);
 
753
            return result;
 
754
        }
 
755
    }
 
756
    else {
 
757
        PyErr_SetString(PyExc_TypeError,
 
758
                        "mmap indices must be integers");
 
759
        return NULL;
 
760
    }
761
761
}
762
762
 
763
763
static PyObject *
764
764
mmap_concat(mmap_object *self, PyObject *bb)
765
765
{
766
 
        CHECK_VALID(NULL);
767
 
        PyErr_SetString(PyExc_SystemError,
768
 
                        "mmaps don't support concatenation");
769
 
        return NULL;
 
766
    CHECK_VALID(NULL);
 
767
    PyErr_SetString(PyExc_SystemError,
 
768
                    "mmaps don't support concatenation");
 
769
    return NULL;
770
770
}
771
771
 
772
772
static PyObject *
773
773
mmap_repeat(mmap_object *self, Py_ssize_t n)
774
774
{
775
 
        CHECK_VALID(NULL);
776
 
        PyErr_SetString(PyExc_SystemError,
777
 
                        "mmaps don't support repeat operation");
778
 
        return NULL;
 
775
    CHECK_VALID(NULL);
 
776
    PyErr_SetString(PyExc_SystemError,
 
777
                    "mmaps don't support repeat operation");
 
778
    return NULL;
779
779
}
780
780
 
781
781
static int
782
782
mmap_ass_item(mmap_object *self, Py_ssize_t i, PyObject *v)
783
783
{
784
 
        const char *buf;
 
784
    const char *buf;
785
785
 
786
 
        CHECK_VALID(-1);
787
 
        if (i < 0 || (size_t)i >= self->size) {
788
 
                PyErr_SetString(PyExc_IndexError, "mmap index out of range");
789
 
                return -1;
790
 
        }
791
 
        if (v == NULL) {
792
 
                PyErr_SetString(PyExc_TypeError,
793
 
                                "mmap object doesn't support item deletion");
794
 
                return -1;
795
 
        }
796
 
        if (! (PyBytes_Check(v) && PyBytes_Size(v)==1) ) {
797
 
                PyErr_SetString(PyExc_IndexError,
798
 
                                "mmap assignment must be length-1 bytes()");
799
 
                return -1;
800
 
        }
801
 
        if (!is_writable(self))
802
 
                return -1;
803
 
        buf = PyBytes_AsString(v);
804
 
        self->data[i] = buf[0];
805
 
        return 0;
 
786
    CHECK_VALID(-1);
 
787
    if (i < 0 || (size_t)i >= self->size) {
 
788
        PyErr_SetString(PyExc_IndexError, "mmap index out of range");
 
789
        return -1;
 
790
    }
 
791
    if (v == NULL) {
 
792
        PyErr_SetString(PyExc_TypeError,
 
793
                        "mmap object doesn't support item deletion");
 
794
        return -1;
 
795
    }
 
796
    if (! (PyBytes_Check(v) && PyBytes_Size(v)==1) ) {
 
797
        PyErr_SetString(PyExc_IndexError,
 
798
                        "mmap assignment must be length-1 bytes()");
 
799
        return -1;
 
800
    }
 
801
    if (!is_writable(self))
 
802
        return -1;
 
803
    buf = PyBytes_AsString(v);
 
804
    self->data[i] = buf[0];
 
805
    return 0;
806
806
}
807
807
 
808
808
static int
809
809
mmap_ass_subscript(mmap_object *self, PyObject *item, PyObject *value)
810
810
{
811
 
        CHECK_VALID(-1);
812
 
 
813
 
        if (!is_writable(self))
814
 
                return -1;
815
 
 
816
 
        if (PyIndex_Check(item)) {
817
 
                Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
818
 
                Py_ssize_t v;
819
 
 
820
 
                if (i == -1 && PyErr_Occurred())
821
 
                        return -1;
822
 
                if (i < 0)
823
 
                        i += self->size;
824
 
                if (i < 0 || (size_t)i >= self->size) {
825
 
                        PyErr_SetString(PyExc_IndexError,
826
 
                                        "mmap index out of range");
827
 
                        return -1;
828
 
                }
829
 
                if (value == NULL) {
830
 
                        PyErr_SetString(PyExc_TypeError,
831
 
                                        "mmap doesn't support item deletion");
832
 
                        return -1;
833
 
                }
834
 
                if (!PyIndex_Check(value)) {
835
 
                        PyErr_SetString(PyExc_TypeError,
836
 
                                        "mmap item value must be an int");
837
 
                        return -1;
838
 
                }
839
 
                v = PyNumber_AsSsize_t(value, PyExc_TypeError);
840
 
                if (v == -1 && PyErr_Occurred())
841
 
                        return -1;
842
 
                if (v < 0 || v > 255) {
843
 
                        PyErr_SetString(PyExc_ValueError,
844
 
                                        "mmap item value must be "
845
 
                                        "in range(0, 256)");
846
 
                        return -1;
847
 
                }
848
 
                self->data[i] = v;
849
 
                return 0;
850
 
        }
851
 
        else if (PySlice_Check(item)) {
852
 
                Py_ssize_t start, stop, step, slicelen;
853
 
                Py_buffer vbuf;
854
 
 
855
 
                if (PySlice_GetIndicesEx((PySliceObject *)item,
856
 
                                         self->size, &start, &stop,
857
 
                                         &step, &slicelen) < 0) {
858
 
                        return -1;
859
 
                }
860
 
                if (value == NULL) {
861
 
                        PyErr_SetString(PyExc_TypeError,
862
 
                                "mmap object doesn't support slice deletion");
863
 
                        return -1;
864
 
                }
865
 
                if (PyObject_GetBuffer(value, &vbuf, PyBUF_SIMPLE) < 0)
866
 
                        return -1;
867
 
                if (vbuf.len != slicelen) {
868
 
                        PyErr_SetString(PyExc_IndexError,
869
 
                                "mmap slice assignment is wrong size");
870
 
                        PyBuffer_Release(&vbuf);
871
 
                        return -1;
872
 
                }
873
 
 
874
 
                if (slicelen == 0) {
875
 
                }
876
 
                else if (step == 1) {
877
 
                        memcpy(self->data + start, vbuf.buf, slicelen);
878
 
                }
879
 
                else {
880
 
                        Py_ssize_t cur, i;
881
 
 
882
 
                        for (cur = start, i = 0;
883
 
                             i < slicelen;
884
 
                             cur += step, i++)
885
 
                        {
886
 
                                self->data[cur] = ((char *)vbuf.buf)[i];
887
 
                        }
888
 
                }
889
 
                PyBuffer_Release(&vbuf);
890
 
                return 0;
891
 
        }
892
 
        else {
893
 
                PyErr_SetString(PyExc_TypeError,
894
 
                                "mmap indices must be integer");
895
 
                return -1;
896
 
        }
 
811
    CHECK_VALID(-1);
 
812
 
 
813
    if (!is_writable(self))
 
814
        return -1;
 
815
 
 
816
    if (PyIndex_Check(item)) {
 
817
        Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
 
818
        Py_ssize_t v;
 
819
 
 
820
        if (i == -1 && PyErr_Occurred())
 
821
            return -1;
 
822
        if (i < 0)
 
823
            i += self->size;
 
824
        if (i < 0 || (size_t)i >= self->size) {
 
825
            PyErr_SetString(PyExc_IndexError,
 
826
                            "mmap index out of range");
 
827
            return -1;
 
828
        }
 
829
        if (value == NULL) {
 
830
            PyErr_SetString(PyExc_TypeError,
 
831
                            "mmap doesn't support item deletion");
 
832
            return -1;
 
833
        }
 
834
        if (!PyIndex_Check(value)) {
 
835
            PyErr_SetString(PyExc_TypeError,
 
836
                            "mmap item value must be an int");
 
837
            return -1;
 
838
        }
 
839
        v = PyNumber_AsSsize_t(value, PyExc_TypeError);
 
840
        if (v == -1 && PyErr_Occurred())
 
841
            return -1;
 
842
        if (v < 0 || v > 255) {
 
843
            PyErr_SetString(PyExc_ValueError,
 
844
                            "mmap item value must be "
 
845
                            "in range(0, 256)");
 
846
            return -1;
 
847
        }
 
848
        self->data[i] = v;
 
849
        return 0;
 
850
    }
 
851
    else if (PySlice_Check(item)) {
 
852
        Py_ssize_t start, stop, step, slicelen;
 
853
        Py_buffer vbuf;
 
854
 
 
855
        if (PySlice_GetIndicesEx((PySliceObject *)item,
 
856
                                 self->size, &start, &stop,
 
857
                                 &step, &slicelen) < 0) {
 
858
            return -1;
 
859
        }
 
860
        if (value == NULL) {
 
861
            PyErr_SetString(PyExc_TypeError,
 
862
                "mmap object doesn't support slice deletion");
 
863
            return -1;
 
864
        }
 
865
        if (PyObject_GetBuffer(value, &vbuf, PyBUF_SIMPLE) < 0)
 
866
            return -1;
 
867
        if (vbuf.len != slicelen) {
 
868
            PyErr_SetString(PyExc_IndexError,
 
869
                "mmap slice assignment is wrong size");
 
870
            PyBuffer_Release(&vbuf);
 
871
            return -1;
 
872
        }
 
873
 
 
874
        if (slicelen == 0) {
 
875
        }
 
876
        else if (step == 1) {
 
877
            memcpy(self->data + start, vbuf.buf, slicelen);
 
878
        }
 
879
        else {
 
880
            Py_ssize_t cur, i;
 
881
 
 
882
            for (cur = start, i = 0;
 
883
                 i < slicelen;
 
884
                 cur += step, i++)
 
885
            {
 
886
                self->data[cur] = ((char *)vbuf.buf)[i];
 
887
            }
 
888
        }
 
889
        PyBuffer_Release(&vbuf);
 
890
        return 0;
 
891
    }
 
892
    else {
 
893
        PyErr_SetString(PyExc_TypeError,
 
894
                        "mmap indices must be integer");
 
895
        return -1;
 
896
    }
897
897
}
898
898
 
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*/
904
 
        0,                                    /*sq_slice*/
905
 
        (ssizeobjargproc)mmap_ass_item,        /*sq_ass_item*/
906
 
        0,                                    /*sq_ass_slice*/
 
900
    (lenfunc)mmap_length,                      /*sq_length*/
 
901
    (binaryfunc)mmap_concat,                   /*sq_concat*/
 
902
    (ssizeargfunc)mmap_repeat,                 /*sq_repeat*/
 
903
    (ssizeargfunc)mmap_item,                           /*sq_item*/
 
904
    0,                                        /*sq_slice*/
 
905
    (ssizeobjargproc)mmap_ass_item,            /*sq_ass_item*/
 
906
    0,                                        /*sq_ass_slice*/
907
907
};
908
908
 
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,
913
913
};
914
914
 
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,
918
918
};
919
919
 
920
920
static PyObject *
945
945
 
946
946
 
947
947
static PyTypeObject mmap_object_type = {
948
 
        PyVarObject_HEAD_INIT(NULL, 0)
949
 
        "mmap.mmap",                            /* tp_name */
950
 
        sizeof(mmap_object),                    /* tp_size */
951
 
        0,                                      /* tp_itemsize */
952
 
        /* methods */
953
 
        (destructor) mmap_object_dealloc,       /* tp_dealloc */
954
 
        0,                                      /* tp_print */
955
 
        0,                                      /* tp_getattr */
956
 
        0,                                      /* tp_setattr */
957
 
        0,                                      /* tp_reserved */
958
 
        0,                                      /* tp_repr */
959
 
        0,                                      /* tp_as_number */
960
 
        &mmap_as_sequence,                      /*tp_as_sequence*/
961
 
        &mmap_as_mapping,                       /*tp_as_mapping*/
962
 
        0,                                      /*tp_hash*/
963
 
        0,                                      /*tp_call*/
964
 
        0,                                      /*tp_str*/
965
 
        PyObject_GenericGetAttr,                /*tp_getattro*/
966
 
        0,                                      /*tp_setattro*/
967
 
        &mmap_as_buffer,                        /*tp_as_buffer*/
968
 
        Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,               /*tp_flags*/
969
 
        mmap_doc,                               /*tp_doc*/
970
 
        0,                                      /* tp_traverse */
971
 
        0,                                      /* tp_clear */
972
 
        0,                                      /* tp_richcompare */
973
 
        0,                                      /* tp_weaklistoffset */
974
 
        0,                                      /* tp_iter */
975
 
        0,                                      /* tp_iternext */
976
 
        mmap_object_methods,                    /* tp_methods */
977
 
        0,                                      /* tp_members */
978
 
        0,                                      /* tp_getset */
979
 
        0,                                      /* tp_base */
980
 
        0,                                      /* tp_dict */
981
 
        0,                                      /* tp_descr_get */
982
 
        0,                                      /* tp_descr_set */
983
 
        0,                                      /* tp_dictoffset */
984
 
        0,                                      /* tp_init */
985
 
        PyType_GenericAlloc,                    /* tp_alloc */
986
 
        new_mmap_object,                        /* tp_new */
987
 
        PyObject_Del,                           /* tp_free */
 
948
    PyVarObject_HEAD_INIT(NULL, 0)
 
949
    "mmap.mmap",                                /* tp_name */
 
950
    sizeof(mmap_object),                        /* tp_size */
 
951
    0,                                          /* tp_itemsize */
 
952
    /* methods */
 
953
    (destructor) mmap_object_dealloc,           /* tp_dealloc */
 
954
    0,                                          /* tp_print */
 
955
    0,                                          /* tp_getattr */
 
956
    0,                                          /* tp_setattr */
 
957
    0,                                          /* tp_reserved */
 
958
    0,                                          /* tp_repr */
 
959
    0,                                          /* tp_as_number */
 
960
    &mmap_as_sequence,                          /*tp_as_sequence*/
 
961
    &mmap_as_mapping,                           /*tp_as_mapping*/
 
962
    0,                                          /*tp_hash*/
 
963
    0,                                          /*tp_call*/
 
964
    0,                                          /*tp_str*/
 
965
    PyObject_GenericGetAttr,                    /*tp_getattro*/
 
966
    0,                                          /*tp_setattro*/
 
967
    &mmap_as_buffer,                            /*tp_as_buffer*/
 
968
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,                   /*tp_flags*/
 
969
    mmap_doc,                                   /*tp_doc*/
 
970
    0,                                          /* tp_traverse */
 
971
    0,                                          /* tp_clear */
 
972
    0,                                          /* tp_richcompare */
 
973
    0,                                          /* tp_weaklistoffset */
 
974
    0,                                          /* tp_iter */
 
975
    0,                                          /* tp_iternext */
 
976
    mmap_object_methods,                        /* tp_methods */
 
977
    0,                                          /* tp_members */
 
978
    0,                                          /* tp_getset */
 
979
    0,                                          /* tp_base */
 
980
    0,                                          /* tp_dict */
 
981
    0,                                          /* tp_descr_get */
 
982
    0,                                          /* tp_descr_set */
 
983
    0,                                          /* tp_dictoffset */
 
984
    0,                                      /* tp_init */
 
985
    PyType_GenericAlloc,                        /* tp_alloc */
 
986
    new_mmap_object,                            /* tp_new */
 
987
    PyObject_Del,                           /* tp_free */
988
988
};
989
989
 
990
990
 
995
995
static Py_ssize_t
996
996
_GetMapSize(PyObject *o, const char* param)
997
997
{
998
 
        if (o == NULL)
999
 
                return 0;
1000
 
        if (PyIndex_Check(o)) {
1001
 
                Py_ssize_t i = PyNumber_AsSsize_t(o, PyExc_OverflowError);
1002
 
                if (i==-1 && PyErr_Occurred())
1003
 
                        return -1;
1004
 
                if (i < 0) {
1005
 
                        PyErr_Format(PyExc_OverflowError,
1006
 
                                        "memory mapped %s must be positive",
1007
 
                                        param);
1008
 
                        return -1;
1009
 
                }
1010
 
                return i;
1011
 
        }
 
998
    if (o == NULL)
 
999
        return 0;
 
1000
    if (PyIndex_Check(o)) {
 
1001
        Py_ssize_t i = PyNumber_AsSsize_t(o, PyExc_OverflowError);
 
1002
        if (i==-1 && PyErr_Occurred())
 
1003
            return -1;
 
1004
        if (i < 0) {
 
1005
            PyErr_Format(PyExc_OverflowError,
 
1006
                            "memory mapped %s must be positive",
 
1007
                            param);
 
1008
            return -1;
 
1009
        }
 
1010
        return i;
 
1011
    }
1012
1012
 
1013
 
        PyErr_SetString(PyExc_TypeError, "map size must be an integral value");
1014
 
        return -1;
 
1013
    PyErr_SetString(PyExc_TypeError, "map size must be an integral value");
 
1014
    return -1;
1015
1015
}
1016
1016
 
1017
1017
#ifdef UNIX
1019
1019
new_mmap_object(PyTypeObject *type, PyObject *args, PyObject *kwdict)
1020
1020
{
1021
1021
#ifdef HAVE_FSTAT
1022
 
        struct stat st;
 
1022
    struct stat st;
1023
1023
#endif
1024
 
        mmap_object *m_obj;
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;
1028
 
        int devzero = -1;
1029
 
        int access = (int)ACCESS_DEFAULT;
1030
 
        static char *keywords[] = {"fileno", "length",
1031
 
                                         "flags", "prot",
1032
 
                                         "access", "offset", NULL};
1033
 
 
1034
 
        if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iO|iiiO", keywords,
1035
 
                                         &fd, &map_size_obj, &flags, &prot,
1036
 
                                         &access, &offset_obj))
1037
 
                return NULL;
1038
 
        map_size = _GetMapSize(map_size_obj, "size");
1039
 
        if (map_size < 0)
1040
 
                return NULL;
1041
 
        offset = _GetMapSize(offset_obj, "offset");
1042
 
        if (offset < 0)
1043
 
                return NULL;
1044
 
 
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) {
1050
 
        case ACCESS_READ:
1051
 
                flags = MAP_SHARED;
1052
 
                prot = PROT_READ;
1053
 
                break;
1054
 
        case ACCESS_WRITE:
1055
 
                flags = MAP_SHARED;
1056
 
                prot = PROT_READ | PROT_WRITE;
1057
 
                break;
1058
 
        case ACCESS_COPY:
1059
 
                flags = MAP_PRIVATE;
1060
 
                prot = PROT_READ | PROT_WRITE;
1061
 
                break;
1062
 
        case ACCESS_DEFAULT:
1063
 
                /* use the specified or default values of flags and prot */
1064
 
                break;
1065
 
        default:
1066
 
                return PyErr_Format(PyExc_ValueError,
1067
 
                                    "mmap invalid access parameter.");
1068
 
        }
 
1024
    mmap_object *m_obj;
 
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;
 
1028
    int devzero = -1;
 
1029
    int access = (int)ACCESS_DEFAULT;
 
1030
    static char *keywords[] = {"fileno", "length",
 
1031
                                     "flags", "prot",
 
1032
                                     "access", "offset", NULL};
 
1033
 
 
1034
    if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iO|iiiO", keywords,
 
1035
                                     &fd, &map_size_obj, &flags, &prot,
 
1036
                                     &access, &offset_obj))
 
1037
        return NULL;
 
1038
    map_size = _GetMapSize(map_size_obj, "size");
 
1039
    if (map_size < 0)
 
1040
        return NULL;
 
1041
    offset = _GetMapSize(offset_obj, "offset");
 
1042
    if (offset < 0)
 
1043
        return NULL;
 
1044
 
 
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) {
 
1050
    case ACCESS_READ:
 
1051
        flags = MAP_SHARED;
 
1052
        prot = PROT_READ;
 
1053
        break;
 
1054
    case ACCESS_WRITE:
 
1055
        flags = MAP_SHARED;
 
1056
        prot = PROT_READ | PROT_WRITE;
 
1057
        break;
 
1058
    case ACCESS_COPY:
 
1059
        flags = MAP_PRIVATE;
 
1060
        prot = PROT_READ | PROT_WRITE;
 
1061
        break;
 
1062
    case ACCESS_DEFAULT:
 
1063
        /* use the specified or default values of flags and prot */
 
1064
        break;
 
1065
    default:
 
1066
        return PyErr_Format(PyExc_ValueError,
 
1067
                            "mmap invalid access parameter.");
 
1068
    }
1069
1069
 
1070
1070
    if (prot == PROT_READ) {
1071
 
        access = ACCESS_READ;
 
1071
    access = ACCESS_READ;
1072
1072
    }
1073
1073
 
1074
1074
#ifdef HAVE_FSTAT
1075
1075
#  ifdef __VMS
1076
 
        /* on OpenVMS we must ensure that all bytes are written to the file */
1077
 
        if (fd != -1) {
1078
 
                fsync(fd);
1079
 
        }
 
1076
    /* on OpenVMS we must ensure that all bytes are written to the file */
 
1077
    if (fd != -1) {
 
1078
        fsync(fd);
 
1079
    }
1080
1080
#  endif
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");
1087
 
                        return NULL;
1088
 
                }
1089
 
        }
 
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");
 
1087
            return NULL;
 
1088
        }
 
1089
    }
1090
1090
#endif
1091
 
        m_obj = (mmap_object *)type->tp_alloc(type, 0);
1092
 
        if (m_obj == NULL) {return NULL;}
1093
 
        m_obj->data = NULL;
1094
 
        m_obj->size = (size_t) map_size;
1095
 
        m_obj->pos = (size_t) 0;
1096
 
        m_obj->exports = 0;
1097
 
        m_obj->offset = offset;
1098
 
        if (fd == -1) {
1099
 
                m_obj->fd = -1;
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.
1103
 
                */
 
1091
    m_obj = (mmap_object *)type->tp_alloc(type, 0);
 
1092
    if (m_obj == NULL) {return NULL;}
 
1093
    m_obj->data = NULL;
 
1094
    m_obj->size = (size_t) map_size;
 
1095
    m_obj->pos = (size_t) 0;
 
1096
    m_obj->exports = 0;
 
1097
    m_obj->offset = offset;
 
1098
    if (fd == -1) {
 
1099
        m_obj->fd = -1;
 
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.
 
1103
        */
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;
1107
1107
#else
1108
 
                /* SVR4 method to map anonymous memory is to open /dev/zero */
1109
 
                fd = devzero = open("/dev/zero", O_RDWR);
1110
 
                if (devzero == -1) {
1111
 
                        Py_DECREF(m_obj);
1112
 
                        PyErr_SetFromErrno(mmap_module_error);
1113
 
                        return NULL;
1114
 
                }
 
1108
        /* SVR4 method to map anonymous memory is to open /dev/zero */
 
1109
        fd = devzero = open("/dev/zero", O_RDWR);
 
1110
        if (devzero == -1) {
 
1111
            Py_DECREF(m_obj);
 
1112
            PyErr_SetFromErrno(mmap_module_error);
 
1113
            return NULL;
 
1114
        }
1115
1115
#endif
1116
 
        } else {
1117
 
                m_obj->fd = dup(fd);
1118
 
                if (m_obj->fd == -1) {
1119
 
                        Py_DECREF(m_obj);
1120
 
                        PyErr_SetFromErrno(mmap_module_error);
1121
 
                        return NULL;
1122
 
                }
1123
 
        }
1124
 
        
1125
 
        m_obj->data = mmap(NULL, map_size,
1126
 
                           prot, flags,
1127
 
                           fd, offset);
1128
 
 
1129
 
        if (devzero != -1) {
1130
 
                close(devzero);
1131
 
        }
1132
 
 
1133
 
        if (m_obj->data == (char *)-1) {
1134
 
                m_obj->data = NULL;
1135
 
                Py_DECREF(m_obj);
1136
 
                PyErr_SetFromErrno(mmap_module_error);
1137
 
                return NULL;
1138
 
        }
1139
 
        m_obj->access = (access_mode)access;
1140
 
        return (PyObject *)m_obj;
 
1116
    } else {
 
1117
        m_obj->fd = dup(fd);
 
1118
        if (m_obj->fd == -1) {
 
1119
            Py_DECREF(m_obj);
 
1120
            PyErr_SetFromErrno(mmap_module_error);
 
1121
            return NULL;
 
1122
        }
 
1123
    }
 
1124
 
 
1125
    m_obj->data = mmap(NULL, map_size,
 
1126
                       prot, flags,
 
1127
                       fd, offset);
 
1128
 
 
1129
    if (devzero != -1) {
 
1130
        close(devzero);
 
1131
    }
 
1132
 
 
1133
    if (m_obj->data == (char *)-1) {
 
1134
        m_obj->data = NULL;
 
1135
        Py_DECREF(m_obj);
 
1136
        PyErr_SetFromErrno(mmap_module_error);
 
1137
        return NULL;
 
1138
    }
 
1139
    m_obj->access = (access_mode)access;
 
1140
    return (PyObject *)m_obj;
1141
1141
}
1142
1142
#endif /* UNIX */
1143
1143
 
1145
1145
static PyObject *
1146
1146
new_mmap_object(PyTypeObject *type, PyObject *args, PyObject *kwdict)
1147
1147
{
1148
 
        mmap_object *m_obj;
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 */
1155
 
        char *tagname = "";
1156
 
        DWORD dwErr = 0;
1157
 
        int fileno;
1158
 
        HANDLE fh = 0;
1159
 
        int access = (access_mode)ACCESS_DEFAULT;
1160
 
        DWORD flProtect, dwDesiredAccess;
1161
 
        static char *keywords[] = { "fileno", "length",
1162
 
                                          "tagname",
1163
 
                                          "access", "offset", NULL };
1164
 
 
1165
 
        if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iO|ziO", keywords,
1166
 
                                         &fileno, &map_size_obj,
1167
 
                                         &tagname, &access, &offset_obj)) {
1168
 
                return NULL;
1169
 
        }
1170
 
 
1171
 
        switch((access_mode)access) {
1172
 
        case ACCESS_READ:
1173
 
                flProtect = PAGE_READONLY;
1174
 
                dwDesiredAccess = FILE_MAP_READ;
1175
 
                break;
1176
 
        case ACCESS_DEFAULT:  case ACCESS_WRITE:
1177
 
                flProtect = PAGE_READWRITE;
1178
 
                dwDesiredAccess = FILE_MAP_WRITE;
1179
 
                break;
1180
 
        case ACCESS_COPY:
1181
 
                flProtect = PAGE_WRITECOPY;
1182
 
                dwDesiredAccess = FILE_MAP_COPY;
1183
 
                break;
1184
 
        default:
1185
 
                return PyErr_Format(PyExc_ValueError,
1186
 
                                    "mmap invalid access parameter.");
1187
 
        }
1188
 
 
1189
 
        map_size = _GetMapSize(map_size_obj, "size");
1190
 
        if (map_size < 0)
1191
 
                return NULL;
1192
 
        offset = _GetMapSize(offset_obj, "offset");
1193
 
        if (offset < 0)
1194
 
                return NULL;
1195
 
 
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?
1200
 
           if (fileno == 0)
1201
 
                PyErr_WarnEx(PyExc_DeprecationWarning,
1202
 
                             "don't use 0 for anonymous memory",
1203
 
                             1);
1204
 
         */
1205
 
        if (fileno != -1 && fileno != 0) {
1206
 
                fh = (HANDLE)_get_osfhandle(fileno);
1207
 
                if (fh==(HANDLE)-1) {
1208
 
                        PyErr_SetFromErrno(mmap_module_error);
1209
 
                        return NULL;
1210
 
                }
1211
 
                /* Win9x appears to need us seeked to zero */
1212
 
                lseek(fileno, 0, SEEK_SET);
1213
 
        }
1214
 
 
1215
 
        m_obj = (mmap_object *)type->tp_alloc(type, 0);
1216
 
        if (m_obj == NULL)
1217
 
                return NULL;
1218
 
        /* Set every field to an invalid marker, so we can safely
1219
 
           destruct the object in the face of failure */
1220
 
        m_obj->data = NULL;
1221
 
        m_obj->file_handle = INVALID_HANDLE_VALUE;
1222
 
        m_obj->map_handle = NULL;
1223
 
        m_obj->tagname = NULL;
1224
 
        m_obj->offset = offset;
1225
 
 
1226
 
        if (fh) {
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();
1238
 
                        Py_DECREF(m_obj);
1239
 
                        PyErr_SetFromWindowsErr(dwErr);
1240
 
                        return NULL;
1241
 
                }
1242
 
                if (!map_size) {
1243
 
                        DWORD low,high;
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) {
1249
 
                                Py_DECREF(m_obj);
1250
 
                                return PyErr_SetFromWindowsErr(dwErr);
1251
 
                        }
1252
 
 
1253
 
#if SIZEOF_SIZE_T > 4
1254
 
                        m_obj->size = (((size_t)high)<<32) + low;
1255
 
#else
1256
 
                        if (high)
1257
 
                                /* File is too large to map completely */
1258
 
                                m_obj->size = (size_t)-1;
1259
 
                        else
1260
 
                                m_obj->size = low;
1261
 
#endif
1262
 
                } else {
1263
 
                        m_obj->size = map_size;
1264
 
                }
1265
 
        }
1266
 
        else {
1267
 
                m_obj->size = map_size;
1268
 
        }
1269
 
 
1270
 
        /* set the initial position */
1271
 
        m_obj->pos = (size_t) 0;
1272
 
 
1273
 
        m_obj->exports = 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) {
1278
 
                        PyErr_NoMemory();
1279
 
                        Py_DECREF(m_obj);
1280
 
                        return NULL;
1281
 
                }
1282
 
                strcpy(m_obj->tagname, tagname);
1283
 
        }
1284
 
        else
1285
 
                m_obj->tagname = NULL;
1286
 
 
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.
1292
 
         */
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);
1298
 
#else
1299
 
        size_hi = 0;
1300
 
        size_lo = (DWORD)(offset + m_obj->size);
1301
 
        off_hi = 0;
1302
 
        off_lo = (DWORD)offset;
1303
 
#endif
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,
1307
 
                                              NULL,
1308
 
                                              flProtect,
1309
 
                                              size_hi,
1310
 
                                              size_lo,
1311
 
                                              m_obj->tagname);
1312
 
        if (m_obj->map_handle != NULL) {
1313
 
                m_obj->data = (char *) MapViewOfFile(m_obj->map_handle,
1314
 
                                                     dwDesiredAccess,
1315
 
                                                     off_hi,
1316
 
                                                     off_lo,
1317
 
                                                     m_obj->size);
1318
 
                if (m_obj->data != NULL)
1319
 
                        return (PyObject *)m_obj;
1320
 
                else {
1321
 
                        dwErr = GetLastError();
1322
 
                        CloseHandle(m_obj->map_handle);
1323
 
                        m_obj->map_handle = NULL;
1324
 
                }
1325
 
        } else
1326
 
                dwErr = GetLastError();
1327
 
        Py_DECREF(m_obj);
1328
 
        PyErr_SetFromWindowsErr(dwErr);
1329
 
        return NULL;
 
1148
    mmap_object *m_obj;
 
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 */
 
1155
    char *tagname = "";
 
1156
    DWORD dwErr = 0;
 
1157
    int fileno;
 
1158
    HANDLE fh = 0;
 
1159
    int access = (access_mode)ACCESS_DEFAULT;
 
1160
    DWORD flProtect, dwDesiredAccess;
 
1161
    static char *keywords[] = { "fileno", "length",
 
1162
                                      "tagname",
 
1163
                                      "access", "offset", NULL };
 
1164
 
 
1165
    if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iO|ziO", keywords,
 
1166
                                     &fileno, &map_size_obj,
 
1167
                                     &tagname, &access, &offset_obj)) {
 
1168
        return NULL;
 
1169
    }
 
1170
 
 
1171
    switch((access_mode)access) {
 
1172
    case ACCESS_READ:
 
1173
        flProtect = PAGE_READONLY;
 
1174
        dwDesiredAccess = FILE_MAP_READ;
 
1175
        break;
 
1176
    case ACCESS_DEFAULT:  case ACCESS_WRITE:
 
1177
        flProtect = PAGE_READWRITE;
 
1178
        dwDesiredAccess = FILE_MAP_WRITE;
 
1179
        break;
 
1180
    case ACCESS_COPY:
 
1181
        flProtect = PAGE_WRITECOPY;
 
1182
        dwDesiredAccess = FILE_MAP_COPY;
 
1183
        break;
 
1184
    default:
 
1185
        return PyErr_Format(PyExc_ValueError,
 
1186
                            "mmap invalid access parameter.");
 
1187
    }
 
1188
 
 
1189
    map_size = _GetMapSize(map_size_obj, "size");
 
1190
    if (map_size < 0)
 
1191
        return NULL;
 
1192
    offset = _GetMapSize(offset_obj, "offset");
 
1193
    if (offset < 0)
 
1194
        return NULL;
 
1195
 
 
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?
 
1200
       if (fileno == 0)
 
1201
        PyErr_WarnEx(PyExc_DeprecationWarning,
 
1202
                     "don't use 0 for anonymous memory",
 
1203
                     1);
 
1204
     */
 
1205
    if (fileno != -1 && fileno != 0) {
 
1206
        fh = (HANDLE)_get_osfhandle(fileno);
 
1207
        if (fh==(HANDLE)-1) {
 
1208
            PyErr_SetFromErrno(mmap_module_error);
 
1209
            return NULL;
 
1210
        }
 
1211
        /* Win9x appears to need us seeked to zero */
 
1212
        lseek(fileno, 0, SEEK_SET);
 
1213
    }
 
1214
 
 
1215
    m_obj = (mmap_object *)type->tp_alloc(type, 0);
 
1216
    if (m_obj == NULL)
 
1217
        return NULL;
 
1218
    /* Set every field to an invalid marker, so we can safely
 
1219
       destruct the object in the face of failure */
 
1220
    m_obj->data = NULL;
 
1221
    m_obj->file_handle = INVALID_HANDLE_VALUE;
 
1222
    m_obj->map_handle = NULL;
 
1223
    m_obj->tagname = NULL;
 
1224
    m_obj->offset = offset;
 
1225
 
 
1226
    if (fh) {
 
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();
 
1238
            Py_DECREF(m_obj);
 
1239
            PyErr_SetFromWindowsErr(dwErr);
 
1240
            return NULL;
 
1241
        }
 
1242
        if (!map_size) {
 
1243
            DWORD low,high;
 
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) {
 
1249
                Py_DECREF(m_obj);
 
1250
                return PyErr_SetFromWindowsErr(dwErr);
 
1251
            }
 
1252
 
 
1253
#if SIZEOF_SIZE_T > 4
 
1254
            m_obj->size = (((size_t)high)<<32) + low;
 
1255
#else
 
1256
            if (high)
 
1257
                /* File is too large to map completely */
 
1258
                m_obj->size = (size_t)-1;
 
1259
            else
 
1260
                m_obj->size = low;
 
1261
#endif
 
1262
        } else {
 
1263
            m_obj->size = map_size;
 
1264
        }
 
1265
    }
 
1266
    else {
 
1267
        m_obj->size = map_size;
 
1268
    }
 
1269
 
 
1270
    /* set the initial position */
 
1271
    m_obj->pos = (size_t) 0;
 
1272
 
 
1273
    m_obj->exports = 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) {
 
1278
            PyErr_NoMemory();
 
1279
            Py_DECREF(m_obj);
 
1280
            return NULL;
 
1281
        }
 
1282
        strcpy(m_obj->tagname, tagname);
 
1283
    }
 
1284
    else
 
1285
        m_obj->tagname = NULL;
 
1286
 
 
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.
 
1292
     */
 
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);
 
1298
#else
 
1299
    size_hi = 0;
 
1300
    size_lo = (DWORD)(offset + m_obj->size);
 
1301
    off_hi = 0;
 
1302
    off_lo = (DWORD)offset;
 
1303
#endif
 
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,
 
1307
                                          NULL,
 
1308
                                          flProtect,
 
1309
                                          size_hi,
 
1310
                                          size_lo,
 
1311
                                          m_obj->tagname);
 
1312
    if (m_obj->map_handle != NULL) {
 
1313
        m_obj->data = (char *) MapViewOfFile(m_obj->map_handle,
 
1314
                                             dwDesiredAccess,
 
1315
                                             off_hi,
 
1316
                                             off_lo,
 
1317
                                             m_obj->size);
 
1318
        if (m_obj->data != NULL)
 
1319
            return (PyObject *)m_obj;
 
1320
        else {
 
1321
            dwErr = GetLastError();
 
1322
            CloseHandle(m_obj->map_handle);
 
1323
            m_obj->map_handle = NULL;
 
1324
        }
 
1325
    } else
 
1326
        dwErr = GetLastError();
 
1327
    Py_DECREF(m_obj);
 
1328
    PyErr_SetFromWindowsErr(dwErr);
 
1329
    return NULL;
1330
1330
}
1331
1331
#endif /* MS_WINDOWS */
1332
1332
 
1333
1333
static void
1334
1334
setint(PyObject *d, const char *name, long value)
1335
1335
{
1336
 
        PyObject *o = PyLong_FromLong(value);
1337
 
        if (o && PyDict_SetItemString(d, name, o) == 0) {
1338
 
                Py_DECREF(o);
1339
 
        }
 
1336
    PyObject *o = PyLong_FromLong(value);
 
1337
    if (o && PyDict_SetItemString(d, name, o) == 0) {
 
1338
        Py_DECREF(o);
 
1339
    }
1340
1340
}
1341
1341
 
1342
1342
 
1343
1343
static struct PyModuleDef mmapmodule = {
1344
 
        PyModuleDef_HEAD_INIT,
1345
 
        "mmap",
1346
 
        NULL,
1347
 
        -1,
1348
 
        NULL,
1349
 
        NULL,
1350
 
        NULL,
1351
 
        NULL,
1352
 
        NULL
 
1344
    PyModuleDef_HEAD_INIT,
 
1345
    "mmap",
 
1346
    NULL,
 
1347
    -1,
 
1348
    NULL,
 
1349
    NULL,
 
1350
    NULL,
 
1351
    NULL,
 
1352
    NULL
1353
1353
};
1354
1354
 
1355
1355
PyMODINIT_FUNC
1356
1356
PyInit_mmap(void)
1357
1357
{
1358
 
        PyObject *dict, *module;
1359
 
 
1360
 
        if (PyType_Ready(&mmap_object_type) < 0)
1361
 
                return NULL;
1362
 
 
1363
 
        module = PyModule_Create(&mmapmodule);
1364
 
        if (module == NULL)
1365
 
                return NULL;
1366
 
        dict = PyModule_GetDict(module);
1367
 
        if (!dict)
1368
 
                return NULL;
1369
 
        mmap_module_error = PyErr_NewException("mmap.error",
1370
 
                PyExc_EnvironmentError , NULL);
1371
 
        if (mmap_module_error == NULL)
1372
 
                return NULL;
1373
 
        PyDict_SetItemString(dict, "error", mmap_module_error);
1374
 
        PyDict_SetItemString(dict, "mmap", (PyObject*) &mmap_object_type);
 
1358
    PyObject *dict, *module;
 
1359
 
 
1360
    if (PyType_Ready(&mmap_object_type) < 0)
 
1361
        return NULL;
 
1362
 
 
1363
    module = PyModule_Create(&mmapmodule);
 
1364
    if (module == NULL)
 
1365
        return NULL;
 
1366
    dict = PyModule_GetDict(module);
 
1367
    if (!dict)
 
1368
        return NULL;
 
1369
    mmap_module_error = PyErr_NewException("mmap.error",
 
1370
        PyExc_EnvironmentError , NULL);
 
1371
    if (mmap_module_error == NULL)
 
1372
        return 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);
1377
1377
#endif
1378
1378
#ifdef PROT_READ
1379
 
        setint(dict, "PROT_READ", PROT_READ);
 
1379
    setint(dict, "PROT_READ", PROT_READ);
1380
1380
#endif
1381
1381
#ifdef PROT_WRITE
1382
 
        setint(dict, "PROT_WRITE", PROT_WRITE);
 
1382
    setint(dict, "PROT_WRITE", PROT_WRITE);
1383
1383
#endif
1384
1384
 
1385
1385
#ifdef MAP_SHARED
1386
 
        setint(dict, "MAP_SHARED", MAP_SHARED);
 
1386
    setint(dict, "MAP_SHARED", MAP_SHARED);
1387
1387
#endif
1388
1388
#ifdef MAP_PRIVATE
1389
 
        setint(dict, "MAP_PRIVATE", MAP_PRIVATE);
 
1389
    setint(dict, "MAP_PRIVATE", MAP_PRIVATE);
1390
1390
#endif
1391
1391
#ifdef MAP_DENYWRITE
1392
 
        setint(dict, "MAP_DENYWRITE", MAP_DENYWRITE);
 
1392
    setint(dict, "MAP_DENYWRITE", MAP_DENYWRITE);
1393
1393
#endif
1394
1394
#ifdef MAP_EXECUTABLE
1395
 
        setint(dict, "MAP_EXECUTABLE", MAP_EXECUTABLE);
 
1395
    setint(dict, "MAP_EXECUTABLE", MAP_EXECUTABLE);
1396
1396
#endif
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);
1400
1400
#endif
1401
1401
 
1402
 
        setint(dict, "PAGESIZE", (long)my_getpagesize());
1403
 
 
1404
 
        setint(dict, "ALLOCATIONGRANULARITY", (long)my_getallocationgranularity()); 
1405
 
 
1406
 
        setint(dict, "ACCESS_READ", ACCESS_READ);
1407
 
        setint(dict, "ACCESS_WRITE", ACCESS_WRITE);
1408
 
        setint(dict, "ACCESS_COPY", ACCESS_COPY);
1409
 
        return module;
 
1402
    setint(dict, "PAGESIZE", (long)my_getpagesize());
 
1403
 
 
1404
    setint(dict, "ALLOCATIONGRANULARITY", (long)my_getallocationgranularity());
 
1405
 
 
1406
    setint(dict, "ACCESS_READ", ACCESS_READ);
 
1407
    setint(dict, "ACCESS_WRITE", ACCESS_WRITE);
 
1408
    setint(dict, "ACCESS_COPY", ACCESS_COPY);
 
1409
    return module;
1410
1410
}