From 484770255f421d71954df4511e3541d2d4654d4e Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Fri, 22 Oct 2010 16:00:24 +0100 Subject: Re-enable emulated QFile::map on symbian Memory mapping of RFile handles is not supported in current symbian OS versions. However the "open C" libraries provide an emulated mmap() implementation which was used by QFile::map in Qt 4.6 release. To avoid breaking applications which rely on this function, QFile::map will now open the file with open C as well in order to use that handle to call mmap(). When symbian implements a file mapping API, we can switch the implementation to use that for RFile handles. Reviewed-By: joao --- src/corelib/io/qfile.cpp | 2 ++ src/corelib/io/qfsfileengine.cpp | 12 +++++++++ src/corelib/io/qfsfileengine_p.h | 2 ++ src/corelib/io/qfsfileengine_unix.cpp | 47 ++++++++++++++++------------------- tests/auto/qfile/tst_qfile.cpp | 12 --------- 5 files changed, 37 insertions(+), 38 deletions(-) diff --git a/src/corelib/io/qfile.cpp b/src/corelib/io/qfile.cpp index a0bc68e..f0ca11b 100644 --- a/src/corelib/io/qfile.cpp +++ b/src/corelib/io/qfile.cpp @@ -48,6 +48,7 @@ #include "qfileinfo.h" #include "private/qiodevice_p.h" #include "private/qfile_p.h" +#include "private/qsystemerror_p.h" #if defined(QT_BUILD_CORE_LIB) # include "qcoreapplication.h" #endif @@ -1223,6 +1224,7 @@ bool QFile::unmap(uchar *address) d->setError(d->fileEngine->error(), d->fileEngine->errorString()); return success; } + d->setError(PermissionsError, QSystemError(EACCES, QSystemError::StandardLibraryError).toString()); return false; } diff --git a/src/corelib/io/qfsfileengine.cpp b/src/corelib/io/qfsfileengine.cpp index 5491caf..ae301f7 100644 --- a/src/corelib/io/qfsfileengine.cpp +++ b/src/corelib/io/qfsfileengine.cpp @@ -120,6 +120,9 @@ void QFSFileEnginePrivate::init() openMode = QIODevice::NotOpen; fd = -1; fh = 0; +#ifdef Q_OS_SYMBIAN + fileHandleForMaps = -1; +#endif lastIOCommand = IOFlushCommand; lastFlushFailed = false; closeFileHandle = false; @@ -355,6 +358,7 @@ bool QFSFileEnginePrivate::closeFdFh() if (fd == -1 && !fh #ifdef Q_OS_SYMBIAN && !symbianFile.SubSessionHandle() + && fileHandleForMaps == -1 #endif ) return false; @@ -364,6 +368,14 @@ bool QFSFileEnginePrivate::closeFdFh() bool closed = true; tried_stat = 0; +#ifdef Q_OS_SYMBIAN + // Map handle is always owned by us so always close it + if (fileHandleForMaps >= 0) { + QT_CLOSE(fileHandleForMaps); + fileHandleForMaps = -1; + } +#endif + // Close the file if we created the handle. if (closeFileHandle) { int ret; diff --git a/src/corelib/io/qfsfileengine_p.h b/src/corelib/io/qfsfileengine_p.h index 715b46f..7c088b8 100644 --- a/src/corelib/io/qfsfileengine_p.h +++ b/src/corelib/io/qfsfileengine_p.h @@ -139,6 +139,8 @@ public: */ TInt symbianFilePos; #endif + mutable int fileHandleForMaps; + int getMapHandle(); #endif #ifdef Q_WS_WIN diff --git a/src/corelib/io/qfsfileengine_unix.cpp b/src/corelib/io/qfsfileengine_unix.cpp index 28e0677..035e78f 100644 --- a/src/corelib/io/qfsfileengine_unix.cpp +++ b/src/corelib/io/qfsfileengine_unix.cpp @@ -85,6 +85,7 @@ static bool isRelativePathSymbian(const QString& fileName) #endif +#ifndef Q_OS_SYMBIAN /*! \internal @@ -124,6 +125,7 @@ static inline QByteArray openModeToFopenMode(QIODevice::OpenMode flags, const QF return mode; } +#endif /*! \internal @@ -153,6 +155,7 @@ static inline int openModeToOpenFlags(QIODevice::OpenMode mode) return oflags; } +#ifndef Q_OS_SYMBIAN /*! \internal @@ -163,6 +166,7 @@ static inline bool setCloseOnExec(int fd) { return fd != -1 && fcntl(fd, F_SETFD, FD_CLOEXEC) != -1; } +#endif #ifdef Q_OS_SYMBIAN /*! @@ -539,6 +543,22 @@ int QFSFileEnginePrivate::nativeHandle() const return fh ? fileno(fh) : fd; } +#ifdef Q_OS_SYMBIAN +int QFSFileEnginePrivate::getMapHandle() +{ + if (symbianFile.SubSessionHandle()) { + // Symbian file handle can't be used for open C mmap() so open the file with open C as well. + if (fileHandleForMaps < 0) { + int flags = openModeToOpenFlags(openMode); + flags &= ~(O_CREAT | O_TRUNC); + fileHandleForMaps = ::wopen((wchar_t*)(fileEntry.nativeFilePath().utf16()), flags, 0666); + } + return fileHandleForMaps; + } + return nativeHandle(); +} +#endif + /*! \internal */ @@ -921,30 +941,6 @@ QDateTime QFSFileEngine::fileTime(FileTime time) const return QDateTime(); } -#ifdef Q_OS_SYMBIAN -uchar *QFSFileEnginePrivate::map(qint64 offset, qint64 size, QFile::MemoryMapFlags flags) -{ - //Q_Q(QFSFileEngine); - Q_UNUSED(flags) - Q_UNUSED(offset) - Q_UNUSED(size) - return 0; - //TODO: use RFileMap when available in symbian^4 -} - -bool QFSFileEnginePrivate::unmap(uchar *ptr) -{ - //TODO: RFileMap as the value in maps, unmap it here when API is available... - //Q_Q(QFSFileEngine); - //if (!maps.contains(ptr)) { - // q->setError(QFile::PermissionsError, qt_error_string(EACCES)); - // return false; - //} - Q_UNUSED(ptr) - - return false; -} -#else uchar *QFSFileEnginePrivate::map(qint64 offset, qint64 size, QFile::MemoryMapFlags flags) { Q_Q(QFSFileEngine); @@ -985,7 +981,7 @@ uchar *QFSFileEnginePrivate::map(qint64 offset, qint64 size, QFile::MemoryMapFla #ifdef Q_OS_SYMBIAN void *mapAddress; TRAPD(err, mapAddress = QT_MMAP((void*)0, realSize, - access, MAP_SHARED, nativeHandle(), realOffset)); + access, MAP_SHARED, getMapHandle(), realOffset)); if (err != KErrNone) { qWarning("OpenC bug: leave from mmap %d", err); mapAddress = MAP_FAILED; @@ -1035,7 +1031,6 @@ bool QFSFileEnginePrivate::unmap(uchar *ptr) maps.remove(ptr); return true; } -#endif QT_END_NAMESPACE diff --git a/tests/auto/qfile/tst_qfile.cpp b/tests/auto/qfile/tst_qfile.cpp index 4e7cb9f..088c1f2 100644 --- a/tests/auto/qfile/tst_qfile.cpp +++ b/tests/auto/qfile/tst_qfile.cpp @@ -2800,10 +2800,6 @@ void tst_QFile::map() QFETCH(int, size); QFETCH(QFile::FileError, error); -#ifdef Q_OS_SYMBIAN - QSKIP("memory mapped files not supported on this platform", SkipAll); -#endif - QString fileName = QDir::currentPath() + '/' + "qfile_map_testfile"; #ifdef Q_WS_WINCE @@ -2925,10 +2921,6 @@ void tst_QFile::mapResource() QFETCH(int, size); QFETCH(QFile::FileError, error); -#ifdef Q_OS_SYMBIAN - QSKIP("memory mapped files not supported on this platform", SkipAll); -#endif - QFile file(fileName); uchar *memory = file.map(offset, size); QCOMPARE(file.error(), error); @@ -2954,10 +2946,6 @@ void tst_QFile::mapOpenMode() QFETCH(int, openMode); static const qint64 fileSize = 4096; -#ifdef Q_OS_SYMBIAN - QSKIP("memory mapped files not supported on this platform", SkipAll); -#endif - QByteArray pattern(fileSize, 'A'); QString fileName = QDir::currentPath() + '/' + "qfile_map_testfile"; -- cgit v0.12