Ignore:
Timestamp:
Mar 19, 2014, 11:11:30 AM (11 years ago)
Author:
dmik
Message:

python: Update vendor to 2.7.6.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • python/vendor/current/Modules/mmapmodule.c

    r2 r388  
    22 /  Author: Sam Rushing <rushing@nightmare.com>
    33 /  Hacked for Unix by AMK
    4  /  $Id: mmapmodule.c 73682 2009-06-29 14:37:28Z hirokazu.yamamoto $
     4 /  $Id$
    55
    66 / Modified to support mmap with offset - to map a 'window' of a file
     
    2424#ifndef MS_WINDOWS
    2525#define UNIX
     26# ifdef __APPLE__
     27#  include <fcntl.h>
     28# endif
    2629#endif
    2730
     
    3134my_getpagesize(void)
    3235{
    33         SYSTEM_INFO si;
    34         GetSystemInfo(&si);
    35         return si.dwPageSize;
     36    SYSTEM_INFO si;
     37    GetSystemInfo(&si);
     38    return si.dwPageSize;
    3639}
    3740
     
    4043{
    4144
    42         SYSTEM_INFO si;
    43         GetSystemInfo(&si);
    44         return si.dwAllocationGranularity;
     45    SYSTEM_INFO si;
     46    GetSystemInfo(&si);
     47    return si.dwAllocationGranularity;
    4548}
    4649
     
    5558my_getpagesize(void)
    5659{
    57         return sysconf(_SC_PAGESIZE);
     60    return sysconf(_SC_PAGESIZE);
    5861}
    5962
     
    8083typedef enum
    8184{
    82         ACCESS_DEFAULT,
    83         ACCESS_READ,
    84         ACCESS_WRITE,
    85         ACCESS_COPY
     85    ACCESS_DEFAULT,
     86    ACCESS_READ,
     87    ACCESS_WRITE,
     88    ACCESS_COPY
    8689} access_mode;
    8790
    8891typedef struct {
    89         PyObject_HEAD
    90         char *  data;
    91         size_t  size;
    92         size_t  pos;    /* relative to offset */
    93         size_t  offset;
    94 
     92    PyObject_HEAD
     93    char *      data;
     94    size_t      size;
     95    size_t      pos;    /* relative to offset */
    9596#ifdef MS_WINDOWS
    96         HANDLE  map_handle;
    97         HANDLE  file_handle;
    98         char *  tagname;
     97    PY_LONG_LONG offset;
     98#else
     99    off_t       offset;
     100#endif
     101
     102#ifdef MS_WINDOWS
     103    HANDLE      map_handle;
     104    HANDLE      file_handle;
     105    char *      tagname;
    99106#endif
    100107
    101108#ifdef UNIX
    102         int fd;
    103 #endif
    104 
    105         access_mode access;
     109    int fd;
     110#endif
     111
     112    access_mode access;
    106113} mmap_object;
    107114
     
    111118{
    112119#ifdef MS_WINDOWS
    113         if (m_obj->data != NULL)
    114                 UnmapViewOfFile (m_obj->data);
    115         if (m_obj->map_handle != NULL)
    116                 CloseHandle (m_obj->map_handle);
    117         if (m_obj->file_handle != INVALID_HANDLE_VALUE)
    118                 CloseHandle (m_obj->file_handle);
    119         if (m_obj->tagname)
    120                 PyMem_Free(m_obj->tagname);
     120    if (m_obj->data != NULL)
     121        UnmapViewOfFile (m_obj->data);
     122    if (m_obj->map_handle != NULL)
     123        CloseHandle (m_obj->map_handle);
     124    if (m_obj->file_handle != INVALID_HANDLE_VALUE)
     125        CloseHandle (m_obj->file_handle);
     126    if (m_obj->tagname)
     127        PyMem_Free(m_obj->tagname);
    121128#endif /* MS_WINDOWS */
    122129
    123130#ifdef UNIX
    124         if (m_obj->fd >= 0)
    125                 (void) close(m_obj->fd);
    126         if (m_obj->data!=NULL) {
    127                 msync(m_obj->data, m_obj->size, MS_SYNC);
    128                 munmap(m_obj->data, m_obj->size);
    129         }
     131    if (m_obj->fd >= 0)
     132        (void) close(m_obj->fd);
     133    if (m_obj->data!=NULL) {
     134        if (m_obj->access != ACCESS_READ && m_obj->access != ACCESS_COPY)
     135            msync(m_obj->data, m_obj->size, MS_SYNC);
     136        munmap(m_obj->data, m_obj->size);
     137    }
    130138#endif /* UNIX */
    131139
    132         Py_TYPE(m_obj)->tp_free((PyObject*)m_obj);
     140    Py_TYPE(m_obj)->tp_free((PyObject*)m_obj);
    133141}
    134142
     
    137145{
    138146#ifdef MS_WINDOWS
    139         /* For each resource we maintain, we need to check
    140            the value is valid, and if so, free the resource
    141            and set the member value to an invalid value so
    142            the dealloc does not attempt to resource clearing
    143            again.
    144            TODO - should we check for errors in the close operations???
    145         */
    146         if (self->data != NULL) {
    147                 UnmapViewOfFile(self->data);
    148                 self->data = NULL;
    149         }
    150         if (self->map_handle != NULL) {
    151                 CloseHandle(self->map_handle);
    152                 self->map_handle = NULL;
    153         }
    154         if (self->file_handle != INVALID_HANDLE_VALUE) {
    155                 CloseHandle(self->file_handle);
    156                 self->file_handle = INVALID_HANDLE_VALUE;
    157         }
     147    /* For each resource we maintain, we need to check
     148       the value is valid, and if so, free the resource
     149       and set the member value to an invalid value so
     150       the dealloc does not attempt to resource clearing
     151       again.
     152       TODO - should we check for errors in the close operations???
     153    */
     154    if (self->data != NULL) {
     155        UnmapViewOfFile(self->data);
     156        self->data = NULL;
     157    }
     158    if (self->map_handle != NULL) {
     159        CloseHandle(self->map_handle);
     160        self->map_handle = NULL;
     161    }
     162    if (self->file_handle != INVALID_HANDLE_VALUE) {
     163        CloseHandle(self->file_handle);
     164        self->file_handle = INVALID_HANDLE_VALUE;
     165    }
    158166#endif /* MS_WINDOWS */
    159167
    160168#ifdef UNIX
    161         if (0 <= self->fd)
    162                 (void) close(self->fd);
    163         self->fd = -1;
    164         if (self->data != NULL) {
    165                 munmap(self->data, self->size);
    166                 self->data = NULL;
    167         }
    168 #endif
    169 
    170         Py_INCREF(Py_None);
    171         return Py_None;
     169    if (0 <= self->fd)
     170        (void) close(self->fd);
     171    self->fd = -1;
     172    if (self->data != NULL) {
     173        munmap(self->data, self->size);
     174        self->data = NULL;
     175    }
     176#endif
     177
     178    Py_INCREF(Py_None);
     179    return Py_None;
    172180}
    173181
    174182#ifdef MS_WINDOWS
    175 #define CHECK_VALID(err)                                                \
    176 do {                                                                    \
    177     if (self->map_handle == NULL) {                                     \
    178         PyErr_SetString(PyExc_ValueError, "mmap closed or invalid");    \
    179         return err;                                                     \
    180     }                                                                   \
     183#define CHECK_VALID(err)                                                \
     184do {                                                                    \
     185    if (self->map_handle == NULL) {                                     \
     186    PyErr_SetString(PyExc_ValueError, "mmap closed or invalid");        \
     187    return err;                                                         \
     188    }                                                                   \
    181189} while (0)
    182190#endif /* MS_WINDOWS */
    183191
    184192#ifdef UNIX
    185 #define CHECK_VALID(err)                                                \
    186 do {                                                                    \
    187     if (self->data == NULL) {                                           \
    188         PyErr_SetString(PyExc_ValueError, "mmap closed or invalid");    \
    189         return err;                                                     \
    190         }                                                               \
     193#define CHECK_VALID(err)                                                \
     194do {                                                                    \
     195    if (self->data == NULL) {                                           \
     196    PyErr_SetString(PyExc_ValueError, "mmap closed or invalid");        \
     197    return err;                                                         \
     198    }                                                                   \
    191199} while (0)
    192200#endif /* UNIX */
     
    194202static PyObject *
    195203mmap_read_byte_method(mmap_object *self,
    196                       PyObject *unused)
    197 {
    198         CHECK_VALID(NULL);
    199         if (self->pos < self->size) {
    200                 char value = self->data[self->pos];
    201                 self->pos += 1;
    202                 return Py_BuildValue("c", value);
    203         } else {
    204                 PyErr_SetString(PyExc_ValueError, "read byte out of range");
    205                 return NULL;
    206         }
     204                      PyObject *unused)
     205{
     206    CHECK_VALID(NULL);
     207    if (self->pos < self->size) {
     208        char value = self->data[self->pos];
     209        self->pos += 1;
     210        return Py_BuildValue("c", value);
     211    } else {
     212        PyErr_SetString(PyExc_ValueError, "read byte out of range");
     213        return NULL;
     214    }
    207215}
    208216
    209217static PyObject *
    210218mmap_read_line_method(mmap_object *self,
    211                       PyObject *unused)
    212 {
    213         char *start = self->data+self->pos;
    214         char *eof = self->data+self->size;
    215         char *eol;
    216         PyObject *result;
    217 
    218         CHECK_VALID(NULL);
    219 
    220         eol = memchr(start, '\n', self->size - self->pos);
    221         if (!eol)
    222                 eol = eof;
    223         else
    224                 ++eol;          /* we're interested in the position after the
    225                                    newline. */
    226         result = PyString_FromStringAndSize(start, (eol - start));
    227         self->pos += (eol - start);
    228         return result;
     219                      PyObject *unused)
     220{
     221    char *start = self->data+self->pos;
     222    char *eof = self->data+self->size;
     223    char *eol;
     224    PyObject *result;
     225
     226    CHECK_VALID(NULL);
     227
     228    eol = memchr(start, '\n', self->size - self->pos);
     229    if (!eol)
     230        eol = eof;
     231    else
     232        ++eol;                  /* we're interested in the position after the
     233                           newline. */
     234    result = PyString_FromStringAndSize(start, (eol - start));
     235    self->pos += (eol - start);
     236    return result;
    229237}
    230238
    231239static PyObject *
    232240mmap_read_method(mmap_object *self,
    233                 PyObject *args)
    234 {
    235         Py_ssize_t num_bytes, n;
    236         PyObject *result;
    237 
    238         CHECK_VALID(NULL);
    239         if (!PyArg_ParseTuple(args, "n:read", &num_bytes))
    240                 return(NULL);
    241 
    242         /* silently 'adjust' out-of-range requests */
    243         assert(self->size >= self->pos);
    244         n = self->size - self->pos;
    245         /* The difference can overflow, only if self->size is greater than
    246         * PY_SSIZE_T_MAX.  But then the operation cannot possibly succeed,
    247          * because the mapped area and the returned string each need more
    248         * than half of the addressable memory.  So we clip the size, and let
    249         * the code below raise MemoryError.
    250         */
    251         if (n < 0)
    252                 n = PY_SSIZE_T_MAX;
    253         if (num_bytes < 0 || num_bytes > n) {
    254                 num_bytes = n;
    255         }
    256         result = Py_BuildValue("s#", self->data+self->pos, num_bytes);
    257         self->pos += num_bytes;
    258         return result;
     241                PyObject *args)
     242{
     243    Py_ssize_t num_bytes, n;
     244    PyObject *result;
     245
     246    CHECK_VALID(NULL);
     247    if (!PyArg_ParseTuple(args, "n:read", &num_bytes))
     248        return(NULL);
     249
     250    /* silently 'adjust' out-of-range requests */
     251    assert(self->size >= self->pos);
     252    n = self->size - self->pos;
     253    /* The difference can overflow, only if self->size is greater than
     254    * PY_SSIZE_T_MAX.  But then the operation cannot possibly succeed,
     255     * because the mapped area and the returned string each need more
     256    * than half of the addressable memory.  So we clip the size, and let
     257    * the code below raise MemoryError.
     258    */
     259    if (n < 0)
     260        n = PY_SSIZE_T_MAX;
     261    if (num_bytes < 0 || num_bytes > n) {
     262        num_bytes = n;
     263    }
     264    result = Py_BuildValue("s#", self->data+self->pos, num_bytes);
     265    self->pos += num_bytes;
     266    return result;
    259267}
    260268
    261269static PyObject *
    262270mmap_gfind(mmap_object *self,
    263            PyObject *args,
    264            int reverse)
    265 {
    266         Py_ssize_t start = self->pos;
    267         Py_ssize_t end = self->size;
    268         const char *needle;
    269         Py_ssize_t len;
    270 
    271         CHECK_VALID(NULL);
    272         if (!PyArg_ParseTuple(args, reverse ? "s#|nn:rfind" : "s#|nn:find",
    273                               &needle, &len, &start, &end)) {
    274                 return NULL;
    275         } else {
    276                 const char *p, *start_p, *end_p;
    277                 int sign = reverse ? -1 : 1;
    278 
    279                 if (start < 0)
    280                         start += self->size;
    281                 if (start < 0)
    282                         start = 0;
    283                 else if ((size_t)start > self->size)
    284                         start = self->size;
    285 
    286                 if (end < 0)
    287                         end += self->size;
    288                 if (end < 0)
    289                         end = 0;
    290                 else if ((size_t)end > self->size)
    291                         end = self->size;
    292 
    293                 start_p = self->data + start;
    294                 end_p = self->data + end;
    295 
    296                 for (p = (reverse ? end_p - len : start_p);
    297                      (p >= start_p) && (p + len <= end_p); p += sign) {
    298                         Py_ssize_t i;
    299                         for (i = 0; i < len && needle[i] == p[i]; ++i)
    300                                 /* nothing */;
    301                         if (i == len) {
    302                                 return PyInt_FromSsize_t(p - self->data);
    303                         }
    304                 }
    305                 return PyInt_FromLong(-1);
    306         }
     271           PyObject *args,
     272           int reverse)
     273{
     274    Py_ssize_t start = self->pos;
     275    Py_ssize_t end = self->size;
     276    const char *needle;
     277    Py_ssize_t len;
     278
     279    CHECK_VALID(NULL);
     280    if (!PyArg_ParseTuple(args, reverse ? "s#|nn:rfind" : "s#|nn:find",
     281                          &needle, &len, &start, &end)) {
     282        return NULL;
     283    } else {
     284        const char *p, *start_p, *end_p;
     285        int sign = reverse ? -1 : 1;
     286
     287        if (start < 0)
     288            start += self->size;
     289        if (start < 0)
     290            start = 0;
     291        else if ((size_t)start > self->size)
     292            start = self->size;
     293
     294        if (end < 0)
     295            end += self->size;
     296        if (end < 0)
     297            end = 0;
     298        else if ((size_t)end > self->size)
     299            end = self->size;
     300
     301        start_p = self->data + start;
     302        end_p = self->data + end;
     303
     304        for (p = (reverse ? end_p - len : start_p);
     305             (p >= start_p) && (p + len <= end_p); p += sign) {
     306            Py_ssize_t i;
     307            for (i = 0; i < len && needle[i] == p[i]; ++i)
     308                /* nothing */;
     309            if (i == len) {
     310                return PyInt_FromSsize_t(p - self->data);
     311            }
     312        }
     313        return PyInt_FromLong(-1);
     314    }
    307315}
    308316
    309317static PyObject *
    310318mmap_find_method(mmap_object *self,
    311                 PyObject *args)
    312 {
    313         return mmap_gfind(self, args, 0);
     319                PyObject *args)
     320{
     321    return mmap_gfind(self, args, 0);
    314322}
    315323
    316324static PyObject *
    317325mmap_rfind_method(mmap_object *self,
    318                 PyObject *args)
    319 {
    320         return mmap_gfind(self, args, 1);
     326                PyObject *args)
     327{
     328    return mmap_gfind(self, args, 1);
    321329}
    322330
     
    324332is_writeable(mmap_object *self)
    325333{
    326         if (self->access != ACCESS_READ)
    327                 return 1;
    328         PyErr_Format(PyExc_TypeError, "mmap can't modify a readonly memory map.");
    329         return 0;
     334    if (self->access != ACCESS_READ)
     335        return 1;
     336    PyErr_Format(PyExc_TypeError, "mmap can't modify a readonly memory map.");
     337    return 0;
    330338}
    331339
     
    333341is_resizeable(mmap_object *self)
    334342{
    335         if ((self->access == ACCESS_WRITE) || (self->access == ACCESS_DEFAULT))
    336                 return 1;
    337         PyErr_Format(PyExc_TypeError,
    338                      "mmap can't resize a readonly or copy-on-write memory map.");
    339         return 0;
     343    if ((self->access == ACCESS_WRITE) || (self->access == ACCESS_DEFAULT))
     344        return 1;
     345    PyErr_Format(PyExc_TypeError,
     346                 "mmap can't resize a readonly or copy-on-write memory map.");
     347    return 0;
    340348}
    341349
     
    343351static PyObject *
    344352mmap_write_method(mmap_object *self,
    345                   PyObject *args)
    346 {
    347         Py_ssize_t length;
    348         char *data;
    349 
    350         CHECK_VALID(NULL);
    351         if (!PyArg_ParseTuple(args, "s#:write", &data, &length))
    352                 return(NULL);
    353 
    354         if (!is_writeable(self))
    355                 return NULL;
    356 
    357         if ((self->pos + length) > self->size) {
    358                 PyErr_SetString(PyExc_ValueError, "data out of range");
    359                 return NULL;
    360         }
    361         memcpy(self->data+self->pos, data, length);
    362         self->pos = self->pos+length;
    363         Py_INCREF(Py_None);
    364         return Py_None;
     353                  PyObject *args)
     354{
     355    Py_ssize_t length;
     356    char *data;
     357
     358    CHECK_VALID(NULL);
     359    if (!PyArg_ParseTuple(args, "s#:write", &data, &length))
     360        return(NULL);
     361
     362    if (!is_writeable(self))
     363        return NULL;
     364
     365    if ((self->pos + length) > self->size) {
     366        PyErr_SetString(PyExc_ValueError, "data out of range");
     367        return NULL;
     368    }
     369    memcpy(self->data+self->pos, data, length);
     370    self->pos = self->pos+length;
     371    Py_INCREF(Py_None);
     372    return Py_None;
    365373}
    366374
    367375static PyObject *
    368376mmap_write_byte_method(mmap_object *self,
    369                        PyObject *args)
    370 {
    371         char value;
    372 
    373         CHECK_VALID(NULL);
    374         if (!PyArg_ParseTuple(args, "c:write_byte", &value))
    375                 return(NULL);
    376 
    377         if (!is_writeable(self))
    378                 return NULL;
    379 
    380         if (self->pos < self->size) {
    381                 *(self->data+self->pos) = value;
    382                 self->pos += 1;
    383                 Py_INCREF(Py_None);
    384                 return Py_None;
    385         }
    386         else {
    387                 PyErr_SetString(PyExc_ValueError, "write byte out of range");
    388                 return NULL;
    389         }
     377                       PyObject *args)
     378{
     379    char value;
     380
     381    CHECK_VALID(NULL);
     382    if (!PyArg_ParseTuple(args, "c:write_byte", &value))
     383        return(NULL);
     384
     385    if (!is_writeable(self))
     386        return NULL;
     387
     388    if (self->pos < self->size) {
     389        *(self->data+self->pos) = value;
     390        self->pos += 1;
     391        Py_INCREF(Py_None);
     392        return Py_None;
     393    }
     394    else {
     395        PyErr_SetString(PyExc_ValueError, "write byte out of range");
     396        return NULL;
     397    }
    390398}
    391399
    392400static PyObject *
    393401mmap_size_method(mmap_object *self,
    394                 PyObject *unused)
    395 {
    396         CHECK_VALID(NULL);
     402                PyObject *unused)
     403{
     404    CHECK_VALID(NULL);
    397405
    398406#ifdef MS_WINDOWS
    399         if (self->file_handle != INVALID_HANDLE_VALUE) {
    400                 DWORD low,high;
    401                 PY_LONG_LONG size;
    402                 low = GetFileSize(self->file_handle, &high);
    403                 if (low == INVALID_FILE_SIZE) {
    404                         /* It might be that the function appears to have failed,
    405                            when indeed its size equals INVALID_FILE_SIZE */
    406                         DWORD error = GetLastError();
    407                         if (error != NO_ERROR)
    408                                 return PyErr_SetFromWindowsErr(error);
    409                 }
    410                 if (!high && low < LONG_MAX)
    411                         return PyInt_FromLong((long)low);
    412                 size = (((PY_LONG_LONG)high)<<32) + low;
    413                 return PyLong_FromLongLong(size);
    414         } else {
    415                 return PyInt_FromSsize_t(self->size);
    416         }
     407    if (self->file_handle != INVALID_HANDLE_VALUE) {
     408        DWORD low,high;
     409        PY_LONG_LONG size;
     410        low = GetFileSize(self->file_handle, &high);
     411        if (low == INVALID_FILE_SIZE) {
     412            /* It might be that the function appears to have failed,
     413               when indeed its size equals INVALID_FILE_SIZE */
     414            DWORD error = GetLastError();
     415            if (error != NO_ERROR)
     416                return PyErr_SetFromWindowsErr(error);
     417        }
     418        if (!high && low < LONG_MAX)
     419            return PyInt_FromLong((long)low);
     420        size = (((PY_LONG_LONG)high)<<32) + low;
     421        return PyLong_FromLongLong(size);
     422    } else {
     423        return PyInt_FromSsize_t(self->size);
     424    }
    417425#endif /* MS_WINDOWS */
    418426
    419427#ifdef UNIX
    420         {
    421                 struct stat buf;
    422                 if (-1 == fstat(self->fd, &buf)) {
    423                         PyErr_SetFromErrno(mmap_module_error);
    424                         return NULL;
    425                 }
    426                 return PyInt_FromSsize_t(buf.st_size);
    427         }
     428    {
     429        struct stat buf;
     430        if (-1 == fstat(self->fd, &buf)) {
     431            PyErr_SetFromErrno(mmap_module_error);
     432            return NULL;
     433        }
     434#ifdef HAVE_LARGEFILE_SUPPORT
     435        return PyLong_FromLongLong(buf.st_size);
     436#else
     437        return PyInt_FromLong(buf.st_size);
     438#endif
     439    }
    428440#endif /* UNIX */
    429441}
     
    440452static PyObject *
    441453mmap_resize_method(mmap_object *self,
    442                    PyObject *args)
    443 {
    444         Py_ssize_t new_size;
    445         CHECK_VALID(NULL);
    446         if (!PyArg_ParseTuple(args, "n:resize", &new_size) ||
    447             !is_resizeable(self)) {
    448                 return NULL;
     454                   PyObject *args)
     455{
     456    Py_ssize_t new_size;
     457    CHECK_VALID(NULL);
     458    if (!PyArg_ParseTuple(args, "n:resize", &new_size) ||
     459        !is_resizeable(self)) {
     460        return NULL;
    449461#ifdef MS_WINDOWS
    450         } else {
    451                 DWORD dwErrCode = 0;
    452                 DWORD off_hi, off_lo, newSizeLow, newSizeHigh;
    453                 /* First, unmap the file view */
    454                 UnmapViewOfFile(self->data);
    455                 self->data = NULL;
    456                 /* Close the mapping object */
    457                 CloseHandle(self->map_handle);
    458                 self->map_handle = NULL;
    459                 /* Move to the desired EOF position */
    460 #if SIZEOF_SIZE_T > 4
    461                 newSizeHigh = (DWORD)((self->offset + new_size) >> 32);
    462                 newSizeLow = (DWORD)((self->offset + new_size) & 0xFFFFFFFF);
    463                 off_hi = (DWORD)(self->offset >> 32);
    464                 off_lo = (DWORD)(self->offset & 0xFFFFFFFF);
    465 #else
    466                 newSizeHigh = 0;
    467                 newSizeLow = (DWORD)(self->offset + new_size);
    468                 off_hi = 0;
    469                 off_lo = (DWORD)self->offset;
    470 #endif
    471                 SetFilePointer(self->file_handle,
    472                                newSizeLow, &newSizeHigh, FILE_BEGIN);
    473                 /* Change the size of the file */
    474                 SetEndOfFile(self->file_handle);
    475                 /* Create another mapping object and remap the file view */
    476                 self->map_handle = CreateFileMapping(
    477                         self->file_handle,
    478                         NULL,
    479                         PAGE_READWRITE,
    480                         0,
    481                         0,
    482                         self->tagname);
    483                 if (self->map_handle != NULL) {
    484                         self->data = (char *) MapViewOfFile(self->map_handle,
    485                                                             FILE_MAP_WRITE,
    486                                                             off_hi,
    487                                                             off_lo,
    488                                                             new_size);
    489                         if (self->data != NULL) {
    490                                 self->size = new_size;
    491                                 Py_INCREF(Py_None);
    492                                 return Py_None;
    493                         } else {
    494                                 dwErrCode = GetLastError();
    495                                 CloseHandle(self->map_handle);
    496                                 self->map_handle = NULL;
    497                         }
    498                 } else {
    499                         dwErrCode = GetLastError();
    500                 }
    501                 PyErr_SetFromWindowsErr(dwErrCode);
    502                 return NULL;
     462    } else {
     463        DWORD dwErrCode = 0;
     464        DWORD off_hi, off_lo, newSizeLow, newSizeHigh;
     465        /* First, unmap the file view */
     466        UnmapViewOfFile(self->data);
     467        self->data = NULL;
     468        /* Close the mapping object */
     469        CloseHandle(self->map_handle);
     470        self->map_handle = NULL;
     471        /* Move to the desired EOF position */
     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        SetFilePointer(self->file_handle,
     477                       newSizeLow, &newSizeHigh, FILE_BEGIN);
     478        /* Change the size of the file */
     479        SetEndOfFile(self->file_handle);
     480        /* Create another mapping object and remap the file view */
     481        self->map_handle = CreateFileMapping(
     482            self->file_handle,
     483            NULL,
     484            PAGE_READWRITE,
     485            0,
     486            0,
     487            self->tagname);
     488        if (self->map_handle != NULL) {
     489            self->data = (char *) MapViewOfFile(self->map_handle,
     490                                                FILE_MAP_WRITE,
     491                                                off_hi,
     492                                                off_lo,
     493                                                new_size);
     494            if (self->data != NULL) {
     495                self->size = new_size;
     496                Py_INCREF(Py_None);
     497                return Py_None;
     498            } else {
     499                dwErrCode = GetLastError();
     500                CloseHandle(self->map_handle);
     501                self->map_handle = NULL;
     502            }
     503        } else {
     504            dwErrCode = GetLastError();
     505        }
     506        PyErr_SetFromWindowsErr(dwErrCode);
     507        return NULL;
    503508#endif /* MS_WINDOWS */
    504509
    505510#ifdef UNIX
    506511#ifndef HAVE_MREMAP
    507         } else {
    508                 PyErr_SetString(PyExc_SystemError,
    509                                 "mmap: resizing not available--no mremap()");
    510                 return NULL;
     512    } else {
     513        PyErr_SetString(PyExc_SystemError,
     514                        "mmap: resizing not available--no mremap()");
     515        return NULL;
    511516#else
    512         } else {
    513                 void *newmap;
    514 
    515                 if (ftruncate(self->fd, self->offset + new_size) == -1) {
    516                         PyErr_SetFromErrno(mmap_module_error);
    517                         return NULL;
    518                 }
     517    } else {
     518        void *newmap;
     519
     520        if (ftruncate(self->fd, self->offset + new_size) == -1) {
     521            PyErr_SetFromErrno(mmap_module_error);
     522            return NULL;
     523        }
    519524
    520525#ifdef MREMAP_MAYMOVE
    521                 newmap = mremap(self->data, self->size, new_size, MREMAP_MAYMOVE);
     526        newmap = mremap(self->data, self->size, new_size, MREMAP_MAYMOVE);
    522527#else
    523                 #if defined(__NetBSD__)
    524                         newmap = mremap(self->data, self->size, self->data, new_size, 0);
    525                 #else
    526                         newmap = mremap(self->data, self->size, new_size, 0);
    527                 #endif /* __NetBSD__ */
    528 #endif
    529                 if (newmap == (void *)-1)
    530                 {
    531                         PyErr_SetFromErrno(mmap_module_error);
    532                         return NULL;
    533                 }
    534                 self->data = newmap;
    535                 self->size = new_size;
    536                 Py_INCREF(Py_None);
    537                 return Py_None;
     528        #if defined(__NetBSD__)
     529            newmap = mremap(self->data, self->size, self->data, new_size, 0);
     530        #else
     531            newmap = mremap(self->data, self->size, new_size, 0);
     532        #endif /* __NetBSD__ */
     533#endif
     534        if (newmap == (void *)-1)
     535        {
     536            PyErr_SetFromErrno(mmap_module_error);
     537            return NULL;
     538        }
     539        self->data = newmap;
     540        self->size = new_size;
     541        Py_INCREF(Py_None);
     542        return Py_None;
    538543#endif /* HAVE_MREMAP */
    539544#endif /* UNIX */
    540         }
     545    }
    541546}
    542547
     
    544549mmap_tell_method(mmap_object *self, PyObject *unused)
    545550{
    546         CHECK_VALID(NULL);
    547         return PyInt_FromSize_t(self->pos);
     551    CHECK_VALID(NULL);
     552    return PyInt_FromSize_t(self->pos);
    548553}
    549554
     
    551556mmap_flush_method(mmap_object *self, PyObject *args)
    552557{
    553         Py_ssize_t offset = 0;
    554         Py_ssize_t size = self->size;
    555         CHECK_VALID(NULL);
    556         if (!PyArg_ParseTuple(args, "|nn:flush", &offset, &size))
    557                 return NULL;
    558         if ((size_t)(offset + size) > self->size) {
    559                 PyErr_SetString(PyExc_ValueError, "flush values out of range");
    560                 return NULL;
    561         }
     558    Py_ssize_t offset = 0;
     559    Py_ssize_t size = self->size;
     560    CHECK_VALID(NULL);
     561    if (!PyArg_ParseTuple(args, "|nn:flush", &offset, &size))
     562        return NULL;
     563    if ((size_t)(offset + size) > self->size) {
     564        PyErr_SetString(PyExc_ValueError, "flush values out of range");
     565        return NULL;
     566    }
     567
     568    if (self->access == ACCESS_READ || self->access == ACCESS_COPY)
     569        return PyLong_FromLong(0);
     570
    562571#ifdef MS_WINDOWS
    563         return PyInt_FromLong((long) FlushViewOfFile(self->data+offset, size));
     572    return PyInt_FromLong((long) FlushViewOfFile(self->data+offset, size));
    564573#elif defined(UNIX)
    565         /* XXX semantics of return value? */
    566         /* XXX flags for msync? */
    567         if (-1 == msync(self->data + offset, size, MS_SYNC)) {
    568                 PyErr_SetFromErrno(mmap_module_error);
    569                 return NULL;
    570         }
    571         return PyInt_FromLong(0);
     574    /* XXX semantics of return value? */
     575    /* XXX flags for msync? */
     576    if (-1 == msync(self->data + offset, size, MS_SYNC)) {
     577        PyErr_SetFromErrno(mmap_module_error);
     578        return NULL;
     579    }
     580    return PyInt_FromLong(0);
    572581#else
    573         PyErr_SetString(PyExc_ValueError, "flush not supported on this system");
    574         return NULL;
     582    PyErr_SetString(PyExc_ValueError, "flush not supported on this system");
     583    return NULL;
    575584#endif
    576585}
     
    579588mmap_seek_method(mmap_object *self, PyObject *args)
    580589{
    581         Py_ssize_t dist;
    582         int how=0;
    583         CHECK_VALID(NULL);
    584         if (!PyArg_ParseTuple(args, "n|i:seek", &dist, &how))
    585                 return NULL;
    586         else {
    587                 size_t where;
    588                 switch (how) {
    589                 case 0: /* relative to start */
    590                         if (dist < 0)
    591                                 goto onoutofrange;
    592                         where = dist;
    593                         break;
    594                 case 1: /* relative to current position */
    595                         if ((Py_ssize_t)self->pos + dist < 0)
    596                                 goto onoutofrange;
    597                         where = self->pos + dist;
    598                         break;
    599                 case 2: /* relative to end */
    600                         if ((Py_ssize_t)self->size + dist < 0)
    601                                 goto onoutofrange;
    602                         where = self->size + dist;
    603                         break;
    604                 default:
    605                         PyErr_SetString(PyExc_ValueError, "unknown seek type");
    606                         return NULL;
    607                 }
    608                 if (where > self->size)
    609                         goto onoutofrange;
    610                 self->pos = where;
    611                 Py_INCREF(Py_None);
    612                 return Py_None;
    613         }
     590    Py_ssize_t dist;
     591    int how=0;
     592    CHECK_VALID(NULL);
     593    if (!PyArg_ParseTuple(args, "n|i:seek", &dist, &how))
     594        return NULL;
     595    else {
     596        size_t where;
     597        switch (how) {
     598        case 0: /* relative to start */
     599            if (dist < 0)
     600                goto onoutofrange;
     601            where = dist;
     602            break;
     603        case 1: /* relative to current position */
     604            if ((Py_ssize_t)self->pos + dist < 0)
     605                goto onoutofrange;
     606            where = self->pos + dist;
     607            break;
     608        case 2: /* relative to end */
     609            if ((Py_ssize_t)self->size + dist < 0)
     610                goto onoutofrange;
     611            where = self->size + dist;
     612            break;
     613        default:
     614            PyErr_SetString(PyExc_ValueError, "unknown seek type");
     615            return NULL;
     616        }
     617        if (where > self->size)
     618            goto onoutofrange;
     619        self->pos = where;
     620        Py_INCREF(Py_None);
     621        return Py_None;
     622    }
    614623
    615624  onoutofrange:
    616         PyErr_SetString(PyExc_ValueError, "seek out of range");
    617         return NULL;
     625    PyErr_SetString(PyExc_ValueError, "seek out of range");
     626    return NULL;
    618627}
    619628
     
    621630mmap_move_method(mmap_object *self, PyObject *args)
    622631{
    623         unsigned long dest, src, count;
    624         CHECK_VALID(NULL);
    625         if (!PyArg_ParseTuple(args, "kkk:move", &dest, &src, &count) ||
    626             !is_writeable(self)) {
    627                 return NULL;
    628         } else {
    629                 /* bounds check the values */
    630                 unsigned long pos = src > dest ? src : dest;
    631                 if (self->size < pos || count > self->size - pos) {
    632                         PyErr_SetString(PyExc_ValueError,
    633                                         "source or destination out of range");
    634                         return NULL;
    635                 } else {
    636                         memmove(self->data+dest, self->data+src, count);
    637                         Py_INCREF(Py_None);
    638                         return Py_None;
    639                 }
    640         }
     632    unsigned long dest, src, cnt;
     633    CHECK_VALID(NULL);
     634    if (!PyArg_ParseTuple(args, "kkk:move", &dest, &src, &cnt) ||
     635        !is_writeable(self)) {
     636        return NULL;
     637    } else {
     638        /* bounds check the values */
     639        if (cnt < 0 || (cnt + dest) < cnt || (cnt + src) < cnt ||
     640           src < 0 || src > self->size || (src + cnt) > self->size ||
     641           dest < 0 || dest > self->size || (dest + cnt) > self->size) {
     642            PyErr_SetString(PyExc_ValueError,
     643                "source, destination, or count out of range");
     644            return NULL;
     645        }
     646        memmove(self->data+dest, self->data+src, cnt);
     647        Py_INCREF(Py_None);
     648        return Py_None;
     649    }
    641650}
    642651
    643652static struct PyMethodDef mmap_object_methods[] = {
    644         {"close",       (PyCFunction) mmap_close_method,        METH_NOARGS},
    645         {"find",        (PyCFunction) mmap_find_method,         METH_VARARGS},
    646         {"rfind",       (PyCFunction) mmap_rfind_method,        METH_VARARGS},
    647         {"flush",       (PyCFunction) mmap_flush_method,        METH_VARARGS},
    648         {"move",        (PyCFunction) mmap_move_method,         METH_VARARGS},
    649         {"read",        (PyCFunction) mmap_read_method,         METH_VARARGS},
    650         {"read_byte",   (PyCFunction) mmap_read_byte_method,    METH_NOARGS},
    651         {"readline",    (PyCFunction) mmap_read_line_method,    METH_NOARGS},
    652         {"resize",      (PyCFunction) mmap_resize_method,       METH_VARARGS},
    653         {"seek",        (PyCFunction) mmap_seek_method,         METH_VARARGS},
    654         {"size",        (PyCFunction) mmap_size_method,         METH_NOARGS},
    655         {"tell",        (PyCFunction) mmap_tell_method,         METH_NOARGS},
    656         {"write",       (PyCFunction) mmap_write_method,        METH_VARARGS},
    657         {"write_byte",  (PyCFunction) mmap_write_byte_method,   METH_VARARGS},
    658         {NULL,     NULL}       /* sentinel */
     653    {"close",           (PyCFunction) mmap_close_method,        METH_NOARGS},
     654    {"find",            (PyCFunction) mmap_find_method,         METH_VARARGS},
     655    {"rfind",           (PyCFunction) mmap_rfind_method,        METH_VARARGS},
     656    {"flush",           (PyCFunction) mmap_flush_method,        METH_VARARGS},
     657    {"move",            (PyCFunction) mmap_move_method,         METH_VARARGS},
     658    {"read",            (PyCFunction) mmap_read_method,         METH_VARARGS},
     659    {"read_byte",       (PyCFunction) mmap_read_byte_method,    METH_NOARGS},
     660    {"readline",        (PyCFunction) mmap_read_line_method,    METH_NOARGS},
     661    {"resize",          (PyCFunction) mmap_resize_method,       METH_VARARGS},
     662    {"seek",            (PyCFunction) mmap_seek_method,         METH_VARARGS},
     663    {"size",            (PyCFunction) mmap_size_method,         METH_NOARGS},
     664    {"tell",            (PyCFunction) mmap_tell_method,         METH_NOARGS},
     665    {"write",           (PyCFunction) mmap_write_method,        METH_VARARGS},
     666    {"write_byte",      (PyCFunction) mmap_write_byte_method,   METH_VARARGS},
     667    {NULL,         NULL}       /* sentinel */
    659668};
    660669
     
    664673mmap_buffer_getreadbuf(mmap_object *self, Py_ssize_t index, const void **ptr)
    665674{
    666         CHECK_VALID(-1);
    667         if (index != 0) {
    668                 PyErr_SetString(PyExc_SystemError,
    669                                 "Accessing non-existent mmap segment");
    670                 return -1;
    671         }
    672         *ptr = self->data;
    673         return self->size;
     675    CHECK_VALID(-1);
     676    if (index != 0) {
     677        PyErr_SetString(PyExc_SystemError,
     678                        "Accessing non-existent mmap segment");
     679        return -1;
     680    }
     681    *ptr = self->data;
     682    return self->size;
    674683}
    675684
     
    677686mmap_buffer_getwritebuf(mmap_object *self, Py_ssize_t index, const void **ptr)
    678687{
    679         CHECK_VALID(-1);
    680         if (index != 0) {
    681                 PyErr_SetString(PyExc_SystemError,
    682                                 "Accessing non-existent mmap segment");
    683                 return -1;
    684         }
    685         if (!is_writeable(self))
    686                 return -1;
    687         *ptr = self->data;
    688         return self->size;
     688    CHECK_VALID(-1);
     689    if (index != 0) {
     690        PyErr_SetString(PyExc_SystemError,
     691                        "Accessing non-existent mmap segment");
     692        return -1;
     693    }
     694    if (!is_writeable(self))
     695        return -1;
     696    *ptr = self->data;
     697    return self->size;
    689698}
    690699
     
    692701mmap_buffer_getsegcount(mmap_object *self, Py_ssize_t *lenp)
    693702{
    694         CHECK_VALID(-1);
    695         if (lenp)
    696                 *lenp = self->size;
    697         return 1;
     703    CHECK_VALID(-1);
     704    if (lenp)
     705        *lenp = self->size;
     706    return 1;
    698707}
    699708
     
    701710mmap_buffer_getcharbuffer(mmap_object *self, Py_ssize_t index, const void **ptr)
    702711{
    703         if (index != 0) {
    704                 PyErr_SetString(PyExc_SystemError,
    705                                 "accessing non-existent buffer segment");
    706                 return -1;
    707         }
    708         *ptr = (const char *)self->data;
    709         return self->size;
     712    if (index != 0) {
     713        PyErr_SetString(PyExc_SystemError,
     714                        "accessing non-existent buffer segment");
     715        return -1;
     716    }
     717    *ptr = (const char *)self->data;
     718    return self->size;
    710719}
    711720
     
    713722mmap_length(mmap_object *self)
    714723{
    715         CHECK_VALID(-1);
    716         return self->size;
     724    CHECK_VALID(-1);
     725    return self->size;
    717726}
    718727
     
    720729mmap_item(mmap_object *self, Py_ssize_t i)
    721730{
    722         CHECK_VALID(NULL);
    723         if (i < 0 || (size_t)i >= self->size) {
    724                 PyErr_SetString(PyExc_IndexError, "mmap index out of range");
    725                 return NULL;
    726         }
    727         return PyString_FromStringAndSize(self->data + i, 1);
     731    CHECK_VALID(NULL);
     732    if (i < 0 || (size_t)i >= self->size) {
     733        PyErr_SetString(PyExc_IndexError, "mmap index out of range");
     734        return NULL;
     735    }
     736    return PyString_FromStringAndSize(self->data + i, 1);
    728737}
    729738
     
    731740mmap_slice(mmap_object *self, Py_ssize_t ilow, Py_ssize_t ihigh)
    732741{
    733         CHECK_VALID(NULL);
    734         if (ilow < 0)
    735                 ilow = 0;
    736         else if ((size_t)ilow > self->size)
    737                 ilow = self->size;
    738         if (ihigh < 0)
    739                 ihigh = 0;
    740         if (ihigh < ilow)
    741                 ihigh = ilow;
    742         else if ((size_t)ihigh > self->size)
    743                 ihigh = self->size;
    744 
    745         return PyString_FromStringAndSize(self->data + ilow, ihigh-ilow);
     742    CHECK_VALID(NULL);
     743    if (ilow < 0)
     744        ilow = 0;
     745    else if ((size_t)ilow > self->size)
     746        ilow = self->size;
     747    if (ihigh < 0)
     748        ihigh = 0;
     749    if (ihigh < ilow)
     750        ihigh = ilow;
     751    else if ((size_t)ihigh > self->size)
     752        ihigh = self->size;
     753
     754    return PyString_FromStringAndSize(self->data + ilow, ihigh-ilow);
    746755}
    747756
     
    749758mmap_subscript(mmap_object *self, PyObject *item)
    750759{
    751         CHECK_VALID(NULL);
    752         if (PyIndex_Check(item)) {
    753                 Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
    754                 if (i == -1 && PyErr_Occurred())
    755                         return NULL;
    756                 if (i < 0)
    757                         i += self->size;
    758                 if (i < 0 || (size_t)i >= self->size) {
    759                         PyErr_SetString(PyExc_IndexError,
    760                                 "mmap index out of range");
    761                         return NULL;
    762                 }
    763                 return PyString_FromStringAndSize(self->data + i, 1);
    764         }
    765         else if (PySlice_Check(item)) {
    766                 Py_ssize_t start, stop, step, slicelen;
    767 
    768                 if (PySlice_GetIndicesEx((PySliceObject *)item, self->size,
    769                                 &start, &stop, &step, &slicelen) < 0) {
    770                         return NULL;
    771                 }
    772                
    773                 if (slicelen <= 0)
    774                         return PyString_FromStringAndSize("", 0);
    775                 else if (step == 1)
    776                         return PyString_FromStringAndSize(self->data + start,
    777                                                           slicelen);
    778                 else {
    779                         char *result_buf = (char *)PyMem_Malloc(slicelen);
    780                         Py_ssize_t cur, i;
    781                         PyObject *result;
    782 
    783                         if (result_buf == NULL)
    784                                 return PyErr_NoMemory();
    785                         for (cur = start, i = 0; i < slicelen;
    786                              cur += step, i++) {
    787                                 result_buf[i] = self->data[cur];
    788                         }
    789                         result = PyString_FromStringAndSize(result_buf,
    790                                                             slicelen);
    791                         PyMem_Free(result_buf);
    792                         return result;
    793                 }
    794         }
    795         else {
    796                 PyErr_SetString(PyExc_TypeError,
    797                                 "mmap indices must be integers");
    798                 return NULL;
    799         }
     760    CHECK_VALID(NULL);
     761    if (PyIndex_Check(item)) {
     762        Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
     763        if (i == -1 && PyErr_Occurred())
     764            return NULL;
     765        if (i < 0)
     766            i += self->size;
     767        if (i < 0 || (size_t)i >= self->size) {
     768            PyErr_SetString(PyExc_IndexError,
     769                "mmap index out of range");
     770            return NULL;
     771        }
     772        return PyString_FromStringAndSize(self->data + i, 1);
     773    }
     774    else if (PySlice_Check(item)) {
     775        Py_ssize_t start, stop, step, slicelen;
     776
     777        if (PySlice_GetIndicesEx((PySliceObject *)item, self->size,
     778                        &start, &stop, &step, &slicelen) < 0) {
     779            return NULL;
     780        }
     781
     782        if (slicelen <= 0)
     783            return PyString_FromStringAndSize("", 0);
     784        else if (step == 1)
     785            return PyString_FromStringAndSize(self->data + start,
     786                                              slicelen);
     787        else {
     788            char *result_buf = (char *)PyMem_Malloc(slicelen);
     789            Py_ssize_t cur, i;
     790            PyObject *result;
     791
     792            if (result_buf == NULL)
     793                return PyErr_NoMemory();
     794            for (cur = start, i = 0; i < slicelen;
     795                 cur += step, i++) {
     796                result_buf[i] = self->data[cur];
     797            }
     798            result = PyString_FromStringAndSize(result_buf,
     799                                                slicelen);
     800            PyMem_Free(result_buf);
     801            return result;
     802        }
     803    }
     804    else {
     805        PyErr_SetString(PyExc_TypeError,
     806                        "mmap indices must be integers");
     807        return NULL;
     808    }
    800809}
    801810
     
    803812mmap_concat(mmap_object *self, PyObject *bb)
    804813{
    805         CHECK_VALID(NULL);
    806         PyErr_SetString(PyExc_SystemError,
    807                         "mmaps don't support concatenation");
    808         return NULL;
     814    CHECK_VALID(NULL);
     815    PyErr_SetString(PyExc_SystemError,
     816                    "mmaps don't support concatenation");
     817    return NULL;
    809818}
    810819
     
    812821mmap_repeat(mmap_object *self, Py_ssize_t n)
    813822{
    814         CHECK_VALID(NULL);
    815         PyErr_SetString(PyExc_SystemError,
    816                         "mmaps don't support repeat operation");
    817         return NULL;
     823    CHECK_VALID(NULL);
     824    PyErr_SetString(PyExc_SystemError,
     825                    "mmaps don't support repeat operation");
     826    return NULL;
    818827}
    819828
     
    821830mmap_ass_slice(mmap_object *self, Py_ssize_t ilow, Py_ssize_t ihigh, PyObject *v)
    822831{
    823         const char *buf;
    824 
    825         CHECK_VALID(-1);
    826         if (ilow < 0)
    827                 ilow = 0;
    828         else if ((size_t)ilow > self->size)
    829                 ilow = self->size;
    830         if (ihigh < 0)
    831                 ihigh = 0;
    832         if (ihigh < ilow)
    833                 ihigh = ilow;
    834         else if ((size_t)ihigh > self->size)
    835                 ihigh = self->size;
    836 
    837         if (v == NULL) {
    838                 PyErr_SetString(PyExc_TypeError,
    839                                 "mmap object doesn't support slice deletion");
    840                 return -1;
    841         }
    842         if (! (PyString_Check(v)) ) {
    843                 PyErr_SetString(PyExc_IndexError,
    844                                 "mmap slice assignment must be a string");
    845                 return -1;
    846         }
    847         if (PyString_Size(v) != (ihigh - ilow)) {
    848                 PyErr_SetString(PyExc_IndexError,
    849                                 "mmap slice assignment is wrong size");
    850                 return -1;
    851         }
    852         if (!is_writeable(self))
    853                 return -1;
    854         buf = PyString_AsString(v);
    855         memcpy(self->data + ilow, buf, ihigh-ilow);
    856         return 0;
     832    const char *buf;
     833
     834    CHECK_VALID(-1);
     835    if (ilow < 0)
     836        ilow = 0;
     837    else if ((size_t)ilow > self->size)
     838        ilow = self->size;
     839    if (ihigh < 0)
     840        ihigh = 0;
     841    if (ihigh < ilow)
     842        ihigh = ilow;
     843    else if ((size_t)ihigh > self->size)
     844        ihigh = self->size;
     845
     846    if (v == NULL) {
     847        PyErr_SetString(PyExc_TypeError,
     848                        "mmap object doesn't support slice deletion");
     849        return -1;
     850    }
     851    if (! (PyString_Check(v)) ) {
     852        PyErr_SetString(PyExc_IndexError,
     853                        "mmap slice assignment must be a string");
     854        return -1;
     855    }
     856    if (PyString_Size(v) != (ihigh - ilow)) {
     857        PyErr_SetString(PyExc_IndexError,
     858                        "mmap slice assignment is wrong size");
     859        return -1;
     860    }
     861    if (!is_writeable(self))
     862        return -1;
     863    buf = PyString_AsString(v);
     864    memcpy(self->data + ilow, buf, ihigh-ilow);
     865    return 0;
    857866}
    858867
     
    860869mmap_ass_item(mmap_object *self, Py_ssize_t i, PyObject *v)
    861870{
    862         const char *buf;
    863 
    864         CHECK_VALID(-1);
    865         if (i < 0 || (size_t)i >= self->size) {
    866                 PyErr_SetString(PyExc_IndexError, "mmap index out of range");
    867                 return -1;
    868         }
    869         if (v == NULL) {
    870                 PyErr_SetString(PyExc_TypeError,
    871                                 "mmap object doesn't support item deletion");
    872                 return -1;
    873         }
    874         if (! (PyString_Check(v) && PyString_Size(v)==1) ) {
    875                 PyErr_SetString(PyExc_IndexError,
    876                                 "mmap assignment must be single-character string");
    877                 return -1;
    878         }
    879         if (!is_writeable(self))
    880                 return -1;
    881         buf = PyString_AsString(v);
    882         self->data[i] = buf[0];
    883         return 0;
     871    const char *buf;
     872
     873    CHECK_VALID(-1);
     874    if (i < 0 || (size_t)i >= self->size) {
     875        PyErr_SetString(PyExc_IndexError, "mmap index out of range");
     876        return -1;
     877    }
     878    if (v == NULL) {
     879        PyErr_SetString(PyExc_TypeError,
     880                        "mmap object doesn't support item deletion");
     881        return -1;
     882    }
     883    if (! (PyString_Check(v) && PyString_Size(v)==1) ) {
     884        PyErr_SetString(PyExc_IndexError,
     885                        "mmap assignment must be single-character string");
     886        return -1;
     887    }
     888    if (!is_writeable(self))
     889        return -1;
     890    buf = PyString_AsString(v);
     891    self->data[i] = buf[0];
     892    return 0;
    884893}
    885894
     
    887896mmap_ass_subscript(mmap_object *self, PyObject *item, PyObject *value)
    888897{
    889         CHECK_VALID(-1);
    890 
    891         if (PyIndex_Check(item)) {
    892                 Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
    893                 const char *buf;
    894 
    895                 if (i == -1 && PyErr_Occurred())
    896                         return -1;
    897                 if (i < 0)
    898                         i += self->size;
    899                 if (i < 0 || (size_t)i >= self->size) {
    900                         PyErr_SetString(PyExc_IndexError,
    901                                 "mmap index out of range");
    902                         return -1;
    903                 }
    904                 if (value == NULL) {
    905                         PyErr_SetString(PyExc_TypeError,
    906                                 "mmap object doesn't support item deletion");
    907                         return -1;
    908                 }
    909                 if (!PyString_Check(value) || PyString_Size(value) != 1) {
    910                         PyErr_SetString(PyExc_IndexError,
    911                           "mmap assignment must be single-character string");
    912                         return -1;
    913                 }
    914                 if (!is_writeable(self))
    915                         return -1;
    916                 buf = PyString_AsString(value);
    917                 self->data[i] = buf[0];
    918                 return 0;
    919         }
    920         else if (PySlice_Check(item)) {
    921                 Py_ssize_t start, stop, step, slicelen;
    922                
    923                 if (PySlice_GetIndicesEx((PySliceObject *)item,
    924                                         self->size, &start, &stop,
    925                                         &step, &slicelen) < 0) {
    926                         return -1;
    927                 }
    928                 if (value == NULL) {
    929                         PyErr_SetString(PyExc_TypeError,
    930                                 "mmap object doesn't support slice deletion");
    931                         return -1;
    932                 }
    933                 if (!PyString_Check(value)) {
    934                         PyErr_SetString(PyExc_IndexError,
    935                                 "mmap slice assignment must be a string");
    936                         return -1;
    937                 }
    938                 if (PyString_Size(value) != slicelen) {
    939                         PyErr_SetString(PyExc_IndexError,
    940                                 "mmap slice assignment is wrong size");
    941                         return -1;
    942                 }
    943                 if (!is_writeable(self))
    944                         return -1;
    945 
    946                 if (slicelen == 0)
    947                         return 0;
    948                 else if (step == 1) {
    949                         const char *buf = PyString_AsString(value);
    950 
    951                         if (buf == NULL)
    952                                 return -1;
    953                         memcpy(self->data + start, buf, slicelen);
    954                         return 0;
    955                 }
    956                 else {
    957                         Py_ssize_t cur, i;
    958                         const char *buf = PyString_AsString(value);
    959                        
    960                         if (buf == NULL)
    961                                 return -1;
    962                         for (cur = start, i = 0; i < slicelen;
    963                              cur += step, i++) {
    964                                 self->data[cur] = buf[i];
    965                         }
    966                         return 0;
    967                 }
    968         }
    969         else {
    970                 PyErr_SetString(PyExc_TypeError,
    971                                 "mmap indices must be integer");
    972                 return -1;
    973         }
     898    CHECK_VALID(-1);
     899
     900    if (PyIndex_Check(item)) {
     901        Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
     902        const char *buf;
     903
     904        if (i == -1 && PyErr_Occurred())
     905            return -1;
     906        if (i < 0)
     907            i += self->size;
     908        if (i < 0 || (size_t)i >= self->size) {
     909            PyErr_SetString(PyExc_IndexError,
     910                "mmap index out of range");
     911            return -1;
     912        }
     913        if (value == NULL) {
     914            PyErr_SetString(PyExc_TypeError,
     915                "mmap object doesn't support item deletion");
     916            return -1;
     917        }
     918        if (!PyString_Check(value) || PyString_Size(value) != 1) {
     919            PyErr_SetString(PyExc_IndexError,
     920              "mmap assignment must be single-character string");
     921            return -1;
     922        }
     923        if (!is_writeable(self))
     924            return -1;
     925        buf = PyString_AsString(value);
     926        self->data[i] = buf[0];
     927        return 0;
     928    }
     929    else if (PySlice_Check(item)) {
     930        Py_ssize_t start, stop, step, slicelen;
     931
     932        if (PySlice_GetIndicesEx((PySliceObject *)item,
     933                                self->size, &start, &stop,
     934                                &step, &slicelen) < 0) {
     935            return -1;
     936        }
     937        if (value == NULL) {
     938            PyErr_SetString(PyExc_TypeError,
     939                "mmap object doesn't support slice deletion");
     940            return -1;
     941        }
     942        if (!PyString_Check(value)) {
     943            PyErr_SetString(PyExc_IndexError,
     944                "mmap slice assignment must be a string");
     945            return -1;
     946        }
     947        if (PyString_Size(value) != slicelen) {
     948            PyErr_SetString(PyExc_IndexError,
     949                "mmap slice assignment is wrong size");
     950            return -1;
     951        }
     952        if (!is_writeable(self))
     953            return -1;
     954
     955        if (slicelen == 0)
     956            return 0;
     957        else if (step == 1) {
     958            const char *buf = PyString_AsString(value);
     959
     960            if (buf == NULL)
     961                return -1;
     962            memcpy(self->data + start, buf, slicelen);
     963            return 0;
     964        }
     965        else {
     966            Py_ssize_t cur, i;
     967            const char *buf = PyString_AsString(value);
     968
     969            if (buf == NULL)
     970                return -1;
     971            for (cur = start, i = 0; i < slicelen;
     972                 cur += step, i++) {
     973                self->data[cur] = buf[i];
     974            }
     975            return 0;
     976        }
     977    }
     978    else {
     979        PyErr_SetString(PyExc_TypeError,
     980                        "mmap indices must be integer");
     981        return -1;
     982    }
    974983}
    975984
    976985static PySequenceMethods mmap_as_sequence = {
    977         (lenfunc)mmap_length,                  /*sq_length*/
    978         (binaryfunc)mmap_concat,               /*sq_concat*/
    979         (ssizeargfunc)mmap_repeat,             /*sq_repeat*/
    980         (ssizeargfunc)mmap_item,                       /*sq_item*/
    981         (ssizessizeargfunc)mmap_slice,         /*sq_slice*/
    982         (ssizeobjargproc)mmap_ass_item,        /*sq_ass_item*/
    983         (ssizessizeobjargproc)mmap_ass_slice,      /*sq_ass_slice*/
     986    (lenfunc)mmap_length,                      /*sq_length*/
     987    (binaryfunc)mmap_concat,                   /*sq_concat*/
     988    (ssizeargfunc)mmap_repeat,                 /*sq_repeat*/
     989    (ssizeargfunc)mmap_item,                           /*sq_item*/
     990    (ssizessizeargfunc)mmap_slice,             /*sq_slice*/
     991    (ssizeobjargproc)mmap_ass_item,            /*sq_ass_item*/
     992    (ssizessizeobjargproc)mmap_ass_slice,      /*sq_ass_slice*/
    984993};
    985994
    986995static PyMappingMethods mmap_as_mapping = {
    987         (lenfunc)mmap_length,
    988         (binaryfunc)mmap_subscript,
    989         (objobjargproc)mmap_ass_subscript,
     996    (lenfunc)mmap_length,
     997    (binaryfunc)mmap_subscript,
     998    (objobjargproc)mmap_ass_subscript,
    990999};
    9911000
    9921001static PyBufferProcs mmap_as_buffer = {
    993         (readbufferproc)mmap_buffer_getreadbuf,
    994         (writebufferproc)mmap_buffer_getwritebuf,
    995         (segcountproc)mmap_buffer_getsegcount,
    996         (charbufferproc)mmap_buffer_getcharbuffer,
     1002    (readbufferproc)mmap_buffer_getreadbuf,
     1003    (writebufferproc)mmap_buffer_getwritebuf,
     1004    (segcountproc)mmap_buffer_getsegcount,
     1005    (charbufferproc)mmap_buffer_getcharbuffer,
    9971006};
    9981007
     
    10251034
    10261035static PyTypeObject mmap_object_type = {
    1027         PyVarObject_HEAD_INIT(NULL, 0)
    1028         "mmap.mmap",                            /* tp_name */
    1029         sizeof(mmap_object),                    /* tp_size */
    1030         0,                                      /* tp_itemsize */
    1031         /* methods */
    1032         (destructor) mmap_object_dealloc,       /* tp_dealloc */
    1033         0,                                      /* tp_print */
    1034         0,                                      /* tp_getattr */
    1035         0,                                      /* tp_setattr */
    1036         0,                                      /* tp_compare */
    1037         0,                                      /* tp_repr */
    1038         0,                                      /* tp_as_number */
    1039         &mmap_as_sequence,                      /*tp_as_sequence*/
    1040         &mmap_as_mapping,                       /*tp_as_mapping*/
    1041         0,                                      /*tp_hash*/
    1042         0,                                      /*tp_call*/
    1043         0,                                      /*tp_str*/
    1044         PyObject_GenericGetAttr,                /*tp_getattro*/
    1045         0,                                      /*tp_setattro*/
    1046         &mmap_as_buffer,                        /*tp_as_buffer*/
    1047         Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GETCHARBUFFER,               /*tp_flags*/
    1048         mmap_doc,                               /*tp_doc*/
    1049         0,                                      /* tp_traverse */
    1050         0,                                      /* tp_clear */
    1051         0,                                      /* tp_richcompare */
    1052         0,                                      /* tp_weaklistoffset */
    1053         0,                                      /* tp_iter */
    1054         0,                                      /* tp_iternext */
    1055         mmap_object_methods,                    /* tp_methods */
    1056         0,                                      /* tp_members */
    1057         0,                                      /* tp_getset */
    1058         0,                                      /* tp_base */
    1059         0,                                      /* tp_dict */
    1060         0,                                      /* tp_descr_get */
    1061         0,                                      /* tp_descr_set */
    1062         0,                                      /* tp_dictoffset */
    1063         0,                                      /* tp_init */
    1064         PyType_GenericAlloc,                    /* tp_alloc */
    1065         new_mmap_object,                        /* tp_new */
    1066         PyObject_Del,                           /* tp_free */
     1036    PyVarObject_HEAD_INIT(NULL, 0)
     1037    "mmap.mmap",                                /* tp_name */
     1038    sizeof(mmap_object),                        /* tp_size */
     1039    0,                                          /* tp_itemsize */
     1040    /* methods */
     1041    (destructor) mmap_object_dealloc,           /* tp_dealloc */
     1042    0,                                          /* tp_print */
     1043    0,                                          /* tp_getattr */
     1044    0,                                          /* tp_setattr */
     1045    0,                                          /* tp_compare */
     1046    0,                                          /* tp_repr */
     1047    0,                                          /* tp_as_number */
     1048    &mmap_as_sequence,                          /*tp_as_sequence*/
     1049    &mmap_as_mapping,                           /*tp_as_mapping*/
     1050    0,                                          /*tp_hash*/
     1051    0,                                          /*tp_call*/
     1052    0,                                          /*tp_str*/
     1053    PyObject_GenericGetAttr,                    /*tp_getattro*/
     1054    0,                                          /*tp_setattro*/
     1055    &mmap_as_buffer,                            /*tp_as_buffer*/
     1056    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GETCHARBUFFER,                   /*tp_flags*/
     1057    mmap_doc,                                   /*tp_doc*/
     1058    0,                                          /* tp_traverse */
     1059    0,                                          /* tp_clear */
     1060    0,                                          /* tp_richcompare */
     1061    0,                                          /* tp_weaklistoffset */
     1062    0,                                          /* tp_iter */
     1063    0,                                          /* tp_iternext */
     1064    mmap_object_methods,                        /* tp_methods */
     1065    0,                                          /* tp_members */
     1066    0,                                          /* tp_getset */
     1067    0,                                          /* tp_base */
     1068    0,                                          /* tp_dict */
     1069    0,                                          /* tp_descr_get */
     1070    0,                                          /* tp_descr_set */
     1071    0,                                          /* tp_dictoffset */
     1072    0,                                      /* tp_init */
     1073    PyType_GenericAlloc,                        /* tp_alloc */
     1074    new_mmap_object,                            /* tp_new */
     1075    PyObject_Del,                           /* tp_free */
    10671076};
    10681077
     
    10751084_GetMapSize(PyObject *o, const char* param)
    10761085{
    1077         if (o == NULL)
    1078                 return 0;
    1079         if (PyIndex_Check(o)) {
    1080                 Py_ssize_t i = PyNumber_AsSsize_t(o, PyExc_OverflowError);
    1081                 if (i==-1 && PyErr_Occurred())
    1082                         return -1;
    1083                 if (i < 0) {     
    1084                         PyErr_Format(PyExc_OverflowError,
    1085                                         "memory mapped %s must be positive",
    1086                                         param);
    1087                         return -1;
    1088                 }
    1089                 return i;
    1090         }
    1091 
    1092         PyErr_SetString(PyExc_TypeError, "map size must be an integral value");
    1093         return -1;
     1086    if (o == NULL)
     1087        return 0;
     1088    if (PyIndex_Check(o)) {
     1089        Py_ssize_t i = PyNumber_AsSsize_t(o, PyExc_OverflowError);
     1090        if (i==-1 && PyErr_Occurred())
     1091            return -1;
     1092        if (i < 0) {
     1093            PyErr_Format(PyExc_OverflowError,
     1094                            "memory mapped %s must be positive",
     1095                            param);
     1096            return -1;
     1097        }
     1098        return i;
     1099    }
     1100
     1101    PyErr_SetString(PyExc_TypeError, "map size must be an integral value");
     1102    return -1;
    10941103}
    10951104
    10961105#ifdef UNIX
     1106#ifdef HAVE_LARGEFILE_SUPPORT
     1107#define _Py_PARSE_OFF_T "L"
     1108#else
     1109#define _Py_PARSE_OFF_T "l"
     1110#endif
     1111
    10971112static PyObject *
    10981113new_mmap_object(PyTypeObject *type, PyObject *args, PyObject *kwdict)
    10991114{
    11001115#ifdef HAVE_FSTAT
    1101         struct stat st;
    1102 #endif
    1103         mmap_object *m_obj;
    1104         PyObject *map_size_obj = NULL, *offset_obj = NULL;
    1105         Py_ssize_t map_size, offset;
    1106         int fd, flags = MAP_SHARED, prot = PROT_WRITE | PROT_READ;
    1107         int devzero = -1;
    1108         int access = (int)ACCESS_DEFAULT;
    1109         static char *keywords[] = {"fileno", "length",
    1110                                          "flags", "prot",
    1111                                          "access", "offset", NULL};
    1112 
    1113         if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iO|iiiO", keywords,
    1114                                          &fd, &map_size_obj, &flags, &prot,
    1115                                          &access, &offset_obj))
    1116                 return NULL;
    1117         map_size = _GetMapSize(map_size_obj, "size");
    1118         if (map_size < 0)
    1119                 return NULL;
    1120         offset = _GetMapSize(offset_obj, "offset");
    1121         if (offset < 0)
    1122                 return NULL;
    1123 
    1124         if ((access != (int)ACCESS_DEFAULT) &&
    1125             ((flags != MAP_SHARED) || (prot != (PROT_WRITE | PROT_READ))))
    1126                 return PyErr_Format(PyExc_ValueError,
    1127                                     "mmap can't specify both access and flags, prot.");
    1128         switch ((access_mode)access) {
    1129         case ACCESS_READ:
    1130                 flags = MAP_SHARED;
    1131                 prot = PROT_READ;
    1132                 break;
    1133         case ACCESS_WRITE:
    1134                 flags = MAP_SHARED;
    1135                 prot = PROT_READ | PROT_WRITE;
    1136                 break;
    1137         case ACCESS_COPY:
    1138                 flags = MAP_PRIVATE;
    1139                 prot = PROT_READ | PROT_WRITE;
    1140                 break;
    1141         case ACCESS_DEFAULT:
    1142                 /* use the specified or default values of flags and prot */
    1143                 break;
    1144         default:
    1145                 return PyErr_Format(PyExc_ValueError,
    1146                                     "mmap invalid access parameter.");
    1147         }
    1148 
    1149     if (prot == PROT_READ) {
    1150         access = ACCESS_READ;
    1151     }
    1152 
     1116    struct stat st;
     1117#endif
     1118    mmap_object *m_obj;
     1119    PyObject *map_size_obj = NULL;
     1120    Py_ssize_t map_size;
     1121    off_t offset = 0;
     1122    int fd, flags = MAP_SHARED, prot = PROT_WRITE | PROT_READ;
     1123    int devzero = -1;
     1124    int access = (int)ACCESS_DEFAULT;
     1125    static char *keywords[] = {"fileno", "length",
     1126                                     "flags", "prot",
     1127                                     "access", "offset", NULL};
     1128
     1129    if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iO|iii" _Py_PARSE_OFF_T, keywords,
     1130                                     &fd, &map_size_obj, &flags, &prot,
     1131                                     &access, &offset))
     1132        return NULL;
     1133    map_size = _GetMapSize(map_size_obj, "size");
     1134    if (map_size < 0)
     1135        return NULL;
     1136    if (offset < 0) {
     1137        PyErr_SetString(PyExc_OverflowError,
     1138            "memory mapped offset must be positive");
     1139        return NULL;
     1140    }
     1141
     1142    if ((access != (int)ACCESS_DEFAULT) &&
     1143        ((flags != MAP_SHARED) || (prot != (PROT_WRITE | PROT_READ))))
     1144        return PyErr_Format(PyExc_ValueError,
     1145                            "mmap can't specify both access and flags, prot.");
     1146    switch ((access_mode)access) {
     1147    case ACCESS_READ:
     1148        flags = MAP_SHARED;
     1149        prot = PROT_READ;
     1150        break;
     1151    case ACCESS_WRITE:
     1152        flags = MAP_SHARED;
     1153        prot = PROT_READ | PROT_WRITE;
     1154        break;
     1155    case ACCESS_COPY:
     1156        flags = MAP_PRIVATE;
     1157        prot = PROT_READ | PROT_WRITE;
     1158        break;
     1159    case ACCESS_DEFAULT:
     1160        /* map prot to access type */
     1161        if ((prot & PROT_READ) && (prot & PROT_WRITE)) {
     1162            /* ACCESS_DEFAULT */
     1163        }
     1164        else if (prot & PROT_WRITE) {
     1165            access = ACCESS_WRITE;
     1166        }
     1167        else {
     1168            access = ACCESS_READ;
     1169        }
     1170        break;
     1171    default:
     1172        return PyErr_Format(PyExc_ValueError,
     1173                            "mmap invalid access parameter.");
     1174    }
     1175
     1176#ifdef __APPLE__
     1177    /* Issue #11277: fsync(2) is not enough on OS X - a special, OS X specific
     1178       fcntl(2) is necessary to force DISKSYNC and get around mmap(2) bug */
     1179    if (fd != -1)
     1180        (void)fcntl(fd, F_FULLFSYNC);
     1181#endif
    11531182#ifdef HAVE_FSTAT
    11541183#  ifdef __VMS
    1155         /* on OpenVMS we must ensure that all bytes are written to the file */
    1156         if (fd != -1) {
    1157                 fsync(fd);
    1158         }
     1184    /* on OpenVMS we must ensure that all bytes are written to the file */
     1185    if (fd != -1) {
     1186        fsync(fd);
     1187    }
    11591188#  endif
    1160         if (fd != -1 && fstat(fd, &st) == 0 && S_ISREG(st.st_mode)) {
    1161                 if (map_size == 0) {
    1162                         map_size = st.st_size;
    1163                 } else if ((size_t)offset + (size_t)map_size > st.st_size) {
    1164                         PyErr_SetString(PyExc_ValueError,
    1165                                         "mmap length is greater than file size");
    1166                         return NULL;
    1167                 }
    1168         }
    1169 #endif
    1170         m_obj = (mmap_object *)type->tp_alloc(type, 0);
    1171         if (m_obj == NULL) {return NULL;}
    1172         m_obj->data = NULL;
    1173         m_obj->size = (size_t) map_size;
    1174         m_obj->pos = (size_t) 0;
    1175         m_obj->offset = offset;
    1176         if (fd == -1) {
    1177                 m_obj->fd = -1;
    1178                 /* Assume the caller wants to map anonymous memory.
    1179                    This is the same behaviour as Windows.  mmap.mmap(-1, size)
    1180                    on both Windows and Unix map anonymous memory.
    1181                 */
     1189    if (fd != -1 && fstat(fd, &st) == 0 && S_ISREG(st.st_mode)) {
     1190        if (map_size == 0) {
     1191            if (st.st_size == 0) {
     1192                PyErr_SetString(PyExc_ValueError,
     1193                                "cannot mmap an empty file");
     1194                return NULL;
     1195            }
     1196            if (offset >= st.st_size) {
     1197                PyErr_SetString(PyExc_ValueError,
     1198                                "mmap offset is greater than file size");
     1199                return NULL;
     1200            }
     1201            if (st.st_size - offset > PY_SSIZE_T_MAX) {
     1202                PyErr_SetString(PyExc_ValueError,
     1203                                 "mmap length is too large");
     1204                return NULL;
     1205            }
     1206            map_size = (Py_ssize_t) (st.st_size - offset);
     1207        } else if (offset + (size_t)map_size > st.st_size) {
     1208            PyErr_SetString(PyExc_ValueError,
     1209                            "mmap length is greater than file size");
     1210            return NULL;
     1211        }
     1212    }
     1213#endif
     1214    m_obj = (mmap_object *)type->tp_alloc(type, 0);
     1215    if (m_obj == NULL) {return NULL;}
     1216    m_obj->data = NULL;
     1217    m_obj->size = (size_t) map_size;
     1218    m_obj->pos = (size_t) 0;
     1219    m_obj->offset = offset;
     1220    if (fd == -1) {
     1221        m_obj->fd = -1;
     1222        /* Assume the caller wants to map anonymous memory.
     1223           This is the same behaviour as Windows.  mmap.mmap(-1, size)
     1224           on both Windows and Unix map anonymous memory.
     1225        */
    11821226#ifdef MAP_ANONYMOUS
    1183                 /* BSD way to map anonymous memory */
    1184                 flags |= MAP_ANONYMOUS;
     1227        /* BSD way to map anonymous memory */
     1228        flags |= MAP_ANONYMOUS;
    11851229#else
    1186                 /* SVR4 method to map anonymous memory is to open /dev/zero */
    1187                 fd = devzero = open("/dev/zero", O_RDWR);
    1188                 if (devzero == -1) {
    1189                         Py_DECREF(m_obj);
    1190                         PyErr_SetFromErrno(mmap_module_error);
    1191                         return NULL;
    1192                 }
    1193 #endif
    1194         } else {
    1195                 m_obj->fd = dup(fd);
    1196                 if (m_obj->fd == -1) {
    1197                         Py_DECREF(m_obj);
    1198                         PyErr_SetFromErrno(mmap_module_error);
    1199                         return NULL;
    1200                 }
    1201         }
    1202        
    1203         m_obj->data = mmap(NULL, map_size,
    1204                            prot, flags,
    1205                            fd, offset);
    1206 
    1207         if (devzero != -1) {
    1208                 close(devzero);
    1209         }
    1210 
    1211         if (m_obj->data == (char *)-1) {
    1212                 m_obj->data = NULL;
    1213                 Py_DECREF(m_obj);
    1214                 PyErr_SetFromErrno(mmap_module_error);
    1215                 return NULL;
    1216         }
    1217         m_obj->access = (access_mode)access;
    1218         return (PyObject *)m_obj;
     1230        /* SVR4 method to map anonymous memory is to open /dev/zero */
     1231        fd = devzero = open("/dev/zero", O_RDWR);
     1232        if (devzero == -1) {
     1233            Py_DECREF(m_obj);
     1234            PyErr_SetFromErrno(mmap_module_error);
     1235            return NULL;
     1236        }
     1237#endif
     1238    } else {
     1239        m_obj->fd = dup(fd);
     1240        if (m_obj->fd == -1) {
     1241            Py_DECREF(m_obj);
     1242            PyErr_SetFromErrno(mmap_module_error);
     1243            return NULL;
     1244        }
     1245    }
     1246
     1247    m_obj->data = mmap(NULL, map_size,
     1248                       prot, flags,
     1249                       fd, offset);
     1250
     1251    if (devzero != -1) {
     1252        close(devzero);
     1253    }
     1254
     1255    if (m_obj->data == (char *)-1) {
     1256        m_obj->data = NULL;
     1257        Py_DECREF(m_obj);
     1258        PyErr_SetFromErrno(mmap_module_error);
     1259        return NULL;
     1260    }
     1261    m_obj->access = (access_mode)access;
     1262    return (PyObject *)m_obj;
    12191263}
    12201264#endif /* UNIX */
    12211265
    12221266#ifdef MS_WINDOWS
     1267
     1268/* A note on sizes and offsets: while the actual map size must hold in a
     1269   Py_ssize_t, both the total file size and the start offset can be longer
     1270   than a Py_ssize_t, so we use PY_LONG_LONG which is always 64-bit.
     1271*/
     1272
    12231273static PyObject *
    12241274new_mmap_object(PyTypeObject *type, PyObject *args, PyObject *kwdict)
    12251275{
    1226         mmap_object *m_obj;
    1227         PyObject *map_size_obj = NULL, *offset_obj = NULL;
    1228         Py_ssize_t map_size, offset;
    1229         DWORD off_hi;   /* upper 32 bits of offset */
    1230         DWORD off_lo;   /* lower 32 bits of offset */
    1231         DWORD size_hi;  /* upper 32 bits of size */
    1232         DWORD size_lo;  /* lower 32 bits of size */
    1233         char *tagname = "";
    1234         DWORD dwErr = 0;
    1235         int fileno;
    1236         HANDLE fh = 0;
    1237         int access = (access_mode)ACCESS_DEFAULT;
    1238         DWORD flProtect, dwDesiredAccess;
    1239         static char *keywords[] = { "fileno", "length",
    1240                                           "tagname",
    1241                                           "access", "offset", NULL };
    1242 
    1243         if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iO|ziO", keywords,
    1244                                          &fileno, &map_size_obj,
    1245                                          &tagname, &access, &offset_obj)) {
    1246                 return NULL;
    1247         }
    1248 
    1249         switch((access_mode)access) {
    1250         case ACCESS_READ:
    1251                 flProtect = PAGE_READONLY;
    1252                 dwDesiredAccess = FILE_MAP_READ;
    1253                 break;
    1254         case ACCESS_DEFAULT:  case ACCESS_WRITE:
    1255                 flProtect = PAGE_READWRITE;
    1256                 dwDesiredAccess = FILE_MAP_WRITE;
    1257                 break;
    1258         case ACCESS_COPY:
    1259                 flProtect = PAGE_WRITECOPY;
    1260                 dwDesiredAccess = FILE_MAP_COPY;
    1261                 break;
    1262         default:
    1263                 return PyErr_Format(PyExc_ValueError,
    1264                                     "mmap invalid access parameter.");
    1265         }
    1266 
    1267         map_size = _GetMapSize(map_size_obj, "size");
    1268         if (map_size < 0)
    1269                 return NULL;
    1270         offset = _GetMapSize(offset_obj, "offset");
    1271         if (offset < 0)
     1276    mmap_object *m_obj;
     1277    PyObject *map_size_obj = NULL;
     1278    Py_ssize_t map_size;
     1279    PY_LONG_LONG offset = 0, size;
     1280    DWORD off_hi;       /* upper 32 bits of offset */
     1281    DWORD off_lo;       /* lower 32 bits of offset */
     1282    DWORD size_hi;      /* upper 32 bits of size */
     1283    DWORD size_lo;      /* lower 32 bits of size */
     1284    char *tagname = "";
     1285    DWORD dwErr = 0;
     1286    int fileno;
     1287    HANDLE fh = 0;
     1288    int access = (access_mode)ACCESS_DEFAULT;
     1289    DWORD flProtect, dwDesiredAccess;
     1290    static char *keywords[] = { "fileno", "length",
     1291                                      "tagname",
     1292                                      "access", "offset", NULL };
     1293
     1294    if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iO|ziL", keywords,
     1295                                     &fileno, &map_size_obj,
     1296                                     &tagname, &access, &offset)) {
     1297        return NULL;
     1298    }
     1299
     1300    switch((access_mode)access) {
     1301    case ACCESS_READ:
     1302        flProtect = PAGE_READONLY;
     1303        dwDesiredAccess = FILE_MAP_READ;
     1304        break;
     1305    case ACCESS_DEFAULT:  case ACCESS_WRITE:
     1306        flProtect = PAGE_READWRITE;
     1307        dwDesiredAccess = FILE_MAP_WRITE;
     1308        break;
     1309    case ACCESS_COPY:
     1310        flProtect = PAGE_WRITECOPY;
     1311        dwDesiredAccess = FILE_MAP_COPY;
     1312        break;
     1313    default:
     1314        return PyErr_Format(PyExc_ValueError,
     1315                            "mmap invalid access parameter.");
     1316    }
     1317
     1318    map_size = _GetMapSize(map_size_obj, "size");
     1319    if (map_size < 0)
     1320        return NULL;
     1321    if (offset < 0) {
     1322        PyErr_SetString(PyExc_OverflowError,
     1323            "memory mapped offset must be positive");
     1324        return NULL;
     1325    }
     1326
     1327    /* assume -1 and 0 both mean invalid filedescriptor
     1328       to 'anonymously' map memory.
     1329       XXX: fileno == 0 is a valid fd, but was accepted prior to 2.5.
     1330       XXX: Should this code be added?
     1331       if (fileno == 0)
     1332        PyErr_Warn(PyExc_DeprecationWarning,
     1333                   "don't use 0 for anonymous memory");
     1334     */
     1335    if (fileno != -1 && fileno != 0) {
     1336        /* Ensure that fileno is within the CRT's valid range */
     1337        if (_PyVerify_fd(fileno) == 0) {
     1338            PyErr_SetFromErrno(mmap_module_error);
     1339            return NULL;
     1340        }
     1341        fh = (HANDLE)_get_osfhandle(fileno);
     1342        if (fh==(HANDLE)-1) {
     1343            PyErr_SetFromErrno(mmap_module_error);
     1344            return NULL;
     1345        }
     1346        /* Win9x appears to need us seeked to zero */
     1347        lseek(fileno, 0, SEEK_SET);
     1348    }
     1349
     1350    m_obj = (mmap_object *)type->tp_alloc(type, 0);
     1351    if (m_obj == NULL)
     1352        return NULL;
     1353    /* Set every field to an invalid marker, so we can safely
     1354       destruct the object in the face of failure */
     1355    m_obj->data = NULL;
     1356    m_obj->file_handle = INVALID_HANDLE_VALUE;
     1357    m_obj->map_handle = NULL;
     1358    m_obj->tagname = NULL;
     1359    m_obj->offset = offset;
     1360
     1361    if (fh) {
     1362        /* It is necessary to duplicate the handle, so the
     1363           Python code can close it on us */
     1364        if (!DuplicateHandle(
     1365            GetCurrentProcess(), /* source process handle */
     1366            fh, /* handle to be duplicated */
     1367            GetCurrentProcess(), /* target proc handle */
     1368            (LPHANDLE)&m_obj->file_handle, /* result */
     1369            0, /* access - ignored due to options value */
     1370            FALSE, /* inherited by child processes? */
     1371            DUPLICATE_SAME_ACCESS)) { /* options */
     1372            dwErr = GetLastError();
     1373            Py_DECREF(m_obj);
     1374            PyErr_SetFromWindowsErr(dwErr);
     1375            return NULL;
     1376        }
     1377        if (!map_size) {
     1378            DWORD low,high;
     1379            low = GetFileSize(fh, &high);
     1380            /* low might just happen to have the value INVALID_FILE_SIZE;
     1381               so we need to check the last error also. */
     1382            if (low == INVALID_FILE_SIZE &&
     1383                (dwErr = GetLastError()) != NO_ERROR) {
     1384                Py_DECREF(m_obj);
     1385                return PyErr_SetFromWindowsErr(dwErr);
     1386            }
     1387
     1388            size = (((PY_LONG_LONG) high) << 32) + low;
     1389            if (size == 0) {
     1390                PyErr_SetString(PyExc_ValueError,
     1391                                "cannot mmap an empty file");
     1392                Py_DECREF(m_obj);
    12721393                return NULL;
    1273 
    1274         /* assume -1 and 0 both mean invalid filedescriptor
    1275            to 'anonymously' map memory.
    1276            XXX: fileno == 0 is a valid fd, but was accepted prior to 2.5.
    1277            XXX: Should this code be added?
    1278            if (fileno == 0)
    1279                 PyErr_Warn(PyExc_DeprecationWarning,
    1280                            "don't use 0 for anonymous memory");
    1281          */
    1282         if (fileno != -1 && fileno != 0) {
    1283                 fh = (HANDLE)_get_osfhandle(fileno);
    1284                 if (fh==(HANDLE)-1) {
    1285                         PyErr_SetFromErrno(mmap_module_error);
    1286                         return NULL;
    1287                 }
    1288                 /* Win9x appears to need us seeked to zero */
    1289                 lseek(fileno, 0, SEEK_SET);
    1290         }
    1291 
    1292         m_obj = (mmap_object *)type->tp_alloc(type, 0);
    1293         if (m_obj == NULL)
    1294                 return NULL;
    1295         /* Set every field to an invalid marker, so we can safely
    1296            destruct the object in the face of failure */
    1297         m_obj->data = NULL;
    1298         m_obj->file_handle = INVALID_HANDLE_VALUE;
    1299         m_obj->map_handle = NULL;
    1300         m_obj->tagname = NULL;
    1301         m_obj->offset = offset;
    1302 
    1303         if (fh) {
    1304                 /* It is necessary to duplicate the handle, so the
    1305                    Python code can close it on us */
    1306                 if (!DuplicateHandle(
    1307                         GetCurrentProcess(), /* source process handle */
    1308                         fh, /* handle to be duplicated */
    1309                         GetCurrentProcess(), /* target proc handle */
    1310                         (LPHANDLE)&m_obj->file_handle, /* result */
    1311                         0, /* access - ignored due to options value */
    1312                         FALSE, /* inherited by child processes? */
    1313                         DUPLICATE_SAME_ACCESS)) { /* options */
    1314                         dwErr = GetLastError();
    1315                         Py_DECREF(m_obj);
    1316                         PyErr_SetFromWindowsErr(dwErr);
    1317                         return NULL;
    1318                 }
    1319                 if (!map_size) {
    1320                         DWORD low,high;
    1321                         low = GetFileSize(fh, &high);
    1322                         /* low might just happen to have the value INVALID_FILE_SIZE;
    1323                            so we need to check the last error also. */
    1324                         if (low == INVALID_FILE_SIZE &&
    1325                             (dwErr = GetLastError()) != NO_ERROR) {
    1326                                 Py_DECREF(m_obj);
    1327                                 return PyErr_SetFromWindowsErr(dwErr);
    1328                         }       
    1329                                    
    1330 #if SIZEOF_SIZE_T > 4
    1331                         m_obj->size = (((size_t)high)<<32) + low;
    1332 #else
    1333                         if (high)
    1334                                 /* File is too large to map completely */
    1335                                 m_obj->size = (size_t)-1;
    1336                         else
    1337                                 m_obj->size = low;
    1338 #endif
    1339                 } else {
    1340                         m_obj->size = map_size;
    1341                 }
    1342         }
    1343         else {
    1344                 m_obj->size = map_size;
    1345         }
    1346 
    1347         /* set the initial position */
    1348         m_obj->pos = (size_t) 0;
    1349 
    1350         /* set the tag name */
    1351         if (tagname != NULL && *tagname != '\0') {
    1352                 m_obj->tagname = PyMem_Malloc(strlen(tagname)+1);
    1353                 if (m_obj->tagname == NULL) {
    1354                         PyErr_NoMemory();
    1355                         Py_DECREF(m_obj);
    1356                         return NULL;
    1357                 }
    1358                 strcpy(m_obj->tagname, tagname);
    1359         }
    1360         else
    1361                 m_obj->tagname = NULL;
    1362 
    1363         m_obj->access = (access_mode)access;
    1364         /* DWORD is a 4-byte int.  If we're on a box where size_t consumes
    1365          * more than 4 bytes, we need to break it apart.  Else (size_t
    1366          * consumes 4 bytes), C doesn't define what happens if we shift
    1367          * right by 32, so we need different code.
    1368          */
    1369 #if SIZEOF_SIZE_T > 4
    1370         size_hi = (DWORD)((offset + m_obj->size) >> 32);
    1371         size_lo = (DWORD)((offset + m_obj->size) & 0xFFFFFFFF);
    1372         off_hi = (DWORD)(offset >> 32);
    1373         off_lo = (DWORD)(offset & 0xFFFFFFFF);
    1374 #else
    1375         size_hi = 0;
    1376         size_lo = (DWORD)(offset + m_obj->size);
    1377         off_hi = 0;
    1378         off_lo = (DWORD)offset;
    1379 #endif
    1380         /* For files, it would be sufficient to pass 0 as size.
    1381            For anonymous maps, we have to pass the size explicitly. */
    1382         m_obj->map_handle = CreateFileMapping(m_obj->file_handle,
    1383                                               NULL,
    1384                                               flProtect,
    1385                                               size_hi,
    1386                                               size_lo,
    1387                                               m_obj->tagname);
    1388         if (m_obj->map_handle != NULL) {
    1389                 m_obj->data = (char *) MapViewOfFile(m_obj->map_handle,
    1390                                                      dwDesiredAccess,
    1391                                                      off_hi,
    1392                                                      off_lo,
    1393                                                      m_obj->size);
    1394                 if (m_obj->data != NULL)
    1395                         return (PyObject *)m_obj;
    1396                 else {
    1397                         dwErr = GetLastError();
    1398                         CloseHandle(m_obj->map_handle);
    1399                         m_obj->map_handle = NULL;
    1400                 }
    1401         } else
    1402                 dwErr = GetLastError();
    1403         Py_DECREF(m_obj);
    1404         PyErr_SetFromWindowsErr(dwErr);
    1405         return NULL;
     1394            }
     1395            if (offset >= size) {
     1396                PyErr_SetString(PyExc_ValueError,
     1397                                "mmap offset is greater than file size");
     1398                Py_DECREF(m_obj);
     1399                return NULL;
     1400            }
     1401            if (size - offset > PY_SSIZE_T_MAX) {
     1402                PyErr_SetString(PyExc_ValueError,
     1403                                "mmap length is too large");
     1404                Py_DECREF(m_obj);
     1405                return NULL;
     1406            }
     1407            m_obj->size = (Py_ssize_t) (size - offset);
     1408        } else {
     1409            m_obj->size = map_size;
     1410            size = offset + map_size;
     1411        }
     1412    }
     1413    else {
     1414        m_obj->size = map_size;
     1415        size = offset + map_size;
     1416    }
     1417
     1418    /* set the initial position */
     1419    m_obj->pos = (size_t) 0;
     1420
     1421    /* set the tag name */
     1422    if (tagname != NULL && *tagname != '\0') {
     1423        m_obj->tagname = PyMem_Malloc(strlen(tagname)+1);
     1424        if (m_obj->tagname == NULL) {
     1425            PyErr_NoMemory();
     1426            Py_DECREF(m_obj);
     1427            return NULL;
     1428        }
     1429        strcpy(m_obj->tagname, tagname);
     1430    }
     1431    else
     1432        m_obj->tagname = NULL;
     1433
     1434    m_obj->access = (access_mode)access;
     1435    size_hi = (DWORD)(size >> 32);
     1436    size_lo = (DWORD)(size & 0xFFFFFFFF);
     1437    off_hi = (DWORD)(offset >> 32);
     1438    off_lo = (DWORD)(offset & 0xFFFFFFFF);
     1439    /* For files, it would be sufficient to pass 0 as size.
     1440       For anonymous maps, we have to pass the size explicitly. */
     1441    m_obj->map_handle = CreateFileMapping(m_obj->file_handle,
     1442                                          NULL,
     1443                                          flProtect,
     1444                                          size_hi,
     1445                                          size_lo,
     1446                                          m_obj->tagname);
     1447    if (m_obj->map_handle != NULL) {
     1448        m_obj->data = (char *) MapViewOfFile(m_obj->map_handle,
     1449                                             dwDesiredAccess,
     1450                                             off_hi,
     1451                                             off_lo,
     1452                                             m_obj->size);
     1453        if (m_obj->data != NULL)
     1454            return (PyObject *)m_obj;
     1455        else {
     1456            dwErr = GetLastError();
     1457            CloseHandle(m_obj->map_handle);
     1458            m_obj->map_handle = NULL;
     1459        }
     1460    } else
     1461        dwErr = GetLastError();
     1462    Py_DECREF(m_obj);
     1463    PyErr_SetFromWindowsErr(dwErr);
     1464    return NULL;
    14061465}
    14071466#endif /* MS_WINDOWS */
     
    14101469setint(PyObject *d, const char *name, long value)
    14111470{
    1412         PyObject *o = PyInt_FromLong(value);
    1413         if (o && PyDict_SetItemString(d, name, o) == 0) {
    1414                 Py_DECREF(o);
    1415         }
     1471    PyObject *o = PyInt_FromLong(value);
     1472    if (o && PyDict_SetItemString(d, name, o) == 0) {
     1473        Py_DECREF(o);
     1474    }
    14161475}
    14171476
     
    14191478initmmap(void)
    14201479{
    1421         PyObject *dict, *module;
    1422 
    1423         if (PyType_Ready(&mmap_object_type) < 0)
    1424                 return;
    1425 
    1426         module = Py_InitModule("mmap", NULL);
    1427         if (module == NULL)
    1428                 return;
    1429         dict = PyModule_GetDict(module);
    1430         if (!dict)
    1431                 return;
    1432         mmap_module_error = PyErr_NewException("mmap.error",
    1433                 PyExc_EnvironmentError , NULL);
    1434         if (mmap_module_error == NULL)
    1435                 return;
    1436         PyDict_SetItemString(dict, "error", mmap_module_error);
    1437         PyDict_SetItemString(dict, "mmap", (PyObject*) &mmap_object_type);
     1480    PyObject *dict, *module;
     1481
     1482    if (PyType_Ready(&mmap_object_type) < 0)
     1483        return;
     1484
     1485    module = Py_InitModule("mmap", NULL);
     1486    if (module == NULL)
     1487        return;
     1488    dict = PyModule_GetDict(module);
     1489    if (!dict)
     1490        return;
     1491    mmap_module_error = PyErr_NewException("mmap.error",
     1492        PyExc_EnvironmentError , NULL);
     1493    if (mmap_module_error == NULL)
     1494        return;
     1495    PyDict_SetItemString(dict, "error", mmap_module_error);
     1496    PyDict_SetItemString(dict, "mmap", (PyObject*) &mmap_object_type);
    14381497#ifdef PROT_EXEC
    1439         setint(dict, "PROT_EXEC", PROT_EXEC);
     1498    setint(dict, "PROT_EXEC", PROT_EXEC);
    14401499#endif
    14411500#ifdef PROT_READ
    1442         setint(dict, "PROT_READ", PROT_READ);
     1501    setint(dict, "PROT_READ", PROT_READ);
    14431502#endif
    14441503#ifdef PROT_WRITE
    1445         setint(dict, "PROT_WRITE", PROT_WRITE);
     1504    setint(dict, "PROT_WRITE", PROT_WRITE);
    14461505#endif
    14471506
    14481507#ifdef MAP_SHARED
    1449         setint(dict, "MAP_SHARED", MAP_SHARED);
     1508    setint(dict, "MAP_SHARED", MAP_SHARED);
    14501509#endif
    14511510#ifdef MAP_PRIVATE
    1452         setint(dict, "MAP_PRIVATE", MAP_PRIVATE);
     1511    setint(dict, "MAP_PRIVATE", MAP_PRIVATE);
    14531512#endif
    14541513#ifdef MAP_DENYWRITE
    1455         setint(dict, "MAP_DENYWRITE", MAP_DENYWRITE);
     1514    setint(dict, "MAP_DENYWRITE", MAP_DENYWRITE);
    14561515#endif
    14571516#ifdef MAP_EXECUTABLE
    1458         setint(dict, "MAP_EXECUTABLE", MAP_EXECUTABLE);
     1517    setint(dict, "MAP_EXECUTABLE", MAP_EXECUTABLE);
    14591518#endif
    14601519#ifdef MAP_ANONYMOUS
    1461         setint(dict, "MAP_ANON", MAP_ANONYMOUS);
    1462         setint(dict, "MAP_ANONYMOUS", MAP_ANONYMOUS);
    1463 #endif
    1464 
    1465         setint(dict, "PAGESIZE", (long)my_getpagesize());
    1466 
    1467         setint(dict, "ALLOCATIONGRANULARITY", (long)my_getallocationgranularity());
    1468 
    1469         setint(dict, "ACCESS_READ", ACCESS_READ);
    1470         setint(dict, "ACCESS_WRITE", ACCESS_WRITE);
    1471         setint(dict, "ACCESS_COPY", ACCESS_COPY);
    1472 }
     1520    setint(dict, "MAP_ANON", MAP_ANONYMOUS);
     1521    setint(dict, "MAP_ANONYMOUS", MAP_ANONYMOUS);
     1522#endif
     1523
     1524    setint(dict, "PAGESIZE", (long)my_getpagesize());
     1525
     1526    setint(dict, "ALLOCATIONGRANULARITY", (long)my_getallocationgranularity());
     1527
     1528    setint(dict, "ACCESS_READ", ACCESS_READ);
     1529    setint(dict, "ACCESS_WRITE", ACCESS_WRITE);
     1530    setint(dict, "ACCESS_COPY", ACCESS_COPY);
     1531}
Note: See TracChangeset for help on using the changeset viewer.