17db96d56Sopenharmony_ci/* 27db96d56Sopenharmony_ci / Author: Sam Rushing <rushing@nightmare.com> 37db96d56Sopenharmony_ci / Hacked for Unix by AMK 47db96d56Sopenharmony_ci / $Id$ 57db96d56Sopenharmony_ci 67db96d56Sopenharmony_ci / Modified to support mmap with offset - to map a 'window' of a file 77db96d56Sopenharmony_ci / Author: Yotam Medini yotamm@mellanox.co.il 87db96d56Sopenharmony_ci / 97db96d56Sopenharmony_ci / mmapmodule.cpp -- map a view of a file into memory 107db96d56Sopenharmony_ci / 117db96d56Sopenharmony_ci / todo: need permission flags, perhaps a 'chsize' analog 127db96d56Sopenharmony_ci / not all functions check range yet!!! 137db96d56Sopenharmony_ci / 147db96d56Sopenharmony_ci / 157db96d56Sopenharmony_ci / This version of mmapmodule.c has been changed significantly 167db96d56Sopenharmony_ci / from the original mmapfile.c on which it was based. 177db96d56Sopenharmony_ci / The original version of mmapfile is maintained by Sam at 187db96d56Sopenharmony_ci / ftp://squirl.nightmare.com/pub/python/python-ext. 197db96d56Sopenharmony_ci*/ 207db96d56Sopenharmony_ci 217db96d56Sopenharmony_ci#ifndef Py_BUILD_CORE_BUILTIN 227db96d56Sopenharmony_ci# define Py_BUILD_CORE_MODULE 1 237db96d56Sopenharmony_ci#endif 247db96d56Sopenharmony_ci 257db96d56Sopenharmony_ci#define PY_SSIZE_T_CLEAN 267db96d56Sopenharmony_ci#include <Python.h> 277db96d56Sopenharmony_ci#include "pycore_bytesobject.h" // _PyBytes_Find() 287db96d56Sopenharmony_ci#include "pycore_fileutils.h" // _Py_stat_struct 297db96d56Sopenharmony_ci#include "structmember.h" // PyMemberDef 307db96d56Sopenharmony_ci#include <stddef.h> // offsetof() 317db96d56Sopenharmony_ci 327db96d56Sopenharmony_ci#ifndef MS_WINDOWS 337db96d56Sopenharmony_ci#define UNIX 347db96d56Sopenharmony_ci# ifdef HAVE_FCNTL_H 357db96d56Sopenharmony_ci# include <fcntl.h> 367db96d56Sopenharmony_ci# endif /* HAVE_FCNTL_H */ 377db96d56Sopenharmony_ci#endif 387db96d56Sopenharmony_ci 397db96d56Sopenharmony_ci#ifdef MS_WINDOWS 407db96d56Sopenharmony_ci#include <windows.h> 417db96d56Sopenharmony_cistatic int 427db96d56Sopenharmony_cimy_getpagesize(void) 437db96d56Sopenharmony_ci{ 447db96d56Sopenharmony_ci SYSTEM_INFO si; 457db96d56Sopenharmony_ci GetSystemInfo(&si); 467db96d56Sopenharmony_ci return si.dwPageSize; 477db96d56Sopenharmony_ci} 487db96d56Sopenharmony_ci 497db96d56Sopenharmony_cistatic int 507db96d56Sopenharmony_cimy_getallocationgranularity (void) 517db96d56Sopenharmony_ci{ 527db96d56Sopenharmony_ci 537db96d56Sopenharmony_ci SYSTEM_INFO si; 547db96d56Sopenharmony_ci GetSystemInfo(&si); 557db96d56Sopenharmony_ci return si.dwAllocationGranularity; 567db96d56Sopenharmony_ci} 577db96d56Sopenharmony_ci 587db96d56Sopenharmony_ci#endif 597db96d56Sopenharmony_ci 607db96d56Sopenharmony_ci#ifdef UNIX 617db96d56Sopenharmony_ci#include <sys/mman.h> 627db96d56Sopenharmony_ci#include <sys/stat.h> 637db96d56Sopenharmony_ci 647db96d56Sopenharmony_ci#if defined(HAVE_SYSCONF) && defined(_SC_PAGESIZE) 657db96d56Sopenharmony_cistatic int 667db96d56Sopenharmony_cimy_getpagesize(void) 677db96d56Sopenharmony_ci{ 687db96d56Sopenharmony_ci return sysconf(_SC_PAGESIZE); 697db96d56Sopenharmony_ci} 707db96d56Sopenharmony_ci 717db96d56Sopenharmony_ci#define my_getallocationgranularity my_getpagesize 727db96d56Sopenharmony_ci#else 737db96d56Sopenharmony_ci#define my_getpagesize getpagesize 747db96d56Sopenharmony_ci#endif 757db96d56Sopenharmony_ci 767db96d56Sopenharmony_ci#endif /* UNIX */ 777db96d56Sopenharmony_ci 787db96d56Sopenharmony_ci#include <string.h> 797db96d56Sopenharmony_ci 807db96d56Sopenharmony_ci#ifdef HAVE_SYS_TYPES_H 817db96d56Sopenharmony_ci#include <sys/types.h> 827db96d56Sopenharmony_ci#endif /* HAVE_SYS_TYPES_H */ 837db96d56Sopenharmony_ci 847db96d56Sopenharmony_ci/* Prefer MAP_ANONYMOUS since MAP_ANON is deprecated according to man page. */ 857db96d56Sopenharmony_ci#if !defined(MAP_ANONYMOUS) && defined(MAP_ANON) 867db96d56Sopenharmony_ci# define MAP_ANONYMOUS MAP_ANON 877db96d56Sopenharmony_ci#endif 887db96d56Sopenharmony_ci 897db96d56Sopenharmony_citypedef enum 907db96d56Sopenharmony_ci{ 917db96d56Sopenharmony_ci ACCESS_DEFAULT, 927db96d56Sopenharmony_ci ACCESS_READ, 937db96d56Sopenharmony_ci ACCESS_WRITE, 947db96d56Sopenharmony_ci ACCESS_COPY 957db96d56Sopenharmony_ci} access_mode; 967db96d56Sopenharmony_ci 977db96d56Sopenharmony_citypedef struct { 987db96d56Sopenharmony_ci PyObject_HEAD 997db96d56Sopenharmony_ci char * data; 1007db96d56Sopenharmony_ci Py_ssize_t size; 1017db96d56Sopenharmony_ci Py_ssize_t pos; /* relative to offset */ 1027db96d56Sopenharmony_ci#ifdef MS_WINDOWS 1037db96d56Sopenharmony_ci long long offset; 1047db96d56Sopenharmony_ci#else 1057db96d56Sopenharmony_ci off_t offset; 1067db96d56Sopenharmony_ci#endif 1077db96d56Sopenharmony_ci Py_ssize_t exports; 1087db96d56Sopenharmony_ci 1097db96d56Sopenharmony_ci#ifdef MS_WINDOWS 1107db96d56Sopenharmony_ci HANDLE map_handle; 1117db96d56Sopenharmony_ci HANDLE file_handle; 1127db96d56Sopenharmony_ci char * tagname; 1137db96d56Sopenharmony_ci#endif 1147db96d56Sopenharmony_ci 1157db96d56Sopenharmony_ci#ifdef UNIX 1167db96d56Sopenharmony_ci int fd; 1177db96d56Sopenharmony_ci#endif 1187db96d56Sopenharmony_ci 1197db96d56Sopenharmony_ci PyObject *weakreflist; 1207db96d56Sopenharmony_ci access_mode access; 1217db96d56Sopenharmony_ci} mmap_object; 1227db96d56Sopenharmony_ci 1237db96d56Sopenharmony_citypedef struct { 1247db96d56Sopenharmony_ci PyTypeObject *mmap_object_type; 1257db96d56Sopenharmony_ci} mmap_state; 1267db96d56Sopenharmony_ci 1277db96d56Sopenharmony_cistatic mmap_state * 1287db96d56Sopenharmony_ciget_mmap_state(PyObject *module) 1297db96d56Sopenharmony_ci{ 1307db96d56Sopenharmony_ci mmap_state *state = PyModule_GetState(module); 1317db96d56Sopenharmony_ci assert(state); 1327db96d56Sopenharmony_ci return state; 1337db96d56Sopenharmony_ci} 1347db96d56Sopenharmony_ci 1357db96d56Sopenharmony_cistatic int 1367db96d56Sopenharmony_cimmap_object_traverse(mmap_object *m_obj, visitproc visit, void *arg) 1377db96d56Sopenharmony_ci{ 1387db96d56Sopenharmony_ci Py_VISIT(Py_TYPE(m_obj)); 1397db96d56Sopenharmony_ci return 0; 1407db96d56Sopenharmony_ci} 1417db96d56Sopenharmony_ci 1427db96d56Sopenharmony_cistatic void 1437db96d56Sopenharmony_cimmap_object_dealloc(mmap_object *m_obj) 1447db96d56Sopenharmony_ci{ 1457db96d56Sopenharmony_ci PyTypeObject *tp = Py_TYPE(m_obj); 1467db96d56Sopenharmony_ci PyObject_GC_UnTrack(m_obj); 1477db96d56Sopenharmony_ci 1487db96d56Sopenharmony_ci#ifdef MS_WINDOWS 1497db96d56Sopenharmony_ci Py_BEGIN_ALLOW_THREADS 1507db96d56Sopenharmony_ci if (m_obj->data != NULL) 1517db96d56Sopenharmony_ci UnmapViewOfFile (m_obj->data); 1527db96d56Sopenharmony_ci if (m_obj->map_handle != NULL) 1537db96d56Sopenharmony_ci CloseHandle (m_obj->map_handle); 1547db96d56Sopenharmony_ci if (m_obj->file_handle != INVALID_HANDLE_VALUE) 1557db96d56Sopenharmony_ci CloseHandle (m_obj->file_handle); 1567db96d56Sopenharmony_ci Py_END_ALLOW_THREADS 1577db96d56Sopenharmony_ci if (m_obj->tagname) 1587db96d56Sopenharmony_ci PyMem_Free(m_obj->tagname); 1597db96d56Sopenharmony_ci#endif /* MS_WINDOWS */ 1607db96d56Sopenharmony_ci 1617db96d56Sopenharmony_ci#ifdef UNIX 1627db96d56Sopenharmony_ci Py_BEGIN_ALLOW_THREADS 1637db96d56Sopenharmony_ci if (m_obj->fd >= 0) 1647db96d56Sopenharmony_ci (void) close(m_obj->fd); 1657db96d56Sopenharmony_ci if (m_obj->data!=NULL) { 1667db96d56Sopenharmony_ci munmap(m_obj->data, m_obj->size); 1677db96d56Sopenharmony_ci } 1687db96d56Sopenharmony_ci Py_END_ALLOW_THREADS 1697db96d56Sopenharmony_ci#endif /* UNIX */ 1707db96d56Sopenharmony_ci 1717db96d56Sopenharmony_ci if (m_obj->weakreflist != NULL) 1727db96d56Sopenharmony_ci PyObject_ClearWeakRefs((PyObject *) m_obj); 1737db96d56Sopenharmony_ci 1747db96d56Sopenharmony_ci tp->tp_free(m_obj); 1757db96d56Sopenharmony_ci Py_DECREF(tp); 1767db96d56Sopenharmony_ci} 1777db96d56Sopenharmony_ci 1787db96d56Sopenharmony_cistatic PyObject * 1797db96d56Sopenharmony_cimmap_close_method(mmap_object *self, PyObject *unused) 1807db96d56Sopenharmony_ci{ 1817db96d56Sopenharmony_ci if (self->exports > 0) { 1827db96d56Sopenharmony_ci PyErr_SetString(PyExc_BufferError, "cannot close "\ 1837db96d56Sopenharmony_ci "exported pointers exist"); 1847db96d56Sopenharmony_ci return NULL; 1857db96d56Sopenharmony_ci } 1867db96d56Sopenharmony_ci#ifdef MS_WINDOWS 1877db96d56Sopenharmony_ci /* For each resource we maintain, we need to check 1887db96d56Sopenharmony_ci the value is valid, and if so, free the resource 1897db96d56Sopenharmony_ci and set the member value to an invalid value so 1907db96d56Sopenharmony_ci the dealloc does not attempt to resource clearing 1917db96d56Sopenharmony_ci again. 1927db96d56Sopenharmony_ci TODO - should we check for errors in the close operations??? 1937db96d56Sopenharmony_ci */ 1947db96d56Sopenharmony_ci HANDLE map_handle = self->map_handle; 1957db96d56Sopenharmony_ci HANDLE file_handle = self->file_handle; 1967db96d56Sopenharmony_ci char *data = self->data; 1977db96d56Sopenharmony_ci self->map_handle = NULL; 1987db96d56Sopenharmony_ci self->file_handle = INVALID_HANDLE_VALUE; 1997db96d56Sopenharmony_ci self->data = NULL; 2007db96d56Sopenharmony_ci Py_BEGIN_ALLOW_THREADS 2017db96d56Sopenharmony_ci if (data != NULL) { 2027db96d56Sopenharmony_ci UnmapViewOfFile(data); 2037db96d56Sopenharmony_ci } 2047db96d56Sopenharmony_ci if (map_handle != NULL) { 2057db96d56Sopenharmony_ci CloseHandle(map_handle); 2067db96d56Sopenharmony_ci } 2077db96d56Sopenharmony_ci if (file_handle != INVALID_HANDLE_VALUE) { 2087db96d56Sopenharmony_ci CloseHandle(file_handle); 2097db96d56Sopenharmony_ci } 2107db96d56Sopenharmony_ci Py_END_ALLOW_THREADS 2117db96d56Sopenharmony_ci#endif /* MS_WINDOWS */ 2127db96d56Sopenharmony_ci 2137db96d56Sopenharmony_ci#ifdef UNIX 2147db96d56Sopenharmony_ci int fd = self->fd; 2157db96d56Sopenharmony_ci char *data = self->data; 2167db96d56Sopenharmony_ci self->fd = -1; 2177db96d56Sopenharmony_ci self->data = NULL; 2187db96d56Sopenharmony_ci Py_BEGIN_ALLOW_THREADS 2197db96d56Sopenharmony_ci if (0 <= fd) 2207db96d56Sopenharmony_ci (void) close(fd); 2217db96d56Sopenharmony_ci if (data != NULL) { 2227db96d56Sopenharmony_ci munmap(data, self->size); 2237db96d56Sopenharmony_ci } 2247db96d56Sopenharmony_ci Py_END_ALLOW_THREADS 2257db96d56Sopenharmony_ci#endif 2267db96d56Sopenharmony_ci 2277db96d56Sopenharmony_ci Py_RETURN_NONE; 2287db96d56Sopenharmony_ci} 2297db96d56Sopenharmony_ci 2307db96d56Sopenharmony_ci#ifdef MS_WINDOWS 2317db96d56Sopenharmony_ci#define CHECK_VALID(err) \ 2327db96d56Sopenharmony_cido { \ 2337db96d56Sopenharmony_ci if (self->map_handle == NULL) { \ 2347db96d56Sopenharmony_ci PyErr_SetString(PyExc_ValueError, "mmap closed or invalid"); \ 2357db96d56Sopenharmony_ci return err; \ 2367db96d56Sopenharmony_ci } \ 2377db96d56Sopenharmony_ci} while (0) 2387db96d56Sopenharmony_ci#define CHECK_VALID_OR_RELEASE(err, buffer) \ 2397db96d56Sopenharmony_cido { \ 2407db96d56Sopenharmony_ci if (self->map_handle == NULL) { \ 2417db96d56Sopenharmony_ci PyErr_SetString(PyExc_ValueError, "mmap closed or invalid"); \ 2427db96d56Sopenharmony_ci PyBuffer_Release(&(buffer)); \ 2437db96d56Sopenharmony_ci return (err); \ 2447db96d56Sopenharmony_ci } \ 2457db96d56Sopenharmony_ci} while (0) 2467db96d56Sopenharmony_ci#endif /* MS_WINDOWS */ 2477db96d56Sopenharmony_ci 2487db96d56Sopenharmony_ci#ifdef UNIX 2497db96d56Sopenharmony_ci#define CHECK_VALID(err) \ 2507db96d56Sopenharmony_cido { \ 2517db96d56Sopenharmony_ci if (self->data == NULL) { \ 2527db96d56Sopenharmony_ci PyErr_SetString(PyExc_ValueError, "mmap closed or invalid"); \ 2537db96d56Sopenharmony_ci return err; \ 2547db96d56Sopenharmony_ci } \ 2557db96d56Sopenharmony_ci} while (0) 2567db96d56Sopenharmony_ci#define CHECK_VALID_OR_RELEASE(err, buffer) \ 2577db96d56Sopenharmony_cido { \ 2587db96d56Sopenharmony_ci if (self->data == NULL) { \ 2597db96d56Sopenharmony_ci PyErr_SetString(PyExc_ValueError, "mmap closed or invalid"); \ 2607db96d56Sopenharmony_ci PyBuffer_Release(&(buffer)); \ 2617db96d56Sopenharmony_ci return (err); \ 2627db96d56Sopenharmony_ci } \ 2637db96d56Sopenharmony_ci} while (0) 2647db96d56Sopenharmony_ci#endif /* UNIX */ 2657db96d56Sopenharmony_ci 2667db96d56Sopenharmony_cistatic PyObject * 2677db96d56Sopenharmony_cimmap_read_byte_method(mmap_object *self, 2687db96d56Sopenharmony_ci PyObject *unused) 2697db96d56Sopenharmony_ci{ 2707db96d56Sopenharmony_ci CHECK_VALID(NULL); 2717db96d56Sopenharmony_ci if (self->pos >= self->size) { 2727db96d56Sopenharmony_ci PyErr_SetString(PyExc_ValueError, "read byte out of range"); 2737db96d56Sopenharmony_ci return NULL; 2747db96d56Sopenharmony_ci } 2757db96d56Sopenharmony_ci return PyLong_FromLong((unsigned char)self->data[self->pos++]); 2767db96d56Sopenharmony_ci} 2777db96d56Sopenharmony_ci 2787db96d56Sopenharmony_cistatic PyObject * 2797db96d56Sopenharmony_cimmap_read_line_method(mmap_object *self, 2807db96d56Sopenharmony_ci PyObject *unused) 2817db96d56Sopenharmony_ci{ 2827db96d56Sopenharmony_ci Py_ssize_t remaining; 2837db96d56Sopenharmony_ci char *start, *eol; 2847db96d56Sopenharmony_ci PyObject *result; 2857db96d56Sopenharmony_ci 2867db96d56Sopenharmony_ci CHECK_VALID(NULL); 2877db96d56Sopenharmony_ci 2887db96d56Sopenharmony_ci remaining = (self->pos < self->size) ? self->size - self->pos : 0; 2897db96d56Sopenharmony_ci if (!remaining) 2907db96d56Sopenharmony_ci return PyBytes_FromString(""); 2917db96d56Sopenharmony_ci start = self->data + self->pos; 2927db96d56Sopenharmony_ci eol = memchr(start, '\n', remaining); 2937db96d56Sopenharmony_ci if (!eol) 2947db96d56Sopenharmony_ci eol = self->data + self->size; 2957db96d56Sopenharmony_ci else 2967db96d56Sopenharmony_ci ++eol; /* advance past newline */ 2977db96d56Sopenharmony_ci result = PyBytes_FromStringAndSize(start, (eol - start)); 2987db96d56Sopenharmony_ci self->pos += (eol - start); 2997db96d56Sopenharmony_ci return result; 3007db96d56Sopenharmony_ci} 3017db96d56Sopenharmony_ci 3027db96d56Sopenharmony_cistatic PyObject * 3037db96d56Sopenharmony_cimmap_read_method(mmap_object *self, 3047db96d56Sopenharmony_ci PyObject *args) 3057db96d56Sopenharmony_ci{ 3067db96d56Sopenharmony_ci Py_ssize_t num_bytes = PY_SSIZE_T_MAX, remaining; 3077db96d56Sopenharmony_ci PyObject *result; 3087db96d56Sopenharmony_ci 3097db96d56Sopenharmony_ci CHECK_VALID(NULL); 3107db96d56Sopenharmony_ci if (!PyArg_ParseTuple(args, "|O&:read", _Py_convert_optional_to_ssize_t, &num_bytes)) 3117db96d56Sopenharmony_ci return NULL; 3127db96d56Sopenharmony_ci CHECK_VALID(NULL); 3137db96d56Sopenharmony_ci 3147db96d56Sopenharmony_ci /* silently 'adjust' out-of-range requests */ 3157db96d56Sopenharmony_ci remaining = (self->pos < self->size) ? self->size - self->pos : 0; 3167db96d56Sopenharmony_ci if (num_bytes < 0 || num_bytes > remaining) 3177db96d56Sopenharmony_ci num_bytes = remaining; 3187db96d56Sopenharmony_ci result = PyBytes_FromStringAndSize(&self->data[self->pos], num_bytes); 3197db96d56Sopenharmony_ci self->pos += num_bytes; 3207db96d56Sopenharmony_ci return result; 3217db96d56Sopenharmony_ci} 3227db96d56Sopenharmony_ci 3237db96d56Sopenharmony_cistatic PyObject * 3247db96d56Sopenharmony_cimmap_gfind(mmap_object *self, 3257db96d56Sopenharmony_ci PyObject *args, 3267db96d56Sopenharmony_ci int reverse) 3277db96d56Sopenharmony_ci{ 3287db96d56Sopenharmony_ci Py_ssize_t start = self->pos; 3297db96d56Sopenharmony_ci Py_ssize_t end = self->size; 3307db96d56Sopenharmony_ci Py_buffer view; 3317db96d56Sopenharmony_ci 3327db96d56Sopenharmony_ci CHECK_VALID(NULL); 3337db96d56Sopenharmony_ci if (!PyArg_ParseTuple(args, reverse ? "y*|nn:rfind" : "y*|nn:find", 3347db96d56Sopenharmony_ci &view, &start, &end)) { 3357db96d56Sopenharmony_ci return NULL; 3367db96d56Sopenharmony_ci } 3377db96d56Sopenharmony_ci else { 3387db96d56Sopenharmony_ci if (start < 0) 3397db96d56Sopenharmony_ci start += self->size; 3407db96d56Sopenharmony_ci if (start < 0) 3417db96d56Sopenharmony_ci start = 0; 3427db96d56Sopenharmony_ci else if (start > self->size) 3437db96d56Sopenharmony_ci start = self->size; 3447db96d56Sopenharmony_ci 3457db96d56Sopenharmony_ci if (end < 0) 3467db96d56Sopenharmony_ci end += self->size; 3477db96d56Sopenharmony_ci if (end < 0) 3487db96d56Sopenharmony_ci end = 0; 3497db96d56Sopenharmony_ci else if (end > self->size) 3507db96d56Sopenharmony_ci end = self->size; 3517db96d56Sopenharmony_ci 3527db96d56Sopenharmony_ci Py_ssize_t res; 3537db96d56Sopenharmony_ci CHECK_VALID_OR_RELEASE(NULL, view); 3547db96d56Sopenharmony_ci if (reverse) { 3557db96d56Sopenharmony_ci res = _PyBytes_ReverseFind( 3567db96d56Sopenharmony_ci self->data + start, end - start, 3577db96d56Sopenharmony_ci view.buf, view.len, start); 3587db96d56Sopenharmony_ci } 3597db96d56Sopenharmony_ci else { 3607db96d56Sopenharmony_ci res = _PyBytes_Find( 3617db96d56Sopenharmony_ci self->data + start, end - start, 3627db96d56Sopenharmony_ci view.buf, view.len, start); 3637db96d56Sopenharmony_ci } 3647db96d56Sopenharmony_ci PyBuffer_Release(&view); 3657db96d56Sopenharmony_ci return PyLong_FromSsize_t(res); 3667db96d56Sopenharmony_ci } 3677db96d56Sopenharmony_ci} 3687db96d56Sopenharmony_ci 3697db96d56Sopenharmony_cistatic PyObject * 3707db96d56Sopenharmony_cimmap_find_method(mmap_object *self, 3717db96d56Sopenharmony_ci PyObject *args) 3727db96d56Sopenharmony_ci{ 3737db96d56Sopenharmony_ci return mmap_gfind(self, args, 0); 3747db96d56Sopenharmony_ci} 3757db96d56Sopenharmony_ci 3767db96d56Sopenharmony_cistatic PyObject * 3777db96d56Sopenharmony_cimmap_rfind_method(mmap_object *self, 3787db96d56Sopenharmony_ci PyObject *args) 3797db96d56Sopenharmony_ci{ 3807db96d56Sopenharmony_ci return mmap_gfind(self, args, 1); 3817db96d56Sopenharmony_ci} 3827db96d56Sopenharmony_ci 3837db96d56Sopenharmony_cistatic int 3847db96d56Sopenharmony_ciis_writable(mmap_object *self) 3857db96d56Sopenharmony_ci{ 3867db96d56Sopenharmony_ci if (self->access != ACCESS_READ) 3877db96d56Sopenharmony_ci return 1; 3887db96d56Sopenharmony_ci PyErr_Format(PyExc_TypeError, "mmap can't modify a readonly memory map."); 3897db96d56Sopenharmony_ci return 0; 3907db96d56Sopenharmony_ci} 3917db96d56Sopenharmony_ci 3927db96d56Sopenharmony_cistatic int 3937db96d56Sopenharmony_ciis_resizeable(mmap_object *self) 3947db96d56Sopenharmony_ci{ 3957db96d56Sopenharmony_ci if (self->exports > 0) { 3967db96d56Sopenharmony_ci PyErr_SetString(PyExc_BufferError, 3977db96d56Sopenharmony_ci "mmap can't resize with extant buffers exported."); 3987db96d56Sopenharmony_ci return 0; 3997db96d56Sopenharmony_ci } 4007db96d56Sopenharmony_ci if ((self->access == ACCESS_WRITE) || (self->access == ACCESS_DEFAULT)) 4017db96d56Sopenharmony_ci return 1; 4027db96d56Sopenharmony_ci PyErr_Format(PyExc_TypeError, 4037db96d56Sopenharmony_ci "mmap can't resize a readonly or copy-on-write memory map."); 4047db96d56Sopenharmony_ci return 0; 4057db96d56Sopenharmony_ci 4067db96d56Sopenharmony_ci} 4077db96d56Sopenharmony_ci 4087db96d56Sopenharmony_ci 4097db96d56Sopenharmony_cistatic PyObject * 4107db96d56Sopenharmony_cimmap_write_method(mmap_object *self, 4117db96d56Sopenharmony_ci PyObject *args) 4127db96d56Sopenharmony_ci{ 4137db96d56Sopenharmony_ci Py_buffer data; 4147db96d56Sopenharmony_ci 4157db96d56Sopenharmony_ci CHECK_VALID(NULL); 4167db96d56Sopenharmony_ci if (!PyArg_ParseTuple(args, "y*:write", &data)) 4177db96d56Sopenharmony_ci return NULL; 4187db96d56Sopenharmony_ci 4197db96d56Sopenharmony_ci if (!is_writable(self)) { 4207db96d56Sopenharmony_ci PyBuffer_Release(&data); 4217db96d56Sopenharmony_ci return NULL; 4227db96d56Sopenharmony_ci } 4237db96d56Sopenharmony_ci 4247db96d56Sopenharmony_ci if (self->pos > self->size || self->size - self->pos < data.len) { 4257db96d56Sopenharmony_ci PyBuffer_Release(&data); 4267db96d56Sopenharmony_ci PyErr_SetString(PyExc_ValueError, "data out of range"); 4277db96d56Sopenharmony_ci return NULL; 4287db96d56Sopenharmony_ci } 4297db96d56Sopenharmony_ci 4307db96d56Sopenharmony_ci CHECK_VALID_OR_RELEASE(NULL, data); 4317db96d56Sopenharmony_ci memcpy(&self->data[self->pos], data.buf, data.len); 4327db96d56Sopenharmony_ci self->pos += data.len; 4337db96d56Sopenharmony_ci PyBuffer_Release(&data); 4347db96d56Sopenharmony_ci return PyLong_FromSsize_t(data.len); 4357db96d56Sopenharmony_ci} 4367db96d56Sopenharmony_ci 4377db96d56Sopenharmony_cistatic PyObject * 4387db96d56Sopenharmony_cimmap_write_byte_method(mmap_object *self, 4397db96d56Sopenharmony_ci PyObject *args) 4407db96d56Sopenharmony_ci{ 4417db96d56Sopenharmony_ci char value; 4427db96d56Sopenharmony_ci 4437db96d56Sopenharmony_ci CHECK_VALID(NULL); 4447db96d56Sopenharmony_ci if (!PyArg_ParseTuple(args, "b:write_byte", &value)) 4457db96d56Sopenharmony_ci return(NULL); 4467db96d56Sopenharmony_ci 4477db96d56Sopenharmony_ci if (!is_writable(self)) 4487db96d56Sopenharmony_ci return NULL; 4497db96d56Sopenharmony_ci 4507db96d56Sopenharmony_ci CHECK_VALID(NULL); 4517db96d56Sopenharmony_ci if (self->pos < self->size) { 4527db96d56Sopenharmony_ci self->data[self->pos++] = value; 4537db96d56Sopenharmony_ci Py_RETURN_NONE; 4547db96d56Sopenharmony_ci } 4557db96d56Sopenharmony_ci else { 4567db96d56Sopenharmony_ci PyErr_SetString(PyExc_ValueError, "write byte out of range"); 4577db96d56Sopenharmony_ci return NULL; 4587db96d56Sopenharmony_ci } 4597db96d56Sopenharmony_ci} 4607db96d56Sopenharmony_ci 4617db96d56Sopenharmony_cistatic PyObject * 4627db96d56Sopenharmony_cimmap_size_method(mmap_object *self, 4637db96d56Sopenharmony_ci PyObject *unused) 4647db96d56Sopenharmony_ci{ 4657db96d56Sopenharmony_ci CHECK_VALID(NULL); 4667db96d56Sopenharmony_ci 4677db96d56Sopenharmony_ci#ifdef MS_WINDOWS 4687db96d56Sopenharmony_ci if (self->file_handle != INVALID_HANDLE_VALUE) { 4697db96d56Sopenharmony_ci DWORD low,high; 4707db96d56Sopenharmony_ci long long size; 4717db96d56Sopenharmony_ci low = GetFileSize(self->file_handle, &high); 4727db96d56Sopenharmony_ci if (low == INVALID_FILE_SIZE) { 4737db96d56Sopenharmony_ci /* It might be that the function appears to have failed, 4747db96d56Sopenharmony_ci when indeed its size equals INVALID_FILE_SIZE */ 4757db96d56Sopenharmony_ci DWORD error = GetLastError(); 4767db96d56Sopenharmony_ci if (error != NO_ERROR) 4777db96d56Sopenharmony_ci return PyErr_SetFromWindowsErr(error); 4787db96d56Sopenharmony_ci } 4797db96d56Sopenharmony_ci if (!high && low < LONG_MAX) 4807db96d56Sopenharmony_ci return PyLong_FromLong((long)low); 4817db96d56Sopenharmony_ci size = (((long long)high)<<32) + low; 4827db96d56Sopenharmony_ci return PyLong_FromLongLong(size); 4837db96d56Sopenharmony_ci } else { 4847db96d56Sopenharmony_ci return PyLong_FromSsize_t(self->size); 4857db96d56Sopenharmony_ci } 4867db96d56Sopenharmony_ci#endif /* MS_WINDOWS */ 4877db96d56Sopenharmony_ci 4887db96d56Sopenharmony_ci#ifdef UNIX 4897db96d56Sopenharmony_ci { 4907db96d56Sopenharmony_ci struct _Py_stat_struct status; 4917db96d56Sopenharmony_ci if (_Py_fstat(self->fd, &status) == -1) 4927db96d56Sopenharmony_ci return NULL; 4937db96d56Sopenharmony_ci#ifdef HAVE_LARGEFILE_SUPPORT 4947db96d56Sopenharmony_ci return PyLong_FromLongLong(status.st_size); 4957db96d56Sopenharmony_ci#else 4967db96d56Sopenharmony_ci return PyLong_FromLong(status.st_size); 4977db96d56Sopenharmony_ci#endif 4987db96d56Sopenharmony_ci } 4997db96d56Sopenharmony_ci#endif /* UNIX */ 5007db96d56Sopenharmony_ci} 5017db96d56Sopenharmony_ci 5027db96d56Sopenharmony_ci/* This assumes that you want the entire file mapped, 5037db96d56Sopenharmony_ci / and when recreating the map will make the new file 5047db96d56Sopenharmony_ci / have the new size 5057db96d56Sopenharmony_ci / 5067db96d56Sopenharmony_ci / Is this really necessary? This could easily be done 5077db96d56Sopenharmony_ci / from python by just closing and re-opening with the 5087db96d56Sopenharmony_ci / new size? 5097db96d56Sopenharmony_ci */ 5107db96d56Sopenharmony_ci 5117db96d56Sopenharmony_cistatic PyObject * 5127db96d56Sopenharmony_cimmap_resize_method(mmap_object *self, 5137db96d56Sopenharmony_ci PyObject *args) 5147db96d56Sopenharmony_ci{ 5157db96d56Sopenharmony_ci Py_ssize_t new_size; 5167db96d56Sopenharmony_ci CHECK_VALID(NULL); 5177db96d56Sopenharmony_ci if (!PyArg_ParseTuple(args, "n:resize", &new_size) || 5187db96d56Sopenharmony_ci !is_resizeable(self)) { 5197db96d56Sopenharmony_ci return NULL; 5207db96d56Sopenharmony_ci } 5217db96d56Sopenharmony_ci if (new_size < 0 || PY_SSIZE_T_MAX - new_size < self->offset) { 5227db96d56Sopenharmony_ci PyErr_SetString(PyExc_ValueError, "new size out of range"); 5237db96d56Sopenharmony_ci return NULL; 5247db96d56Sopenharmony_ci } 5257db96d56Sopenharmony_ci 5267db96d56Sopenharmony_ci { 5277db96d56Sopenharmony_ci#ifdef MS_WINDOWS 5287db96d56Sopenharmony_ci DWORD error = 0, file_resize_error = 0; 5297db96d56Sopenharmony_ci char* old_data = self->data; 5307db96d56Sopenharmony_ci LARGE_INTEGER offset, max_size; 5317db96d56Sopenharmony_ci offset.QuadPart = self->offset; 5327db96d56Sopenharmony_ci max_size.QuadPart = self->offset + new_size; 5337db96d56Sopenharmony_ci /* close the file mapping */ 5347db96d56Sopenharmony_ci CloseHandle(self->map_handle); 5357db96d56Sopenharmony_ci /* if the file mapping still exists, it cannot be resized. */ 5367db96d56Sopenharmony_ci if (self->tagname) { 5377db96d56Sopenharmony_ci self->map_handle = OpenFileMapping(FILE_MAP_WRITE, FALSE, 5387db96d56Sopenharmony_ci self->tagname); 5397db96d56Sopenharmony_ci if (self->map_handle) { 5407db96d56Sopenharmony_ci PyErr_SetFromWindowsErr(ERROR_USER_MAPPED_FILE); 5417db96d56Sopenharmony_ci return NULL; 5427db96d56Sopenharmony_ci } 5437db96d56Sopenharmony_ci } else { 5447db96d56Sopenharmony_ci self->map_handle = NULL; 5457db96d56Sopenharmony_ci } 5467db96d56Sopenharmony_ci 5477db96d56Sopenharmony_ci /* if it's not the paging file, unmap the view and resize the file */ 5487db96d56Sopenharmony_ci if (self->file_handle != INVALID_HANDLE_VALUE) { 5497db96d56Sopenharmony_ci if (!UnmapViewOfFile(self->data)) { 5507db96d56Sopenharmony_ci return PyErr_SetFromWindowsErr(GetLastError()); 5517db96d56Sopenharmony_ci }; 5527db96d56Sopenharmony_ci self->data = NULL; 5537db96d56Sopenharmony_ci /* resize the file */ 5547db96d56Sopenharmony_ci if (!SetFilePointerEx(self->file_handle, max_size, NULL, 5557db96d56Sopenharmony_ci FILE_BEGIN) || 5567db96d56Sopenharmony_ci !SetEndOfFile(self->file_handle)) { 5577db96d56Sopenharmony_ci /* resizing failed. try to remap the file */ 5587db96d56Sopenharmony_ci file_resize_error = GetLastError(); 5597db96d56Sopenharmony_ci max_size.QuadPart = self->size; 5607db96d56Sopenharmony_ci new_size = self->size; 5617db96d56Sopenharmony_ci } 5627db96d56Sopenharmony_ci } 5637db96d56Sopenharmony_ci 5647db96d56Sopenharmony_ci /* create a new file mapping and map a new view */ 5657db96d56Sopenharmony_ci /* FIXME: call CreateFileMappingW with wchar_t tagname */ 5667db96d56Sopenharmony_ci self->map_handle = CreateFileMapping( 5677db96d56Sopenharmony_ci self->file_handle, 5687db96d56Sopenharmony_ci NULL, 5697db96d56Sopenharmony_ci PAGE_READWRITE, 5707db96d56Sopenharmony_ci max_size.HighPart, 5717db96d56Sopenharmony_ci max_size.LowPart, 5727db96d56Sopenharmony_ci self->tagname); 5737db96d56Sopenharmony_ci 5747db96d56Sopenharmony_ci error = GetLastError(); 5757db96d56Sopenharmony_ci /* ERROR_ALREADY_EXISTS implies that between our closing the handle above and 5767db96d56Sopenharmony_ci calling CreateFileMapping here, someone's created a different mapping with 5777db96d56Sopenharmony_ci the same name. There's nothing we can usefully do so we invalidate our 5787db96d56Sopenharmony_ci mapping and error out. 5797db96d56Sopenharmony_ci */ 5807db96d56Sopenharmony_ci if (error == ERROR_ALREADY_EXISTS) { 5817db96d56Sopenharmony_ci CloseHandle(self->map_handle); 5827db96d56Sopenharmony_ci self->map_handle = NULL; 5837db96d56Sopenharmony_ci } 5847db96d56Sopenharmony_ci else if (self->map_handle != NULL) { 5857db96d56Sopenharmony_ci self->data = MapViewOfFile(self->map_handle, 5867db96d56Sopenharmony_ci FILE_MAP_WRITE, 5877db96d56Sopenharmony_ci offset.HighPart, 5887db96d56Sopenharmony_ci offset.LowPart, 5897db96d56Sopenharmony_ci new_size); 5907db96d56Sopenharmony_ci if (self->data != NULL) { 5917db96d56Sopenharmony_ci /* copy the old view if using the paging file */ 5927db96d56Sopenharmony_ci if (self->file_handle == INVALID_HANDLE_VALUE) { 5937db96d56Sopenharmony_ci memcpy(self->data, old_data, 5947db96d56Sopenharmony_ci self->size < new_size ? self->size : new_size); 5957db96d56Sopenharmony_ci if (!UnmapViewOfFile(old_data)) { 5967db96d56Sopenharmony_ci error = GetLastError(); 5977db96d56Sopenharmony_ci } 5987db96d56Sopenharmony_ci } 5997db96d56Sopenharmony_ci self->size = new_size; 6007db96d56Sopenharmony_ci } 6017db96d56Sopenharmony_ci else { 6027db96d56Sopenharmony_ci error = GetLastError(); 6037db96d56Sopenharmony_ci CloseHandle(self->map_handle); 6047db96d56Sopenharmony_ci self->map_handle = NULL; 6057db96d56Sopenharmony_ci } 6067db96d56Sopenharmony_ci } 6077db96d56Sopenharmony_ci 6087db96d56Sopenharmony_ci if (error) { 6097db96d56Sopenharmony_ci return PyErr_SetFromWindowsErr(error); 6107db96d56Sopenharmony_ci return NULL; 6117db96d56Sopenharmony_ci } 6127db96d56Sopenharmony_ci /* It's possible for a resize to fail, typically because another mapping 6137db96d56Sopenharmony_ci is still held against the same underlying file. Even if nothing has 6147db96d56Sopenharmony_ci failed -- ie we're still returning a valid file mapping -- raise the 6157db96d56Sopenharmony_ci error as an exception as the resize won't have happened 6167db96d56Sopenharmony_ci */ 6177db96d56Sopenharmony_ci if (file_resize_error) { 6187db96d56Sopenharmony_ci PyErr_SetFromWindowsErr(file_resize_error); 6197db96d56Sopenharmony_ci return NULL; 6207db96d56Sopenharmony_ci } 6217db96d56Sopenharmony_ci Py_RETURN_NONE; 6227db96d56Sopenharmony_ci#endif /* MS_WINDOWS */ 6237db96d56Sopenharmony_ci 6247db96d56Sopenharmony_ci#ifdef UNIX 6257db96d56Sopenharmony_ci#ifndef HAVE_MREMAP 6267db96d56Sopenharmony_ci PyErr_SetString(PyExc_SystemError, 6277db96d56Sopenharmony_ci "mmap: resizing not available--no mremap()"); 6287db96d56Sopenharmony_ci return NULL; 6297db96d56Sopenharmony_ci#else 6307db96d56Sopenharmony_ci void *newmap; 6317db96d56Sopenharmony_ci 6327db96d56Sopenharmony_ci if (self->fd != -1 && ftruncate(self->fd, self->offset + new_size) == -1) { 6337db96d56Sopenharmony_ci PyErr_SetFromErrno(PyExc_OSError); 6347db96d56Sopenharmony_ci return NULL; 6357db96d56Sopenharmony_ci } 6367db96d56Sopenharmony_ci 6377db96d56Sopenharmony_ci#ifdef MREMAP_MAYMOVE 6387db96d56Sopenharmony_ci newmap = mremap(self->data, self->size, new_size, MREMAP_MAYMOVE); 6397db96d56Sopenharmony_ci#else 6407db96d56Sopenharmony_ci#if defined(__NetBSD__) 6417db96d56Sopenharmony_ci newmap = mremap(self->data, self->size, self->data, new_size, 0); 6427db96d56Sopenharmony_ci#else 6437db96d56Sopenharmony_ci newmap = mremap(self->data, self->size, new_size, 0); 6447db96d56Sopenharmony_ci#endif /* __NetBSD__ */ 6457db96d56Sopenharmony_ci#endif 6467db96d56Sopenharmony_ci if (newmap == (void *)-1) 6477db96d56Sopenharmony_ci { 6487db96d56Sopenharmony_ci PyErr_SetFromErrno(PyExc_OSError); 6497db96d56Sopenharmony_ci return NULL; 6507db96d56Sopenharmony_ci } 6517db96d56Sopenharmony_ci self->data = newmap; 6527db96d56Sopenharmony_ci self->size = new_size; 6537db96d56Sopenharmony_ci Py_RETURN_NONE; 6547db96d56Sopenharmony_ci#endif /* HAVE_MREMAP */ 6557db96d56Sopenharmony_ci#endif /* UNIX */ 6567db96d56Sopenharmony_ci } 6577db96d56Sopenharmony_ci} 6587db96d56Sopenharmony_ci 6597db96d56Sopenharmony_cistatic PyObject * 6607db96d56Sopenharmony_cimmap_tell_method(mmap_object *self, PyObject *unused) 6617db96d56Sopenharmony_ci{ 6627db96d56Sopenharmony_ci CHECK_VALID(NULL); 6637db96d56Sopenharmony_ci return PyLong_FromSize_t(self->pos); 6647db96d56Sopenharmony_ci} 6657db96d56Sopenharmony_ci 6667db96d56Sopenharmony_cistatic PyObject * 6677db96d56Sopenharmony_cimmap_flush_method(mmap_object *self, PyObject *args) 6687db96d56Sopenharmony_ci{ 6697db96d56Sopenharmony_ci Py_ssize_t offset = 0; 6707db96d56Sopenharmony_ci Py_ssize_t size = self->size; 6717db96d56Sopenharmony_ci CHECK_VALID(NULL); 6727db96d56Sopenharmony_ci if (!PyArg_ParseTuple(args, "|nn:flush", &offset, &size)) 6737db96d56Sopenharmony_ci return NULL; 6747db96d56Sopenharmony_ci if (size < 0 || offset < 0 || self->size - offset < size) { 6757db96d56Sopenharmony_ci PyErr_SetString(PyExc_ValueError, "flush values out of range"); 6767db96d56Sopenharmony_ci return NULL; 6777db96d56Sopenharmony_ci } 6787db96d56Sopenharmony_ci 6797db96d56Sopenharmony_ci if (self->access == ACCESS_READ || self->access == ACCESS_COPY) 6807db96d56Sopenharmony_ci Py_RETURN_NONE; 6817db96d56Sopenharmony_ci 6827db96d56Sopenharmony_ci#ifdef MS_WINDOWS 6837db96d56Sopenharmony_ci if (!FlushViewOfFile(self->data+offset, size)) { 6847db96d56Sopenharmony_ci PyErr_SetFromWindowsErr(GetLastError()); 6857db96d56Sopenharmony_ci return NULL; 6867db96d56Sopenharmony_ci } 6877db96d56Sopenharmony_ci Py_RETURN_NONE; 6887db96d56Sopenharmony_ci#elif defined(UNIX) 6897db96d56Sopenharmony_ci /* XXX flags for msync? */ 6907db96d56Sopenharmony_ci if (-1 == msync(self->data + offset, size, MS_SYNC)) { 6917db96d56Sopenharmony_ci PyErr_SetFromErrno(PyExc_OSError); 6927db96d56Sopenharmony_ci return NULL; 6937db96d56Sopenharmony_ci } 6947db96d56Sopenharmony_ci Py_RETURN_NONE; 6957db96d56Sopenharmony_ci#else 6967db96d56Sopenharmony_ci PyErr_SetString(PyExc_ValueError, "flush not supported on this system"); 6977db96d56Sopenharmony_ci return NULL; 6987db96d56Sopenharmony_ci#endif 6997db96d56Sopenharmony_ci} 7007db96d56Sopenharmony_ci 7017db96d56Sopenharmony_cistatic PyObject * 7027db96d56Sopenharmony_cimmap_seek_method(mmap_object *self, PyObject *args) 7037db96d56Sopenharmony_ci{ 7047db96d56Sopenharmony_ci Py_ssize_t dist; 7057db96d56Sopenharmony_ci int how=0; 7067db96d56Sopenharmony_ci CHECK_VALID(NULL); 7077db96d56Sopenharmony_ci if (!PyArg_ParseTuple(args, "n|i:seek", &dist, &how)) 7087db96d56Sopenharmony_ci return NULL; 7097db96d56Sopenharmony_ci else { 7107db96d56Sopenharmony_ci Py_ssize_t where; 7117db96d56Sopenharmony_ci switch (how) { 7127db96d56Sopenharmony_ci case 0: /* relative to start */ 7137db96d56Sopenharmony_ci where = dist; 7147db96d56Sopenharmony_ci break; 7157db96d56Sopenharmony_ci case 1: /* relative to current position */ 7167db96d56Sopenharmony_ci if (PY_SSIZE_T_MAX - self->pos < dist) 7177db96d56Sopenharmony_ci goto onoutofrange; 7187db96d56Sopenharmony_ci where = self->pos + dist; 7197db96d56Sopenharmony_ci break; 7207db96d56Sopenharmony_ci case 2: /* relative to end */ 7217db96d56Sopenharmony_ci if (PY_SSIZE_T_MAX - self->size < dist) 7227db96d56Sopenharmony_ci goto onoutofrange; 7237db96d56Sopenharmony_ci where = self->size + dist; 7247db96d56Sopenharmony_ci break; 7257db96d56Sopenharmony_ci default: 7267db96d56Sopenharmony_ci PyErr_SetString(PyExc_ValueError, "unknown seek type"); 7277db96d56Sopenharmony_ci return NULL; 7287db96d56Sopenharmony_ci } 7297db96d56Sopenharmony_ci if (where > self->size || where < 0) 7307db96d56Sopenharmony_ci goto onoutofrange; 7317db96d56Sopenharmony_ci self->pos = where; 7327db96d56Sopenharmony_ci Py_RETURN_NONE; 7337db96d56Sopenharmony_ci } 7347db96d56Sopenharmony_ci 7357db96d56Sopenharmony_ci onoutofrange: 7367db96d56Sopenharmony_ci PyErr_SetString(PyExc_ValueError, "seek out of range"); 7377db96d56Sopenharmony_ci return NULL; 7387db96d56Sopenharmony_ci} 7397db96d56Sopenharmony_ci 7407db96d56Sopenharmony_cistatic PyObject * 7417db96d56Sopenharmony_cimmap_move_method(mmap_object *self, PyObject *args) 7427db96d56Sopenharmony_ci{ 7437db96d56Sopenharmony_ci Py_ssize_t dest, src, cnt; 7447db96d56Sopenharmony_ci CHECK_VALID(NULL); 7457db96d56Sopenharmony_ci if (!PyArg_ParseTuple(args, "nnn:move", &dest, &src, &cnt) || 7467db96d56Sopenharmony_ci !is_writable(self)) { 7477db96d56Sopenharmony_ci return NULL; 7487db96d56Sopenharmony_ci } else { 7497db96d56Sopenharmony_ci /* bounds check the values */ 7507db96d56Sopenharmony_ci if (dest < 0 || src < 0 || cnt < 0) 7517db96d56Sopenharmony_ci goto bounds; 7527db96d56Sopenharmony_ci if (self->size - dest < cnt || self->size - src < cnt) 7537db96d56Sopenharmony_ci goto bounds; 7547db96d56Sopenharmony_ci 7557db96d56Sopenharmony_ci CHECK_VALID(NULL); 7567db96d56Sopenharmony_ci memmove(&self->data[dest], &self->data[src], cnt); 7577db96d56Sopenharmony_ci 7587db96d56Sopenharmony_ci Py_RETURN_NONE; 7597db96d56Sopenharmony_ci 7607db96d56Sopenharmony_ci bounds: 7617db96d56Sopenharmony_ci PyErr_SetString(PyExc_ValueError, 7627db96d56Sopenharmony_ci "source, destination, or count out of range"); 7637db96d56Sopenharmony_ci return NULL; 7647db96d56Sopenharmony_ci } 7657db96d56Sopenharmony_ci} 7667db96d56Sopenharmony_ci 7677db96d56Sopenharmony_cistatic PyObject * 7687db96d56Sopenharmony_cimmap_closed_get(mmap_object *self, void *Py_UNUSED(ignored)) 7697db96d56Sopenharmony_ci{ 7707db96d56Sopenharmony_ci#ifdef MS_WINDOWS 7717db96d56Sopenharmony_ci return PyBool_FromLong(self->map_handle == NULL ? 1 : 0); 7727db96d56Sopenharmony_ci#elif defined(UNIX) 7737db96d56Sopenharmony_ci return PyBool_FromLong(self->data == NULL ? 1 : 0); 7747db96d56Sopenharmony_ci#endif 7757db96d56Sopenharmony_ci} 7767db96d56Sopenharmony_ci 7777db96d56Sopenharmony_cistatic PyObject * 7787db96d56Sopenharmony_cimmap__enter__method(mmap_object *self, PyObject *args) 7797db96d56Sopenharmony_ci{ 7807db96d56Sopenharmony_ci CHECK_VALID(NULL); 7817db96d56Sopenharmony_ci 7827db96d56Sopenharmony_ci Py_INCREF(self); 7837db96d56Sopenharmony_ci return (PyObject *)self; 7847db96d56Sopenharmony_ci} 7857db96d56Sopenharmony_ci 7867db96d56Sopenharmony_cistatic PyObject * 7877db96d56Sopenharmony_cimmap__exit__method(PyObject *self, PyObject *args) 7887db96d56Sopenharmony_ci{ 7897db96d56Sopenharmony_ci return mmap_close_method((mmap_object *)self, NULL); 7907db96d56Sopenharmony_ci} 7917db96d56Sopenharmony_ci 7927db96d56Sopenharmony_cistatic PyObject * 7937db96d56Sopenharmony_cimmap__repr__method(PyObject *self) 7947db96d56Sopenharmony_ci{ 7957db96d56Sopenharmony_ci mmap_object *mobj = (mmap_object *)self; 7967db96d56Sopenharmony_ci 7977db96d56Sopenharmony_ci#ifdef MS_WINDOWS 7987db96d56Sopenharmony_ci#define _Py_FORMAT_OFFSET "lld" 7997db96d56Sopenharmony_ci if (mobj->map_handle == NULL) 8007db96d56Sopenharmony_ci#elif defined(UNIX) 8017db96d56Sopenharmony_ci# ifdef HAVE_LARGEFILE_SUPPORT 8027db96d56Sopenharmony_ci# define _Py_FORMAT_OFFSET "lld" 8037db96d56Sopenharmony_ci# else 8047db96d56Sopenharmony_ci# define _Py_FORMAT_OFFSET "ld" 8057db96d56Sopenharmony_ci# endif 8067db96d56Sopenharmony_ci if (mobj->data == NULL) 8077db96d56Sopenharmony_ci#endif 8087db96d56Sopenharmony_ci { 8097db96d56Sopenharmony_ci return PyUnicode_FromFormat("<%s closed=True>", Py_TYPE(self)->tp_name); 8107db96d56Sopenharmony_ci } else { 8117db96d56Sopenharmony_ci const char *access_str; 8127db96d56Sopenharmony_ci 8137db96d56Sopenharmony_ci switch (mobj->access) { 8147db96d56Sopenharmony_ci case ACCESS_DEFAULT: 8157db96d56Sopenharmony_ci access_str = "ACCESS_DEFAULT"; 8167db96d56Sopenharmony_ci break; 8177db96d56Sopenharmony_ci case ACCESS_READ: 8187db96d56Sopenharmony_ci access_str = "ACCESS_READ"; 8197db96d56Sopenharmony_ci break; 8207db96d56Sopenharmony_ci case ACCESS_WRITE: 8217db96d56Sopenharmony_ci access_str = "ACCESS_WRITE"; 8227db96d56Sopenharmony_ci break; 8237db96d56Sopenharmony_ci case ACCESS_COPY: 8247db96d56Sopenharmony_ci access_str = "ACCESS_COPY"; 8257db96d56Sopenharmony_ci break; 8267db96d56Sopenharmony_ci default: 8277db96d56Sopenharmony_ci Py_UNREACHABLE(); 8287db96d56Sopenharmony_ci } 8297db96d56Sopenharmony_ci 8307db96d56Sopenharmony_ci return PyUnicode_FromFormat("<%s closed=False, access=%s, length=%zd, " 8317db96d56Sopenharmony_ci "pos=%zd, offset=%" _Py_FORMAT_OFFSET ">", 8327db96d56Sopenharmony_ci Py_TYPE(self)->tp_name, access_str, 8337db96d56Sopenharmony_ci mobj->size, mobj->pos, mobj->offset); 8347db96d56Sopenharmony_ci } 8357db96d56Sopenharmony_ci} 8367db96d56Sopenharmony_ci 8377db96d56Sopenharmony_ci#ifdef MS_WINDOWS 8387db96d56Sopenharmony_cistatic PyObject * 8397db96d56Sopenharmony_cimmap__sizeof__method(mmap_object *self, void *unused) 8407db96d56Sopenharmony_ci{ 8417db96d56Sopenharmony_ci Py_ssize_t res; 8427db96d56Sopenharmony_ci 8437db96d56Sopenharmony_ci res = _PyObject_SIZE(Py_TYPE(self)); 8447db96d56Sopenharmony_ci if (self->tagname) 8457db96d56Sopenharmony_ci res += strlen(self->tagname) + 1; 8467db96d56Sopenharmony_ci return PyLong_FromSsize_t(res); 8477db96d56Sopenharmony_ci} 8487db96d56Sopenharmony_ci#endif 8497db96d56Sopenharmony_ci 8507db96d56Sopenharmony_ci#ifdef HAVE_MADVISE 8517db96d56Sopenharmony_cistatic PyObject * 8527db96d56Sopenharmony_cimmap_madvise_method(mmap_object *self, PyObject *args) 8537db96d56Sopenharmony_ci{ 8547db96d56Sopenharmony_ci int option; 8557db96d56Sopenharmony_ci Py_ssize_t start = 0, length; 8567db96d56Sopenharmony_ci 8577db96d56Sopenharmony_ci CHECK_VALID(NULL); 8587db96d56Sopenharmony_ci length = self->size; 8597db96d56Sopenharmony_ci 8607db96d56Sopenharmony_ci if (!PyArg_ParseTuple(args, "i|nn:madvise", &option, &start, &length)) { 8617db96d56Sopenharmony_ci return NULL; 8627db96d56Sopenharmony_ci } 8637db96d56Sopenharmony_ci 8647db96d56Sopenharmony_ci if (start < 0 || start >= self->size) { 8657db96d56Sopenharmony_ci PyErr_SetString(PyExc_ValueError, "madvise start out of bounds"); 8667db96d56Sopenharmony_ci return NULL; 8677db96d56Sopenharmony_ci } 8687db96d56Sopenharmony_ci if (length < 0) { 8697db96d56Sopenharmony_ci PyErr_SetString(PyExc_ValueError, "madvise length invalid"); 8707db96d56Sopenharmony_ci return NULL; 8717db96d56Sopenharmony_ci } 8727db96d56Sopenharmony_ci if (PY_SSIZE_T_MAX - start < length) { 8737db96d56Sopenharmony_ci PyErr_SetString(PyExc_OverflowError, "madvise length too large"); 8747db96d56Sopenharmony_ci return NULL; 8757db96d56Sopenharmony_ci } 8767db96d56Sopenharmony_ci 8777db96d56Sopenharmony_ci if (start + length > self->size) { 8787db96d56Sopenharmony_ci length = self->size - start; 8797db96d56Sopenharmony_ci } 8807db96d56Sopenharmony_ci 8817db96d56Sopenharmony_ci CHECK_VALID(NULL); 8827db96d56Sopenharmony_ci if (madvise(self->data + start, length, option) != 0) { 8837db96d56Sopenharmony_ci PyErr_SetFromErrno(PyExc_OSError); 8847db96d56Sopenharmony_ci return NULL; 8857db96d56Sopenharmony_ci } 8867db96d56Sopenharmony_ci 8877db96d56Sopenharmony_ci Py_RETURN_NONE; 8887db96d56Sopenharmony_ci} 8897db96d56Sopenharmony_ci#endif // HAVE_MADVISE 8907db96d56Sopenharmony_ci 8917db96d56Sopenharmony_cistatic struct PyMemberDef mmap_object_members[] = { 8927db96d56Sopenharmony_ci {"__weaklistoffset__", T_PYSSIZET, offsetof(mmap_object, weakreflist), READONLY}, 8937db96d56Sopenharmony_ci {NULL}, 8947db96d56Sopenharmony_ci}; 8957db96d56Sopenharmony_ci 8967db96d56Sopenharmony_cistatic struct PyMethodDef mmap_object_methods[] = { 8977db96d56Sopenharmony_ci {"close", (PyCFunction) mmap_close_method, METH_NOARGS}, 8987db96d56Sopenharmony_ci {"find", (PyCFunction) mmap_find_method, METH_VARARGS}, 8997db96d56Sopenharmony_ci {"rfind", (PyCFunction) mmap_rfind_method, METH_VARARGS}, 9007db96d56Sopenharmony_ci {"flush", (PyCFunction) mmap_flush_method, METH_VARARGS}, 9017db96d56Sopenharmony_ci#ifdef HAVE_MADVISE 9027db96d56Sopenharmony_ci {"madvise", (PyCFunction) mmap_madvise_method, METH_VARARGS}, 9037db96d56Sopenharmony_ci#endif 9047db96d56Sopenharmony_ci {"move", (PyCFunction) mmap_move_method, METH_VARARGS}, 9057db96d56Sopenharmony_ci {"read", (PyCFunction) mmap_read_method, METH_VARARGS}, 9067db96d56Sopenharmony_ci {"read_byte", (PyCFunction) mmap_read_byte_method, METH_NOARGS}, 9077db96d56Sopenharmony_ci {"readline", (PyCFunction) mmap_read_line_method, METH_NOARGS}, 9087db96d56Sopenharmony_ci {"resize", (PyCFunction) mmap_resize_method, METH_VARARGS}, 9097db96d56Sopenharmony_ci {"seek", (PyCFunction) mmap_seek_method, METH_VARARGS}, 9107db96d56Sopenharmony_ci {"size", (PyCFunction) mmap_size_method, METH_NOARGS}, 9117db96d56Sopenharmony_ci {"tell", (PyCFunction) mmap_tell_method, METH_NOARGS}, 9127db96d56Sopenharmony_ci {"write", (PyCFunction) mmap_write_method, METH_VARARGS}, 9137db96d56Sopenharmony_ci {"write_byte", (PyCFunction) mmap_write_byte_method, METH_VARARGS}, 9147db96d56Sopenharmony_ci {"__enter__", (PyCFunction) mmap__enter__method, METH_NOARGS}, 9157db96d56Sopenharmony_ci {"__exit__", (PyCFunction) mmap__exit__method, METH_VARARGS}, 9167db96d56Sopenharmony_ci#ifdef MS_WINDOWS 9177db96d56Sopenharmony_ci {"__sizeof__", (PyCFunction) mmap__sizeof__method, METH_NOARGS}, 9187db96d56Sopenharmony_ci#endif 9197db96d56Sopenharmony_ci {NULL, NULL} /* sentinel */ 9207db96d56Sopenharmony_ci}; 9217db96d56Sopenharmony_ci 9227db96d56Sopenharmony_cistatic PyGetSetDef mmap_object_getset[] = { 9237db96d56Sopenharmony_ci {"closed", (getter) mmap_closed_get, NULL, NULL}, 9247db96d56Sopenharmony_ci {NULL} 9257db96d56Sopenharmony_ci}; 9267db96d56Sopenharmony_ci 9277db96d56Sopenharmony_ci 9287db96d56Sopenharmony_ci/* Functions for treating an mmap'ed file as a buffer */ 9297db96d56Sopenharmony_ci 9307db96d56Sopenharmony_cistatic int 9317db96d56Sopenharmony_cimmap_buffer_getbuf(mmap_object *self, Py_buffer *view, int flags) 9327db96d56Sopenharmony_ci{ 9337db96d56Sopenharmony_ci CHECK_VALID(-1); 9347db96d56Sopenharmony_ci if (PyBuffer_FillInfo(view, (PyObject*)self, self->data, self->size, 9357db96d56Sopenharmony_ci (self->access == ACCESS_READ), flags) < 0) 9367db96d56Sopenharmony_ci return -1; 9377db96d56Sopenharmony_ci self->exports++; 9387db96d56Sopenharmony_ci return 0; 9397db96d56Sopenharmony_ci} 9407db96d56Sopenharmony_ci 9417db96d56Sopenharmony_cistatic void 9427db96d56Sopenharmony_cimmap_buffer_releasebuf(mmap_object *self, Py_buffer *view) 9437db96d56Sopenharmony_ci{ 9447db96d56Sopenharmony_ci self->exports--; 9457db96d56Sopenharmony_ci} 9467db96d56Sopenharmony_ci 9477db96d56Sopenharmony_cistatic Py_ssize_t 9487db96d56Sopenharmony_cimmap_length(mmap_object *self) 9497db96d56Sopenharmony_ci{ 9507db96d56Sopenharmony_ci CHECK_VALID(-1); 9517db96d56Sopenharmony_ci return self->size; 9527db96d56Sopenharmony_ci} 9537db96d56Sopenharmony_ci 9547db96d56Sopenharmony_cistatic PyObject * 9557db96d56Sopenharmony_cimmap_item(mmap_object *self, Py_ssize_t i) 9567db96d56Sopenharmony_ci{ 9577db96d56Sopenharmony_ci CHECK_VALID(NULL); 9587db96d56Sopenharmony_ci if (i < 0 || i >= self->size) { 9597db96d56Sopenharmony_ci PyErr_SetString(PyExc_IndexError, "mmap index out of range"); 9607db96d56Sopenharmony_ci return NULL; 9617db96d56Sopenharmony_ci } 9627db96d56Sopenharmony_ci return PyBytes_FromStringAndSize(self->data + i, 1); 9637db96d56Sopenharmony_ci} 9647db96d56Sopenharmony_ci 9657db96d56Sopenharmony_cistatic PyObject * 9667db96d56Sopenharmony_cimmap_subscript(mmap_object *self, PyObject *item) 9677db96d56Sopenharmony_ci{ 9687db96d56Sopenharmony_ci CHECK_VALID(NULL); 9697db96d56Sopenharmony_ci if (PyIndex_Check(item)) { 9707db96d56Sopenharmony_ci Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError); 9717db96d56Sopenharmony_ci if (i == -1 && PyErr_Occurred()) 9727db96d56Sopenharmony_ci return NULL; 9737db96d56Sopenharmony_ci if (i < 0) 9747db96d56Sopenharmony_ci i += self->size; 9757db96d56Sopenharmony_ci if (i < 0 || i >= self->size) { 9767db96d56Sopenharmony_ci PyErr_SetString(PyExc_IndexError, 9777db96d56Sopenharmony_ci "mmap index out of range"); 9787db96d56Sopenharmony_ci return NULL; 9797db96d56Sopenharmony_ci } 9807db96d56Sopenharmony_ci CHECK_VALID(NULL); 9817db96d56Sopenharmony_ci return PyLong_FromLong(Py_CHARMASK(self->data[i])); 9827db96d56Sopenharmony_ci } 9837db96d56Sopenharmony_ci else if (PySlice_Check(item)) { 9847db96d56Sopenharmony_ci Py_ssize_t start, stop, step, slicelen; 9857db96d56Sopenharmony_ci 9867db96d56Sopenharmony_ci if (PySlice_Unpack(item, &start, &stop, &step) < 0) { 9877db96d56Sopenharmony_ci return NULL; 9887db96d56Sopenharmony_ci } 9897db96d56Sopenharmony_ci slicelen = PySlice_AdjustIndices(self->size, &start, &stop, step); 9907db96d56Sopenharmony_ci 9917db96d56Sopenharmony_ci CHECK_VALID(NULL); 9927db96d56Sopenharmony_ci if (slicelen <= 0) 9937db96d56Sopenharmony_ci return PyBytes_FromStringAndSize("", 0); 9947db96d56Sopenharmony_ci else if (step == 1) 9957db96d56Sopenharmony_ci return PyBytes_FromStringAndSize(self->data + start, 9967db96d56Sopenharmony_ci slicelen); 9977db96d56Sopenharmony_ci else { 9987db96d56Sopenharmony_ci char *result_buf = (char *)PyMem_Malloc(slicelen); 9997db96d56Sopenharmony_ci size_t cur; 10007db96d56Sopenharmony_ci Py_ssize_t i; 10017db96d56Sopenharmony_ci PyObject *result; 10027db96d56Sopenharmony_ci 10037db96d56Sopenharmony_ci if (result_buf == NULL) 10047db96d56Sopenharmony_ci return PyErr_NoMemory(); 10057db96d56Sopenharmony_ci 10067db96d56Sopenharmony_ci for (cur = start, i = 0; i < slicelen; 10077db96d56Sopenharmony_ci cur += step, i++) { 10087db96d56Sopenharmony_ci result_buf[i] = self->data[cur]; 10097db96d56Sopenharmony_ci } 10107db96d56Sopenharmony_ci result = PyBytes_FromStringAndSize(result_buf, 10117db96d56Sopenharmony_ci slicelen); 10127db96d56Sopenharmony_ci PyMem_Free(result_buf); 10137db96d56Sopenharmony_ci return result; 10147db96d56Sopenharmony_ci } 10157db96d56Sopenharmony_ci } 10167db96d56Sopenharmony_ci else { 10177db96d56Sopenharmony_ci PyErr_SetString(PyExc_TypeError, 10187db96d56Sopenharmony_ci "mmap indices must be integers"); 10197db96d56Sopenharmony_ci return NULL; 10207db96d56Sopenharmony_ci } 10217db96d56Sopenharmony_ci} 10227db96d56Sopenharmony_ci 10237db96d56Sopenharmony_cistatic int 10247db96d56Sopenharmony_cimmap_ass_item(mmap_object *self, Py_ssize_t i, PyObject *v) 10257db96d56Sopenharmony_ci{ 10267db96d56Sopenharmony_ci const char *buf; 10277db96d56Sopenharmony_ci 10287db96d56Sopenharmony_ci CHECK_VALID(-1); 10297db96d56Sopenharmony_ci if (i < 0 || i >= self->size) { 10307db96d56Sopenharmony_ci PyErr_SetString(PyExc_IndexError, "mmap index out of range"); 10317db96d56Sopenharmony_ci return -1; 10327db96d56Sopenharmony_ci } 10337db96d56Sopenharmony_ci if (v == NULL) { 10347db96d56Sopenharmony_ci PyErr_SetString(PyExc_TypeError, 10357db96d56Sopenharmony_ci "mmap object doesn't support item deletion"); 10367db96d56Sopenharmony_ci return -1; 10377db96d56Sopenharmony_ci } 10387db96d56Sopenharmony_ci if (! (PyBytes_Check(v) && PyBytes_Size(v)==1) ) { 10397db96d56Sopenharmony_ci PyErr_SetString(PyExc_IndexError, 10407db96d56Sopenharmony_ci "mmap assignment must be length-1 bytes()"); 10417db96d56Sopenharmony_ci return -1; 10427db96d56Sopenharmony_ci } 10437db96d56Sopenharmony_ci if (!is_writable(self)) 10447db96d56Sopenharmony_ci return -1; 10457db96d56Sopenharmony_ci buf = PyBytes_AsString(v); 10467db96d56Sopenharmony_ci self->data[i] = buf[0]; 10477db96d56Sopenharmony_ci return 0; 10487db96d56Sopenharmony_ci} 10497db96d56Sopenharmony_ci 10507db96d56Sopenharmony_cistatic int 10517db96d56Sopenharmony_cimmap_ass_subscript(mmap_object *self, PyObject *item, PyObject *value) 10527db96d56Sopenharmony_ci{ 10537db96d56Sopenharmony_ci CHECK_VALID(-1); 10547db96d56Sopenharmony_ci 10557db96d56Sopenharmony_ci if (!is_writable(self)) 10567db96d56Sopenharmony_ci return -1; 10577db96d56Sopenharmony_ci 10587db96d56Sopenharmony_ci if (PyIndex_Check(item)) { 10597db96d56Sopenharmony_ci Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError); 10607db96d56Sopenharmony_ci Py_ssize_t v; 10617db96d56Sopenharmony_ci 10627db96d56Sopenharmony_ci if (i == -1 && PyErr_Occurred()) 10637db96d56Sopenharmony_ci return -1; 10647db96d56Sopenharmony_ci if (i < 0) 10657db96d56Sopenharmony_ci i += self->size; 10667db96d56Sopenharmony_ci if (i < 0 || i >= self->size) { 10677db96d56Sopenharmony_ci PyErr_SetString(PyExc_IndexError, 10687db96d56Sopenharmony_ci "mmap index out of range"); 10697db96d56Sopenharmony_ci return -1; 10707db96d56Sopenharmony_ci } 10717db96d56Sopenharmony_ci if (value == NULL) { 10727db96d56Sopenharmony_ci PyErr_SetString(PyExc_TypeError, 10737db96d56Sopenharmony_ci "mmap doesn't support item deletion"); 10747db96d56Sopenharmony_ci return -1; 10757db96d56Sopenharmony_ci } 10767db96d56Sopenharmony_ci if (!PyIndex_Check(value)) { 10777db96d56Sopenharmony_ci PyErr_SetString(PyExc_TypeError, 10787db96d56Sopenharmony_ci "mmap item value must be an int"); 10797db96d56Sopenharmony_ci return -1; 10807db96d56Sopenharmony_ci } 10817db96d56Sopenharmony_ci v = PyNumber_AsSsize_t(value, PyExc_TypeError); 10827db96d56Sopenharmony_ci if (v == -1 && PyErr_Occurred()) 10837db96d56Sopenharmony_ci return -1; 10847db96d56Sopenharmony_ci if (v < 0 || v > 255) { 10857db96d56Sopenharmony_ci PyErr_SetString(PyExc_ValueError, 10867db96d56Sopenharmony_ci "mmap item value must be " 10877db96d56Sopenharmony_ci "in range(0, 256)"); 10887db96d56Sopenharmony_ci return -1; 10897db96d56Sopenharmony_ci } 10907db96d56Sopenharmony_ci CHECK_VALID(-1); 10917db96d56Sopenharmony_ci self->data[i] = (char) v; 10927db96d56Sopenharmony_ci return 0; 10937db96d56Sopenharmony_ci } 10947db96d56Sopenharmony_ci else if (PySlice_Check(item)) { 10957db96d56Sopenharmony_ci Py_ssize_t start, stop, step, slicelen; 10967db96d56Sopenharmony_ci Py_buffer vbuf; 10977db96d56Sopenharmony_ci 10987db96d56Sopenharmony_ci if (PySlice_Unpack(item, &start, &stop, &step) < 0) { 10997db96d56Sopenharmony_ci return -1; 11007db96d56Sopenharmony_ci } 11017db96d56Sopenharmony_ci slicelen = PySlice_AdjustIndices(self->size, &start, &stop, step); 11027db96d56Sopenharmony_ci if (value == NULL) { 11037db96d56Sopenharmony_ci PyErr_SetString(PyExc_TypeError, 11047db96d56Sopenharmony_ci "mmap object doesn't support slice deletion"); 11057db96d56Sopenharmony_ci return -1; 11067db96d56Sopenharmony_ci } 11077db96d56Sopenharmony_ci if (PyObject_GetBuffer(value, &vbuf, PyBUF_SIMPLE) < 0) 11087db96d56Sopenharmony_ci return -1; 11097db96d56Sopenharmony_ci if (vbuf.len != slicelen) { 11107db96d56Sopenharmony_ci PyErr_SetString(PyExc_IndexError, 11117db96d56Sopenharmony_ci "mmap slice assignment is wrong size"); 11127db96d56Sopenharmony_ci PyBuffer_Release(&vbuf); 11137db96d56Sopenharmony_ci return -1; 11147db96d56Sopenharmony_ci } 11157db96d56Sopenharmony_ci 11167db96d56Sopenharmony_ci CHECK_VALID_OR_RELEASE(-1, vbuf); 11177db96d56Sopenharmony_ci if (slicelen == 0) { 11187db96d56Sopenharmony_ci } 11197db96d56Sopenharmony_ci else if (step == 1) { 11207db96d56Sopenharmony_ci memcpy(self->data + start, vbuf.buf, slicelen); 11217db96d56Sopenharmony_ci } 11227db96d56Sopenharmony_ci else { 11237db96d56Sopenharmony_ci size_t cur; 11247db96d56Sopenharmony_ci Py_ssize_t i; 11257db96d56Sopenharmony_ci 11267db96d56Sopenharmony_ci for (cur = start, i = 0; 11277db96d56Sopenharmony_ci i < slicelen; 11287db96d56Sopenharmony_ci cur += step, i++) 11297db96d56Sopenharmony_ci { 11307db96d56Sopenharmony_ci self->data[cur] = ((char *)vbuf.buf)[i]; 11317db96d56Sopenharmony_ci } 11327db96d56Sopenharmony_ci } 11337db96d56Sopenharmony_ci PyBuffer_Release(&vbuf); 11347db96d56Sopenharmony_ci return 0; 11357db96d56Sopenharmony_ci } 11367db96d56Sopenharmony_ci else { 11377db96d56Sopenharmony_ci PyErr_SetString(PyExc_TypeError, 11387db96d56Sopenharmony_ci "mmap indices must be integer"); 11397db96d56Sopenharmony_ci return -1; 11407db96d56Sopenharmony_ci } 11417db96d56Sopenharmony_ci} 11427db96d56Sopenharmony_ci 11437db96d56Sopenharmony_cistatic PyObject * 11447db96d56Sopenharmony_cinew_mmap_object(PyTypeObject *type, PyObject *args, PyObject *kwdict); 11457db96d56Sopenharmony_ci 11467db96d56Sopenharmony_ciPyDoc_STRVAR(mmap_doc, 11477db96d56Sopenharmony_ci"Windows: mmap(fileno, length[, tagname[, access[, offset]]])\n\ 11487db96d56Sopenharmony_ci\n\ 11497db96d56Sopenharmony_ciMaps length bytes from the file specified by the file handle fileno,\n\ 11507db96d56Sopenharmony_ciand returns a mmap object. If length is larger than the current size\n\ 11517db96d56Sopenharmony_ciof the file, the file is extended to contain length bytes. If length\n\ 11527db96d56Sopenharmony_ciis 0, the maximum length of the map is the current size of the file,\n\ 11537db96d56Sopenharmony_ciexcept that if the file is empty Windows raises an exception (you cannot\n\ 11547db96d56Sopenharmony_cicreate an empty mapping on Windows).\n\ 11557db96d56Sopenharmony_ci\n\ 11567db96d56Sopenharmony_ciUnix: mmap(fileno, length[, flags[, prot[, access[, offset]]]])\n\ 11577db96d56Sopenharmony_ci\n\ 11587db96d56Sopenharmony_ciMaps length bytes from the file specified by the file descriptor fileno,\n\ 11597db96d56Sopenharmony_ciand returns a mmap object. If length is 0, the maximum length of the map\n\ 11607db96d56Sopenharmony_ciwill be the current size of the file when mmap is called.\n\ 11617db96d56Sopenharmony_ciflags specifies the nature of the mapping. MAP_PRIVATE creates a\n\ 11627db96d56Sopenharmony_ciprivate copy-on-write mapping, so changes to the contents of the mmap\n\ 11637db96d56Sopenharmony_ciobject will be private to this process, and MAP_SHARED creates a mapping\n\ 11647db96d56Sopenharmony_cithat's shared with all other processes mapping the same areas of the file.\n\ 11657db96d56Sopenharmony_ciThe default value is MAP_SHARED.\n\ 11667db96d56Sopenharmony_ci\n\ 11677db96d56Sopenharmony_ciTo map anonymous memory, pass -1 as the fileno (both versions)."); 11687db96d56Sopenharmony_ci 11697db96d56Sopenharmony_ci 11707db96d56Sopenharmony_cistatic PyType_Slot mmap_object_slots[] = { 11717db96d56Sopenharmony_ci {Py_tp_new, new_mmap_object}, 11727db96d56Sopenharmony_ci {Py_tp_dealloc, mmap_object_dealloc}, 11737db96d56Sopenharmony_ci {Py_tp_repr, mmap__repr__method}, 11747db96d56Sopenharmony_ci {Py_tp_doc, (void *)mmap_doc}, 11757db96d56Sopenharmony_ci {Py_tp_methods, mmap_object_methods}, 11767db96d56Sopenharmony_ci {Py_tp_members, mmap_object_members}, 11777db96d56Sopenharmony_ci {Py_tp_getset, mmap_object_getset}, 11787db96d56Sopenharmony_ci {Py_tp_getattro, PyObject_GenericGetAttr}, 11797db96d56Sopenharmony_ci {Py_tp_traverse, mmap_object_traverse}, 11807db96d56Sopenharmony_ci 11817db96d56Sopenharmony_ci /* as sequence */ 11827db96d56Sopenharmony_ci {Py_sq_length, mmap_length}, 11837db96d56Sopenharmony_ci {Py_sq_item, mmap_item}, 11847db96d56Sopenharmony_ci {Py_sq_ass_item, mmap_ass_item}, 11857db96d56Sopenharmony_ci 11867db96d56Sopenharmony_ci /* as mapping */ 11877db96d56Sopenharmony_ci {Py_mp_length, mmap_length}, 11887db96d56Sopenharmony_ci {Py_mp_subscript, mmap_subscript}, 11897db96d56Sopenharmony_ci {Py_mp_ass_subscript, mmap_ass_subscript}, 11907db96d56Sopenharmony_ci 11917db96d56Sopenharmony_ci /* as buffer */ 11927db96d56Sopenharmony_ci {Py_bf_getbuffer, mmap_buffer_getbuf}, 11937db96d56Sopenharmony_ci {Py_bf_releasebuffer, mmap_buffer_releasebuf}, 11947db96d56Sopenharmony_ci {0, NULL}, 11957db96d56Sopenharmony_ci}; 11967db96d56Sopenharmony_ci 11977db96d56Sopenharmony_cistatic PyType_Spec mmap_object_spec = { 11987db96d56Sopenharmony_ci .name = "mmap.mmap", 11997db96d56Sopenharmony_ci .basicsize = sizeof(mmap_object), 12007db96d56Sopenharmony_ci .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | 12017db96d56Sopenharmony_ci Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_IMMUTABLETYPE), 12027db96d56Sopenharmony_ci .slots = mmap_object_slots, 12037db96d56Sopenharmony_ci}; 12047db96d56Sopenharmony_ci 12057db96d56Sopenharmony_ci 12067db96d56Sopenharmony_ci#ifdef UNIX 12077db96d56Sopenharmony_ci#ifdef HAVE_LARGEFILE_SUPPORT 12087db96d56Sopenharmony_ci#define _Py_PARSE_OFF_T "L" 12097db96d56Sopenharmony_ci#else 12107db96d56Sopenharmony_ci#define _Py_PARSE_OFF_T "l" 12117db96d56Sopenharmony_ci#endif 12127db96d56Sopenharmony_ci 12137db96d56Sopenharmony_cistatic PyObject * 12147db96d56Sopenharmony_cinew_mmap_object(PyTypeObject *type, PyObject *args, PyObject *kwdict) 12157db96d56Sopenharmony_ci{ 12167db96d56Sopenharmony_ci struct _Py_stat_struct status; 12177db96d56Sopenharmony_ci int fstat_result = -1; 12187db96d56Sopenharmony_ci mmap_object *m_obj; 12197db96d56Sopenharmony_ci Py_ssize_t map_size; 12207db96d56Sopenharmony_ci off_t offset = 0; 12217db96d56Sopenharmony_ci int fd, flags = MAP_SHARED, prot = PROT_WRITE | PROT_READ; 12227db96d56Sopenharmony_ci int devzero = -1; 12237db96d56Sopenharmony_ci int access = (int)ACCESS_DEFAULT; 12247db96d56Sopenharmony_ci static char *keywords[] = {"fileno", "length", 12257db96d56Sopenharmony_ci "flags", "prot", 12267db96d56Sopenharmony_ci "access", "offset", NULL}; 12277db96d56Sopenharmony_ci 12287db96d56Sopenharmony_ci if (!PyArg_ParseTupleAndKeywords(args, kwdict, "in|iii" _Py_PARSE_OFF_T, keywords, 12297db96d56Sopenharmony_ci &fd, &map_size, &flags, &prot, 12307db96d56Sopenharmony_ci &access, &offset)) 12317db96d56Sopenharmony_ci return NULL; 12327db96d56Sopenharmony_ci if (map_size < 0) { 12337db96d56Sopenharmony_ci PyErr_SetString(PyExc_OverflowError, 12347db96d56Sopenharmony_ci "memory mapped length must be positive"); 12357db96d56Sopenharmony_ci return NULL; 12367db96d56Sopenharmony_ci } 12377db96d56Sopenharmony_ci if (offset < 0) { 12387db96d56Sopenharmony_ci PyErr_SetString(PyExc_OverflowError, 12397db96d56Sopenharmony_ci "memory mapped offset must be positive"); 12407db96d56Sopenharmony_ci return NULL; 12417db96d56Sopenharmony_ci } 12427db96d56Sopenharmony_ci 12437db96d56Sopenharmony_ci if ((access != (int)ACCESS_DEFAULT) && 12447db96d56Sopenharmony_ci ((flags != MAP_SHARED) || (prot != (PROT_WRITE | PROT_READ)))) 12457db96d56Sopenharmony_ci return PyErr_Format(PyExc_ValueError, 12467db96d56Sopenharmony_ci "mmap can't specify both access and flags, prot."); 12477db96d56Sopenharmony_ci switch ((access_mode)access) { 12487db96d56Sopenharmony_ci case ACCESS_READ: 12497db96d56Sopenharmony_ci flags = MAP_SHARED; 12507db96d56Sopenharmony_ci prot = PROT_READ; 12517db96d56Sopenharmony_ci break; 12527db96d56Sopenharmony_ci case ACCESS_WRITE: 12537db96d56Sopenharmony_ci flags = MAP_SHARED; 12547db96d56Sopenharmony_ci prot = PROT_READ | PROT_WRITE; 12557db96d56Sopenharmony_ci break; 12567db96d56Sopenharmony_ci case ACCESS_COPY: 12577db96d56Sopenharmony_ci flags = MAP_PRIVATE; 12587db96d56Sopenharmony_ci prot = PROT_READ | PROT_WRITE; 12597db96d56Sopenharmony_ci break; 12607db96d56Sopenharmony_ci case ACCESS_DEFAULT: 12617db96d56Sopenharmony_ci /* map prot to access type */ 12627db96d56Sopenharmony_ci if ((prot & PROT_READ) && (prot & PROT_WRITE)) { 12637db96d56Sopenharmony_ci /* ACCESS_DEFAULT */ 12647db96d56Sopenharmony_ci } 12657db96d56Sopenharmony_ci else if (prot & PROT_WRITE) { 12667db96d56Sopenharmony_ci access = ACCESS_WRITE; 12677db96d56Sopenharmony_ci } 12687db96d56Sopenharmony_ci else { 12697db96d56Sopenharmony_ci access = ACCESS_READ; 12707db96d56Sopenharmony_ci } 12717db96d56Sopenharmony_ci break; 12727db96d56Sopenharmony_ci default: 12737db96d56Sopenharmony_ci return PyErr_Format(PyExc_ValueError, 12747db96d56Sopenharmony_ci "mmap invalid access parameter."); 12757db96d56Sopenharmony_ci } 12767db96d56Sopenharmony_ci 12777db96d56Sopenharmony_ci if (PySys_Audit("mmap.__new__", "ini" _Py_PARSE_OFF_T, 12787db96d56Sopenharmony_ci fd, map_size, access, offset) < 0) { 12797db96d56Sopenharmony_ci return NULL; 12807db96d56Sopenharmony_ci } 12817db96d56Sopenharmony_ci 12827db96d56Sopenharmony_ci#ifdef __APPLE__ 12837db96d56Sopenharmony_ci /* Issue #11277: fsync(2) is not enough on OS X - a special, OS X specific 12847db96d56Sopenharmony_ci fcntl(2) is necessary to force DISKSYNC and get around mmap(2) bug */ 12857db96d56Sopenharmony_ci if (fd != -1) 12867db96d56Sopenharmony_ci (void)fcntl(fd, F_FULLFSYNC); 12877db96d56Sopenharmony_ci#endif 12887db96d56Sopenharmony_ci 12897db96d56Sopenharmony_ci if (fd != -1) { 12907db96d56Sopenharmony_ci Py_BEGIN_ALLOW_THREADS 12917db96d56Sopenharmony_ci fstat_result = _Py_fstat_noraise(fd, &status); 12927db96d56Sopenharmony_ci Py_END_ALLOW_THREADS 12937db96d56Sopenharmony_ci } 12947db96d56Sopenharmony_ci 12957db96d56Sopenharmony_ci if (fd != -1 && fstat_result == 0 && S_ISREG(status.st_mode)) { 12967db96d56Sopenharmony_ci if (map_size == 0) { 12977db96d56Sopenharmony_ci if (status.st_size == 0) { 12987db96d56Sopenharmony_ci PyErr_SetString(PyExc_ValueError, 12997db96d56Sopenharmony_ci "cannot mmap an empty file"); 13007db96d56Sopenharmony_ci return NULL; 13017db96d56Sopenharmony_ci } 13027db96d56Sopenharmony_ci if (offset >= status.st_size) { 13037db96d56Sopenharmony_ci PyErr_SetString(PyExc_ValueError, 13047db96d56Sopenharmony_ci "mmap offset is greater than file size"); 13057db96d56Sopenharmony_ci return NULL; 13067db96d56Sopenharmony_ci } 13077db96d56Sopenharmony_ci if (status.st_size - offset > PY_SSIZE_T_MAX) { 13087db96d56Sopenharmony_ci PyErr_SetString(PyExc_ValueError, 13097db96d56Sopenharmony_ci "mmap length is too large"); 13107db96d56Sopenharmony_ci return NULL; 13117db96d56Sopenharmony_ci } 13127db96d56Sopenharmony_ci map_size = (Py_ssize_t) (status.st_size - offset); 13137db96d56Sopenharmony_ci } else if (offset > status.st_size || status.st_size - offset < map_size) { 13147db96d56Sopenharmony_ci PyErr_SetString(PyExc_ValueError, 13157db96d56Sopenharmony_ci "mmap length is greater than file size"); 13167db96d56Sopenharmony_ci return NULL; 13177db96d56Sopenharmony_ci } 13187db96d56Sopenharmony_ci } 13197db96d56Sopenharmony_ci m_obj = (mmap_object *)type->tp_alloc(type, 0); 13207db96d56Sopenharmony_ci if (m_obj == NULL) {return NULL;} 13217db96d56Sopenharmony_ci m_obj->data = NULL; 13227db96d56Sopenharmony_ci m_obj->size = map_size; 13237db96d56Sopenharmony_ci m_obj->pos = 0; 13247db96d56Sopenharmony_ci m_obj->weakreflist = NULL; 13257db96d56Sopenharmony_ci m_obj->exports = 0; 13267db96d56Sopenharmony_ci m_obj->offset = offset; 13277db96d56Sopenharmony_ci if (fd == -1) { 13287db96d56Sopenharmony_ci m_obj->fd = -1; 13297db96d56Sopenharmony_ci /* Assume the caller wants to map anonymous memory. 13307db96d56Sopenharmony_ci This is the same behaviour as Windows. mmap.mmap(-1, size) 13317db96d56Sopenharmony_ci on both Windows and Unix map anonymous memory. 13327db96d56Sopenharmony_ci */ 13337db96d56Sopenharmony_ci#ifdef MAP_ANONYMOUS 13347db96d56Sopenharmony_ci /* BSD way to map anonymous memory */ 13357db96d56Sopenharmony_ci flags |= MAP_ANONYMOUS; 13367db96d56Sopenharmony_ci 13377db96d56Sopenharmony_ci /* VxWorks only supports MAP_ANONYMOUS with MAP_PRIVATE flag */ 13387db96d56Sopenharmony_ci#ifdef __VXWORKS__ 13397db96d56Sopenharmony_ci flags &= ~MAP_SHARED; 13407db96d56Sopenharmony_ci flags |= MAP_PRIVATE; 13417db96d56Sopenharmony_ci#endif 13427db96d56Sopenharmony_ci 13437db96d56Sopenharmony_ci#else 13447db96d56Sopenharmony_ci /* SVR4 method to map anonymous memory is to open /dev/zero */ 13457db96d56Sopenharmony_ci fd = devzero = _Py_open("/dev/zero", O_RDWR); 13467db96d56Sopenharmony_ci if (devzero == -1) { 13477db96d56Sopenharmony_ci Py_DECREF(m_obj); 13487db96d56Sopenharmony_ci return NULL; 13497db96d56Sopenharmony_ci } 13507db96d56Sopenharmony_ci#endif 13517db96d56Sopenharmony_ci } 13527db96d56Sopenharmony_ci else { 13537db96d56Sopenharmony_ci m_obj->fd = _Py_dup(fd); 13547db96d56Sopenharmony_ci if (m_obj->fd == -1) { 13557db96d56Sopenharmony_ci Py_DECREF(m_obj); 13567db96d56Sopenharmony_ci return NULL; 13577db96d56Sopenharmony_ci } 13587db96d56Sopenharmony_ci } 13597db96d56Sopenharmony_ci 13607db96d56Sopenharmony_ci m_obj->data = mmap(NULL, map_size, 13617db96d56Sopenharmony_ci prot, flags, 13627db96d56Sopenharmony_ci fd, offset); 13637db96d56Sopenharmony_ci 13647db96d56Sopenharmony_ci if (devzero != -1) { 13657db96d56Sopenharmony_ci close(devzero); 13667db96d56Sopenharmony_ci } 13677db96d56Sopenharmony_ci 13687db96d56Sopenharmony_ci if (m_obj->data == (char *)-1) { 13697db96d56Sopenharmony_ci m_obj->data = NULL; 13707db96d56Sopenharmony_ci Py_DECREF(m_obj); 13717db96d56Sopenharmony_ci PyErr_SetFromErrno(PyExc_OSError); 13727db96d56Sopenharmony_ci return NULL; 13737db96d56Sopenharmony_ci } 13747db96d56Sopenharmony_ci m_obj->access = (access_mode)access; 13757db96d56Sopenharmony_ci return (PyObject *)m_obj; 13767db96d56Sopenharmony_ci} 13777db96d56Sopenharmony_ci#endif /* UNIX */ 13787db96d56Sopenharmony_ci 13797db96d56Sopenharmony_ci#ifdef MS_WINDOWS 13807db96d56Sopenharmony_ci 13817db96d56Sopenharmony_ci/* A note on sizes and offsets: while the actual map size must hold in a 13827db96d56Sopenharmony_ci Py_ssize_t, both the total file size and the start offset can be longer 13837db96d56Sopenharmony_ci than a Py_ssize_t, so we use long long which is always 64-bit. 13847db96d56Sopenharmony_ci*/ 13857db96d56Sopenharmony_ci 13867db96d56Sopenharmony_cistatic PyObject * 13877db96d56Sopenharmony_cinew_mmap_object(PyTypeObject *type, PyObject *args, PyObject *kwdict) 13887db96d56Sopenharmony_ci{ 13897db96d56Sopenharmony_ci mmap_object *m_obj; 13907db96d56Sopenharmony_ci Py_ssize_t map_size; 13917db96d56Sopenharmony_ci long long offset = 0, size; 13927db96d56Sopenharmony_ci DWORD off_hi; /* upper 32 bits of offset */ 13937db96d56Sopenharmony_ci DWORD off_lo; /* lower 32 bits of offset */ 13947db96d56Sopenharmony_ci DWORD size_hi; /* upper 32 bits of size */ 13957db96d56Sopenharmony_ci DWORD size_lo; /* lower 32 bits of size */ 13967db96d56Sopenharmony_ci const char *tagname = ""; 13977db96d56Sopenharmony_ci DWORD dwErr = 0; 13987db96d56Sopenharmony_ci int fileno; 13997db96d56Sopenharmony_ci HANDLE fh = 0; 14007db96d56Sopenharmony_ci int access = (access_mode)ACCESS_DEFAULT; 14017db96d56Sopenharmony_ci DWORD flProtect, dwDesiredAccess; 14027db96d56Sopenharmony_ci static char *keywords[] = { "fileno", "length", 14037db96d56Sopenharmony_ci "tagname", 14047db96d56Sopenharmony_ci "access", "offset", NULL }; 14057db96d56Sopenharmony_ci 14067db96d56Sopenharmony_ci if (!PyArg_ParseTupleAndKeywords(args, kwdict, "in|ziL", keywords, 14077db96d56Sopenharmony_ci &fileno, &map_size, 14087db96d56Sopenharmony_ci &tagname, &access, &offset)) { 14097db96d56Sopenharmony_ci return NULL; 14107db96d56Sopenharmony_ci } 14117db96d56Sopenharmony_ci 14127db96d56Sopenharmony_ci if (PySys_Audit("mmap.__new__", "iniL", 14137db96d56Sopenharmony_ci fileno, map_size, access, offset) < 0) { 14147db96d56Sopenharmony_ci return NULL; 14157db96d56Sopenharmony_ci } 14167db96d56Sopenharmony_ci 14177db96d56Sopenharmony_ci switch((access_mode)access) { 14187db96d56Sopenharmony_ci case ACCESS_READ: 14197db96d56Sopenharmony_ci flProtect = PAGE_READONLY; 14207db96d56Sopenharmony_ci dwDesiredAccess = FILE_MAP_READ; 14217db96d56Sopenharmony_ci break; 14227db96d56Sopenharmony_ci case ACCESS_DEFAULT: case ACCESS_WRITE: 14237db96d56Sopenharmony_ci flProtect = PAGE_READWRITE; 14247db96d56Sopenharmony_ci dwDesiredAccess = FILE_MAP_WRITE; 14257db96d56Sopenharmony_ci break; 14267db96d56Sopenharmony_ci case ACCESS_COPY: 14277db96d56Sopenharmony_ci flProtect = PAGE_WRITECOPY; 14287db96d56Sopenharmony_ci dwDesiredAccess = FILE_MAP_COPY; 14297db96d56Sopenharmony_ci break; 14307db96d56Sopenharmony_ci default: 14317db96d56Sopenharmony_ci return PyErr_Format(PyExc_ValueError, 14327db96d56Sopenharmony_ci "mmap invalid access parameter."); 14337db96d56Sopenharmony_ci } 14347db96d56Sopenharmony_ci 14357db96d56Sopenharmony_ci if (map_size < 0) { 14367db96d56Sopenharmony_ci PyErr_SetString(PyExc_OverflowError, 14377db96d56Sopenharmony_ci "memory mapped length must be positive"); 14387db96d56Sopenharmony_ci return NULL; 14397db96d56Sopenharmony_ci } 14407db96d56Sopenharmony_ci if (offset < 0) { 14417db96d56Sopenharmony_ci PyErr_SetString(PyExc_OverflowError, 14427db96d56Sopenharmony_ci "memory mapped offset must be positive"); 14437db96d56Sopenharmony_ci return NULL; 14447db96d56Sopenharmony_ci } 14457db96d56Sopenharmony_ci 14467db96d56Sopenharmony_ci /* assume -1 and 0 both mean invalid filedescriptor 14477db96d56Sopenharmony_ci to 'anonymously' map memory. 14487db96d56Sopenharmony_ci XXX: fileno == 0 is a valid fd, but was accepted prior to 2.5. 14497db96d56Sopenharmony_ci XXX: Should this code be added? 14507db96d56Sopenharmony_ci if (fileno == 0) 14517db96d56Sopenharmony_ci PyErr_WarnEx(PyExc_DeprecationWarning, 14527db96d56Sopenharmony_ci "don't use 0 for anonymous memory", 14537db96d56Sopenharmony_ci 1); 14547db96d56Sopenharmony_ci */ 14557db96d56Sopenharmony_ci if (fileno != -1 && fileno != 0) { 14567db96d56Sopenharmony_ci /* Ensure that fileno is within the CRT's valid range */ 14577db96d56Sopenharmony_ci fh = _Py_get_osfhandle(fileno); 14587db96d56Sopenharmony_ci if (fh == INVALID_HANDLE_VALUE) 14597db96d56Sopenharmony_ci return NULL; 14607db96d56Sopenharmony_ci 14617db96d56Sopenharmony_ci /* Win9x appears to need us seeked to zero */ 14627db96d56Sopenharmony_ci lseek(fileno, 0, SEEK_SET); 14637db96d56Sopenharmony_ci } 14647db96d56Sopenharmony_ci 14657db96d56Sopenharmony_ci m_obj = (mmap_object *)type->tp_alloc(type, 0); 14667db96d56Sopenharmony_ci if (m_obj == NULL) 14677db96d56Sopenharmony_ci return NULL; 14687db96d56Sopenharmony_ci /* Set every field to an invalid marker, so we can safely 14697db96d56Sopenharmony_ci destruct the object in the face of failure */ 14707db96d56Sopenharmony_ci m_obj->data = NULL; 14717db96d56Sopenharmony_ci m_obj->file_handle = INVALID_HANDLE_VALUE; 14727db96d56Sopenharmony_ci m_obj->map_handle = NULL; 14737db96d56Sopenharmony_ci m_obj->tagname = NULL; 14747db96d56Sopenharmony_ci m_obj->offset = offset; 14757db96d56Sopenharmony_ci 14767db96d56Sopenharmony_ci if (fh) { 14777db96d56Sopenharmony_ci /* It is necessary to duplicate the handle, so the 14787db96d56Sopenharmony_ci Python code can close it on us */ 14797db96d56Sopenharmony_ci if (!DuplicateHandle( 14807db96d56Sopenharmony_ci GetCurrentProcess(), /* source process handle */ 14817db96d56Sopenharmony_ci fh, /* handle to be duplicated */ 14827db96d56Sopenharmony_ci GetCurrentProcess(), /* target proc handle */ 14837db96d56Sopenharmony_ci (LPHANDLE)&m_obj->file_handle, /* result */ 14847db96d56Sopenharmony_ci 0, /* access - ignored due to options value */ 14857db96d56Sopenharmony_ci FALSE, /* inherited by child processes? */ 14867db96d56Sopenharmony_ci DUPLICATE_SAME_ACCESS)) { /* options */ 14877db96d56Sopenharmony_ci dwErr = GetLastError(); 14887db96d56Sopenharmony_ci Py_DECREF(m_obj); 14897db96d56Sopenharmony_ci PyErr_SetFromWindowsErr(dwErr); 14907db96d56Sopenharmony_ci return NULL; 14917db96d56Sopenharmony_ci } 14927db96d56Sopenharmony_ci if (!map_size) { 14937db96d56Sopenharmony_ci DWORD low,high; 14947db96d56Sopenharmony_ci low = GetFileSize(fh, &high); 14957db96d56Sopenharmony_ci /* low might just happen to have the value INVALID_FILE_SIZE; 14967db96d56Sopenharmony_ci so we need to check the last error also. */ 14977db96d56Sopenharmony_ci if (low == INVALID_FILE_SIZE && 14987db96d56Sopenharmony_ci (dwErr = GetLastError()) != NO_ERROR) { 14997db96d56Sopenharmony_ci Py_DECREF(m_obj); 15007db96d56Sopenharmony_ci return PyErr_SetFromWindowsErr(dwErr); 15017db96d56Sopenharmony_ci } 15027db96d56Sopenharmony_ci 15037db96d56Sopenharmony_ci size = (((long long) high) << 32) + low; 15047db96d56Sopenharmony_ci if (size == 0) { 15057db96d56Sopenharmony_ci PyErr_SetString(PyExc_ValueError, 15067db96d56Sopenharmony_ci "cannot mmap an empty file"); 15077db96d56Sopenharmony_ci Py_DECREF(m_obj); 15087db96d56Sopenharmony_ci return NULL; 15097db96d56Sopenharmony_ci } 15107db96d56Sopenharmony_ci if (offset >= size) { 15117db96d56Sopenharmony_ci PyErr_SetString(PyExc_ValueError, 15127db96d56Sopenharmony_ci "mmap offset is greater than file size"); 15137db96d56Sopenharmony_ci Py_DECREF(m_obj); 15147db96d56Sopenharmony_ci return NULL; 15157db96d56Sopenharmony_ci } 15167db96d56Sopenharmony_ci if (size - offset > PY_SSIZE_T_MAX) { 15177db96d56Sopenharmony_ci PyErr_SetString(PyExc_ValueError, 15187db96d56Sopenharmony_ci "mmap length is too large"); 15197db96d56Sopenharmony_ci Py_DECREF(m_obj); 15207db96d56Sopenharmony_ci return NULL; 15217db96d56Sopenharmony_ci } 15227db96d56Sopenharmony_ci m_obj->size = (Py_ssize_t) (size - offset); 15237db96d56Sopenharmony_ci } else { 15247db96d56Sopenharmony_ci m_obj->size = map_size; 15257db96d56Sopenharmony_ci size = offset + map_size; 15267db96d56Sopenharmony_ci } 15277db96d56Sopenharmony_ci } 15287db96d56Sopenharmony_ci else { 15297db96d56Sopenharmony_ci m_obj->size = map_size; 15307db96d56Sopenharmony_ci size = offset + map_size; 15317db96d56Sopenharmony_ci } 15327db96d56Sopenharmony_ci 15337db96d56Sopenharmony_ci /* set the initial position */ 15347db96d56Sopenharmony_ci m_obj->pos = (size_t) 0; 15357db96d56Sopenharmony_ci 15367db96d56Sopenharmony_ci m_obj->weakreflist = NULL; 15377db96d56Sopenharmony_ci m_obj->exports = 0; 15387db96d56Sopenharmony_ci /* set the tag name */ 15397db96d56Sopenharmony_ci if (tagname != NULL && *tagname != '\0') { 15407db96d56Sopenharmony_ci m_obj->tagname = PyMem_Malloc(strlen(tagname)+1); 15417db96d56Sopenharmony_ci if (m_obj->tagname == NULL) { 15427db96d56Sopenharmony_ci PyErr_NoMemory(); 15437db96d56Sopenharmony_ci Py_DECREF(m_obj); 15447db96d56Sopenharmony_ci return NULL; 15457db96d56Sopenharmony_ci } 15467db96d56Sopenharmony_ci strcpy(m_obj->tagname, tagname); 15477db96d56Sopenharmony_ci } 15487db96d56Sopenharmony_ci else 15497db96d56Sopenharmony_ci m_obj->tagname = NULL; 15507db96d56Sopenharmony_ci 15517db96d56Sopenharmony_ci m_obj->access = (access_mode)access; 15527db96d56Sopenharmony_ci size_hi = (DWORD)(size >> 32); 15537db96d56Sopenharmony_ci size_lo = (DWORD)(size & 0xFFFFFFFF); 15547db96d56Sopenharmony_ci off_hi = (DWORD)(offset >> 32); 15557db96d56Sopenharmony_ci off_lo = (DWORD)(offset & 0xFFFFFFFF); 15567db96d56Sopenharmony_ci /* For files, it would be sufficient to pass 0 as size. 15577db96d56Sopenharmony_ci For anonymous maps, we have to pass the size explicitly. */ 15587db96d56Sopenharmony_ci m_obj->map_handle = CreateFileMapping(m_obj->file_handle, 15597db96d56Sopenharmony_ci NULL, 15607db96d56Sopenharmony_ci flProtect, 15617db96d56Sopenharmony_ci size_hi, 15627db96d56Sopenharmony_ci size_lo, 15637db96d56Sopenharmony_ci m_obj->tagname); 15647db96d56Sopenharmony_ci if (m_obj->map_handle != NULL) { 15657db96d56Sopenharmony_ci m_obj->data = (char *) MapViewOfFile(m_obj->map_handle, 15667db96d56Sopenharmony_ci dwDesiredAccess, 15677db96d56Sopenharmony_ci off_hi, 15687db96d56Sopenharmony_ci off_lo, 15697db96d56Sopenharmony_ci m_obj->size); 15707db96d56Sopenharmony_ci if (m_obj->data != NULL) 15717db96d56Sopenharmony_ci return (PyObject *)m_obj; 15727db96d56Sopenharmony_ci else { 15737db96d56Sopenharmony_ci dwErr = GetLastError(); 15747db96d56Sopenharmony_ci CloseHandle(m_obj->map_handle); 15757db96d56Sopenharmony_ci m_obj->map_handle = NULL; 15767db96d56Sopenharmony_ci } 15777db96d56Sopenharmony_ci } else 15787db96d56Sopenharmony_ci dwErr = GetLastError(); 15797db96d56Sopenharmony_ci Py_DECREF(m_obj); 15807db96d56Sopenharmony_ci PyErr_SetFromWindowsErr(dwErr); 15817db96d56Sopenharmony_ci return NULL; 15827db96d56Sopenharmony_ci} 15837db96d56Sopenharmony_ci#endif /* MS_WINDOWS */ 15847db96d56Sopenharmony_ci 15857db96d56Sopenharmony_cistatic int 15867db96d56Sopenharmony_cimmap_traverse(PyObject *module, visitproc visit, void *arg) 15877db96d56Sopenharmony_ci{ 15887db96d56Sopenharmony_ci mmap_state *state = get_mmap_state(module); 15897db96d56Sopenharmony_ci Py_VISIT(state->mmap_object_type); 15907db96d56Sopenharmony_ci return 0; 15917db96d56Sopenharmony_ci} 15927db96d56Sopenharmony_ci 15937db96d56Sopenharmony_cistatic int 15947db96d56Sopenharmony_cimmap_clear(PyObject *module) 15957db96d56Sopenharmony_ci{ 15967db96d56Sopenharmony_ci mmap_state *state = get_mmap_state(module); 15977db96d56Sopenharmony_ci Py_CLEAR(state->mmap_object_type); 15987db96d56Sopenharmony_ci return 0; 15997db96d56Sopenharmony_ci} 16007db96d56Sopenharmony_ci 16017db96d56Sopenharmony_cistatic void 16027db96d56Sopenharmony_cimmap_free(void *module) 16037db96d56Sopenharmony_ci{ 16047db96d56Sopenharmony_ci mmap_clear((PyObject *)module); 16057db96d56Sopenharmony_ci} 16067db96d56Sopenharmony_ci 16077db96d56Sopenharmony_cistatic int 16087db96d56Sopenharmony_cimmap_exec(PyObject *module) 16097db96d56Sopenharmony_ci{ 16107db96d56Sopenharmony_ci mmap_state *state = get_mmap_state(module); 16117db96d56Sopenharmony_ci 16127db96d56Sopenharmony_ci Py_INCREF(PyExc_OSError); 16137db96d56Sopenharmony_ci if (PyModule_AddObject(module, "error", PyExc_OSError) < 0) { 16147db96d56Sopenharmony_ci Py_DECREF(PyExc_OSError); 16157db96d56Sopenharmony_ci return -1; 16167db96d56Sopenharmony_ci } 16177db96d56Sopenharmony_ci 16187db96d56Sopenharmony_ci state->mmap_object_type = (PyTypeObject *)PyType_FromModuleAndSpec(module, 16197db96d56Sopenharmony_ci &mmap_object_spec, 16207db96d56Sopenharmony_ci NULL); 16217db96d56Sopenharmony_ci if (state->mmap_object_type == NULL) { 16227db96d56Sopenharmony_ci return -1; 16237db96d56Sopenharmony_ci } 16247db96d56Sopenharmony_ci if (PyModule_AddType(module, state->mmap_object_type) < 0) { 16257db96d56Sopenharmony_ci return -1; 16267db96d56Sopenharmony_ci } 16277db96d56Sopenharmony_ci 16287db96d56Sopenharmony_ci#define ADD_INT_MACRO(module, constant) \ 16297db96d56Sopenharmony_ci do { \ 16307db96d56Sopenharmony_ci if (PyModule_AddIntConstant(module, #constant, constant) < 0) { \ 16317db96d56Sopenharmony_ci return -1; \ 16327db96d56Sopenharmony_ci } \ 16337db96d56Sopenharmony_ci } while (0) 16347db96d56Sopenharmony_ci 16357db96d56Sopenharmony_ci#ifdef PROT_EXEC 16367db96d56Sopenharmony_ci ADD_INT_MACRO(module, PROT_EXEC); 16377db96d56Sopenharmony_ci#endif 16387db96d56Sopenharmony_ci#ifdef PROT_READ 16397db96d56Sopenharmony_ci ADD_INT_MACRO(module, PROT_READ); 16407db96d56Sopenharmony_ci#endif 16417db96d56Sopenharmony_ci#ifdef PROT_WRITE 16427db96d56Sopenharmony_ci ADD_INT_MACRO(module, PROT_WRITE); 16437db96d56Sopenharmony_ci#endif 16447db96d56Sopenharmony_ci 16457db96d56Sopenharmony_ci#ifdef MAP_SHARED 16467db96d56Sopenharmony_ci ADD_INT_MACRO(module, MAP_SHARED); 16477db96d56Sopenharmony_ci#endif 16487db96d56Sopenharmony_ci#ifdef MAP_PRIVATE 16497db96d56Sopenharmony_ci ADD_INT_MACRO(module, MAP_PRIVATE); 16507db96d56Sopenharmony_ci#endif 16517db96d56Sopenharmony_ci#ifdef MAP_DENYWRITE 16527db96d56Sopenharmony_ci ADD_INT_MACRO(module, MAP_DENYWRITE); 16537db96d56Sopenharmony_ci#endif 16547db96d56Sopenharmony_ci#ifdef MAP_EXECUTABLE 16557db96d56Sopenharmony_ci ADD_INT_MACRO(module, MAP_EXECUTABLE); 16567db96d56Sopenharmony_ci#endif 16577db96d56Sopenharmony_ci#ifdef MAP_ANONYMOUS 16587db96d56Sopenharmony_ci if (PyModule_AddIntConstant(module, "MAP_ANON", MAP_ANONYMOUS) < 0 ) { 16597db96d56Sopenharmony_ci return -1; 16607db96d56Sopenharmony_ci } 16617db96d56Sopenharmony_ci ADD_INT_MACRO(module, MAP_ANONYMOUS); 16627db96d56Sopenharmony_ci#endif 16637db96d56Sopenharmony_ci#ifdef MAP_POPULATE 16647db96d56Sopenharmony_ci ADD_INT_MACRO(module, MAP_POPULATE); 16657db96d56Sopenharmony_ci#endif 16667db96d56Sopenharmony_ci#ifdef MAP_STACK 16677db96d56Sopenharmony_ci // Mostly a no-op on Linux and NetBSD, but useful on OpenBSD 16687db96d56Sopenharmony_ci // for stack usage (even on x86 arch) 16697db96d56Sopenharmony_ci ADD_INT_MACRO(module, MAP_STACK); 16707db96d56Sopenharmony_ci#endif 16717db96d56Sopenharmony_ci if (PyModule_AddIntConstant(module, "PAGESIZE", (long)my_getpagesize()) < 0 ) { 16727db96d56Sopenharmony_ci return -1; 16737db96d56Sopenharmony_ci } 16747db96d56Sopenharmony_ci 16757db96d56Sopenharmony_ci if (PyModule_AddIntConstant(module, "ALLOCATIONGRANULARITY", (long)my_getallocationgranularity()) < 0 ) { 16767db96d56Sopenharmony_ci return -1; 16777db96d56Sopenharmony_ci } 16787db96d56Sopenharmony_ci 16797db96d56Sopenharmony_ci ADD_INT_MACRO(module, ACCESS_DEFAULT); 16807db96d56Sopenharmony_ci ADD_INT_MACRO(module, ACCESS_READ); 16817db96d56Sopenharmony_ci ADD_INT_MACRO(module, ACCESS_WRITE); 16827db96d56Sopenharmony_ci ADD_INT_MACRO(module, ACCESS_COPY); 16837db96d56Sopenharmony_ci 16847db96d56Sopenharmony_ci#ifdef HAVE_MADVISE 16857db96d56Sopenharmony_ci // Conventional advice values 16867db96d56Sopenharmony_ci#ifdef MADV_NORMAL 16877db96d56Sopenharmony_ci ADD_INT_MACRO(module, MADV_NORMAL); 16887db96d56Sopenharmony_ci#endif 16897db96d56Sopenharmony_ci#ifdef MADV_RANDOM 16907db96d56Sopenharmony_ci ADD_INT_MACRO(module, MADV_RANDOM); 16917db96d56Sopenharmony_ci#endif 16927db96d56Sopenharmony_ci#ifdef MADV_SEQUENTIAL 16937db96d56Sopenharmony_ci ADD_INT_MACRO(module, MADV_SEQUENTIAL); 16947db96d56Sopenharmony_ci#endif 16957db96d56Sopenharmony_ci#ifdef MADV_WILLNEED 16967db96d56Sopenharmony_ci ADD_INT_MACRO(module, MADV_WILLNEED); 16977db96d56Sopenharmony_ci#endif 16987db96d56Sopenharmony_ci#ifdef MADV_DONTNEED 16997db96d56Sopenharmony_ci ADD_INT_MACRO(module, MADV_DONTNEED); 17007db96d56Sopenharmony_ci#endif 17017db96d56Sopenharmony_ci 17027db96d56Sopenharmony_ci // Linux-specific advice values 17037db96d56Sopenharmony_ci#ifdef MADV_REMOVE 17047db96d56Sopenharmony_ci ADD_INT_MACRO(module, MADV_REMOVE); 17057db96d56Sopenharmony_ci#endif 17067db96d56Sopenharmony_ci#ifdef MADV_DONTFORK 17077db96d56Sopenharmony_ci ADD_INT_MACRO(module, MADV_DONTFORK); 17087db96d56Sopenharmony_ci#endif 17097db96d56Sopenharmony_ci#ifdef MADV_DOFORK 17107db96d56Sopenharmony_ci ADD_INT_MACRO(module, MADV_DOFORK); 17117db96d56Sopenharmony_ci#endif 17127db96d56Sopenharmony_ci#ifdef MADV_HWPOISON 17137db96d56Sopenharmony_ci ADD_INT_MACRO(module, MADV_HWPOISON); 17147db96d56Sopenharmony_ci#endif 17157db96d56Sopenharmony_ci#ifdef MADV_MERGEABLE 17167db96d56Sopenharmony_ci ADD_INT_MACRO(module, MADV_MERGEABLE); 17177db96d56Sopenharmony_ci#endif 17187db96d56Sopenharmony_ci#ifdef MADV_UNMERGEABLE 17197db96d56Sopenharmony_ci ADD_INT_MACRO(module, MADV_UNMERGEABLE); 17207db96d56Sopenharmony_ci#endif 17217db96d56Sopenharmony_ci#ifdef MADV_SOFT_OFFLINE 17227db96d56Sopenharmony_ci ADD_INT_MACRO(module, MADV_SOFT_OFFLINE); 17237db96d56Sopenharmony_ci#endif 17247db96d56Sopenharmony_ci#ifdef MADV_HUGEPAGE 17257db96d56Sopenharmony_ci ADD_INT_MACRO(module, MADV_HUGEPAGE); 17267db96d56Sopenharmony_ci#endif 17277db96d56Sopenharmony_ci#ifdef MADV_NOHUGEPAGE 17287db96d56Sopenharmony_ci ADD_INT_MACRO(module, MADV_NOHUGEPAGE); 17297db96d56Sopenharmony_ci#endif 17307db96d56Sopenharmony_ci#ifdef MADV_DONTDUMP 17317db96d56Sopenharmony_ci ADD_INT_MACRO(module, MADV_DONTDUMP); 17327db96d56Sopenharmony_ci#endif 17337db96d56Sopenharmony_ci#ifdef MADV_DODUMP 17347db96d56Sopenharmony_ci ADD_INT_MACRO(module, MADV_DODUMP); 17357db96d56Sopenharmony_ci#endif 17367db96d56Sopenharmony_ci#ifdef MADV_FREE // (Also present on FreeBSD and macOS.) 17377db96d56Sopenharmony_ci ADD_INT_MACRO(module, MADV_FREE); 17387db96d56Sopenharmony_ci#endif 17397db96d56Sopenharmony_ci 17407db96d56Sopenharmony_ci // FreeBSD-specific 17417db96d56Sopenharmony_ci#ifdef MADV_NOSYNC 17427db96d56Sopenharmony_ci ADD_INT_MACRO(module, MADV_NOSYNC); 17437db96d56Sopenharmony_ci#endif 17447db96d56Sopenharmony_ci#ifdef MADV_AUTOSYNC 17457db96d56Sopenharmony_ci ADD_INT_MACRO(module, MADV_AUTOSYNC); 17467db96d56Sopenharmony_ci#endif 17477db96d56Sopenharmony_ci#ifdef MADV_NOCORE 17487db96d56Sopenharmony_ci ADD_INT_MACRO(module, MADV_NOCORE); 17497db96d56Sopenharmony_ci#endif 17507db96d56Sopenharmony_ci#ifdef MADV_CORE 17517db96d56Sopenharmony_ci ADD_INT_MACRO(module, MADV_CORE); 17527db96d56Sopenharmony_ci#endif 17537db96d56Sopenharmony_ci#ifdef MADV_PROTECT 17547db96d56Sopenharmony_ci ADD_INT_MACRO(module, MADV_PROTECT); 17557db96d56Sopenharmony_ci#endif 17567db96d56Sopenharmony_ci 17577db96d56Sopenharmony_ci // Darwin-specific 17587db96d56Sopenharmony_ci#ifdef MADV_FREE_REUSABLE // (As MADV_FREE but reclaims more faithful for task_info/Activity Monitor...) 17597db96d56Sopenharmony_ci ADD_INT_MACRO(module, MADV_FREE_REUSABLE); 17607db96d56Sopenharmony_ci#endif 17617db96d56Sopenharmony_ci#ifdef MADV_FREE_REUSE // (Reuse pages previously tagged as reusable) 17627db96d56Sopenharmony_ci ADD_INT_MACRO(module, MADV_FREE_REUSE); 17637db96d56Sopenharmony_ci#endif 17647db96d56Sopenharmony_ci#endif // HAVE_MADVISE 17657db96d56Sopenharmony_ci return 0; 17667db96d56Sopenharmony_ci} 17677db96d56Sopenharmony_ci 17687db96d56Sopenharmony_cistatic PyModuleDef_Slot mmap_slots[] = { 17697db96d56Sopenharmony_ci {Py_mod_exec, mmap_exec}, 17707db96d56Sopenharmony_ci {0, NULL} 17717db96d56Sopenharmony_ci}; 17727db96d56Sopenharmony_ci 17737db96d56Sopenharmony_cistatic struct PyModuleDef mmapmodule = { 17747db96d56Sopenharmony_ci PyModuleDef_HEAD_INIT, 17757db96d56Sopenharmony_ci .m_name = "mmap", 17767db96d56Sopenharmony_ci .m_size = sizeof(mmap_state), 17777db96d56Sopenharmony_ci .m_slots = mmap_slots, 17787db96d56Sopenharmony_ci .m_traverse = mmap_traverse, 17797db96d56Sopenharmony_ci .m_clear = mmap_clear, 17807db96d56Sopenharmony_ci .m_free = mmap_free, 17817db96d56Sopenharmony_ci}; 17827db96d56Sopenharmony_ci 17837db96d56Sopenharmony_ciPyMODINIT_FUNC 17847db96d56Sopenharmony_ciPyInit_mmap(void) 17857db96d56Sopenharmony_ci{ 17867db96d56Sopenharmony_ci return PyModuleDef_Init(&mmapmodule); 17877db96d56Sopenharmony_ci} 1788