From 366d2ed09ebf5aa27171a46d723497e5aaa5dd06 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Mon, 18 Oct 2010 15:15:39 +0100 Subject: Implement seek beyond end of file for symbian On Symbian, the Seek() function clamps to the end of file position if a position beyond the end of file is given. Also the write functions which take a position silently append at the end of file position if asked to write to a start position beyond EOF. To avoid this behaviour, we don't use seek but rather maintain our own cursor position. When writing, we check if the cursor is beyond EOF and if so extend the file using SetSize() before writing. Reviewed-By: joao --- src/corelib/io/qfsfileengine_unix.cpp | 51 ++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 25 deletions(-) (limited to 'src/corelib/io/qfsfileengine_unix.cpp') diff --git a/src/corelib/io/qfsfileengine_unix.cpp b/src/corelib/io/qfsfileengine_unix.cpp index caf5f4c278..96946d69a3 100644 --- a/src/corelib/io/qfsfileengine_unix.cpp +++ b/src/corelib/io/qfsfileengine_unix.cpp @@ -382,12 +382,13 @@ qint64 QFSFileEnginePrivate::nativeRead(char *data, qint64 len) return -1; } TPtr8 ptr(reinterpret_cast(data), static_cast(len)); - TInt r = symbianFile.Read(ptr); + TInt r = symbianFile.Read(symbianFilePos, ptr); if (r != KErrNone) { q->setError(QFile::ReadError, QSystemError(r, QSystemError::NativeError).toString()); return -1; } + symbianFilePos += ptr.Length(); return qint64(ptr.Length()); } #endif @@ -467,12 +468,28 @@ qint64 QFSFileEnginePrivate::nativeWrite(const char *data, qint64 len) return -1; } const TPtrC8 ptr(reinterpret_cast(data), static_cast(len)); - TInt r = symbianFile.Write(ptr); - if (r != KErrNone) - { +#ifdef SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API + TInt64 eofpos = 0; +#else + TInt eofpos = 0; +#endif + //The end of file position is not cached because QFile is read/write sharable, therefore another + //process may have altered the file size. + TInt r = symbianFile.Seek(ESeekEnd, eofpos); + if (r == KErrNone && symbianFilePos > eofpos) { + //seek position is beyond end of file so file needs to be extended before write. + //note that SetSize does not zero-initialise (c.f. posix lseek) + r = symbianFile.SetSize(symbianFilePos); + } + if (r == KErrNone) { + //write to specific position in the file (i.e. use our own cursor rather than calling seek) + r = symbianFile.Write(symbianFilePos, ptr); + } + if (r != KErrNone) { q->setError(QFile::WriteError, QSystemError(r, QSystemError::NativeError).toString()); return -1; } + symbianFilePos += len; return len; } #endif @@ -487,17 +504,7 @@ qint64 QFSFileEnginePrivate::nativePos() const #ifdef Q_OS_SYMBIAN const Q_Q(QFSFileEngine); if (symbianFile.SubSessionHandle()) { -#ifdef SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API - qint64 pos = 0; -#else - TInt pos = 0; -#endif - TInt err = symbianFile.Seek(ESeekCurrent, pos); - if(err != KErrNone) { - const_cast(q)->setError(QFile::PositionError, QSystemError(err, QSystemError::NativeError).toString()); - return -1; - } - return pos; + return symbianFilePos; } #endif return posFdFh(); @@ -511,21 +518,13 @@ bool QFSFileEnginePrivate::nativeSeek(qint64 pos) #ifdef Q_OS_SYMBIAN Q_Q(QFSFileEngine); if (symbianFile.SubSessionHandle()) { -#ifdef SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API - TInt r = symbianFile.Seek(ESeekStart, pos); -#else +#ifndef SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API if(pos > KMaxTInt) { q->setError(QFile::PositionError, QLatin1String("Maximum 2GB file position on this platform")); return false; } - TInt pos32(pos); - TInt r = symbianFile.Seek(ESeekStart, pos32); #endif - if (r != KErrNone) - { - q->setError(QFile::PositionError, QSystemError(r, QSystemError::NativeError).toString()); - return false; - } + symbianFilePos = pos; return true; } #endif @@ -867,6 +866,8 @@ bool QFSFileEngine::setSize(qint64 size) if (d->symbianFile.SubSessionHandle()) { TInt err = d->symbianFile.SetSize(size); ret = (err == KErrNone); + if (ret && d->symbianFilePos > size) + d->symbianFilePos = size; } else if (d->fd != -1) ret = QT_FTRUNCATE(d->fd, size) == 0; -- cgit v1.2.1