summaryrefslogtreecommitdiffstats
path: root/src/corelib/io
diff options
context:
space:
mode:
authorQt Continuous Integration System <qt-info@nokia.com>2010-12-23 19:00:08 (GMT)
committerQt Continuous Integration System <qt-info@nokia.com>2010-12-23 19:00:08 (GMT)
commite8dedfebf8a238662c053c6d983702f635c70a42 (patch)
treee428871276c3e05913179f46d83f1ca8056178dd /src/corelib/io
parente2ff3adad12ad10363a19d2c49d0ed3bdfe20d68 (diff)
parent3c20105f2344172cb1dce95864c0c3b70497f029 (diff)
downloadQt-e8dedfebf8a238662c053c6d983702f635c70a42.zip
Qt-e8dedfebf8a238662c053c6d983702f635c70a42.tar.gz
Qt-e8dedfebf8a238662c053c6d983702f635c70a42.tar.bz2
Merge branch 'earth/file-engine-refactor' of scm.dev.nokia.troll.no:qt/qt-file-engines-refactor into master-integration
* 'earth/file-engine-refactor' of scm.dev.nokia.troll.no:qt/qt-file-engines-refactor: Fix qfile test crash with glibc Fix qfile test errors Update def files Add autotests for AutoCloseHandle / DontCloseHandle and RFile adoption QFile API: add API to specify if adopted file handles should be closed
Diffstat (limited to 'src/corelib/io')
-rw-r--r--src/corelib/io/qfile.cpp187
-rw-r--r--src/corelib/io/qfile.h14
-rw-r--r--src/corelib/io/qfile_p.h7
-rw-r--r--src/corelib/io/qfsfileengine.cpp14
-rw-r--r--src/corelib/io/qfsfileengine.h8
-rw-r--r--src/corelib/io/qfsfileengine_unix.cpp59
6 files changed, 277 insertions, 12 deletions
diff --git a/src/corelib/io/qfile.cpp b/src/corelib/io/qfile.cpp
index 85e78a6..e3bc8da 100644
--- a/src/corelib/io/qfile.cpp
+++ b/src/corelib/io/qfile.cpp
@@ -103,7 +103,7 @@ QFilePrivate::~QFilePrivate()
}
bool
-QFilePrivate::openExternalFile(int flags, int fd)
+QFilePrivate::openExternalFile(int flags, int fd, QFile::FileHandleFlags handleFlags)
{
#ifdef QT_NO_FSFILEENGINE
Q_UNUSED(flags);
@@ -113,14 +113,13 @@ QFilePrivate::openExternalFile(int flags, int fd)
delete fileEngine;
fileEngine = 0;
QFSFileEngine *fe = new QFSFileEngine;
- fe->setFileName(fileName);
fileEngine = fe;
- return fe->open(QIODevice::OpenMode(flags), fd);
+ return fe->open(QIODevice::OpenMode(flags), fd, handleFlags);
#endif
}
bool
-QFilePrivate::openExternalFile(int flags, FILE *fh)
+QFilePrivate::openExternalFile(int flags, FILE *fh, QFile::FileHandleFlags handleFlags)
{
#ifdef QT_NO_FSFILEENGINE
Q_UNUSED(flags);
@@ -130,12 +129,28 @@ QFilePrivate::openExternalFile(int flags, FILE *fh)
delete fileEngine;
fileEngine = 0;
QFSFileEngine *fe = new QFSFileEngine;
- fe->setFileName(fileName);
fileEngine = fe;
- return fe->open(QIODevice::OpenMode(flags), fh);
+ return fe->open(QIODevice::OpenMode(flags), fh, handleFlags);
#endif
}
+#ifdef Q_OS_SYMBIAN
+bool QFilePrivate::openExternalFile(int flags, const RFile &f, QFile::FileHandleFlags handleFlags)
+{
+#ifdef QT_NO_FSFILEENGINE
+ Q_UNUSED(flags);
+ Q_UNUSED(fh);
+ return false;
+#else
+ delete fileEngine;
+ fileEngine = 0;
+ QFSFileEngine *fe = new QFSFileEngine;
+ fileEngine = fe;
+ return fe->open(QIODevice::OpenMode(flags), f, handleFlags);
+#endif
+}
+#endif
+
inline bool QFilePrivate::ensureFlushed() const
{
// This function ensures that the write buffer has been flushed (const
@@ -341,6 +356,20 @@ QFilePrivate::setError(QFile::FileError err, int errNum)
\snippet doc/src/snippets/ntfsp.cpp 1
*/
+/*!
+ \enum QFile::FileHandleFlag
+
+ This enum is used when opening a file to specify additional
+ options which only apply to files and not to a generic
+ QIODevice.
+
+ \value AutoCloseHandle The file handle passed into open() should be
+ closed by close(), the default behaviour is that close just flushes
+ the file and the app is responsible for closing the file handle. When
+ opening a file by name, this flag is ignored as Qt always "owns" the
+ file handle and must close it.
+ */
+
#ifdef QT3_SUPPORT
/*!
\typedef QFile::PermissionSpec
@@ -1058,8 +1087,57 @@ bool QFile::open(OpenMode mode)
\snippet doc/src/snippets/code/src_corelib_io_qfile.cpp 4
*/
+// ### Qt5: merge this into new overload with a default parameter
bool QFile::open(FILE *fh, OpenMode mode)
{
+ return open(fh, mode, DontCloseHandle);
+}
+
+/*!
+ \overload
+
+ Opens the existing file handle \a fh in the given \a mode.
+ Returns true if successful; otherwise returns false.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_io_qfile.cpp 3
+
+ When a QFile is opened using this function, behaviour of close() is
+ controlled by the AutoCloseHandle flag.
+ If AutoCloseHandle is specified, and this function succeeds,
+ then calling close() closes the adopted handle.
+ Otherwise, close() does not actually close the file, but only flushes it.
+
+ \bold{Warning:}
+ \list 1
+ \o If \a fh does not refer to a regular file, e.g., it is \c stdin,
+ \c stdout, or \c stderr, you may not be able to seek(). size()
+ returns \c 0 in those cases. See QIODevice::isSequential() for
+ more information.
+ \o Since this function opens the file without specifying the file name,
+ you cannot use this QFile with a QFileInfo.
+ \endlist
+
+ \note For Windows CE you may not be able to call resize().
+
+ \sa close(), {qmake Variable Reference#CONFIG}{qmake Variable Reference}
+
+ \bold{Note for the Windows Platform}
+
+ \a fh must be opened in binary mode (i.e., the mode string must contain
+ 'b', as in "rb" or "wb") when accessing files and other random-access
+ devices. Qt will translate the end-of-line characters if you pass
+ QIODevice::Text to \a mode. Sequential devices, such as stdin and stdout,
+ are unaffected by this limitation.
+
+ You need to enable support for console applications in order to use the
+ stdin, stdout and stderr streams at the console. To do this, add the
+ following declaration to your application's project file:
+
+ \snippet doc/src/snippets/code/src_corelib_io_qfile.cpp 4
+*/
+bool QFile::open(FILE *fh, OpenMode mode, FileHandleFlags handleFlags)
+{
Q_D(QFile);
if (isOpen()) {
qWarning("QFile::open: File (%s) already open", qPrintable(fileName()));
@@ -1072,7 +1150,7 @@ bool QFile::open(FILE *fh, OpenMode mode)
qWarning("QFile::open: File access not specified");
return false;
}
- if(d->openExternalFile(mode, fh)) {
+ if (d->openExternalFile(mode, fh, handleFlags)) {
QIODevice::open(mode);
if (mode & Append) {
seek(size());
@@ -1118,8 +1196,44 @@ bool QFile::open(FILE *fh, OpenMode mode)
\sa close()
*/
+// ### Qt5: merge this into new overload with a default parameter
bool QFile::open(int fd, OpenMode mode)
{
+ return open(fd, mode, DontCloseHandle);
+}
+
+/*!
+ \overload
+
+ Opens the existing file descriptor \a fd in the given \a mode.
+ Returns true if successful; otherwise returns false.
+
+ When a QFile is opened using this function, behaviour of close() is
+ controlled by the AutoCloseHandle flag.
+ If AutoCloseHandle is specified, and this function succeeds,
+ then calling close() closes the adopted handle.
+ Otherwise, close() does not actually close the file, but only flushes it.
+
+ The QFile that is opened using this function is automatically set
+ to be in raw mode; this means that the file input/output functions
+ are slow. If you run into performance issues, you should try to
+ use one of the other open functions.
+
+ \warning If \a fd is not a regular file, e.g, it is 0 (\c stdin),
+ 1 (\c stdout), or 2 (\c stderr), you may not be able to seek(). In
+ those cases, size() returns \c 0. See QIODevice::isSequential()
+ for more information.
+
+ \warning For Windows CE you may not be able to call seek(), setSize(),
+ fileTime(). size() returns \c 0.
+
+ \warning Since this function opens the file without specifying the file name,
+ you cannot use this QFile with a QFileInfo.
+
+ \sa close()
+*/
+bool QFile::open(int fd, OpenMode mode, FileHandleFlags handleFlags)
+{
Q_D(QFile);
if (isOpen()) {
qWarning("QFile::open: File (%s) already open", qPrintable(fileName()));
@@ -1132,7 +1246,7 @@ bool QFile::open(int fd, OpenMode mode)
qWarning("QFile::open: File access not specified");
return false;
}
- if(d->openExternalFile(mode, fd)) {
+ if (d->openExternalFile(mode, fd, handleFlags)) {
QIODevice::open(mode);
if (mode & Append) {
seek(size());
@@ -1146,6 +1260,63 @@ bool QFile::open(int fd, OpenMode mode)
return false;
}
+#ifdef Q_OS_SYMBIAN
+/*!
+ \overload
+
+ Opens the existing file object \a f in the given \a mode.
+ Returns true if successful; otherwise returns false.
+
+ When a QFile is opened using this function, behaviour of close() is
+ controlled by the AutoCloseHandle flag.
+ If AutoCloseHandle is specified, and this function succeeds,
+ then calling close() closes the adopted handle.
+ Otherwise, close() does not actually close the file, but only flushes it.
+
+ \warning If the file handle is adopted from another process,
+ you may not be able to use this QFile with a QFileInfo.
+
+ \sa close()
+*/
+bool QFile::open(const RFile &f, OpenMode mode, FileHandleFlags handleFlags)
+{
+ Q_D(QFile);
+ if (isOpen()) {
+ qWarning("QFile::open: File (%s) already open", qPrintable(fileName()));
+ return false;
+ }
+ if (mode & Append)
+ mode |= WriteOnly;
+ unsetError();
+ if ((mode & (ReadOnly | WriteOnly)) == 0) {
+ qWarning("QFile::open: File access not specified");
+ return false;
+ }
+ if (d->openExternalFile(mode, f, handleFlags)) {
+ bool ok = QIODevice::open(mode);
+ if (ok) {
+ if (mode & Append) {
+ ok = seek(size());
+ } else {
+ qint64 pos = 0;
+ TInt err;
+#ifdef SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API
+ err = static_cast<const RFile64&>(f).Seek(ESeekCurrent, pos);
+#else
+ TInt pos32 = 0;
+ err = f.Seek(ESeekCurrent, pos32);
+ pos = pos32;
+#endif
+ ok = ok && (err == KErrNone);
+ ok = ok && seek(pos);
+ }
+ }
+ return ok;
+ }
+ return false;
+}
+#endif
+
/*!
Returns the file handle of the file.
diff --git a/src/corelib/io/qfile.h b/src/corelib/io/qfile.h
index 212576c..fa9e5aa 100644
--- a/src/corelib/io/qfile.h
+++ b/src/corelib/io/qfile.h
@@ -45,6 +45,9 @@
#include <QtCore/qiodevice.h>
#include <QtCore/qstring.h>
#include <stdio.h>
+#ifdef Q_OS_SYMBIAN
+#include <f32file.h>
+#endif
#ifdef open
#error qfile.h must be included before any header file that defines open
@@ -97,6 +100,12 @@ public:
};
Q_DECLARE_FLAGS(Permissions, Permission)
+ enum FileHandleFlag {
+ AutoCloseHandle = 0x0001,
+ DontCloseHandle = 0
+ };
+ Q_DECLARE_FLAGS(FileHandleFlags, FileHandleFlag)
+
QFile();
QFile(const QString &name);
#ifndef QT_NO_QOBJECT
@@ -145,6 +154,11 @@ public:
bool open(OpenMode flags);
bool open(FILE *f, OpenMode flags);
bool open(int fd, OpenMode flags);
+#ifdef Q_OS_SYMBIAN
+ bool open(const RFile &f, OpenMode flags, FileHandleFlags handleFlags = DontCloseHandle);
+#endif
+ bool open(FILE *f, OpenMode ioFlags, FileHandleFlags handleFlags);
+ bool open(int fd, OpenMode ioFlags, FileHandleFlags handleFlags);
virtual void close();
qint64 size() const;
diff --git a/src/corelib/io/qfile_p.h b/src/corelib/io/qfile_p.h
index cf76c09..085bbf0 100644
--- a/src/corelib/io/qfile_p.h
+++ b/src/corelib/io/qfile_p.h
@@ -67,8 +67,11 @@ protected:
QFilePrivate();
~QFilePrivate();
- bool openExternalFile(int flags, int fd);
- bool openExternalFile(int flags, FILE *fh);
+ bool openExternalFile(int flags, int fd, QFile::FileHandleFlags handleFlags);
+ bool openExternalFile(int flags, FILE *fh, QFile::FileHandleFlags handleFlags);
+#ifdef Q_OS_SYMBIAN
+ bool openExternalFile(int flags, const RFile& f, QFile::FileHandleFlags handleFlags);
+#endif
QString fileName;
mutable QAbstractFileEngine *fileEngine;
diff --git a/src/corelib/io/qfsfileengine.cpp b/src/corelib/io/qfsfileengine.cpp
index ae301f7..f1d3db5 100644
--- a/src/corelib/io/qfsfileengine.cpp
+++ b/src/corelib/io/qfsfileengine.cpp
@@ -230,6 +230,11 @@ bool QFSFileEngine::open(QIODevice::OpenMode openMode)
*/
bool QFSFileEngine::open(QIODevice::OpenMode openMode, FILE *fh)
{
+ return open(openMode, fh, QFile::DontCloseHandle);
+}
+
+bool QFSFileEngine::open(QIODevice::OpenMode openMode, FILE *fh, QFile::FileHandleFlags handleFlags)
+{
Q_D(QFSFileEngine);
// Append implies WriteOnly.
@@ -242,7 +247,7 @@ bool QFSFileEngine::open(QIODevice::OpenMode openMode, FILE *fh)
d->openMode = openMode;
d->lastFlushFailed = false;
- d->closeFileHandle = false;
+ d->closeFileHandle = (handleFlags & QFile::AutoCloseHandle);
d->fileEntry.clear();
d->tried_stat = 0;
d->fd = -1;
@@ -286,6 +291,11 @@ bool QFSFileEnginePrivate::openFh(QIODevice::OpenMode openMode, FILE *fh)
*/
bool QFSFileEngine::open(QIODevice::OpenMode openMode, int fd)
{
+ return open(openMode, fd, QFile::DontCloseHandle);
+}
+
+bool QFSFileEngine::open(QIODevice::OpenMode openMode, int fd, QFile::FileHandleFlags handleFlags)
+{
Q_D(QFSFileEngine);
// Append implies WriteOnly.
@@ -298,7 +308,7 @@ bool QFSFileEngine::open(QIODevice::OpenMode openMode, int fd)
d->openMode = openMode;
d->lastFlushFailed = false;
- d->closeFileHandle = false;
+ d->closeFileHandle = (handleFlags & QFile::AutoCloseHandle);
d->fileEntry.clear();
d->fh = 0;
d->fd = -1;
diff --git a/src/corelib/io/qfsfileengine.h b/src/corelib/io/qfsfileengine.h
index 6b077ed..73c8c77 100644
--- a/src/corelib/io/qfsfileengine.h
+++ b/src/corelib/io/qfsfileengine.h
@@ -43,6 +43,9 @@
#define QFSFILEENGINE_H
#include <QtCore/qabstractfileengine.h>
+#ifdef Q_OS_SYMBIAN
+#include <f32file.h>
+#endif
#ifndef QT_NO_FSFILEENGINE
@@ -101,6 +104,11 @@ public:
//FS only!!
bool open(QIODevice::OpenMode flags, int fd);
+ bool open(QIODevice::OpenMode flags, int fd, QFile::FileHandleFlags handleFlags);
+ bool open(QIODevice::OpenMode flags, FILE *fh, QFile::FileHandleFlags handleFlags);
+#ifdef Q_OS_SYMBIAN
+ bool open(QIODevice::OpenMode flags, const RFile &f, QFile::FileHandleFlags handleFlags);
+#endif
static bool setCurrentPath(const QString &path);
static QString currentPath(const QString &path = QString());
static QString homePath();
diff --git a/src/corelib/io/qfsfileengine_unix.cpp b/src/corelib/io/qfsfileengine_unix.cpp
index 1e1b35b..d0350f0 100644
--- a/src/corelib/io/qfsfileengine_unix.cpp
+++ b/src/corelib/io/qfsfileengine_unix.cpp
@@ -251,6 +251,65 @@ bool QFSFileEnginePrivate::nativeOpen(QIODevice::OpenMode openMode)
closeFileHandle = true;
return true;
}
+
+bool QFSFileEngine::open(QIODevice::OpenMode openMode, const RFile &file, QFile::FileHandleFlags handleFlags)
+{
+ Q_D(QFSFileEngine);
+
+ // Append implies WriteOnly.
+ if (openMode & QFile::Append)
+ openMode |= QFile::WriteOnly;
+
+ // WriteOnly implies Truncate if neither ReadOnly nor Append are sent.
+ if ((openMode & QFile::WriteOnly) && !(openMode & (QFile::ReadOnly | QFile::Append)))
+ openMode |= QFile::Truncate;
+
+ d->openMode = openMode;
+ d->lastFlushFailed = false;
+ d->closeFileHandle = (handleFlags & QFile::AutoCloseHandle);
+ d->fileEntry.clear();
+ d->fh = 0;
+ d->fd = -1;
+ d->tried_stat = 0;
+
+#ifdef SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API
+ //RFile64 adds only functions to RFile, no data members
+ d->symbianFile = static_cast<const RFile64&>(file);
+#else
+ d->symbianFile = file;
+#endif
+ TInt ret;
+ d->symbianFilePos = 0;
+ if (openMode & QFile::Append) {
+ // Seek to the end when in Append mode.
+ ret = d->symbianFile.Size(d->symbianFilePos);
+ } else {
+ // Seek to current otherwise
+ ret = d->symbianFile.Seek(ESeekCurrent, d->symbianFilePos);
+ }
+
+ if (ret != KErrNone) {
+ setError(QFile::OpenError, QSystemError(ret, QSystemError::NativeError).toString());
+
+ d->openMode = QIODevice::NotOpen;
+#ifdef SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API
+ d->symbianFile = RFile64();
+#else
+ d->symbianFile = RFile();
+#endif
+ return false;
+ }
+
+ // Extract filename (best effort)
+ TFileName fn;
+ TInt err = d->symbianFile.FullName(fn);
+ if (err == KErrNone)
+ d->fileEntry = QFileSystemEntry(qt_TDesC2QString(fn), QFileSystemEntry::FromNativePath());
+ else
+ d->fileEntry.clear();
+
+ return true;
+}
#else
/*!
\internal