diff options
author | Shane Kearns <shane.kearns@accenture.com> | 2010-10-18 14:15:39 (GMT) |
---|---|---|
committer | Shane Kearns <shane.kearns@accenture.com> | 2010-10-19 08:36:18 (GMT) |
commit | 366d2ed09ebf5aa27171a46d723497e5aaa5dd06 (patch) | |
tree | cacb6df98c2f147fe720e6ac37f95259da9f1788 /src | |
parent | 2e35e9c1eabe667798572457c61e1d1d1f373317 (diff) | |
download | Qt-366d2ed09ebf5aa27171a46d723497e5aaa5dd06.zip Qt-366d2ed09ebf5aa27171a46d723497e5aaa5dd06.tar.gz Qt-366d2ed09ebf5aa27171a46d723497e5aaa5dd06.tar.bz2 |
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
Diffstat (limited to 'src')
-rw-r--r-- | src/corelib/io/qfsfileengine_unix.cpp | 51 |
1 files changed, 26 insertions, 25 deletions
diff --git a/src/corelib/io/qfsfileengine_unix.cpp b/src/corelib/io/qfsfileengine_unix.cpp index caf5f4c..96946d6 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<TUint8*>(data), static_cast<TInt>(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<const TUint8*>(data), static_cast<TInt>(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<QFSFileEngine*>(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; |