summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShane Kearns <ext-shane.2.kearns@nokia.com>2012-01-17 19:51:39 +0000
committerPasi Pentikäinen <ext-pasi.a.pentikainen@nokia.com>2012-01-26 10:33:41 +0100
commitafa6fdbb29196b42f3c987626eecaaeb3d3049e0 (patch)
treee09703f7f03eb1e83c985abac5a6f3d7bff69c49
parent943dc8e4a58a32a5b5a14c456d60bd3601e42618 (diff)
downloadqt4-tools-afa6fdbb29196b42f3c987626eecaaeb3d3049e0.tar.gz
Fix BC break with QAbstractFileEngine "mount points"
File system cached metadata can't be trusted when custom file engines are in use, because the custom file engine may want to override the metadata. (e.g. present an archive file as a directory) Therefore, check if a file engine should be instantiated for each result in QDirIterator. This is a fast check if no custom file engines are registered. When pushing a directory (using QDirIterator::SubDirectories) the file engine needs to be instantiated also. Task-number: QTBUG-23688 Task-number: ou1cimx1#965023 Change-Id: I0114c8df6258535553783a2486131c4194926649 Reviewed-by: João Abecasis <joao.abecasis@nokia.com> (cherry picked from commit 3864ad09d578210b52e5f58fca2ee8a1144f5be2) Reviewed-by: Pasi Pentikäinen <ext-pasi.a.pentikainen@nokia.com>
-rw-r--r--src/corelib/io/qfileinfo_p.h5
-rw-r--r--src/corelib/io/qfilesystemiterator_symbian.cpp10
-rw-r--r--tests/auto/qabstractfileengine/tst_qabstractfileengine.cpp93
3 files changed, 103 insertions, 5 deletions
diff --git a/src/corelib/io/qfileinfo_p.h b/src/corelib/io/qfileinfo_p.h
index 23ea0225f5..4f97ca3044 100644
--- a/src/corelib/io/qfileinfo_p.h
+++ b/src/corelib/io/qfileinfo_p.h
@@ -108,10 +108,15 @@ public:
: QSharedData(),
fileEntry(file),
metaData(data),
+ fileEngine(QFileSystemEngine::resolveEntryAndCreateLegacyEngine(fileEntry, metaData)),
cachedFlags(0),
isDefaultConstructed(false),
cache_enabled(true), fileFlags(0), fileSize(0)
{
+ //If the file engine is not null, this maybe a "mount point" for a custom file engine
+ //in which case we can't trust the metadata
+ if (fileEngine)
+ metaData = QFileSystemMetaData();
}
inline void clearFlags() const {
diff --git a/src/corelib/io/qfilesystemiterator_symbian.cpp b/src/corelib/io/qfilesystemiterator_symbian.cpp
index 4347f6acba..8277e50ed1 100644
--- a/src/corelib/io/qfilesystemiterator_symbian.cpp
+++ b/src/corelib/io/qfilesystemiterator_symbian.cpp
@@ -83,10 +83,12 @@ QFileSystemIterator::QFileSystemIterator(const QFileSystemEntry &path, QDir::Fil
symbianMask |= KEntryAttHidden;
if (filters & QDir::System)
symbianMask |= KEntryAttSystem;
- if (((filters & QDir::Files) == 0) && symbianMask == KEntryAttDir)
- symbianMask |= KEntryAttMatchExclusive; //exclude non-directories
- else if (symbianMask == 0) {
- if ((filters & QDir::PermissionMask) == QDir::Writable)
+ //Do not use KEntryAttMatchExclusive to optimise to return only
+ //directories for QDir::Dirs. There may be a file which is actually
+ //a "mount point" for a file engine and needs to be returned so it
+ //can be overriden to be a directory, see QTBUG-23688
+ if (symbianMask == 0
+ && ((filters & QDir::PermissionMask) == QDir::Writable)) {
symbianMask = KEntryAttMatchExclude | KEntryAttReadOnly;
}
diff --git a/tests/auto/qabstractfileengine/tst_qabstractfileengine.cpp b/tests/auto/qabstractfileengine/tst_qabstractfileengine.cpp
index a81633341d..7f3887f1e1 100644
--- a/tests/auto/qabstractfileengine/tst_qabstractfileengine.cpp
+++ b/tests/auto/qabstractfileengine/tst_qabstractfileengine.cpp
@@ -47,10 +47,13 @@
#include <QtCore/QSharedPointer>
#include <QtCore/QScopedPointer>
#include <QtCore/QHash>
+#include <QtCore/QDir>
+#include <QtCore/QDirIterator>
#include <QtTest/QTest>
#include <QtCore/QDebug>
+#include "../../shared/filesystem.h"
class tst_QAbstractFileEngine
: public QObject
@@ -65,6 +68,8 @@ private slots:
void fileIO_data();
void fileIO();
+ void mounting_data();
+ void mounting();
private:
QStringList filesForRemoval;
};
@@ -74,7 +79,7 @@ class ReferenceFileEngine
{
public:
ReferenceFileEngine(const QString &fileName)
- : fileName_(fileName)
+ : fileName_(QDir::cleanPath(fileName))
, position_(-1)
, openForRead_(false)
, openForWrite_(false)
@@ -491,6 +496,60 @@ private:
mutable QSharedPointer<File> openFile_;
};
+class MountingFileEngine : public QFSFileEngine
+{
+public:
+ class Iterator : public QAbstractFileEngineIterator
+ {
+ public:
+ Iterator(QDir::Filters filters, const QStringList &filterNames)
+ : QAbstractFileEngineIterator(filters, filterNames)
+ {
+ names.append("foo");
+ names.append("bar");
+ index = -1;
+ }
+ QString currentFileName() const
+ {
+ return names.at(index);
+ }
+ bool hasNext() const
+ {
+ return index < names.size() - 1;
+ }
+ QString next()
+ {
+ if (!hasNext())
+ return QString();
+ ++index;
+ return currentFilePath();
+ }
+ QStringList names;
+ int index;
+ };
+ MountingFileEngine(QString fileName)
+ : QFSFileEngine(fileName)
+ {
+ }
+ Iterator *beginEntryList(QDir::Filters filters, const QStringList &filterNames)
+ {
+ return new Iterator(filters, filterNames);
+ }
+ FileFlags fileFlags(FileFlags type) const
+ {
+ if (fileName(DefaultName).endsWith(".tar")) {
+ FileFlags ret = QFSFileEngine::fileFlags(type);
+ //make this file in file system appear to be a directory
+ ret &= ~FileType;
+ ret |= DirectoryType;
+ return ret;
+ } else {
+ //file inside the archive
+ return ExistsFlag | FileType;
+ }
+ }
+};
+
QMutex ReferenceFileEngine::fileSystemMutex;
QHash<uint, QString> ReferenceFileEngine::fileSystemUsers, ReferenceFileEngine::fileSystemGroups;
QHash<QString, QSharedPointer<ReferenceFileEngine::File> > ReferenceFileEngine::fileSystem;
@@ -500,6 +559,8 @@ class FileEngineHandler
{
QAbstractFileEngine *create(const QString &fileName) const
{
+ if (fileName.endsWith(".tar") || fileName.contains(".tar/"))
+ return new MountingFileEngine(fileName);
if (fileName.startsWith("QFSFileEngine:"))
return new QFSFileEngine(fileName.mid(14));
if (fileName.startsWith("reference-file-engine:"))
@@ -789,6 +850,36 @@ void tst_QAbstractFileEngine::fileIO()
//
}
+void tst_QAbstractFileEngine::mounting_data()
+{
+ QTest::addColumn<QString>("fileName");
+ QTest::newRow("native") << "test.tar";
+ QTest::newRow("Forced QFSFileEngine") << "QFSFileEngine:test.tar";
+}
+
+void tst_QAbstractFileEngine::mounting()
+{
+ FileSystem fs;
+ QVERIFY(fs.createFile("test.tar"));
+ FileEngineHandler handler;
+
+ QFETCH(QString, fileName);
+
+ QVERIFY(QFileInfo(fileName).isDir());
+ QDir dir(fileName);
+ QCOMPARE(dir.entryList(), (QStringList() << "bar" << "foo"));
+ QDir dir2;
+ bool found = false;
+ foreach (QFileInfo info, dir2.entryInfoList()) {
+ if (info.fileName() == QLatin1String("test.tar")) {
+ QVERIFY(!found);
+ found = true;
+ QVERIFY(info.isDir());
+ }
+ }
+ QVERIFY(found);
+}
+
QTEST_APPLESS_MAIN(tst_QAbstractFileEngine)
#include "tst_qabstractfileengine.moc"