From 3905c6f00d9d11e01d6e211565d5ed58a59fc2d8 Mon Sep 17 00:00:00 2001 From: Simon Sasburg Date: Mon, 21 Jul 2014 19:28:43 +0100 Subject: Add QFileDevice::MemoryMapFlags::MapPrivateOption flag. Passing this flag to QFileDevice::map() will allow writes to the mapped memory without modifying the file that was mapped. These writes will be lost when the memory is unmapped. Change-Id: I7d46b044fc370585de8c06fdb4059f1f1be12d7d Reviewed-by: Thiago Macieira Reviewed-by: Oswald Buddenhagen --- src/corelib/io/qfiledevice.cpp | 11 +++++++++++ src/corelib/io/qfiledevice.h | 4 +++- src/corelib/io/qfsfileengine_unix.cpp | 8 +++++++- src/corelib/io/qfsfileengine_win.cpp | 20 +++++++++++++++----- 4 files changed, 36 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/corelib/io/qfiledevice.cpp b/src/corelib/io/qfiledevice.cpp index f7e58a7bed..33cb6037f5 100644 --- a/src/corelib/io/qfiledevice.cpp +++ b/src/corelib/io/qfiledevice.cpp @@ -680,6 +680,13 @@ bool QFileDevice::setPermissions(Permissions permissions) function. \value NoOptions No options. + \value MapPrivateOption The mapped memory will be private, so any + modifications will not be visible to other processes and will not + be written to disk. Any such modifications will be lost when the + memory is unmapped. It is unspecified whether modifications made + to the file made after the mapping is created will be visible through + the mapped memory. This flag is not supported on Windows CE. + This enum value was introduced in Qt 5.4. */ /*! @@ -689,6 +696,10 @@ bool QFileDevice::setPermissions(Permissions permissions) or a new file is opened with this object, any maps that have not been unmapped will automatically be unmapped. + The mapping will have the same open mode as the file (read and/or write), + except when using MapPrivateOption, in which case it is always possible + to write to the mapped memory. + Any mapping options can be passed through \a flags. Returns a pointer to the memory or 0 if there is an error. diff --git a/src/corelib/io/qfiledevice.h b/src/corelib/io/qfiledevice.h index fc2779086a..4b13ffe589 100644 --- a/src/corelib/io/qfiledevice.h +++ b/src/corelib/io/qfiledevice.h @@ -112,8 +112,10 @@ public: virtual Permissions permissions() const; virtual bool setPermissions(Permissions permissionSpec); + // ### Qt 6: rename to MemoryMapFlag & make it a QFlags enum MemoryMapFlags { - NoOptions = 0 + NoOptions = 0, + MapPrivateOption = 0x0001 }; uchar *map(qint64 offset, qint64 size, MemoryMapFlags flags = NoOptions); diff --git a/src/corelib/io/qfsfileengine_unix.cpp b/src/corelib/io/qfsfileengine_unix.cpp index 064a1a511f..f9c6c8ab98 100644 --- a/src/corelib/io/qfsfileengine_unix.cpp +++ b/src/corelib/io/qfsfileengine_unix.cpp @@ -713,6 +713,12 @@ uchar *QFSFileEnginePrivate::map(qint64 offset, qint64 size, QFile::MemoryMapFla if (openMode & QIODevice::ReadOnly) access |= PROT_READ; if (openMode & QIODevice::WriteOnly) access |= PROT_WRITE; + int sharemode = MAP_SHARED; + if (flags & QFileDevice::MapPrivateOption) { + sharemode = MAP_PRIVATE; + access |= PROT_WRITE; + } + #if defined(Q_OS_INTEGRITY) int pageSize = sysconf(_SC_PAGESIZE); #else @@ -730,7 +736,7 @@ uchar *QFSFileEnginePrivate::map(qint64 offset, qint64 size, QFile::MemoryMapFla realOffset &= ~(QT_OFF_T(pageSize - 1)); void *mapAddress = QT_MMAP((void*)0, realSize, - access, MAP_SHARED, nativeHandle(), realOffset); + access, sharemode, nativeHandle(), realOffset); if (MAP_FAILED != mapAddress) { uchar *address = extra + static_cast(mapAddress); maps[address] = QPair(extra, realSize); diff --git a/src/corelib/io/qfsfileengine_win.cpp b/src/corelib/io/qfsfileengine_win.cpp index fb4107b95d..81aed5f7b4 100644 --- a/src/corelib/io/qfsfileengine_win.cpp +++ b/src/corelib/io/qfsfileengine_win.cpp @@ -965,6 +965,21 @@ uchar *QFSFileEnginePrivate::map(qint64 offset, qint64 size, return 0; } + // check/setup args to map + DWORD access = 0; + if (flags & QFileDevice::MapPrivateOption) { +#ifdef FILE_MAP_COPY + access = FILE_MAP_COPY; +#else + q->setError(QFile::UnspecifiedError, "MapPrivateOption unsupported"); + return 0; +#endif + } else if (openMode & QIODevice::WriteOnly) { + access = FILE_MAP_WRITE; + } else if (openMode & QIODevice::ReadOnly) { + access = FILE_MAP_READ; + } + if (mapHandle == NULL) { // get handle to the file HANDLE handle = fileHandle; @@ -1011,11 +1026,6 @@ uchar *QFSFileEnginePrivate::map(qint64 offset, qint64 size, } } - // setup args to map - DWORD access = 0; - if (openMode & QIODevice::ReadOnly) access = FILE_MAP_READ; - if (openMode & QIODevice::WriteOnly) access = FILE_MAP_WRITE; - DWORD offsetHi = offset >> 32; DWORD offsetLo = offset & Q_UINT64_C(0xffffffff); SYSTEM_INFO sysinfo; -- cgit v1.2.3