Back to index

python3.2  3.2.2
Classes | Defines | Enumerations | Functions | Variables
mmapmodule.c File Reference
#include <Python.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <string.h>

Go to the source code of this file.

Classes

struct  mmap_object

Defines

#define PY_SSIZE_T_CLEAN
#define UNIX
#define my_getpagesize   getpagesize
#define CHECK_VALID(err)
#define _Py_PARSE_OFF_T   "l"

Enumerations

enum  access_mode { ACCESS_DEFAULT, ACCESS_READ, ACCESS_WRITE, ACCESS_COPY }

Functions

static void mmap_object_dealloc (mmap_object *m_obj)
static PyObjectmmap_close_method (mmap_object *self, PyObject *unused)
static PyObjectmmap_read_byte_method (mmap_object *self, PyObject *unused)
static PyObjectmmap_read_line_method (mmap_object *self, PyObject *unused)
static PyObjectmmap_read_method (mmap_object *self, PyObject *args)
static PyObjectmmap_gfind (mmap_object *self, PyObject *args, int reverse)
static PyObjectmmap_find_method (mmap_object *self, PyObject *args)
static PyObjectmmap_rfind_method (mmap_object *self, PyObject *args)
static int is_writable (mmap_object *self)
static int is_resizeable (mmap_object *self)
static PyObjectmmap_write_method (mmap_object *self, PyObject *args)
static PyObjectmmap_write_byte_method (mmap_object *self, PyObject *args)
static PyObjectmmap_size_method (mmap_object *self, PyObject *unused)
static PyObjectmmap_resize_method (mmap_object *self, PyObject *args)
static PyObjectmmap_tell_method (mmap_object *self, PyObject *unused)
static PyObjectmmap_flush_method (mmap_object *self, PyObject *args)
static PyObjectmmap_seek_method (mmap_object *self, PyObject *args)
static PyObjectmmap_move_method (mmap_object *self, PyObject *args)
static PyObjectmmap_closed_get (mmap_object *self)
static PyObjectmmap__enter__method (mmap_object *self, PyObject *args)
static PyObjectmmap__exit__method (PyObject *self, PyObject *args)
static int mmap_buffer_getbuf (mmap_object *self, Py_buffer *view, int flags)
static void mmap_buffer_releasebuf (mmap_object *self, Py_buffer *view)
static Py_ssize_t mmap_length (mmap_object *self)
static PyObjectmmap_item (mmap_object *self, Py_ssize_t i)
static PyObjectmmap_subscript (mmap_object *self, PyObject *item)
static PyObjectmmap_concat (mmap_object *self, PyObject *bb)
static PyObjectmmap_repeat (mmap_object *self, Py_ssize_t n)
static int mmap_ass_item (mmap_object *self, Py_ssize_t i, PyObject *v)
static int mmap_ass_subscript (mmap_object *self, PyObject *item, PyObject *value)
static PyObjectnew_mmap_object (PyTypeObject *type, PyObject *args, PyObject *kwdict)
 PyDoc_STRVAR (mmap_doc,"Windows: mmap(fileno, length[, tagname[, access[, offset]]])\n\ \n\ Maps length bytes from the file specified by the file handle fileno,\n\ and returns a mmap object. If length is larger than the current size\n\ of the file, the file is extended to contain length bytes. If length\n\ is 0, the maximum length of the map is the current size of the file,\n\ except that if the file is empty Windows raises an exception (you cannot\n\ create an empty mapping on Windows).\n\ \n\ Unix: mmap(fileno, length[, flags[, prot[, access[, offset]]]])\n\ \n\ Maps length bytes from the file specified by the file descriptor fileno,\n\ and returns a mmap object. If length is 0, the maximum length of the map\n\ will be the current size of the file when mmap is called.\n\ flags specifies the nature of the mapping. MAP_PRIVATE creates a\n\ private copy-on-write mapping, so changes to the contents of the mmap\n\ object will be private to this process, and MAP_SHARED creates a mapping\n\ that's shared with all other processes mapping the same areas of the file.\n\ The default value is MAP_SHARED.\n\ \n\ To map anonymous memory, pass -1 as the fileno (both versions).")
static Py_ssize_t _GetMapSize (PyObject *o, const char *param)
static void setint (PyObject *d, const char *name, long value)
PyMODINIT_FUNC PyInit_mmap (void)

Variables

static PyObjectmmap_module_error
static struct PyMethodDef []
static PyGetSetDef mmap_object_getset []
static PySequenceMethods mmap_as_sequence
static PyMappingMethods mmap_as_mapping
static PyBufferProcs mmap_as_buffer
static PyTypeObject mmap_object_type
static struct PyModuleDef

Class Documentation

struct mmap_object

Definition at line 91 of file mmapmodule.c.

Class Members
access_mode access
PyObject_HEAD char * data
int exports
int fd
off_t offset
size_t pos
size_t size

Define Documentation

#define _Py_PARSE_OFF_T   "l"

Definition at line 1061 of file mmapmodule.c.

#define CHECK_VALID (   err)
Value:
do {                                                                    \
    if (self->data == NULL) {                                           \
    PyErr_SetString(PyExc_ValueError, "mmap closed or invalid");        \
    return err;                                                         \
    }                                                                   \
} while (0)

Definition at line 197 of file mmapmodule.c.

#define my_getpagesize   getpagesize

Definition at line 65 of file mmapmodule.c.

Definition at line 21 of file mmapmodule.c.

#define UNIX

Definition at line 25 of file mmapmodule.c.


Enumeration Type Documentation

Enumerator:
ACCESS_DEFAULT 
ACCESS_READ 
ACCESS_WRITE 
ACCESS_COPY 

Definition at line 83 of file mmapmodule.c.


Function Documentation

static Py_ssize_t _GetMapSize ( PyObject o,
const char *  param 
) [static]

Definition at line 1036 of file mmapmodule.c.

{
    if (o == NULL)
        return 0;
    if (PyIndex_Check(o)) {
        Py_ssize_t i = PyNumber_AsSsize_t(o, PyExc_OverflowError);
        if (i==-1 && PyErr_Occurred())
            return -1;
        if (i < 0) {
            PyErr_Format(PyExc_OverflowError,
                            "memory mapped %s must be positive",
                            param);
            return -1;
        }
        return i;
    }

    PyErr_SetString(PyExc_TypeError, "map size must be an integral value");
    return -1;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int is_resizeable ( mmap_object self) [static]

Definition at line 345 of file mmapmodule.c.

{
    if (self->exports > 0) {
        PyErr_SetString(PyExc_BufferError,
                        "mmap can't resize with extant buffers exported.");
        return 0;
    }
    if ((self->access == ACCESS_WRITE) || (self->access == ACCESS_DEFAULT))
        return 1;
    PyErr_Format(PyExc_TypeError,
                 "mmap can't resize a readonly or copy-on-write memory map.");
    return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int is_writable ( mmap_object self) [static]

Definition at line 336 of file mmapmodule.c.

{
    if (self->access != ACCESS_READ)
        return 1;
    PyErr_Format(PyExc_TypeError, "mmap can't modify a readonly memory map.");
    return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static PyObject* mmap__enter__method ( mmap_object self,
PyObject args 
) [static]

Definition at line 672 of file mmapmodule.c.

{
    CHECK_VALID(NULL);

    Py_INCREF(self);
    return (PyObject *)self;
}
static PyObject* mmap__exit__method ( PyObject self,
PyObject args 
) [static]

Definition at line 681 of file mmapmodule.c.

{
    return PyObject_CallMethod(self, "close", NULL);
}

Here is the call graph for this function:

static int mmap_ass_item ( mmap_object self,
Py_ssize_t  i,
PyObject v 
) [static]

Definition at line 822 of file mmapmodule.c.

{
    const char *buf;

    CHECK_VALID(-1);
    if (i < 0 || (size_t)i >= self->size) {
        PyErr_SetString(PyExc_IndexError, "mmap index out of range");
        return -1;
    }
    if (v == NULL) {
        PyErr_SetString(PyExc_TypeError,
                        "mmap object doesn't support item deletion");
        return -1;
    }
    if (! (PyBytes_Check(v) && PyBytes_Size(v)==1) ) {
        PyErr_SetString(PyExc_IndexError,
                        "mmap assignment must be length-1 bytes()");
        return -1;
    }
    if (!is_writable(self))
        return -1;
    buf = PyBytes_AsString(v);
    self->data[i] = buf[0];
    return 0;
}

Here is the call graph for this function:

static int mmap_ass_subscript ( mmap_object self,
PyObject item,
PyObject value 
) [static]

Definition at line 849 of file mmapmodule.c.

{
    CHECK_VALID(-1);

    if (!is_writable(self))
        return -1;

    if (PyIndex_Check(item)) {
        Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
        Py_ssize_t v;

        if (i == -1 && PyErr_Occurred())
            return -1;
        if (i < 0)
            i += self->size;
        if (i < 0 || (size_t)i >= self->size) {
            PyErr_SetString(PyExc_IndexError,
                            "mmap index out of range");
            return -1;
        }
        if (value == NULL) {
            PyErr_SetString(PyExc_TypeError,
                            "mmap doesn't support item deletion");
            return -1;
        }
        if (!PyIndex_Check(value)) {
            PyErr_SetString(PyExc_TypeError,
                            "mmap item value must be an int");
            return -1;
        }
        v = PyNumber_AsSsize_t(value, PyExc_TypeError);
        if (v == -1 && PyErr_Occurred())
            return -1;
        if (v < 0 || v > 255) {
            PyErr_SetString(PyExc_ValueError,
                            "mmap item value must be "
                            "in range(0, 256)");
            return -1;
        }
        self->data[i] = (char) v;
        return 0;
    }
    else if (PySlice_Check(item)) {
        Py_ssize_t start, stop, step, slicelen;
        Py_buffer vbuf;

        if (PySlice_GetIndicesEx(item,
                                 self->size, &start, &stop,
                                 &step, &slicelen) < 0) {
            return -1;
        }
        if (value == NULL) {
            PyErr_SetString(PyExc_TypeError,
                "mmap object doesn't support slice deletion");
            return -1;
        }
        if (PyObject_GetBuffer(value, &vbuf, PyBUF_SIMPLE) < 0)
            return -1;
        if (vbuf.len != slicelen) {
            PyErr_SetString(PyExc_IndexError,
                "mmap slice assignment is wrong size");
            PyBuffer_Release(&vbuf);
            return -1;
        }

        if (slicelen == 0) {
        }
        else if (step == 1) {
            memcpy(self->data + start, vbuf.buf, slicelen);
        }
        else {
            Py_ssize_t cur, i;

            for (cur = start, i = 0;
                 i < slicelen;
                 cur += step, i++)
            {
                self->data[cur] = ((char *)vbuf.buf)[i];
            }
        }
        PyBuffer_Release(&vbuf);
        return 0;
    }
    else {
        PyErr_SetString(PyExc_TypeError,
                        "mmap indices must be integer");
        return -1;
    }
}

Here is the call graph for this function:

static int mmap_buffer_getbuf ( mmap_object self,
Py_buffer view,
int  flags 
) [static]

Definition at line 715 of file mmapmodule.c.

{
    CHECK_VALID(-1);
    if (PyBuffer_FillInfo(view, (PyObject*)self, self->data, self->size,
                          (self->access == ACCESS_READ), flags) < 0)
        return -1;
    self->exports++;
    return 0;
}

Here is the call graph for this function:

static void mmap_buffer_releasebuf ( mmap_object self,
Py_buffer view 
) [static]

Definition at line 726 of file mmapmodule.c.

{
    self->exports--;
}
static PyObject* mmap_close_method ( mmap_object self,
PyObject unused 
) [static]

Definition at line 143 of file mmapmodule.c.

{
    if (self->exports > 0) {
        PyErr_SetString(PyExc_BufferError, "cannot close "\
                        "exported pointers exist");
        return NULL;
    }
#ifdef MS_WINDOWS
    /* For each resource we maintain, we need to check
       the value is valid, and if so, free the resource
       and set the member value to an invalid value so
       the dealloc does not attempt to resource clearing
       again.
       TODO - should we check for errors in the close operations???
    */
    if (self->data != NULL) {
        UnmapViewOfFile(self->data);
        self->data = NULL;
    }
    if (self->map_handle != NULL) {
        CloseHandle(self->map_handle);
        self->map_handle = NULL;
    }
    if (self->file_handle != INVALID_HANDLE_VALUE) {
        CloseHandle(self->file_handle);
        self->file_handle = INVALID_HANDLE_VALUE;
    }
#endif /* MS_WINDOWS */

#ifdef UNIX
    if (0 <= self->fd)
        (void) close(self->fd);
    self->fd = -1;
    if (self->data != NULL) {
        munmap(self->data, self->size);
        self->data = NULL;
    }
#endif

    Py_INCREF(Py_None);
    return Py_None;
}

Here is the call graph for this function:

static PyObject* mmap_closed_get ( mmap_object self) [static]

Definition at line 662 of file mmapmodule.c.

{
#ifdef MS_WINDOWS
    return PyBool_FromLong(self->map_handle == NULL ? 1 : 0);
#elif defined(UNIX)
    return PyBool_FromLong(self->data == NULL ? 1 : 0);
#endif
}

Here is the call graph for this function:

static PyObject* mmap_concat ( mmap_object self,
PyObject bb 
) [static]

Definition at line 804 of file mmapmodule.c.

{
    CHECK_VALID(NULL);
    PyErr_SetString(PyExc_SystemError,
                    "mmaps don't support concatenation");
    return NULL;
}

Here is the call graph for this function:

static PyObject* mmap_find_method ( mmap_object self,
PyObject args 
) [static]

Definition at line 322 of file mmapmodule.c.

{
    return mmap_gfind(self, args, 0);
}

Here is the call graph for this function:

static PyObject* mmap_flush_method ( mmap_object self,
PyObject args 
) [static]

Definition at line 565 of file mmapmodule.c.

{
    Py_ssize_t offset = 0;
    Py_ssize_t size = self->size;
    CHECK_VALID(NULL);
    if (!PyArg_ParseTuple(args, "|nn:flush", &offset, &size))
        return NULL;
    if ((size_t)(offset + size) > self->size) {
        PyErr_SetString(PyExc_ValueError, "flush values out of range");
        return NULL;
    }

    if (self->access == ACCESS_READ || self->access == ACCESS_COPY)
        return PyLong_FromLong(0);

#ifdef MS_WINDOWS
    return PyLong_FromLong((long) FlushViewOfFile(self->data+offset, size));
#elif defined(UNIX)
    /* XXX semantics of return value? */
    /* XXX flags for msync? */
    if (-1 == msync(self->data + offset, size, MS_SYNC)) {
        PyErr_SetFromErrno(mmap_module_error);
        return NULL;
    }
    return PyLong_FromLong(0);
#else
    PyErr_SetString(PyExc_ValueError, "flush not supported on this system");
    return NULL;
#endif
}

Here is the call graph for this function:

static PyObject* mmap_gfind ( mmap_object self,
PyObject args,
int  reverse 
) [static]

Definition at line 274 of file mmapmodule.c.

{
    Py_ssize_t start = self->pos;
    Py_ssize_t end = self->size;
    const char *needle;
    Py_ssize_t len;

    CHECK_VALID(NULL);
    if (!PyArg_ParseTuple(args, reverse ? "y#|nn:rfind" : "y#|nn:find",
                          &needle, &len, &start, &end)) {
        return NULL;
    } else {
        const char *p, *start_p, *end_p;
        int sign = reverse ? -1 : 1;

        if (start < 0)
            start += self->size;
        if (start < 0)
            start = 0;
        else if ((size_t)start > self->size)
            start = self->size;

        if (end < 0)
            end += self->size;
        if (end < 0)
            end = 0;
        else if ((size_t)end > self->size)
            end = self->size;

        start_p = self->data + start;
        end_p = self->data + end;

        for (p = (reverse ? end_p - len : start_p);
             (p >= start_p) && (p + len <= end_p); p += sign) {
            Py_ssize_t i;
            for (i = 0; i < len && needle[i] == p[i]; ++i)
                /* nothing */;
            if (i == len) {
                return PyLong_FromSsize_t(p - self->data);
            }
        }
        return PyLong_FromLong(-1);
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static PyObject* mmap_item ( mmap_object self,
Py_ssize_t  i 
) [static]

Definition at line 739 of file mmapmodule.c.

{
    CHECK_VALID(NULL);
    if (i < 0 || (size_t)i >= self->size) {
        PyErr_SetString(PyExc_IndexError, "mmap index out of range");
        return NULL;
    }
    return PyBytes_FromStringAndSize(self->data + i, 1);
}

Here is the call graph for this function:

static Py_ssize_t mmap_length ( mmap_object self) [static]

Definition at line 732 of file mmapmodule.c.

{
    CHECK_VALID(-1);
    return self->size;
}
static PyObject* mmap_move_method ( mmap_object self,
PyObject args 
) [static]

Definition at line 639 of file mmapmodule.c.

{
    unsigned long dest, src, cnt;
    CHECK_VALID(NULL);
    if (!PyArg_ParseTuple(args, "kkk:move", &dest, &src, &cnt) ||
        !is_writable(self)) {
        return NULL;
    } else {
        /* bounds check the values */
        if (cnt < 0 || (cnt + dest) < cnt || (cnt + src) < cnt ||
           src < 0 || src > self->size || (src + cnt) > self->size ||
           dest < 0 || dest > self->size || (dest + cnt) > self->size) {
            PyErr_SetString(PyExc_ValueError,
                "source, destination, or count out of range");
            return NULL;
        }
        memmove(self->data+dest, self->data+src, cnt);
        Py_INCREF(Py_None);
        return Py_None;
    }
}

Here is the call graph for this function:

static void mmap_object_dealloc ( mmap_object m_obj) [static]

Definition at line 118 of file mmapmodule.c.

{
#ifdef MS_WINDOWS
    if (m_obj->data != NULL)
        UnmapViewOfFile (m_obj->data);
    if (m_obj->map_handle != NULL)
        CloseHandle (m_obj->map_handle);
    if (m_obj->file_handle != INVALID_HANDLE_VALUE)
        CloseHandle (m_obj->file_handle);
    if (m_obj->tagname)
        PyMem_Free(m_obj->tagname);
#endif /* MS_WINDOWS */

#ifdef UNIX
    if (m_obj->fd >= 0)
        (void) close(m_obj->fd);
    if (m_obj->data!=NULL) {
        munmap(m_obj->data, m_obj->size);
    }
#endif /* UNIX */

    Py_TYPE(m_obj)->tp_free((PyObject*)m_obj);
}

Here is the call graph for this function:

static PyObject* mmap_read_byte_method ( mmap_object self,
PyObject unused 
) [static]

Definition at line 207 of file mmapmodule.c.

{
    CHECK_VALID(NULL);
    if (self->pos < self->size) {
        char value = self->data[self->pos];
        self->pos += 1;
        return Py_BuildValue("B", (unsigned char)value);
    } else {
        PyErr_SetString(PyExc_ValueError, "read byte out of range");
        return NULL;
    }
}

Here is the call graph for this function:

static PyObject* mmap_read_line_method ( mmap_object self,
PyObject unused 
) [static]

Definition at line 222 of file mmapmodule.c.

{
    char *start = self->data+self->pos;
    char *eof = self->data+self->size;
    char *eol;
    PyObject *result;

    CHECK_VALID(NULL);

    eol = memchr(start, '\n', self->size - self->pos);
    if (!eol)
        eol = eof;
    else
        ++eol;                  /* we're interested in the position after the
                           newline. */
    result = PyBytes_FromStringAndSize(start, (eol - start));
    self->pos += (eol - start);
    return result;
}

Here is the call graph for this function:

static PyObject* mmap_read_method ( mmap_object self,
PyObject args 
) [static]

Definition at line 244 of file mmapmodule.c.

{
    Py_ssize_t num_bytes, n;
    PyObject *result;

    CHECK_VALID(NULL);
    if (!PyArg_ParseTuple(args, "n:read", &num_bytes))
        return(NULL);

    /* silently 'adjust' out-of-range requests */
    assert(self->size >= self->pos);
    n = self->size - self->pos;
    /* The difference can overflow, only if self->size is greater than
     * PY_SSIZE_T_MAX.  But then the operation cannot possibly succeed,
     * because the mapped area and the returned string each need more
     * than half of the addressable memory.  So we clip the size, and let
     * the code below raise MemoryError.
     */
    if (n < 0)
        n = PY_SSIZE_T_MAX;
    if (num_bytes < 0 || num_bytes > n) {
        num_bytes = n;
    }
    result = PyBytes_FromStringAndSize(self->data+self->pos, num_bytes);
    self->pos += num_bytes;
    return result;
}

Here is the call graph for this function:

static PyObject* mmap_repeat ( mmap_object self,
Py_ssize_t  n 
) [static]

Definition at line 813 of file mmapmodule.c.

{
    CHECK_VALID(NULL);
    PyErr_SetString(PyExc_SystemError,
                    "mmaps don't support repeat operation");
    return NULL;
}

Here is the call graph for this function:

static PyObject* mmap_resize_method ( mmap_object self,
PyObject args 
) [static]

Definition at line 462 of file mmapmodule.c.

{
    Py_ssize_t new_size;
    CHECK_VALID(NULL);
    if (!PyArg_ParseTuple(args, "n:resize", &new_size) ||
        !is_resizeable(self)) {
        return NULL;
#ifdef MS_WINDOWS
    } else {
        DWORD dwErrCode = 0;
        DWORD off_hi, off_lo, newSizeLow, newSizeHigh;
        /* First, unmap the file view */
        UnmapViewOfFile(self->data);
        self->data = NULL;
        /* Close the mapping object */
        CloseHandle(self->map_handle);
        self->map_handle = NULL;
        /* Move to the desired EOF position */
        newSizeHigh = (DWORD)((self->offset + new_size) >> 32);
        newSizeLow = (DWORD)((self->offset + new_size) & 0xFFFFFFFF);
        off_hi = (DWORD)(self->offset >> 32);
        off_lo = (DWORD)(self->offset & 0xFFFFFFFF);
        SetFilePointer(self->file_handle,
                       newSizeLow, &newSizeHigh, FILE_BEGIN);
        /* Change the size of the file */
        SetEndOfFile(self->file_handle);
        /* Create another mapping object and remap the file view */
        self->map_handle = CreateFileMapping(
            self->file_handle,
            NULL,
            PAGE_READWRITE,
            0,
            0,
            self->tagname);
        if (self->map_handle != NULL) {
            self->data = (char *) MapViewOfFile(self->map_handle,
                                                FILE_MAP_WRITE,
                                                off_hi,
                                                off_lo,
                                                new_size);
            if (self->data != NULL) {
                self->size = new_size;
                Py_INCREF(Py_None);
                return Py_None;
            } else {
                dwErrCode = GetLastError();
                CloseHandle(self->map_handle);
                self->map_handle = NULL;
            }
        } else {
            dwErrCode = GetLastError();
        }
        PyErr_SetFromWindowsErr(dwErrCode);
        return NULL;
#endif /* MS_WINDOWS */

#ifdef UNIX
#ifndef HAVE_MREMAP
    } else {
        PyErr_SetString(PyExc_SystemError,
                        "mmap: resizing not available--no mremap()");
        return NULL;
#else
    } else {
        void *newmap;

        if (ftruncate(self->fd, self->offset + new_size) == -1) {
            PyErr_SetFromErrno(mmap_module_error);
            return NULL;
        }

#ifdef MREMAP_MAYMOVE
        newmap = mremap(self->data, self->size, new_size, MREMAP_MAYMOVE);
#else
        #if defined(__NetBSD__)
            newmap = mremap(self->data, self->size, self->data, new_size, 0);
        #else
            newmap = mremap(self->data, self->size, new_size, 0);
        #endif /* __NetBSD__ */
#endif
        if (newmap == (void *)-1)
        {
            PyErr_SetFromErrno(mmap_module_error);
            return NULL;
        }
        self->data = newmap;
        self->size = new_size;
        Py_INCREF(Py_None);
        return Py_None;
#endif /* HAVE_MREMAP */
#endif /* UNIX */
    }
}

Here is the call graph for this function:

static PyObject* mmap_rfind_method ( mmap_object self,
PyObject args 
) [static]

Definition at line 329 of file mmapmodule.c.

{
    return mmap_gfind(self, args, 1);
}

Here is the call graph for this function:

static PyObject* mmap_seek_method ( mmap_object self,
PyObject args 
) [static]

Definition at line 597 of file mmapmodule.c.

{
    Py_ssize_t dist;
    int how=0;
    CHECK_VALID(NULL);
    if (!PyArg_ParseTuple(args, "n|i:seek", &dist, &how))
        return NULL;
    else {
        size_t where;
        switch (how) {
        case 0: /* relative to start */
            if (dist < 0)
                goto onoutofrange;
            where = dist;
            break;
        case 1: /* relative to current position */
            if ((Py_ssize_t)self->pos + dist < 0)
                goto onoutofrange;
            where = self->pos + dist;
            break;
        case 2: /* relative to end */
            if ((Py_ssize_t)self->size + dist < 0)
                goto onoutofrange;
            where = self->size + dist;
            break;
        default:
            PyErr_SetString(PyExc_ValueError, "unknown seek type");
            return NULL;
        }
        if (where > self->size)
            goto onoutofrange;
        self->pos = where;
        Py_INCREF(Py_None);
        return Py_None;
    }

  onoutofrange:
    PyErr_SetString(PyExc_ValueError, "seek out of range");
    return NULL;
}

Here is the call graph for this function:

static PyObject* mmap_size_method ( mmap_object self,
PyObject unused 
) [static]

Definition at line 410 of file mmapmodule.c.

{
    CHECK_VALID(NULL);

#ifdef MS_WINDOWS
    if (self->file_handle != INVALID_HANDLE_VALUE) {
        DWORD low,high;
        PY_LONG_LONG size;
        low = GetFileSize(self->file_handle, &high);
        if (low == INVALID_FILE_SIZE) {
            /* It might be that the function appears to have failed,
               when indeed its size equals INVALID_FILE_SIZE */
            DWORD error = GetLastError();
            if (error != NO_ERROR)
                return PyErr_SetFromWindowsErr(error);
        }
        if (!high && low < LONG_MAX)
            return PyLong_FromLong((long)low);
        size = (((PY_LONG_LONG)high)<<32) + low;
        return PyLong_FromLongLong(size);
    } else {
        return PyLong_FromSsize_t(self->size);
    }
#endif /* MS_WINDOWS */

#ifdef UNIX
    {
        struct stat buf;
        if (-1 == fstat(self->fd, &buf)) {
            PyErr_SetFromErrno(mmap_module_error);
            return NULL;
        }
#ifdef HAVE_LARGEFILE_SUPPORT
        return PyLong_FromLongLong(buf.st_size);
#else
        return PyLong_FromLong(buf.st_size);
#endif
    }
#endif /* UNIX */
}

Here is the call graph for this function:

static PyObject* mmap_subscript ( mmap_object self,
PyObject item 
) [static]

Definition at line 750 of file mmapmodule.c.

{
    CHECK_VALID(NULL);
    if (PyIndex_Check(item)) {
        Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
        if (i == -1 && PyErr_Occurred())
            return NULL;
        if (i < 0)
            i += self->size;
        if (i < 0 || (size_t)i >= self->size) {
            PyErr_SetString(PyExc_IndexError,
                "mmap index out of range");
            return NULL;
        }
        return PyLong_FromLong(Py_CHARMASK(self->data[i]));
    }
    else if (PySlice_Check(item)) {
        Py_ssize_t start, stop, step, slicelen;

        if (PySlice_GetIndicesEx(item, self->size,
                         &start, &stop, &step, &slicelen) < 0) {
            return NULL;
        }

        if (slicelen <= 0)
            return PyBytes_FromStringAndSize("", 0);
        else if (step == 1)
            return PyBytes_FromStringAndSize(self->data + start,
                                              slicelen);
        else {
            char *result_buf = (char *)PyMem_Malloc(slicelen);
            Py_ssize_t cur, i;
            PyObject *result;

            if (result_buf == NULL)
                return PyErr_NoMemory();
            for (cur = start, i = 0; i < slicelen;
                 cur += step, i++) {
                result_buf[i] = self->data[cur];
            }
            result = PyBytes_FromStringAndSize(result_buf,
                                                slicelen);
            PyMem_Free(result_buf);
            return result;
        }
    }
    else {
        PyErr_SetString(PyExc_TypeError,
                        "mmap indices must be integers");
        return NULL;
    }
}

Here is the call graph for this function:

static PyObject* mmap_tell_method ( mmap_object self,
PyObject unused 
) [static]

Definition at line 558 of file mmapmodule.c.

{
    CHECK_VALID(NULL);
    return PyLong_FromSize_t(self->pos);
}
static PyObject* mmap_write_byte_method ( mmap_object self,
PyObject args 
) [static]

Definition at line 385 of file mmapmodule.c.

{
    char value;

    CHECK_VALID(NULL);
    if (!PyArg_ParseTuple(args, "b:write_byte", &value))
        return(NULL);

    if (!is_writable(self))
        return NULL;

    if (self->pos < self->size) {
        *(self->data+self->pos) = value;
        self->pos += 1;
        Py_INCREF(Py_None);
        return Py_None;
    }
    else {
        PyErr_SetString(PyExc_ValueError, "write byte out of range");
        return NULL;
    }
}

Here is the call graph for this function:

static PyObject* mmap_write_method ( mmap_object self,
PyObject args 
) [static]

Definition at line 361 of file mmapmodule.c.

{
    Py_ssize_t length;
    char *data;

    CHECK_VALID(NULL);
    if (!PyArg_ParseTuple(args, "y#:write", &data, &length))
        return(NULL);

    if (!is_writable(self))
        return NULL;

    if ((self->pos + length) > self->size) {
        PyErr_SetString(PyExc_ValueError, "data out of range");
        return NULL;
    }
    memcpy(self->data+self->pos, data, length);
    self->pos = self->pos+length;
    Py_INCREF(Py_None);
    return Py_None;
}

Here is the call graph for this function:

static PyObject * new_mmap_object ( PyTypeObject type,
PyObject args,
PyObject kwdict 
) [static]

Definition at line 1065 of file mmapmodule.c.

{
#ifdef HAVE_FSTAT
    struct stat st;
#endif
    mmap_object *m_obj;
    PyObject *map_size_obj = NULL;
    Py_ssize_t map_size;
    off_t offset = 0;
    int fd, flags = MAP_SHARED, prot = PROT_WRITE | PROT_READ;
    int devzero = -1;
    int access = (int)ACCESS_DEFAULT;
    static char *keywords[] = {"fileno", "length",
                                     "flags", "prot",
                                     "access", "offset", NULL};

    if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iO|iii" _Py_PARSE_OFF_T, keywords,
                                     &fd, &map_size_obj, &flags, &prot,
                                     &access, &offset))
        return NULL;
    map_size = _GetMapSize(map_size_obj, "size");
    if (map_size < 0)
        return NULL;
    if (offset < 0) {
        PyErr_SetString(PyExc_OverflowError,
            "memory mapped offset must be positive");
        return NULL;
    }

    if ((access != (int)ACCESS_DEFAULT) &&
        ((flags != MAP_SHARED) || (prot != (PROT_WRITE | PROT_READ))))
        return PyErr_Format(PyExc_ValueError,
                            "mmap can't specify both access and flags, prot.");
    switch ((access_mode)access) {
    case ACCESS_READ:
        flags = MAP_SHARED;
        prot = PROT_READ;
        break;
    case ACCESS_WRITE:
        flags = MAP_SHARED;
        prot = PROT_READ | PROT_WRITE;
        break;
    case ACCESS_COPY:
        flags = MAP_PRIVATE;
        prot = PROT_READ | PROT_WRITE;
        break;
    case ACCESS_DEFAULT:
        /* map prot to access type */
        if ((prot & PROT_READ) && (prot & PROT_WRITE)) {
            /* ACCESS_DEFAULT */
        }
        else if (prot & PROT_WRITE) {
            access = ACCESS_WRITE;
        }
        else {
            access = ACCESS_READ;
        }
        break;
    default:
        return PyErr_Format(PyExc_ValueError,
                            "mmap invalid access parameter.");
    }

#ifdef __APPLE__
    /* Issue #11277: fsync(2) is not enough on OS X - a special, OS X specific
       fcntl(2) is necessary to force DISKSYNC and get around mmap(2) bug */
    if (fd != -1)
        (void)fcntl(fd, F_FULLFSYNC);
#endif
#ifdef HAVE_FSTAT
#  ifdef __VMS
    /* on OpenVMS we must ensure that all bytes are written to the file */
    if (fd != -1) {
        fsync(fd);
    }
#  endif
    if (fd != -1 && fstat(fd, &st) == 0 && S_ISREG(st.st_mode)) {
        if (map_size == 0) {
            off_t calc_size;
            if (offset >= st.st_size) {
                PyErr_SetString(PyExc_ValueError,
                                "mmap offset is greater than file size");
                return NULL;
            }
            calc_size = st.st_size - offset;
            map_size = calc_size;
            if (map_size != calc_size) {
                PyErr_SetString(PyExc_ValueError,
                                 "mmap length is too large");
                 return NULL;
             }
        } else if (offset + (size_t)map_size > st.st_size) {
            PyErr_SetString(PyExc_ValueError,
                            "mmap length is greater than file size");
            return NULL;
        }
    }
#endif
    m_obj = (mmap_object *)type->tp_alloc(type, 0);
    if (m_obj == NULL) {return NULL;}
    m_obj->data = NULL;
    m_obj->size = (size_t) map_size;
    m_obj->pos = (size_t) 0;
    m_obj->exports = 0;
    m_obj->offset = offset;
    if (fd == -1) {
        m_obj->fd = -1;
        /* Assume the caller wants to map anonymous memory.
           This is the same behaviour as Windows.  mmap.mmap(-1, size)
           on both Windows and Unix map anonymous memory.
        */
#ifdef MAP_ANONYMOUS
        /* BSD way to map anonymous memory */
        flags |= MAP_ANONYMOUS;
#else
        /* SVR4 method to map anonymous memory is to open /dev/zero */
        fd = devzero = open("/dev/zero", O_RDWR);
        if (devzero == -1) {
            Py_DECREF(m_obj);
            PyErr_SetFromErrno(mmap_module_error);
            return NULL;
        }
#endif
    } else {
        m_obj->fd = dup(fd);
        if (m_obj->fd == -1) {
            Py_DECREF(m_obj);
            PyErr_SetFromErrno(mmap_module_error);
            return NULL;
        }
    }

    m_obj->data = mmap(NULL, map_size,
                       prot, flags,
                       fd, offset);

    if (devzero != -1) {
        close(devzero);
    }

    if (m_obj->data == (char *)-1) {
        m_obj->data = NULL;
        Py_DECREF(m_obj);
        PyErr_SetFromErrno(mmap_module_error);
        return NULL;
    }
    m_obj->access = (access_mode)access;
    return (PyObject *)m_obj;
}

Here is the call graph for this function:

PyDoc_STRVAR ( mmap_doc  ,
"Windows: mmap(fileno, length[, tagname[, access[, offset]]])\n\\n\Maps length bytes from the file specified by the file handle  fileno,
\n\and returns a mmap object.If length is larger than the current size\n\of the  file,
the file is extended to contain length bytes.If length\n\is  0,
the maximum length of the map is the current size of the  file,
\n\except that if the file is empty Windows raises an exception(you cannot\n\create an empty mapping on Windows).\n\\n\Unix:mmap(fileno, length[, flags[, prot[, access[, offset]]]])\n\\n\Maps length bytes from the file specified by the file descriptor  fileno,
\n\and returns a mmap object.If length is  0,
the maximum length of the map\n\will be the current size of the file when mmap is called.\n\flags specifies the nature of the mapping.MAP_PRIVATE creates a\n\private copy-on-write  mapping,
so changes to the contents of the mmap\n\object will be private to this  process,
and MAP_SHARED creates a mapping\n\that's shared with all other processes mapping the same areas of the file.\n\The default value is MAP_SHARED.\n\\n\To map anonymous  memory,
pass-1 as the fileno(both versions)."   
)

Definition at line 1435 of file mmapmodule.c.

{
    PyObject *dict, *module;

    if (PyType_Ready(&mmap_object_type) < 0)
        return NULL;

    module = PyModule_Create(&mmapmodule);
    if (module == NULL)
        return NULL;
    dict = PyModule_GetDict(module);
    if (!dict)
        return NULL;
    mmap_module_error = PyErr_NewException("mmap.error",
        PyExc_EnvironmentError , NULL);
    if (mmap_module_error == NULL)
        return NULL;
    PyDict_SetItemString(dict, "error", mmap_module_error);
    PyDict_SetItemString(dict, "mmap", (PyObject*) &mmap_object_type);
#ifdef PROT_EXEC
    setint(dict, "PROT_EXEC", PROT_EXEC);
#endif
#ifdef PROT_READ
    setint(dict, "PROT_READ", PROT_READ);
#endif
#ifdef PROT_WRITE
    setint(dict, "PROT_WRITE", PROT_WRITE);
#endif

#ifdef MAP_SHARED
    setint(dict, "MAP_SHARED", MAP_SHARED);
#endif
#ifdef MAP_PRIVATE
    setint(dict, "MAP_PRIVATE", MAP_PRIVATE);
#endif
#ifdef MAP_DENYWRITE
    setint(dict, "MAP_DENYWRITE", MAP_DENYWRITE);
#endif
#ifdef MAP_EXECUTABLE
    setint(dict, "MAP_EXECUTABLE", MAP_EXECUTABLE);
#endif
#ifdef MAP_ANONYMOUS
    setint(dict, "MAP_ANON", MAP_ANONYMOUS);
    setint(dict, "MAP_ANONYMOUS", MAP_ANONYMOUS);
#endif

    setint(dict, "PAGESIZE", (long)my_getpagesize());

    setint(dict, "ALLOCATIONGRANULARITY", (long)my_getallocationgranularity());

    setint(dict, "ACCESS_READ", ACCESS_READ);
    setint(dict, "ACCESS_WRITE", ACCESS_WRITE);
    setint(dict, "ACCESS_COPY", ACCESS_COPY);
    return module;
}

Here is the call graph for this function:

static void setint ( PyObject d,
const char *  name,
long  value 
) [static]

Definition at line 1413 of file mmapmodule.c.

{
    PyObject *o = PyLong_FromLong(value);
    if (o && PyDict_SetItemString(d, name, o) == 0) {
        Py_DECREF(o);
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

Initial value:

Definition at line 955 of file mmapmodule.c.

Initial value:

Definition at line 949 of file mmapmodule.c.

Definition at line 81 of file mmapmodule.c.

Initial value:
 {
    {"closed", (getter) mmap_closed_get, NULL, NULL},
    {NULL}
}

Definition at line 706 of file mmapmodule.c.

Definition at line 987 of file mmapmodule.c.

struct PyMethodDef[] [static]
struct PyModuleDef [static]
Initial value:
 {
    PyModuleDef_HEAD_INIT,
    "mmap",
    NULL,
    -1,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL
}

Definition at line 1422 of file mmapmodule.c.