diff options
author | Qt Continuous Integration System <qt-info@nokia.com> | 2010-12-14 23:20:49 (GMT) |
---|---|---|
committer | Qt Continuous Integration System <qt-info@nokia.com> | 2010-12-14 23:20:49 (GMT) |
commit | 3b274b5d285ca2da0414ce5b2c16e87c7baac43e (patch) | |
tree | f934fb50d74f91763806bc0afecbacd980279aa2 | |
parent | d6dace9bebd8a8ad8caaecb69dd24dd1ddf96f4a (diff) | |
parent | 62e2f0b44c92a0f59416bcd4d9bc87e35cb6d80a (diff) | |
download | Qt-3b274b5d285ca2da0414ce5b2c16e87c7baac43e.zip Qt-3b274b5d285ca2da0414ce5b2c16e87c7baac43e.tar.gz Qt-3b274b5d285ca2da0414ce5b2c16e87c7baac43e.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: (224 commits)
Fix warnings, whitespace cleanup
Don't rely on uninitialized data
Doc: Fixing typo
Doc: Fixing typo
Skip failing tests
Use effective user id instead of getlogin
Fix compile error in tst_qfileinfo on Mac/Linux
Fix tst_QFileInfo owner() & group() failure on Windows.
Fix tst_QFileInfo::canonicalFilePath failure on Windows
Fix QDir::relativeFilePath
Fix spelling in comments
Add missing license header to test case
Define _WIN32_WINNT before any includes
New attempt at fixing compilation failure
Removing unused duplicate definitions
No symbolic links in Windows CE
Set minimum target Windows version to 2000
More missing includes
Add missing include
Fix compile error
...
159 files changed, 8396 insertions, 3048 deletions
@@ -119,6 +119,14 @@ translations/*.qm translations/*_untranslated.ts qrc_*.cpp +# Test generated files +QObject.log +tst_* +!tst_*.* +tst_*.log +tst_*.debug +tst_*~ + # xemacs temporary files *.flc @@ -203,7 +211,7 @@ doc-build # --------------------- ABLD.BAT -bld.inf +bld.inf* *.mmp *.mk *.rss @@ -221,6 +229,10 @@ plugin_commonu.def *.sym *.lib +# runonphone crash dumps +d_exc_*.txt +d_exc_*.stk + # Generated by abldfast.bat from devtools. .abldsteps.* diff --git a/demos/declarative/minehunt/minehunt.pro b/demos/declarative/minehunt/minehunt.pro index f591011..d23bb05 100644 --- a/demos/declarative/minehunt/minehunt.pro +++ b/demos/declarative/minehunt/minehunt.pro @@ -18,6 +18,6 @@ symbian:{ TARGET.EPOCHEAPSIZE = 0x20000 0x2000000 include($$QT_SOURCE_TREE/demos/symbianpkgrules.pri) qmlminehuntfiles.files = MinehuntCore minehunt.qml - DEPLOYMENT = qmlminehuntfiles + DEPLOYMENT += qmlminehuntfiles } diff --git a/examples/declarative/cppextensions/imageprovider/imageprovider.pro b/examples/declarative/cppextensions/imageprovider/imageprovider.pro index f6e09a2..f700f0b 100644 --- a/examples/declarative/cppextensions/imageprovider/imageprovider.pro +++ b/examples/declarative/cppextensions/imageprovider/imageprovider.pro @@ -24,5 +24,5 @@ symbian:{ importFiles.files = ImageProviderCore/qmlimageproviderplugin.dll ImageProviderCore/qmldir importFiles.path = ImageProviderCore - DEPLOYMENT = importFiles + DEPLOYMENT += importFiles } diff --git a/examples/declarative/cppextensions/qwidgets/qwidgets.pro b/examples/declarative/cppextensions/qwidgets/qwidgets.pro index 0f5398b..d92e072 100644 --- a/examples/declarative/cppextensions/qwidgets/qwidgets.pro +++ b/examples/declarative/cppextensions/qwidgets/qwidgets.pro @@ -20,5 +20,5 @@ symbian:{ importFiles.files = QWidgets/qmlqwidgetsplugin.dll QWidgets/qmldir importFiles.path = QWidgets - DEPLOYMENT = importFiles + DEPLOYMENT += importFiles } diff --git a/qmake/Makefile.unix b/qmake/Makefile.unix index b9e281b..a24076e 100644 --- a/qmake/Makefile.unix +++ b/qmake/Makefile.unix @@ -16,10 +16,11 @@ OBJS=project.o property.o main.o makefile.o unixmake2.o unixmake.o \ #qt code QOBJS=qtextcodec.o qutfcodec.o qstring.o qtextstream.o qiodevice.o qmalloc.o qglobal.o \ qbytearray.o qbytearraymatcher.o qdatastream.o qbuffer.o qlist.o qfile.o \ - qfsfileengine_unix.o qfsfileengine_iterator_unix.o qfsfileengine.o \ + qfilesystementry.o qfilesystemengine_unix.o qfilesystemengine.o qfilesystemiterator_unix.o \ + qfsfileengine_unix.o qfsfileengine.o \ qfsfileengine_iterator.o qregexp.o qvector.o qbitarray.o qdir.o qdiriterator.o quuid.o qhash.o \ qfileinfo.o qdatetime.o qstringlist.o qabstractfileengine.o qtemporaryfile.o \ - qmap.o qmetatype.o qsettings.o qlibraryinfo.o qvariant.o qvsnprintf.o \ + qmap.o qmetatype.o qsettings.o qsystemerror.o qlibraryinfo.o qvariant.o qvsnprintf.o \ qlocale.o qlinkedlist.o qurl.o qnumeric.o qcryptographichash.o qxmlstream.o qxmlutils.o \ $(QTOBJS) @@ -44,8 +45,11 @@ DEPEND_SRC=project.cpp property.cpp meta.cpp main.cpp generators/makefile.cpp ge $(SOURCE_PATH)/src/corelib/global/qglobal.cpp $(SOURCE_PATH)/src/corelib/tools/qregexp.cpp \ $(SOURCE_PATH)/src/corelib/tools/qbytearray.cpp $(SOURCE_PATH)/src/corelib/tools/qbytearraymatcher.cpp \ $(SOURCE_PATH)/src/corelib/io/qdatastream.cpp $(SOURCE_PATH)/src/corelib/io/qbuffer.cpp \ + $(SOURCE_PATH)/src/corelib/io/qfilesystementry.cpp $(SOURCE_PATH)/src/corelib/io/qfilesystemengine_unix.cpp \ + $(SOURCE_PATH)/src/corelib/io/qfilesystemengine_mac.cpp \ + $(SOURCE_PATH)/src/corelib/io/qfilesystemengine.cpp $(SOURCE_PATH)/src/corelib/io/qfilesystemiterator_unix.cpp \ $(SOURCE_PATH)/src/corelib/io/qfsfileengine_unix.cpp $(SOURCE_PATH)/src/corelib/io/qabstractfileengine.cpp \ - $(SOURCE_PATH)/src/corelib/io/qfsfileengine_iterator_unix.cpp $(SOURCE_PATH)/src/corelib/io/qfsfileengine_iterator.cpp \ + $(SOURCE_PATH)/src/corelib/io/qfsfileengine_iterator.cpp \ $(SOURCE_PATH)/src/corelib/io/qfsfileengine.cpp $(SOURCE_PATH)/src/corelib/tools/qlist.cpp \ $(SOURCE_PATH)/src/corelib/tools/qvector.cpp $(SOURCE_PATH)/src/corelib/tools/qbitarray.cpp \ $(SOURCE_PATH)/src/corelib/io/qdiriterator.cpp \ @@ -61,6 +65,7 @@ DEPEND_SRC=project.cpp property.cpp meta.cpp main.cpp generators/makefile.cpp ge $(SOURCE_PATH)/src/corelib/tools/qvsnprintf.cpp $(SOURCE_PATH)/src/corelib/global/qnumeric.cpp \ $(SOURCE_PATH)/src/corelib/xml/qxmlstream.cpp \ $(SOURCE_PATH)/src/corelib/xml/qxmlutils.cpp \ + $(SOURCE_PATH)/src/corelib/kernel/qsystemerror.cpp \ $(QTSRCS) CPPFLAGS = -I. -Igenerators -Igenerators/unix -Igenerators/win32 -Igenerators/mac -Igenerators/symbian \ @@ -100,6 +105,9 @@ qvariant.o: $(SOURCE_PATH)/src/corelib/kernel/qvariant.cpp qsettings.o: $(SOURCE_PATH)/src/corelib/io/qsettings.cpp $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qsettings.cpp +qsystemerror.o: $(SOURCE_PATH)/src/corelib/kernel/qsystemerror.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/kernel/qsystemerror.cpp + qlibraryinfo.o: $(SOURCE_PATH)/src/corelib/global/qlibraryinfo.cpp $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/global/qlibraryinfo.cpp @@ -160,6 +168,21 @@ qlist.o: $(SOURCE_PATH)/src/corelib/tools/qlist.cpp qfile.o: $(SOURCE_PATH)/src/corelib/io/qfile.cpp $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qfile.cpp +qfilesystementry.o: $(SOURCE_PATH)/src/corelib/io/qfilesystementry.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qfilesystementry.cpp + +qfilesystemengine.o: $(SOURCE_PATH)/src/corelib/io/qfilesystemengine.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qfilesystemengine.cpp + +qfilesystemengine_unix.o: $(SOURCE_PATH)/src/corelib/io/qfilesystemengine_unix.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qfilesystemengine_unix.cpp + +qfilesystemengine_mac.o: $(SOURCE_PATH)/src/corelib/io/qfilesystemengine_mac.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qfilesystemengine_mac.cpp + +qfilesystemiterator_unix.o: $(SOURCE_PATH)/src/corelib/io/qfilesystemiterator_unix.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qfilesystemiterator_unix.cpp + qfsfileengine.o: $(SOURCE_PATH)/src/corelib/io/qfsfileengine.cpp $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qfsfileengine.cpp @@ -169,9 +192,6 @@ qfsfileengine_iterator.o: $(SOURCE_PATH)/src/corelib/io/qfsfileengine_iterator.c qfsfileengine_unix.o: $(SOURCE_PATH)/src/corelib/io/qfsfileengine_unix.cpp $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qfsfileengine_unix.cpp -qfsfileengine_iterator_unix.o: $(SOURCE_PATH)/src/corelib/io/qfsfileengine_iterator_unix.cpp - $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qfsfileengine_iterator_unix.cpp - qabstractfileengine.o: $(SOURCE_PATH)/src/corelib/io/qabstractfileengine.cpp $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qabstractfileengine.cpp diff --git a/qmake/Makefile.win32 b/qmake/Makefile.win32 index c04bcb2..4d29537 100644 --- a/qmake/Makefile.win32 +++ b/qmake/Makefile.win32 @@ -73,6 +73,10 @@ QTOBJS= \ qbitarray.obj \ qbuffer.obj \ qcryptographichash.obj \ + qfilesystementry.obj \ + qfilesystemengine.obj \ + qfilesystemengine_win.obj \ + qfilesystemiterator_win.obj \ qfsfileengine.obj \ qfsfileengine_iterator.obj \ qbytearray.obj \ @@ -86,7 +90,6 @@ QTOBJS= \ qabstractfileengine.obj \ qfsfileengine_win.obj \ qsystemlibrary.obj \ - qfsfileengine_iterator_win.obj \ qfileinfo.obj \ qglobal.obj \ qhash.obj \ @@ -101,6 +104,7 @@ QTOBJS= \ qutfcodec.obj \ qstring.obj \ qstringlist.obj \ + qsystemerror.obj \ qtextstream.obj \ qdatastream.obj \ quuid.obj \ diff --git a/qmake/Makefile.win32-g++ b/qmake/Makefile.win32-g++ index 29fbd0a..59ac8c2 100644 --- a/qmake/Makefile.win32-g++ +++ b/qmake/Makefile.win32-g++ @@ -61,10 +61,13 @@ QTOBJS= \ qtemporaryfile.o \ qfileinfo.o \ qabstractfileengine.o \ + qfilesystementry.o \ + qfilesystemengine.o \ + qfilesystemengine_win.o \ + qfilesystemiterator_win.o \ qfsfileengine.o \ qfsfileengine_iterator.o \ qfsfileengine_win.o \ - qfsfileengine_iterator_win.o \ qglobal.o \ qhash.o \ qiodevice.o \ @@ -79,6 +82,7 @@ QTOBJS= \ qutfcodec.o \ qstring.o \ qstringlist.o \ + qsystemerror.o \ qsystemlibrary.o \ qtextstream.o \ quuid.o \ @@ -193,12 +197,21 @@ qtemporaryfile.o: $(SOURCE_PATH)/src/corelib/io/qtemporaryfile.cpp qabstractfileengine.o: $(SOURCE_PATH)/src/corelib/io/qabstractfileengine.cpp $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qabstractfileengine.cpp +qfilesystementry.o: $(SOURCE_PATH)/src/corelib/io/qfilesystementry.cpp + $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qfilesystementry.cpp + +qfilesystemengine.o: $(SOURCE_PATH)/src/corelib/io/qfilesystemengine.cpp + $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qfilesystemengine.cpp + +qfilesystemengine_win.o: $(SOURCE_PATH)/src/corelib/io/qfilesystemengine_win.cpp + $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qfilesystemengine_win.cpp + +qfilesystemiterator_win.o: $(SOURCE_PATH)/src/corelib/io/qfilesystemiterator_win.cpp + $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qfilesystemiterator_win.cpp + qfsfileengine_win.o: $(SOURCE_PATH)/src/corelib/io/qfsfileengine_win.cpp $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qfsfileengine_win.cpp -qfsfileengine_iterator_win.o: $(SOURCE_PATH)/src/corelib/io/qfsfileengine_iterator_win.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qfsfileengine_iterator_win.cpp - qfsfileengine.o: $(SOURCE_PATH)/src/corelib/io/qfsfileengine.cpp $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qfsfileengine.cpp @@ -235,6 +248,9 @@ qdatetime.o: $(SOURCE_PATH)/src/corelib/tools/qdatetime.cpp qstringlist.o: $(SOURCE_PATH)/src/corelib/tools/qstringlist.cpp $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qstringlist.cpp +qsystemerror.o: $(SOURCE_PATH)/src/corelib/kernel/qsystemerror.cpp + $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/kernel/qsystemerror.cpp + qsystemlibrary.o: $(SOURCE_PATH)/src/corelib/plugin/qsystemlibrary.cpp $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/plugin/qsystemlibrary.cpp diff --git a/qmake/Makefile.win32-g++-sh b/qmake/Makefile.win32-g++-sh index 9c7942c..a84b3f6 100644 --- a/qmake/Makefile.win32-g++-sh +++ b/qmake/Makefile.win32-g++-sh @@ -61,10 +61,13 @@ QTOBJS= \ qtemporaryfile.o \ qfileinfo.o \ qabstractfileengine.o \ + qfilesystementry.o \ + qfilesystemengine.o \ + qfilesystemengine_win.o \ + qfilesystemiterator_win.o \ qfsfileengine.o \ qfsfileengine_iterator.o \ qfsfileengine_win.o \ - qfsfileengine_iterator_win.o \ qglobal.o \ qhash.o \ qiodevice.o \ @@ -80,6 +83,7 @@ QTOBJS= \ qstring.o \ qstringlist.o \ qsystemlibrary.o \ + qsystemerror.o \ qtextstream.o \ quuid.o \ qvector.o \ @@ -192,12 +196,21 @@ qtemporaryfile.o: $(SOURCE_PATH)/src/corelib/io/qtemporaryfile.cpp qabstractfileengine.o: $(SOURCE_PATH)/src/corelib/io/qabstractfileengine.cpp $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qabstractfileengine.cpp +qfilesystementry.o: $(SOURCE_PATH)/src/corelib/io/qfilesystementry.cpp + $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qfilesystementry.cpp + +qfilesystemengine.o: $(SOURCE_PATH)/src/corelib/io/qfilesystemengine.cpp + $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qfilesystemengine.cpp + +qfilesystemengine_win.o: $(SOURCE_PATH)/src/corelib/io/qfilesystemengine_win.cpp + $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qfilesystemengine_win.cpp + +qfilesystemiterator_win.o: $(SOURCE_PATH)/src/corelib/io/qfilesystemiterator_win.cpp + $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qfilesystemiterator_win.cpp + qfsfileengine_win.o: $(SOURCE_PATH)/src/corelib/io/qfsfileengine_win.cpp $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qfsfileengine_win.cpp -qfsfileengine_iterator_win.o: $(SOURCE_PATH)/src/corelib/io/qfsfileengine_iterator_win.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qfsfileengine_iterator_win.cpp - qfsfileengine.o: $(SOURCE_PATH)/src/corelib/io/qfsfileengine.cpp $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qfsfileengine.cpp @@ -234,6 +247,9 @@ qdatetime.o: $(SOURCE_PATH)/src/corelib/tools/qdatetime.cpp qstringlist.o: $(SOURCE_PATH)/src/corelib/tools/qstringlist.cpp $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qstringlist.cpp +qsystemerror.o: $(SOURCE_PATH)/src/corelib/kernel/qsystemerror.cpp + $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/kernel/qsystemerror.cpp + qsystemlibrary.o: $(SOURCE_PATH)/src/corelib/plugin/qsystemlibrary.cpp $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/plugin/qsystemlibrary.cpp diff --git a/qmake/qmake.pri b/qmake/qmake.pri index 8f46a2e..bc7ddb8 100644 --- a/qmake/qmake.pri +++ b/qmake/qmake.pri @@ -57,6 +57,8 @@ bootstrap { #Qt code qfile.cpp \ qabstractfileengine.cpp \ qfileinfo.cpp \ + qfilesystementry.cpp \ + qfilesystemengine.cpp \ qfsfileengine.cpp \ qfsfileengine_iterator.cpp \ qglobal.cpp \ @@ -80,6 +82,7 @@ bootstrap { #Qt code quuid.cpp \ qsettings.cpp \ qlibraryinfo.cpp \ + qsystemerror.cpp \ qvariant.cpp \ qvector.cpp \ qvsnprintf.cpp \ @@ -96,6 +99,7 @@ bootstrap { #Qt code qdatetime.h \ qdatetime_p.h \ qdir.h \ + qdir_p.h \ qdiriterator.h \ qfile.h \ qabstractfileengine.h \ @@ -116,6 +120,7 @@ bootstrap { #Qt code qstring.h \ qstringlist.h \ qstringmatcher.h \ + qsystemerror_p.h \ qtemporaryfile.h \ qtextstream.h \ qurl.h \ @@ -125,14 +130,15 @@ bootstrap { #Qt code qxmlutils.h unix { - SOURCES += qfsfileengine_unix.cpp qfsfileengine_iterator_unix.cpp + SOURCES += qfilesystemengine_unix.cpp qfilesystemiterator_unix.cpp qfsfileengine_unix.cpp mac { + SOURCES += qfilesystemengine_mac.cpp SOURCES += qcore_mac.cpp qsettings_mac.cpp QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.4 #enables weak linking for 10.4 (exported) LIBS += -framework ApplicationServices } } else:win32 { - SOURCES += qfsfileengine_win.cpp qfsfileengine_iterator_win.cpp qsettings_win.cpp \ + SOURCES += qfilesystemengine_win.cpp qfsfileengine_win.cpp qfilesystemiterator_win.cpp qsettings_win.cpp \ qsystemlibrary.cpp win32-msvc*:LIBS += ole32.lib advapi32.lib win32-g++*:LIBS += -lole32 -luuid diff --git a/src/corelib/io/io.pri b/src/corelib/io/io.pri index cfb40bc..4d4ae21 100644 --- a/src/corelib/io/io.pri +++ b/src/corelib/io/io.pri @@ -9,6 +9,7 @@ HEADERS += \ io/qdataurl_p.h \ io/qdebug.h \ io/qdir.h \ + io/qdir_p.h \ io/qdiriterator.h \ io/qfile.h \ io/qfileinfo.h \ @@ -29,7 +30,11 @@ HEADERS += \ io/qfsfileengine_p.h \ io/qfsfileengine_iterator_p.h \ io/qfilesystemwatcher.h \ - io/qfilesystemwatcher_p.h + io/qfilesystemwatcher_p.h \ + io/qfilesystementry_p.h \ + io/qfilesystemengine_p.h \ + io/qfilesystemmetadata_p.h \ + io/qfilesystemiterator_p.h SOURCES += \ io/qabstractfileengine.cpp \ @@ -52,25 +57,35 @@ SOURCES += \ io/qsettings.cpp \ io/qfsfileengine.cpp \ io/qfsfileengine_iterator.cpp \ - io/qfilesystemwatcher.cpp + io/qfilesystemwatcher.cpp \ + io/qfilesystementry.cpp \ + io/qfilesystemengine.cpp win32 { SOURCES += io/qsettings_win.cpp SOURCES += io/qprocess_win.cpp SOURCES += io/qfsfileengine_win.cpp - SOURCES += io/qfsfileengine_iterator_win.cpp SOURCES += io/qfilesystemwatcher_win.cpp HEADERS += io/qfilesystemwatcher_win_p.h HEADERS += io/qwindowspipewriter_p.h SOURCES += io/qwindowspipewriter.cpp + SOURCES += io/qfilesystemengine_win.cpp + SOURCES += io/qfilesystemiterator_win.cpp } else:unix { SOURCES += io/qfsfileengine_unix.cpp - SOURCES += io/qfsfileengine_iterator_unix.cpp - symbian:SOURCES += io/qprocess_symbian.cpp - else:SOURCES += io/qprocess_unix.cpp + symbian { + SOURCES += io/qfilesystemengine_symbian.cpp + SOURCES += io/qprocess_symbian.cpp + SOURCES += io/qfilesystemiterator_symbian.cpp + } else { + SOURCES += io/qfilesystemengine_unix.cpp + SOURCES += io/qprocess_unix.cpp + SOURCES += io/qfilesystemiterator_unix.cpp + } !nacl:macx-*: { HEADERS += io/qfilesystemwatcher_fsevents_p.h + SOURCES += io/qfilesystemengine_mac.cpp SOURCES += io/qsettings_mac.cpp io/qfilesystemwatcher_fsevents.cpp } diff --git a/src/corelib/io/qabstractfileengine.cpp b/src/corelib/io/qabstractfileengine.cpp index 37a093c..67109aa 100644 --- a/src/corelib/io/qabstractfileengine.cpp +++ b/src/corelib/io/qabstractfileengine.cpp @@ -52,6 +52,10 @@ #include "qdiriterator.h" #include "qstringbuilder.h" +#include <QtCore/private/qfilesystementry_p.h> +#include <QtCore/private/qfilesystemmetadata_p.h> +#include <QtCore/private/qfilesystemengine_p.h> + QT_BEGIN_NAMESPACE /*! @@ -149,6 +153,29 @@ QAbstractFileEngineHandler::~QAbstractFileEngineHandler() } } +/* + \ìnternal + + Handles calls to custom file engine handlers. +*/ +QAbstractFileEngine *qt_custom_file_engine_handler_create(const QString &path) +{ + QAbstractFileEngine *engine = 0; + + if (qt_file_engine_handlers_in_use) { + QReadLocker locker(fileEngineHandlerMutex()); + + // check for registered handlers that can load the file + QAbstractFileEngineHandlerList *handlers = fileEngineHandlers(); + for (int i = 0; i < handlers->size(); i++) { + if ((engine = handlers->at(i)->create(path))) + break; + } + } + + return engine; +} + /*! \fn QAbstractFileEngine *QAbstractFileEngineHandler::create(const QString &fileName) const @@ -177,57 +204,17 @@ QAbstractFileEngineHandler::~QAbstractFileEngineHandler() */ QAbstractFileEngine *QAbstractFileEngine::create(const QString &fileName) { - if (qt_file_engine_handlers_in_use) { - QReadLocker locker(fileEngineHandlerMutex()); - - // check for registered handlers that can load the file - QAbstractFileEngineHandlerList *handlers = fileEngineHandlers(); - for (int i = 0; i < handlers->size(); i++) { - if (QAbstractFileEngine *ret = handlers->at(i)->create(fileName)) - return ret; - } - } - -#ifdef QT_BUILD_CORE_LIB - for (int prefixSeparator = 0; prefixSeparator < fileName.size(); ++prefixSeparator) { - QChar const ch = fileName[prefixSeparator]; - if (ch == QLatin1Char('/')) - break; - - if (ch == QLatin1Char(':')) { - if (prefixSeparator == 0) - return new QResourceFileEngine(fileName); - - if (prefixSeparator == 1) - break; - - const QStringList &paths = QDir::searchPaths(fileName.left(prefixSeparator)); - for (int i = 0; i < paths.count(); i++) { - QAbstractFileEngine *engine = create(paths.at(i) % QLatin1Char('/') % fileName.mid(prefixSeparator + 1)); - if (engine && (engine->fileFlags(QAbstractFileEngine::FlagsMask) & QAbstractFileEngine::ExistsFlag)) { - return engine; - } - delete engine; - } - - break; - } - - // There's no need to fully validate the prefix here. Consulting the - // unicode tables could be expensive and validation is already - // performed in QDir::setSearchPaths. - // - // if (!ch.isLetterOrNumber()) - // break; - } + QFileSystemEntry entry(fileName); + QFileSystemMetaData metaData; + QAbstractFileEngine *engine = QFileSystemEngine::resolveEntryAndCreateLegacyEngine(entry, metaData); + +#ifndef QT_NO_FSFILEENGINE + if (!engine) + // fall back to regular file engine + return new QFSFileEngine(entry.filePath()); #endif -#ifdef QT_NO_FSFILEENGINE - return 0; -#else - // fall back to regular file engine - return new QFSFileEngine(fileName); -#endif + return engine; } /*! diff --git a/src/corelib/io/qabstractfileengine_p.h b/src/corelib/io/qabstractfileengine_p.h index e1eba30..075ec81 100644 --- a/src/corelib/io/qabstractfileengine_p.h +++ b/src/corelib/io/qabstractfileengine_p.h @@ -74,6 +74,8 @@ public: Q_DECLARE_PUBLIC(QAbstractFileEngine) }; +QAbstractFileEngine *qt_custom_file_engine_handler_create(const QString &path); + QT_END_NAMESPACE #endif // QABSTRACTFILEENGINE_P_H diff --git a/src/corelib/io/qdir.cpp b/src/corelib/io/qdir.cpp index 426f61e..2f97c3a 100644 --- a/src/corelib/io/qdir.cpp +++ b/src/corelib/io/qdir.cpp @@ -41,6 +41,7 @@ #include "qplatformdefs.h" #include "qdir.h" +#include "qdir_p.h" #include "qabstractfileengine.h" #ifndef QT_NO_DEBUG_STREAM #include "qdebug.h" @@ -53,6 +54,10 @@ #include "qvector.h" #include "qalgorithms.h" #include "qvarlengtharray.h" +#include "qfilesystementry_p.h" +#include "qfilesystemmetadata_p.h" +#include "qfilesystemengine_p.h" +#include <qstringbuilder.h> #ifdef QT_BUILD_CORE_LIB # include "qresource.h" @@ -81,129 +86,123 @@ static QString driveSpec(const QString &path) } //************* QDirPrivate -class QDirPrivate - : public QSharedData -{ -public: - QDirPrivate(const QString &path, - const QStringList &nameFilters_ = QStringList(), - QDir::SortFlags sort_ = QDir::SortFlags(QDir::Name | QDir::IgnoreCase), - QDir::Filters filters_ = QDir::AllEntries) - : QSharedData() - , nameFilters(nameFilters_) - , sort(sort_) - , filters(filters_) +QDirPrivate::QDirPrivate(const QString &path, const QStringList &nameFilters_, QDir::SortFlags sort_, QDir::Filters filters_) + : QSharedData() + , nameFilters(nameFilters_) + , sort(sort_) + , filters(filters_) #ifdef QT3_SUPPORT - , filterSepChar(0) - , matchAllDirs(false) + , filterSepChar(0) + , matchAllDirs(false) #endif - , fileListsInitialized(false) - { - setPath(path.isEmpty() ? QString::fromLatin1(".") : path); - - bool empty = nameFilters.isEmpty(); - if (!empty) { - empty = true; - for (int i = 0; i < nameFilters.size(); ++i) { - if (!nameFilters.at(i).isEmpty()) { - empty = false; - break; - } + , fileListsInitialized(false) +{ + setPath(path.isEmpty() ? QString::fromLatin1(".") : path); + + bool empty = nameFilters.isEmpty(); + if (!empty) { + empty = true; + for (int i = 0; i < nameFilters.size(); ++i) { + if (!nameFilters.at(i).isEmpty()) { + empty = false; + break; } } - if (empty) - nameFilters = QStringList(QString::fromLatin1("*")); } + if (empty) + nameFilters = QStringList(QString::fromLatin1("*")); +} - QDirPrivate(const QDirPrivate ©) - : QSharedData(copy) - , path(copy.path) - , nameFilters(copy.nameFilters) - , sort(copy.sort) - , filters(copy.filters) +QDirPrivate::QDirPrivate(const QDirPrivate ©) + : QSharedData(copy) + , nameFilters(copy.nameFilters) + , sort(copy.sort) + , filters(copy.filters) #ifdef QT3_SUPPORT - , filterSepChar(copy.filterSepChar) - , matchAllDirs(copy.matchAllDirs) + , filterSepChar(copy.filterSepChar) + , matchAllDirs(copy.matchAllDirs) #endif - , fileListsInitialized(false) - { - } + , fileListsInitialized(false) + , dirEntry(copy.dirEntry) + , metaData(copy.metaData) +{ +} - bool exists() const - { - const QAbstractFileEngine::FileFlags info = - fileEngine->fileFlags(QAbstractFileEngine::DirectoryType - | QAbstractFileEngine::ExistsFlag - | QAbstractFileEngine::Refresh); - if (!(info & QAbstractFileEngine::DirectoryType)) - return false; - return info & QAbstractFileEngine::ExistsFlag; +bool QDirPrivate::exists() const +{ + if (fileEngine.isNull()) { + QFileSystemEngine::fillMetaData(dirEntry, metaData, + QFileSystemMetaData::ExistsAttribute | QFileSystemMetaData::DirectoryType); // always stat + return metaData.exists() && metaData.isDirectory(); } + const QAbstractFileEngine::FileFlags info = + fileEngine->fileFlags(QAbstractFileEngine::DirectoryType + | QAbstractFileEngine::ExistsFlag + | QAbstractFileEngine::Refresh); + if (!(info & QAbstractFileEngine::DirectoryType)) + return false; + return info & QAbstractFileEngine::ExistsFlag; +} - void initFileEngine(); - void initFileLists() const; - - static void sortFileList(QDir::SortFlags, QFileInfoList &, QStringList *, QFileInfoList *); - - static inline QChar getFilterSepChar(const QString &nameFilter) - { - QChar sep(QLatin1Char(';')); - int i = nameFilter.indexOf(sep, 0); - if (i == -1 && nameFilter.indexOf(QLatin1Char(' '), 0) != -1) - sep = QChar(QLatin1Char(' ')); - return sep; - } +// static +inline QChar QDirPrivate::getFilterSepChar(const QString &nameFilter) +{ + QChar sep(QLatin1Char(';')); + int i = nameFilter.indexOf(sep, 0); + if (i == -1 && nameFilter.indexOf(QLatin1Char(' '), 0) != -1) + sep = QChar(QLatin1Char(' ')); + return sep; +} - static inline QStringList splitFilters(const QString &nameFilter, QChar sep = 0) - { - if (sep == 0) - sep = getFilterSepChar(nameFilter); - QStringList ret = nameFilter.split(sep); - for (int i = 0; i < ret.count(); ++i) - ret[i] = ret[i].trimmed(); - return ret; - } +// static +inline QStringList QDirPrivate::splitFilters(const QString &nameFilter, QChar sep) +{ + if (sep == 0) + sep = getFilterSepChar(nameFilter); + QStringList ret = nameFilter.split(sep); + for (int i = 0; i < ret.count(); ++i) + ret[i] = ret[i].trimmed(); + return ret; +} - inline void setPath(QString p) - { - if ((p.endsWith(QLatin1Char('/')) || p.endsWith(QLatin1Char('\\'))) - && p.length() > 1) { +inline void QDirPrivate::setPath(const QString &path) +{ + QString p = QDir::fromNativeSeparators(path); + if (p.endsWith(QLatin1Char('/')) + && p.length() > 1 #if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN) - if (!(p.length() == 3 && p.at(1) == QLatin1Char(':'))) + && (!(p.length() == 3 && p.at(1).unicode() == ':' && p.at(0).isLetter())) #endif - p.truncate(p.length() - 1); - } - - path = p; - initFileEngine(); - - // set the path to be the qt friendly version so then we can operate on it using just / - path = fileEngine->fileName(QAbstractFileEngine::DefaultName); - clearFileLists(); + ) { + p.truncate(p.length() - 1); } - inline void clearFileLists() { - fileListsInitialized = false; - files.clear(); - fileInfos.clear(); - } - - QString path; - QStringList nameFilters; - QDir::SortFlags sort; - QDir::Filters filters; + dirEntry = QFileSystemEntry(p, QFileSystemEntry::FromInternalPath()); + metaData.clear(); + initFileEngine(); + clearFileLists(); + absoluteDirEntry = QFileSystemEntry(); +} -#ifdef QT3_SUPPORT - QChar filterSepChar; - bool matchAllDirs; -#endif +inline void QDirPrivate::clearFileLists() +{ + fileListsInitialized = false; + files.clear(); + fileInfos.clear(); +} - QScopedPointer<QAbstractFileEngine> fileEngine; +inline void QDirPrivate::resolveAbsoluteEntry() const +{ + if (!absoluteDirEntry.isEmpty() || dirEntry.isEmpty()) + return; - mutable bool fileListsInitialized; - mutable QStringList files; - mutable QFileInfoList fileInfos; -}; + if (dirEntry.isRelative()) { + QFileSystemEntry answer = QFileSystemEngine::absoluteName(dirEntry); + absoluteDirEntry = QFileSystemEntry(QDir::cleanPath(answer.filePath()), QFileSystemEntry::FromInternalPath()); + } else { + absoluteDirEntry = dirEntry; + } +} /* For sorting */ struct QDirSortItem @@ -315,12 +314,11 @@ inline void QDirPrivate::sortFileList(QDir::SortFlags sort, QFileInfoList &l, } } } - -inline void QDirPrivate::initFileLists() const +inline void QDirPrivate::initFileLists(const QDir &dir) const { if (!fileListsInitialized) { QFileInfoList l; - QDirIterator it(path, nameFilters, filters); + QDirIterator it(dir); while (it.hasNext()) { it.next(); l.append(it.fileInfo()); @@ -332,7 +330,7 @@ inline void QDirPrivate::initFileLists() const inline void QDirPrivate::initFileEngine() { - fileEngine.reset(QAbstractFileEngine::create(path)); + fileEngine.reset(QFileSystemEngine::resolveEntryAndCreateLegacyEngine(dirEntry, metaData)); } /*! @@ -597,7 +595,7 @@ void QDir::setPath(const QString &path) QString QDir::path() const { const QDirPrivate* d = d_ptr.constData(); - return d->path; + return d->dirEntry.filePath(); } /*! @@ -611,10 +609,8 @@ QString QDir::path() const QString QDir::absolutePath() const { const QDirPrivate* d = d_ptr.constData(); - QString ret = d->path; - if (QDir::isRelativePath(ret)) - ret = absoluteFilePath(QString::fromLatin1("")); - return cleanPath(ret); + d->resolveAbsoluteEntry(); + return d->absoluteDirEntry.filePath(); } /*! @@ -635,7 +631,12 @@ QString QDir::absolutePath() const */ QString QDir::canonicalPath() const { - return cleanPath(d_ptr->fileEngine->fileName(QAbstractFileEngine::CanonicalName)); + const QDirPrivate* d = d_ptr.constData(); + if (d->fileEngine.isNull()) { + QFileSystemEntry answer = QFileSystemEngine::canonicalName(d->dirEntry, d->metaData); + return answer.filePath(); + } + return d->fileEngine->fileName(QAbstractFileEngine::CanonicalName); } /*! @@ -652,10 +653,7 @@ QString QDir::canonicalPath() const QString QDir::dirName() const { const QDirPrivate* d = d_ptr.constData(); - int pos = d->path.lastIndexOf(QLatin1Char('/')); - if (pos == -1) - return d->path; - return d->path.mid(pos + 1); + return d->dirEntry.fileName(); } /*! @@ -673,7 +671,7 @@ QString QDir::filePath(const QString &fileName) const if (isAbsolutePath(fileName)) return QString(fileName); - QString ret = d->path; + QString ret = d->dirEntry.filePath(); if (!fileName.isEmpty()) { if (!ret.isEmpty() && ret[(int)ret.length()-1] != QLatin1Char('/') && fileName[0] != QLatin1Char('/')) ret += QLatin1Char('/'); @@ -696,22 +694,12 @@ QString QDir::absoluteFilePath(const QString &fileName) const if (isAbsolutePath(fileName)) return fileName; - QString ret; -#ifndef QT_NO_FSFILEENGINE - if (isRelativePath(d->path)) //get pwd - ret = QFSFileEngine::currentPath(fileName); -#endif - if (!d->path.isEmpty() && d->path != QLatin1String(".")) { - if (!ret.isEmpty() && !ret.endsWith(QLatin1Char('/'))) - ret += QLatin1Char('/'); - ret += d->path; - } - if (!fileName.isEmpty()) { - if (!ret.isEmpty() && !ret.endsWith(QLatin1Char('/'))) - ret += QLatin1Char('/'); - ret += fileName; - } - return ret; + d->resolveAbsoluteEntry(); + if (fileName.isEmpty()) + return d->absoluteDirEntry.filePath(); + if (!d->absoluteDirEntry.isRoot()) + return d->absoluteDirEntry.filePath() % QLatin1Char('/') % fileName; + return d->absoluteDirEntry.filePath() % fileName; } /*! @@ -723,7 +711,7 @@ QString QDir::absoluteFilePath(const QString &fileName) const */ QString QDir::relativeFilePath(const QString &fileName) const { - QString dir = absolutePath(); + QString dir = cleanPath(absolutePath()); QString file = cleanPath(fileName); if (isRelativePath(file) || isRelativePath(dir)) @@ -859,21 +847,22 @@ bool QDir::cd(const QString &dirName) if (dirName.isEmpty() || dirName == QLatin1String(".")) return true; - QString newPath = d->path; + QString newPath; if (isAbsolutePath(dirName)) { newPath = cleanPath(dirName); } else { if (isRoot()) { if (dirName == QLatin1String("..")) return false; + newPath = d->dirEntry.filePath(); } else { - newPath += QLatin1Char('/'); + newPath = d->dirEntry.filePath() % QLatin1Char('/'); } newPath += dirName; if (dirName.indexOf(QLatin1Char('/')) >= 0 - || d->path == QLatin1String(".") - || dirName == QLatin1String("..")) { + || dirName == QLatin1String("..") + || d->dirEntry.filePath() == QLatin1String(".")) { newPath = cleanPath(newPath); /* If newPath starts with .., we convert it to absolute to @@ -891,7 +880,6 @@ bool QDir::cd(const QString &dirName) QScopedPointer<QDirPrivate> dir(new QDirPrivate(*d_ptr.constData())); dir->setPath(newPath); - if (!dir->exists()) return false; @@ -1204,7 +1192,7 @@ void QDir::setSorting(SortFlags sort) uint QDir::count() const { const QDirPrivate* d = d_ptr.constData(); - d->initFileLists(); + d->initFileLists(*this); return d->files.count(); } @@ -1218,7 +1206,7 @@ uint QDir::count() const QString QDir::operator[](int pos) const { const QDirPrivate* d = d_ptr.constData(); - d->initFileLists(); + d->initFileLists(*this); return d->files[pos]; } @@ -1301,12 +1289,12 @@ QStringList QDir::entryList(const QStringList &nameFilters, Filters filters, sort = d->sort; if (filters == d->filters && sort == d->sort && nameFilters == d->nameFilters) { - d->initFileLists(); + d->initFileLists(*this); return d->files; } QFileInfoList l; - QDirIterator it(d->path, nameFilters, filters); + QDirIterator it(d->dirEntry.filePath(), nameFilters, filters); while (it.hasNext()) { it.next(); l.append(it.fileInfo()); @@ -1347,12 +1335,12 @@ QFileInfoList QDir::entryInfoList(const QStringList &nameFilters, Filters filter sort = d->sort; if (filters == d->filters && sort == d->sort && nameFilters == d->nameFilters) { - d->initFileLists(); + d->initFileLists(*this); return d->fileInfos; } QFileInfoList l; - QDirIterator it(d->path, nameFilters, filters); + QDirIterator it(d->dirEntry.filePath(), nameFilters, filters); while (it.hasNext()) { it.next(); l.append(it.fileInfo()); @@ -1367,8 +1355,11 @@ QFileInfoList QDir::entryInfoList(const QStringList &nameFilters, Filters filter Returns true on success; otherwise returns false. + If the directory already exists when this function is called, it will return false. + \sa rmdir() */ +// ### Qt5: behaviour when directory already exists should be made consistent for mkdir and mkpath bool QDir::mkdir(const QString &dirName) const { const QDirPrivate* d = d_ptr.constData(); @@ -1379,6 +1370,8 @@ bool QDir::mkdir(const QString &dirName) const } QString fn = filePath(dirName); + if (d->fileEngine.isNull()) + return QFileSystemEngine::createDirectory(QFileSystemEntry(fn), false); return d->fileEngine->mkdir(fn, false); } @@ -1401,6 +1394,9 @@ bool QDir::rmdir(const QString &dirName) const } QString fn = filePath(dirName); + if (d->fileEngine.isNull()) + return QFileSystemEngine::removeDirectory(QFileSystemEntry(fn), false); + return d->fileEngine->rmdir(fn, false); } @@ -1412,8 +1408,11 @@ bool QDir::rmdir(const QString &dirName) const Returns true if successful; otherwise returns false. + If the path already exists when this function is called, it will return true. + \sa rmpath() */ +// ### Qt5: behaviour when directory already exists should be made consistent for mkdir and mkpath bool QDir::mkpath(const QString &dirPath) const { const QDirPrivate* d = d_ptr.constData(); @@ -1424,6 +1423,8 @@ bool QDir::mkpath(const QString &dirPath) const } QString fn = filePath(dirPath); + if (d->fileEngine.isNull()) + return QFileSystemEngine::createDirectory(QFileSystemEntry(fn), true); return d->fileEngine->mkdir(fn, true); } @@ -1448,6 +1449,8 @@ bool QDir::rmpath(const QString &dirPath) const } QString fn = filePath(dirPath); + if (d->fileEngine.isNull()) + return QFileSystemEngine::removeDirectory(QFileSystemEntry(fn), true); return d->fileEngine->rmdir(fn, true); } @@ -1464,6 +1467,13 @@ bool QDir::isReadable() const { const QDirPrivate* d = d_ptr.constData(); + if (d->fileEngine.isNull()) { + if (!d->metaData.hasFlags(QFileSystemMetaData::UserReadPermission)) + QFileSystemEngine::fillMetaData(d->dirEntry, d->metaData, QFileSystemMetaData::UserReadPermission); + + return (d->metaData.permissions() & QFile::ReadUser) != 0; + } + const QAbstractFileEngine::FileFlags info = d->fileEngine->fileFlags(QAbstractFileEngine::DirectoryType | QAbstractFileEngine::PermsMask); @@ -1502,6 +1512,8 @@ bool QDir::exists() const */ bool QDir::isRoot() const { + if (d_ptr->fileEngine.isNull()) + return d_ptr->dirEntry.isRoot(); return d_ptr->fileEngine->fileFlags(QAbstractFileEngine::FlagsMask) & QAbstractFileEngine::RootFlag; } @@ -1532,6 +1544,8 @@ bool QDir::isRoot() const */ bool QDir::isRelative() const { + if (d_ptr->fileEngine.isNull()) + return d_ptr->dirEntry.isRelative(); return d_ptr->fileEngine->isRelativePath(); } @@ -1543,20 +1557,23 @@ bool QDir::isRelative() const \sa isAbsolute() isAbsolutePath() isRelative() cleanPath() */ -bool QDir::makeAbsolute() // ### What do the return values signify? +bool QDir::makeAbsolute() { - QString absolutePath = d_ptr.constData()->fileEngine->fileName(QAbstractFileEngine::AbsoluteName); - if (QDir::isRelativePath(absolutePath)) - return false; - - QScopedPointer<QDirPrivate> dir(new QDirPrivate(*d_ptr.constData())); - dir->setPath(absolutePath); - - d_ptr = dir.take(); - - if (!(d_ptr->fileEngine->fileFlags(QAbstractFileEngine::TypesMask) & QAbstractFileEngine::DirectoryType)) - return false; + const QDirPrivate *d = d_ptr.constData(); + QScopedPointer<QDirPrivate> dir; + if (!d->fileEngine.isNull()) { + QString absolutePath = d->fileEngine->fileName(QAbstractFileEngine::AbsoluteName); + if (QDir::isRelativePath(absolutePath)) + return false; + dir.reset(new QDirPrivate(*d_ptr.constData())); + dir->setPath(absolutePath); + } else { // native FS + d->resolveAbsoluteEntry(); + dir.reset(new QDirPrivate(*d_ptr.constData())); + dir->setPath(d->absoluteDirEntry.filePath()); + } + d_ptr = dir.take(); // actually detach return true; } @@ -1576,17 +1593,24 @@ bool QDir::operator==(const QDir &dir) const if (d == other) return true; - if (d->fileEngine->caseSensitive() != other->fileEngine->caseSensitive()) - return false; + Qt::CaseSensitivity sensitive; + if (d->fileEngine.isNull() || other->fileEngine.isNull()) { + if (d->fileEngine.data() != other->fileEngine.data()) // one is native, the other is a custom file-engine + return false; + + sensitive = QFileSystemEngine::isCaseSensitive() ? Qt::CaseSensitive : Qt::CaseInsensitive; + } else { + if (d->fileEngine->caseSensitive() != other->fileEngine->caseSensitive()) + return false; + sensitive = d->fileEngine->caseSensitive() ? Qt::CaseSensitive : Qt::CaseInsensitive; + } + if (d->filters == other->filters && d->sort == other->sort && d->nameFilters == other->nameFilters) { - QString dir1 = absolutePath(), dir2 = dir.absolutePath(); - if (!other->fileEngine->caseSensitive()) - return (dir1.toLower() == dir2.toLower()); - - return (dir1 == dir2); - + d->resolveAbsoluteEntry(); + other->resolveAbsoluteEntry(); + return d->absoluteDirEntry.filePath().compare(other->absoluteDirEntry.filePath(), sensitive) == 0; } return false; } @@ -1735,12 +1759,7 @@ QChar QDir::separator() */ bool QDir::setCurrent(const QString &path) { -#ifdef QT_NO_FSFILEENGINE - Q_UNUSED(path); - return false; -#else - return QFSFileEngine::setCurrentPath(path); -#endif + return QFileSystemEngine::setCurrentPath(QFileSystemEntry(path)); } /*! @@ -1761,11 +1780,7 @@ bool QDir::setCurrent(const QString &path) */ QString QDir::currentPath() { -#ifdef QT_NO_FSFILEENGINE - return QString(); -#else - return QFSFileEngine::currentPath(); -#endif + return QFileSystemEngine::currentPath().filePath(); } /*! @@ -1823,11 +1838,7 @@ QString QDir::currentPath() */ QString QDir::homePath() { -#ifdef QT_NO_FSFILEENGINE - return QString(); -#else - return cleanPath(QFSFileEngine::homePath()); -#endif + return QFileSystemEngine::homePath(); } /*! @@ -1866,11 +1877,7 @@ QString QDir::homePath() */ QString QDir::tempPath() { -#ifdef QT_NO_FSFILEENGINE - return QString(); -#else - return cleanPath(QFSFileEngine::tempPath()); -#endif + return QFileSystemEngine::tempPath(); } /*! @@ -1897,11 +1904,7 @@ QString QDir::tempPath() */ QString QDir::rootPath() { -#ifdef QT_NO_FSFILEENGINE - return QString(); -#else - return QFSFileEngine::rootPath(); -#endif + return QFileSystemEngine::rootPath(); } /*! @@ -2098,6 +2101,7 @@ bool QDir::isRelativePath(const QString &path) void QDir::refresh() const { QDirPrivate *d = const_cast<QDir*>(this)->d_ptr.data(); + d->metaData.clear(); d->initFileEngine(); d->clearFileLists(); } diff --git a/src/corelib/io/qdir_p.h b/src/corelib/io/qdir_p.h new file mode 100644 index 0000000..5f97c1f --- /dev/null +++ b/src/corelib/io/qdir_p.h @@ -0,0 +1,98 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDIR_PRIVATE_H +#define QDIR_PRIVATE_H + +#include "qfilesystementry_p.h" +#include "qfilesystemmetadata_p.h" + +QT_BEGIN_NAMESPACE + +class QDirPrivate : public QSharedData +{ +public: + QDirPrivate(const QString &path, const QStringList &nameFilters_ = QStringList(), + QDir::SortFlags sort_ = QDir::SortFlags(QDir::Name | QDir::IgnoreCase), + QDir::Filters filters_ = QDir::AllEntries); + + QDirPrivate(const QDirPrivate ©); + + bool exists() const; + + void initFileEngine(); + void initFileLists(const QDir &dir) const; + + static void sortFileList(QDir::SortFlags, QFileInfoList &, QStringList *, QFileInfoList *); + + static inline QChar getFilterSepChar(const QString &nameFilter); + + static inline QStringList splitFilters(const QString &nameFilter, QChar sep = 0); + + inline void setPath(const QString &path); + + inline void clearFileLists(); + + inline void resolveAbsoluteEntry() const; + + QStringList nameFilters; + QDir::SortFlags sort; + QDir::Filters filters; + +#ifdef QT3_SUPPORT + QChar filterSepChar; + bool matchAllDirs; +#endif + + QScopedPointer<QAbstractFileEngine> fileEngine; + + mutable bool fileListsInitialized; + mutable QStringList files; + mutable QFileInfoList fileInfos; + + QFileSystemEntry dirEntry; + mutable QFileSystemEntry absoluteDirEntry; + mutable QFileSystemMetaData metaData; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/corelib/io/qdiriterator.cpp b/src/corelib/io/qdiriterator.cpp index fd4b9c1..a8192ea 100644 --- a/src/corelib/io/qdiriterator.cpp +++ b/src/corelib/io/qdiriterator.cpp @@ -90,6 +90,7 @@ */ #include "qdiriterator.h" +#include "qdir_p.h" #include "qabstractfileengine.h" @@ -97,36 +98,41 @@ #include <QtCore/qstack.h> #include <QtCore/qvariant.h> +#include <QtCore/private/qfilesystemiterator_p.h> +#include <QtCore/private/qfilesystementry_p.h> +#include <QtCore/private/qfilesystemmetadata_p.h> +#include <QtCore/private/qfilesystemengine_p.h> +#include <QtCore/qfsfileengine.h> +#include <QtCore/private/qfileinfo_p.h> + QT_BEGIN_NAMESPACE -class QDirIteratorPrivateIteratorStack : public QStack<QAbstractFileEngineIterator *> +template <class Iterator> +class QDirIteratorPrivateIteratorStack : public QStack<Iterator *> { public: - ~QDirIteratorPrivateIteratorStack(); + ~QDirIteratorPrivateIteratorStack() + { + qDeleteAll(*this); + } }; -QDirIteratorPrivateIteratorStack::~QDirIteratorPrivateIteratorStack() -{ - qDeleteAll(*this); -} - - class QDirIteratorPrivate { public: - QDirIteratorPrivate(const QString &path, const QStringList &nameFilters, - QDir::Filters filters, QDirIterator::IteratorFlags flags); - ~QDirIteratorPrivate(); + QDirIteratorPrivate(const QFileSystemEntry &entry, const QStringList &nameFilters, + QDir::Filters filters, QDirIterator::IteratorFlags flags, bool resolveEngine = true); void advance(); + bool entryMatches(const QString & fileName, const QFileInfo &fileInfo); void pushDirectory(const QFileInfo &fileInfo); void checkAndPushDirectory(const QFileInfo &); bool matchesFilters(const QString &fileName, const QFileInfo &fi) const; QScopedPointer<QAbstractFileEngine> engine; - const QString path; + QFileSystemEntry dirEntry; const QStringList nameFilters; const QDir::Filters filters; const QDirIterator::IteratorFlags iteratorFlags; @@ -135,23 +141,22 @@ public: QVector<QRegExp> nameRegExps; #endif - QDirIteratorPrivateIteratorStack fileEngineIterators; + QDirIteratorPrivateIteratorStack<QAbstractFileEngineIterator> fileEngineIterators; + QDirIteratorPrivateIteratorStack<QFileSystemIterator> nativeIterators; + QFileInfo currentFileInfo; QFileInfo nextFileInfo; // Loop protection QSet<QString> visitedLinks; - - QDirIterator *q; }; /*! \internal */ -QDirIteratorPrivate::QDirIteratorPrivate(const QString &path, const QStringList &nameFilters, - QDir::Filters filters, QDirIterator::IteratorFlags flags) - : engine(QAbstractFileEngine::create(path)) - , path(path) +QDirIteratorPrivate::QDirIteratorPrivate(const QFileSystemEntry &entry, const QStringList &nameFilters, + QDir::Filters filters, QDirIterator::IteratorFlags flags, bool resolveEngine) + : dirEntry(entry) , nameFilters(nameFilters.contains(QLatin1String("*")) ? QStringList() : nameFilters) , filters(QDir::NoFilter == filters ? QDir::AllEntries : filters) , iteratorFlags(flags) @@ -164,22 +169,19 @@ QDirIteratorPrivate::QDirIteratorPrivate(const QString &path, const QStringList (filters & QDir::CaseSensitive) ? Qt::CaseSensitive : Qt::CaseInsensitive, QRegExp::Wildcard)); #endif + QFileSystemMetaData metaData; + if (resolveEngine) + engine.reset(QFileSystemEngine::resolveEntryAndCreateLegacyEngine(dirEntry, metaData)); + QFileInfo fileInfo(new QFileInfoPrivate(dirEntry, metaData)); // Populate fields for hasNext() and next() - pushDirectory(QFileInfo(path)); + pushDirectory(fileInfo); advance(); } /*! \internal */ -QDirIteratorPrivate::~QDirIteratorPrivate() -{ -} - -/*! - \internal -*/ void QDirIteratorPrivate::pushDirectory(const QFileInfo &fileInfo) { QString path = fileInfo.filePath(); @@ -201,34 +203,63 @@ void QDirIteratorPrivate::pushDirectory(const QFileInfo &fileInfo) } else { // No iterator; no entry list. } + } else { + QFileSystemIterator *it = new QFileSystemIterator(fileInfo.d_ptr->fileEntry, + filters, nameFilters, iteratorFlags); + nativeIterators << it; } } -/*! - \internal -*/ -void QDirIteratorPrivate::advance() +inline bool QDirIteratorPrivate::entryMatches(const QString & fileName, const QFileInfo &fileInfo) { - while (!fileEngineIterators.isEmpty()) { + checkAndPushDirectory(fileInfo); - // Find the next valid iterator that matches the filters. - while (fileEngineIterators.top()->hasNext()) { - QAbstractFileEngineIterator *it = fileEngineIterators.top(); - it->next(); + if (matchesFilters(fileName, fileInfo)) { + currentFileInfo = nextFileInfo; + nextFileInfo = fileInfo; - const QFileInfo info = it->currentFileInfo(); - checkAndPushDirectory(it->currentFileInfo()); + //We found a matching entry. + return true; + } - if (matchesFilters(it->currentFileName(), info)) { - currentFileInfo = nextFileInfo; - nextFileInfo = info; + return false; +} - //We found a matching entry. - return; +/*! + \internal +*/ +void QDirIteratorPrivate::advance() +{ + if (engine) { + while (!fileEngineIterators.isEmpty()) { + // Find the next valid iterator that matches the filters. + QAbstractFileEngineIterator *it; + while (it = fileEngineIterators.top(), it->hasNext()) { + it->next(); + if (entryMatches(it->currentFileName(), it->currentFileInfo())) + return; } + + fileEngineIterators.pop(); + delete it; } + } else { + QFileSystemEntry nextEntry; + QFileSystemMetaData nextMetaData; + + while (!nativeIterators.isEmpty()) { + // Find the next valid iterator that matches the filters. + QFileSystemIterator *it; + while (it = nativeIterators.top(), it->advance(nextEntry, nextMetaData)) { + QFileInfo info(new QFileInfoPrivate(nextEntry, nextMetaData)); + + if (entryMatches(nextEntry.fileName(), info)) + return; + } - delete fileEngineIterators.pop(); + nativeIterators.pop(); + delete it; + } } currentFileInfo = nextFileInfo; @@ -262,7 +293,8 @@ void QDirIteratorPrivate::checkAndPushDirectory(const QFileInfo &fileInfo) return; // Stop link loops - if (visitedLinks.contains(fileInfo.canonicalFilePath())) + if (!visitedLinks.isEmpty() && + visitedLinks.contains(fileInfo.canonicalFilePath())) return; pushDirectory(fileInfo); @@ -373,9 +405,11 @@ bool QDirIteratorPrivate::matchesFilters(const QString &fileName, const QFileInf \sa hasNext(), next(), IteratorFlags */ QDirIterator::QDirIterator(const QDir &dir, IteratorFlags flags) - : d(new QDirIteratorPrivate(dir.path(), dir.nameFilters(), dir.filter(), flags)) { - d->q = this; + // little trick to get hold of the QDirPrivate while there is no API on QDir to give it to us + class MyQDir : public QDir { public: const QDirPrivate *priv() const { return d_ptr.constData(); } }; + const QDirPrivate *other = static_cast<const MyQDir*>(&dir)->priv(); + d.reset(new QDirIteratorPrivate(other->dirEntry, other->nameFilters, other->filters, flags, !other->fileEngine.isNull())); } /*! @@ -395,9 +429,8 @@ QDirIterator::QDirIterator(const QDir &dir, IteratorFlags flags) \sa hasNext(), next(), IteratorFlags */ QDirIterator::QDirIterator(const QString &path, QDir::Filters filters, IteratorFlags flags) - : d(new QDirIteratorPrivate(path, QStringList(), filters, flags)) + : d(new QDirIteratorPrivate(QFileSystemEntry(path), QStringList(), filters, flags)) { - d->q = this; } /*! @@ -413,9 +446,8 @@ QDirIterator::QDirIterator(const QString &path, QDir::Filters filters, IteratorF \sa hasNext(), next(), IteratorFlags */ QDirIterator::QDirIterator(const QString &path, IteratorFlags flags) - : d(new QDirIteratorPrivate(path, QStringList(), QDir::NoFilter, flags)) + : d(new QDirIteratorPrivate(QFileSystemEntry(path), QStringList(), QDir::NoFilter, flags)) { - d->q = this; } /*! @@ -436,9 +468,8 @@ QDirIterator::QDirIterator(const QString &path, IteratorFlags flags) */ QDirIterator::QDirIterator(const QString &path, const QStringList &nameFilters, QDir::Filters filters, IteratorFlags flags) - : d(new QDirIteratorPrivate(path, nameFilters, filters, flags)) + : d(new QDirIteratorPrivate(QFileSystemEntry(path), nameFilters, filters, flags)) { - d->q = this; } /*! @@ -472,7 +503,10 @@ QString QDirIterator::next() */ bool QDirIterator::hasNext() const { - return !d->fileEngineIterators.isEmpty(); + if (d->engine) + return !d->fileEngineIterators.isEmpty(); + else + return !d->nativeIterators.isEmpty(); } /*! @@ -515,7 +549,7 @@ QFileInfo QDirIterator::fileInfo() const */ QString QDirIterator::path() const { - return d->path; + return d->dirEntry.filePath(); } QT_END_NAMESPACE diff --git a/src/corelib/io/qfile.cpp b/src/corelib/io/qfile.cpp index 50e9a8f..85e78a6 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 @@ -992,8 +993,14 @@ bool QFile::open(OpenMode mode) return false; } +#ifdef Q_OS_SYMBIAN + // For symbian, the unbuffered flag is used to control write-behind cache behaviour + if (fileEngine()->open(mode)) +#else // QIODevice provides the buffering, so there's no need to request it from the file engine. - if (fileEngine()->open(mode | QIODevice::Unbuffered)) { + if (fileEngine()->open(mode | QIODevice::Unbuffered)) +#endif + { QIODevice::open(mode); if (mode & Append) seek(size()); @@ -1223,6 +1230,7 @@ bool QFile::unmap(uchar *address) d->setError(d->fileEngine->error(), d->fileEngine->errorString()); return success; } + d->setError(PermissionsError, tr("No file engine available or engine does not support UnMapExtension")); return false; } @@ -1477,7 +1485,17 @@ bool QFile::atEnd() const } /*! - \reimp + For random-access devices, this function sets the current position + to \a pos, returning true on success, or false if an error occurred. + For sequential devices, the default behavior is to do nothing and + return false. + + Seeking beyond the end of a file: + If the position is beyond the end of a file, then seek() shall not + immediately extend the file. If a write is performed at this position, + then the file shall be extended. The content of the file between the + previous end of file and the newly written data is UNDEFINED and + varies between platforms and file systems. */ bool QFile::seek(qint64 off) diff --git a/src/corelib/io/qfileinfo.cpp b/src/corelib/io/qfileinfo.cpp index 7eca212..9041c94 100644 --- a/src/corelib/io/qfileinfo.cpp +++ b/src/corelib/io/qfileinfo.cpp @@ -51,7 +51,47 @@ QString QFileInfoPrivate::getFileName(QAbstractFileEngine::FileName name) const { if (cache_enabled && !fileNames[(int)name].isNull()) return fileNames[(int)name]; - QString ret = fileEngine->fileName(name); + + QString ret; + if (fileEngine == 0) { // local file; use the QFileSystemEngine directly + switch (name) { + case QAbstractFileEngine::CanonicalName: + case QAbstractFileEngine::CanonicalPathName: { + QFileSystemEntry entry = QFileSystemEngine::canonicalName(fileEntry, metaData); + if (cache_enabled) { // be smart and store both + fileNames[QAbstractFileEngine::CanonicalName] = entry.filePath(); + fileNames[QAbstractFileEngine::CanonicalPathName] = entry.path(); + } + if (name == QAbstractFileEngine::CanonicalName) + ret = entry.filePath(); + else + ret = entry.path(); + break; + } + case QAbstractFileEngine::LinkName: + ret = QFileSystemEngine::getLinkTarget(fileEntry, metaData).filePath(); + break; + case QAbstractFileEngine::BundleName: + ret = QFileSystemEngine::bundleName(fileEntry); + break; + case QAbstractFileEngine::AbsoluteName: + case QAbstractFileEngine::AbsolutePathName: { + QFileSystemEntry entry = QFileSystemEngine::absoluteName(fileEntry); + if (cache_enabled) { // be smart and store both + fileNames[QAbstractFileEngine::AbsoluteName] = entry.filePath(); + fileNames[QAbstractFileEngine::AbsolutePathName] = entry.path(); + } + if (name == QAbstractFileEngine::AbsoluteName) + ret = entry.filePath(); + else + ret = entry.path(); + break; + } + default: break; + } + } else { + ret = fileEngine->fileName(name); + } if (ret.isNull()) ret = QLatin1String(""); if (cache_enabled) @@ -63,7 +103,19 @@ QString QFileInfoPrivate::getFileOwner(QAbstractFileEngine::FileOwner own) const { if (cache_enabled && !fileOwners[(int)own].isNull()) return fileOwners[(int)own]; - QString ret = fileEngine->owner(own); + QString ret; + if (fileEngine == 0) { + switch (own) { + case QAbstractFileEngine::OwnerUser: + ret = QFileSystemEngine::resolveUserName(fileEntry, metaData); + break; + case QAbstractFileEngine::OwnerGroup: + ret = QFileSystemEngine::resolveGroupName(fileEntry, metaData); + break; + } + } else { + ret = fileEngine->owner(own); + } if (ret.isNull()) ret = QLatin1String(""); if (cache_enabled) @@ -73,6 +125,7 @@ QString QFileInfoPrivate::getFileOwner(QAbstractFileEngine::FileOwner own) const uint QFileInfoPrivate::getFileFlags(QAbstractFileEngine::FileFlags request) const { + Q_ASSERT(fileEngine); // should never be called when using the native FS // We split the testing into tests for for LinkType, BundleType, PermsMask // and the rest. // Tests for file permissions on Windows can be slow, expecially on network @@ -133,6 +186,7 @@ uint QFileInfoPrivate::getFileFlags(QAbstractFileEngine::FileFlags request) cons QDateTime &QFileInfoPrivate::getFileTime(QAbstractFileEngine::FileTime request) const { + Q_ASSERT(fileEngine); // should never be called when using the native FS if (!cache_enabled) clearFlags(); uint cf; @@ -237,6 +291,13 @@ QDateTime &QFileInfoPrivate::getFileTime(QAbstractFileEngine::FileTime request) */ /*! + \internal +*/ +QFileInfo::QFileInfo(QFileInfoPrivate *p) : d_ptr(p) +{ +} + +/*! Constructs an empty QFileInfo object. Note that an empty QFileInfo object contain no file reference. @@ -330,23 +391,22 @@ bool QFileInfo::operator==(const QFileInfo &fileinfo) const return true; if (d->isDefaultConstructed || fileinfo.d_ptr->isDefaultConstructed) return false; - if (d->fileEngine->caseSensitive() != fileinfo.d_ptr->fileEngine->caseSensitive()) - return false; - if (fileinfo.size() == size()) { //if the size isn't the same... - QString file1 = canonicalFilePath(), - file2 = fileinfo.canonicalFilePath(); - if (file1.length() == file2.length()) { - if (!fileinfo.d_ptr->fileEngine->caseSensitive()) { - for (int i = 0; i < file1.length(); i++) { - if (file1.at(i).toLower() != file2.at(i).toLower()) - return false; - } - return true; - } - return (file1 == file2); - } + Qt::CaseSensitivity sensitive; + if (d->fileEngine == 0 || fileinfo.d_ptr->fileEngine == 0) { + if (d->fileEngine != fileinfo.d_ptr->fileEngine) // one is native, the other is a custom file-engine + return false; + + sensitive = QFileSystemEngine::isCaseSensitive() ? Qt::CaseSensitive : Qt::CaseInsensitive; + } else { + if (d->fileEngine->caseSensitive() != fileinfo.d_ptr->fileEngine->caseSensitive()) + return false; + sensitive = d->fileEngine->caseSensitive() ? Qt::CaseSensitive : Qt::CaseInsensitive; } - return false; + + if (fileinfo.size() != size()) //if the size isn't the same... + return false; + + return canonicalFilePath().compare(fileinfo.canonicalFilePath(), sensitive) == 0; } /*! @@ -502,7 +562,7 @@ QString QFileInfo::absolutePath() const if (d->isDefaultConstructed) { return QLatin1String(""); - } else if (d->fileName.isEmpty()) { + } else if (d->fileEntry.isEmpty()) { qWarning("QFileInfo::absolutePath: Constructed with empty filename"); return QLatin1String(""); } @@ -539,7 +599,7 @@ QString QFileInfo::path() const Q_D(const QFileInfo); if (d->isDefaultConstructed) return QLatin1String(""); - return d->getFileName(QAbstractFileEngine::PathName); + return d->fileEntry.path(); } /*! @@ -563,6 +623,8 @@ bool QFileInfo::isRelative() const Q_D(const QFileInfo); if (d->isDefaultConstructed) return true; + if (d->fileEngine == 0) + return d->fileEntry.isRelative(); return d->fileEngine->isRelativePath(); } @@ -576,12 +638,10 @@ bool QFileInfo::isRelative() const bool QFileInfo::makeAbsolute() { if (d_ptr.constData()->isDefaultConstructed - || !d_ptr.constData()->fileEngine->isRelativePath()) + || !d_ptr.constData()->fileEntry.isRelative()) return false; - QString absFileName = d_ptr.constData()->getFileName(QAbstractFileEngine::AbsoluteName); - // QSharedDataPointer::operator->() will detach. - setFile(absFileName); + setFile(absoluteFilePath()); return true; } @@ -596,6 +656,11 @@ bool QFileInfo::exists() const Q_D(const QFileInfo); if (d->isDefaultConstructed) return false; + if (d->fileEngine == 0) { + if (!d->cache_enabled || !d->metaData.hasFlags(QFileSystemMetaData::ExistsAttribute)) + QFileSystemEngine::fillMetaData(d->fileEntry, d->metaData, QFileSystemMetaData::ExistsAttribute); + return d->metaData.exists(); + } return d->getFileFlags(QAbstractFileEngine::ExistsFlag); } @@ -623,7 +688,7 @@ QString QFileInfo::filePath() const Q_D(const QFileInfo); if (d->isDefaultConstructed) return QLatin1String(""); - return d->getFileName(QAbstractFileEngine::DefaultName); + return d->fileEntry.filePath(); } /*! @@ -642,7 +707,7 @@ QString QFileInfo::fileName() const Q_D(const QFileInfo); if (d->isDefaultConstructed) return QLatin1String(""); - return d->getFileName(QAbstractFileEngine::BaseName); + return d->fileEntry.fileName(); } /*! @@ -686,7 +751,7 @@ QString QFileInfo::baseName() const Q_D(const QFileInfo); if (d->isDefaultConstructed) return QLatin1String(""); - return d->getFileName(QAbstractFileEngine::BaseName).section(QLatin1Char('.'), 0, 0); + return d->fileEntry.baseName(); } /*! @@ -705,9 +770,7 @@ QString QFileInfo::completeBaseName() const Q_D(const QFileInfo); if (d->isDefaultConstructed) return QLatin1String(""); - QString name = d->getFileName(QAbstractFileEngine::BaseName); - int index = name.lastIndexOf(QLatin1Char('.')); - return (index == -1) ? name : name.left(index); + return d->fileEntry.completeBaseName(); } /*! @@ -726,11 +789,7 @@ QString QFileInfo::completeSuffix() const Q_D(const QFileInfo); if (d->isDefaultConstructed) return QLatin1String(""); - QString fileName = d->getFileName(QAbstractFileEngine::BaseName); - int firstDot = fileName.indexOf(QLatin1Char('.')); - if (firstDot == -1) - return QLatin1String(""); - return fileName.mid(firstDot + 1); + return d->fileEntry.completeSuffix(); } /*! @@ -753,11 +812,7 @@ QString QFileInfo::suffix() const Q_D(const QFileInfo); if (d->isDefaultConstructed) return QLatin1String(""); - QString fileName = d->getFileName(QAbstractFileEngine::BaseName); - int lastDot = fileName.lastIndexOf(QLatin1Char('.')); - if (lastDot == -1) - return QLatin1String(""); - return fileName.mid(lastDot + 1); + return d->fileEntry.suffix(); } @@ -781,8 +836,9 @@ QString QFileInfo::suffix() const */ QDir QFileInfo::dir() const { + Q_D(const QFileInfo); // ### Qt5: Maybe rename this to parentDirectory(), considering what it actually do? - return QDir(path()); + return QDir(d->fileEntry.path()); } /*! @@ -818,6 +874,11 @@ bool QFileInfo::isReadable() const Q_D(const QFileInfo); if (d->isDefaultConstructed) return false; + if (d->fileEngine == 0) { + if (!d->cache_enabled || !d->metaData.hasFlags(QFileSystemMetaData::UserReadPermission)) + QFileSystemEngine::fillMetaData(d->fileEntry, d->metaData, QFileSystemMetaData::UserReadPermission); + return (d->metaData.permissions() & QFile::ReadUser) != 0; + } return d->getFileFlags(QAbstractFileEngine::ReadUserPerm); } @@ -831,6 +892,11 @@ bool QFileInfo::isWritable() const Q_D(const QFileInfo); if (d->isDefaultConstructed) return false; + if (d->fileEngine == 0) { + if (!d->cache_enabled || !d->metaData.hasFlags(QFileSystemMetaData::UserWritePermission)) + QFileSystemEngine::fillMetaData(d->fileEntry, d->metaData, QFileSystemMetaData::UserWritePermission); + return (d->metaData.permissions() & QFile::WriteUser) != 0; + } return d->getFileFlags(QAbstractFileEngine::WriteUserPerm); } @@ -844,6 +910,11 @@ bool QFileInfo::isExecutable() const Q_D(const QFileInfo); if (d->isDefaultConstructed) return false; + if (d->fileEngine == 0) { + if (!d->cache_enabled || !d->metaData.hasFlags(QFileSystemMetaData::UserExecutePermission)) + QFileSystemEngine::fillMetaData(d->fileEntry, d->metaData, QFileSystemMetaData::UserExecutePermission); + return (d->metaData.permissions() & QFile::ExeUser) != 0; + } return d->getFileFlags(QAbstractFileEngine::ExeUserPerm); } @@ -858,6 +929,11 @@ bool QFileInfo::isHidden() const Q_D(const QFileInfo); if (d->isDefaultConstructed) return false; + if (d->fileEngine == 0) { + if (!d->cache_enabled || !d->metaData.hasFlags(QFileSystemMetaData::HiddenAttribute)) + QFileSystemEngine::fillMetaData(d->fileEntry, d->metaData, QFileSystemMetaData::HiddenAttribute); + return d->metaData.isHidden(); + } return d->getFileFlags(QAbstractFileEngine::HiddenFlag); } @@ -873,6 +949,11 @@ bool QFileInfo::isFile() const Q_D(const QFileInfo); if (d->isDefaultConstructed) return false; + if (d->fileEngine == 0) { + if (!d->cache_enabled || !d->metaData.hasFlags(QFileSystemMetaData::FileType)) + QFileSystemEngine::fillMetaData(d->fileEntry, d->metaData, QFileSystemMetaData::FileType); + return d->metaData.isFile(); + } return d->getFileFlags(QAbstractFileEngine::FileType); } @@ -887,6 +968,11 @@ bool QFileInfo::isDir() const Q_D(const QFileInfo); if (d->isDefaultConstructed) return false; + if (d->fileEngine == 0) { + if (!d->cache_enabled || !d->metaData.hasFlags(QFileSystemMetaData::DirectoryType)) + QFileSystemEngine::fillMetaData(d->fileEntry, d->metaData, QFileSystemMetaData::DirectoryType); + return d->metaData.isDirectory(); + } return d->getFileFlags(QAbstractFileEngine::DirectoryType); } @@ -903,6 +989,11 @@ bool QFileInfo::isBundle() const Q_D(const QFileInfo); if (d->isDefaultConstructed) return false; + if (d->fileEngine == 0) { + if (!d->cache_enabled || !d->metaData.hasFlags(QFileSystemMetaData::BundleType)) + QFileSystemEngine::fillMetaData(d->fileEntry, d->metaData, QFileSystemMetaData::BundleType); + return d->metaData.isBundle(); + } return d->getFileFlags(QAbstractFileEngine::BundleType); } @@ -928,6 +1019,11 @@ bool QFileInfo::isSymLink() const Q_D(const QFileInfo); if (d->isDefaultConstructed) return false; + if (d->fileEngine == 0) { + if (!d->cache_enabled || !d->metaData.hasFlags(QFileSystemMetaData::LegacyLinkType)) + QFileSystemEngine::fillMetaData(d->fileEntry, d->metaData, QFileSystemMetaData::LegacyLinkType); + return d->metaData.isLegacyLink(); + } return d->getFileFlags(QAbstractFileEngine::LinkType); } @@ -941,6 +1037,20 @@ bool QFileInfo::isRoot() const Q_D(const QFileInfo); if (d->isDefaultConstructed) return true; + if (d->fileEngine == 0) { + if (d->fileEntry.isRoot()) { +#if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN) + //the path is a drive root, but the drive may not exist + //for backward compatibility, return true only if the drive exists + if (!d->cache_enabled || !d->metaData.hasFlags(QFileSystemMetaData::ExistsAttribute)) + QFileSystemEngine::fillMetaData(d->fileEntry, d->metaData, QFileSystemMetaData::ExistsAttribute); + return d->metaData.exists(); +#else + return true; +#endif + } + return false; + } return d->getFileFlags(QAbstractFileEngine::RootFlag); } @@ -1003,6 +1113,11 @@ uint QFileInfo::ownerId() const Q_D(const QFileInfo); if (d->isDefaultConstructed) return 0; + if (d->fileEngine == 0) { + if (!d->cache_enabled || !d->metaData.hasFlags(QFileSystemMetaData::UserId)) + QFileSystemEngine::fillMetaData(d->fileEntry, d->metaData, QFileSystemMetaData::UserId); + return d->metaData.userId(); + } return d->fileEngine->ownerId(QAbstractFileEngine::OwnerUser); } @@ -1037,6 +1152,11 @@ uint QFileInfo::groupId() const Q_D(const QFileInfo); if (d->isDefaultConstructed) return 0; + if (d->fileEngine == 0) { + if (!d->cache_enabled || !d->metaData.hasFlags(QFileSystemMetaData::GroupId)) + QFileSystemEngine::fillMetaData(d->fileEntry, d->metaData, QFileSystemMetaData::GroupId); + return d->metaData.groupId(); + } return d->fileEngine->ownerId(QAbstractFileEngine::OwnerGroup); } @@ -1058,6 +1178,13 @@ bool QFileInfo::permission(QFile::Permissions permissions) const Q_D(const QFileInfo); if (d->isDefaultConstructed) return false; + if (d->fileEngine == 0) { + // the QFileSystemMetaData::MetaDataFlag and QFile::Permissions overlap, so just static cast. + QFileSystemMetaData::MetaDataFlag permissionFlags = static_cast<QFileSystemMetaData::MetaDataFlag>((int)permissions); + if (!d->cache_enabled || !d->metaData.hasFlags(permissionFlags)) + QFileSystemEngine::fillMetaData(d->fileEntry, d->metaData, permissionFlags); + return (d->metaData.permissions() & permissions) == permissions; + } return d->getFileFlags(QAbstractFileEngine::FileFlags((int)permissions)) == (uint)permissions; } @@ -1070,6 +1197,11 @@ QFile::Permissions QFileInfo::permissions() const Q_D(const QFileInfo); if (d->isDefaultConstructed) return 0; + if (d->fileEngine == 0) { + if (!d->cache_enabled || !d->metaData.hasFlags(QFileSystemMetaData::Permissions)) + QFileSystemEngine::fillMetaData(d->fileEntry, d->metaData, QFileSystemMetaData::Permissions); + return d->metaData.permissions(); + } return QFile::Permissions(d->getFileFlags(QAbstractFileEngine::PermsMask) & QAbstractFileEngine::PermsMask); } @@ -1085,6 +1217,11 @@ qint64 QFileInfo::size() const Q_D(const QFileInfo); if (d->isDefaultConstructed) return 0; + if (d->fileEngine == 0) { + if (!d->cache_enabled || !d->metaData.hasFlags(QFileSystemMetaData::SizeAttribute)) + QFileSystemEngine::fillMetaData(d->fileEntry, d->metaData, QFileSystemMetaData::SizeAttribute); + return d->metaData.size(); + } if (!d->getCachedFlag(QFileInfoPrivate::CachedSize)) { d->setCachedFlag(QFileInfoPrivate::CachedSize); d->fileSize = d->fileEngine->size(); @@ -1110,6 +1247,11 @@ QDateTime QFileInfo::created() const Q_D(const QFileInfo); if (d->isDefaultConstructed) return QDateTime(); + if (d->fileEngine == 0) { + if (!d->cache_enabled || !d->metaData.hasFlags(QFileSystemMetaData::CreationTime)) + QFileSystemEngine::fillMetaData(d->fileEntry, d->metaData, QFileSystemMetaData::CreationTime); + return d->metaData.creationTime(); + } return d->getFileTime(QAbstractFileEngine::CreationTime); } @@ -1123,6 +1265,11 @@ QDateTime QFileInfo::lastModified() const Q_D(const QFileInfo); if (d->isDefaultConstructed) return QDateTime(); + if (d->fileEngine == 0) { + if (!d->cache_enabled || !d->metaData.hasFlags(QFileSystemMetaData::ModificationTime)) + QFileSystemEngine::fillMetaData(d->fileEntry, d->metaData, QFileSystemMetaData::ModificationTime); + return d->metaData.modificationTime(); + } return d->getFileTime(QAbstractFileEngine::ModificationTime); } @@ -1139,6 +1286,11 @@ QDateTime QFileInfo::lastRead() const Q_D(const QFileInfo); if (d->isDefaultConstructed) return QDateTime(); + if (d->fileEngine == 0) { + if (!d->cache_enabled || !d->metaData.hasFlags(QFileSystemMetaData::AccessTime)) + QFileSystemEngine::fillMetaData(d->fileEntry, d->metaData, QFileSystemMetaData::AccessTime); + return d->metaData.accessTime(); + } return d->getFileTime(QAbstractFileEngine::AccessTime); } diff --git a/src/corelib/io/qfileinfo.h b/src/corelib/io/qfileinfo.h index aec7543..3eff208 100644 --- a/src/corelib/io/qfileinfo.h +++ b/src/corelib/io/qfileinfo.h @@ -53,12 +53,16 @@ QT_BEGIN_NAMESPACE QT_MODULE(Core) class QDir; +class QDirIteratorPrivate; class QDateTime; class QFileInfoPrivate; class Q_CORE_EXPORT QFileInfo { + friend class QDirIteratorPrivate; public: + explicit QFileInfo(QFileInfoPrivate *d); + QFileInfo(); QFileInfo(const QString &file); QFileInfo(const QFile &file); diff --git a/src/corelib/io/qfileinfo_p.h b/src/corelib/io/qfileinfo_p.h index b9b1092..869a7a6 100644 --- a/src/corelib/io/qfileinfo_p.h +++ b/src/corelib/io/qfileinfo_p.h @@ -58,13 +58,16 @@ #include "qdatetime.h" #include "qatomic.h" #include "qshareddata.h" +#include "qfilesystemengine_p.h" + +#include <QtCore/private/qfilesystementry_p.h> +#include <QtCore/private/qfilesystemmetadata_p.h> QT_BEGIN_NAMESPACE class QFileInfoPrivate : public QSharedData { public: - enum { CachedFileFlags=0x01, CachedLinkTypeFlag=0x02, CachedBundleTypeFlag=0x04, CachedMTime=0x10, CachedCTime=0x20, CachedATime=0x40, CachedSize =0x08, CachedPerms=0x80 }; @@ -76,8 +79,10 @@ public: cache_enabled(true), fileFlags(0), fileSize(0) {} inline QFileInfoPrivate(const QFileInfoPrivate ©) - : QSharedData(copy), fileEngine(QAbstractFileEngine::create(copy.fileName)), - fileName(copy.fileName), + : QSharedData(copy), + fileEntry(copy.fileEntry), + metaData(copy.metaData), + fileEngine(QFileSystemEngine::resolveEntryAndCreateLegacyEngine(fileEntry, metaData)), cachedFlags(0), #ifndef QT_NO_FSFILEENGINE isDefaultConstructed(false), @@ -87,8 +92,8 @@ public: cache_enabled(copy.cache_enabled), fileFlags(0), fileSize(0) {} inline QFileInfoPrivate(const QString &file) - : QSharedData(), fileEngine(QAbstractFileEngine::create(file)), - fileName(file), + : fileEntry(QDir::fromNativeSeparators(file)), + fileEngine(QFileSystemEngine::resolveEntryAndCreateLegacyEngine(fileEntry, metaData)), cachedFlags(0), #ifndef QT_NO_FSFILEENGINE isDefaultConstructed(false), @@ -99,6 +104,16 @@ public: { } + inline QFileInfoPrivate(const QFileSystemEntry &file, const QFileSystemMetaData &data) + : QSharedData(), + fileEntry(file), + metaData(data), + cachedFlags(0), + isDefaultConstructed(false), + cache_enabled(true), fileFlags(0), fileSize(0) + { + } + inline void clearFlags() const { fileFlags = 0; cachedFlags = 0; @@ -106,6 +121,7 @@ public: (void)fileEngine->fileFlags(QAbstractFileEngine::Refresh); } inline void clear() { + metaData.clear(); clearFlags(); for (int i = QAbstractFileEngine::NFileNames - 1 ; i >= 0 ; --i) fileNames[i].clear(); @@ -118,9 +134,11 @@ public: QString getFileName(QAbstractFileEngine::FileName) const; QString getFileOwner(QAbstractFileEngine::FileOwner own) const; + QFileSystemEntry fileEntry; + mutable QFileSystemMetaData metaData; + QScopedPointer<QAbstractFileEngine> const fileEngine; - mutable QString fileName; mutable QString fileNames[QAbstractFileEngine::NFileNames]; mutable QString fileOwners[2]; @@ -134,6 +152,7 @@ public: { return cache_enabled ? (cachedFlags & c) : 0; } inline void setCachedFlag(uint c) const { if (cache_enabled) cachedFlags |= c; } + }; QT_END_NAMESPACE diff --git a/src/corelib/io/qfilesystemengine.cpp b/src/corelib/io/qfilesystemengine.cpp new file mode 100644 index 0000000..d9d802e --- /dev/null +++ b/src/corelib/io/qfilesystemengine.cpp @@ -0,0 +1,385 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qfilesystemengine_p.h" +#include <QtCore/qdir.h> +#include <QtCore/qset.h> +#include <QtCore/qstringbuilder.h> +#include <QtCore/private/qabstractfileengine_p.h> +#ifdef QT_BUILD_CORE_LIB +#include <QtCore/private/qresource_p.h> +#endif + +QT_BEGIN_NAMESPACE + +/*! + \internal + + Returns the canonicalized form of \a path (i.e., with all symlinks + resolved, and all redundant path elements removed. +*/ +QString QFileSystemEngine::slowCanonicalized(const QString &path) +{ + if (path.isEmpty()) + return path; + + QFileInfo fi; + const QChar slash(QLatin1Char('/')); + QString tmpPath = path; + int separatorPos = 0; + QSet<QString> nonSymlinks; + QSet<QString> known; + + known.insert(path); + do { +#ifdef Q_OS_WIN + if (separatorPos == 0) { + if (tmpPath.size() >= 2 && tmpPath.at(0) == slash && tmpPath.at(1) == slash) { + // UNC, skip past the first two elements + separatorPos = tmpPath.indexOf(slash, 2); + } else if (tmpPath.size() >= 3 && tmpPath.at(1) == QLatin1Char(':') && tmpPath.at(2) == slash) { + // volume root, skip since it can not be a symlink + separatorPos = 2; + } + } + if (separatorPos != -1) +#endif + separatorPos = tmpPath.indexOf(slash, separatorPos + 1); + QString prefix = separatorPos == -1 ? tmpPath : tmpPath.left(separatorPos); + if ( +#ifdef Q_OS_SYMBIAN + // Symbian doesn't support directory symlinks, so do not check for link unless we + // are handling the last path element. This not only slightly improves performance, + // but also saves us from lot of unnecessary platform security check failures + // when dealing with files under *:/private directories. + separatorPos == -1 && +#endif + !nonSymlinks.contains(prefix)) { + fi.setFile(prefix); + if (fi.isSymLink()) { + QString target = fi.symLinkTarget(); + if(QFileInfo(target).isRelative()) + target = fi.absolutePath() + slash + target; + if (separatorPos != -1) { + if (fi.isDir() && !target.endsWith(slash)) + target.append(slash); + target.append(tmpPath.mid(separatorPos)); + } + tmpPath = QDir::cleanPath(target); + separatorPos = 0; + + if (known.contains(tmpPath)) + return QString(); + known.insert(tmpPath); + } else { + nonSymlinks.insert(prefix); + } + } + } while (separatorPos != -1); + + return QDir::cleanPath(tmpPath); +} + +static inline bool _q_checkEntry(QFileSystemEntry &entry, QFileSystemMetaData &data, bool resolvingEntry) +{ + if (resolvingEntry) { + if (!QFileSystemEngine::fillMetaData(entry, data, QFileSystemMetaData::ExistsAttribute) + || !data.exists()) { + data.clear(); + return false; + } + } + + return true; +} + +static inline bool _q_checkEntry(QAbstractFileEngine *&engine, bool resolvingEntry) +{ + if (resolvingEntry) { + if (!(engine->fileFlags(QAbstractFileEngine::FlagsMask) & QAbstractFileEngine::ExistsFlag)) { + delete engine; + engine = 0; + return false; + } + } + + return true; +} + +static bool _q_resolveEntryAndCreateLegacyEngine_recursive(QFileSystemEntry &entry, QFileSystemMetaData &data, + QAbstractFileEngine *&engine, bool resolvingEntry = false) +{ + QString const &filePath = entry.filePath(); + if ((engine = qt_custom_file_engine_handler_create(filePath))) + return _q_checkEntry(engine, resolvingEntry); + +#if defined(QT_BUILD_CORE_LIB) + for (int prefixSeparator = 0; prefixSeparator < filePath.size(); ++prefixSeparator) { + QChar const ch = filePath[prefixSeparator]; + if (ch == QLatin1Char('/')) + break; + + if (ch == QLatin1Char(':')) { + if (prefixSeparator == 0) { + engine = new QResourceFileEngine(filePath); + return _q_checkEntry(engine, resolvingEntry); + } + + if (prefixSeparator == 1) + break; + + const QStringList &paths = QDir::searchPaths(filePath.left(prefixSeparator)); + for (int i = 0; i < paths.count(); i++) { + entry = QFileSystemEntry(paths.at(i) % QLatin1Char('/') % filePath.mid(prefixSeparator + 1)); + // Recurse! + if (_q_resolveEntryAndCreateLegacyEngine_recursive(entry, data, engine, true)) + return true; + } + + // entry may have been clobbered at this point. + return false; + } + + // There's no need to fully validate the prefix here. Consulting the + // unicode tables could be expensive and validation is already + // performed in QDir::setSearchPaths. + // + // if (!ch.isLetterOrNumber()) + // break; + } +#endif // defined(QT_BUILD_CORE_LIB) + + return _q_checkEntry(entry, data, resolvingEntry); +} + +/*! + \internal + + Resolves the \a entry (see QDir::searchPaths) and returns an engine for + it, but never a QFSFileEngine. + + \returns a file engine that can be used to access the entry. Returns 0 if + QFileSystemEngine API should be used to query and interact with the file + system object. +*/ +QAbstractFileEngine *QFileSystemEngine::resolveEntryAndCreateLegacyEngine( + QFileSystemEntry &entry, QFileSystemMetaData &data) { + QFileSystemEntry copy = entry; + QAbstractFileEngine *engine = 0; + + if (_q_resolveEntryAndCreateLegacyEngine_recursive(copy, data, engine)) + // Reset entry to resolved copy. + entry = copy; + else + data.clear(); + + return engine; +} + +//these unix functions are in this file, because they are shared by symbian port +//for open C file handles. +#ifdef Q_OS_UNIX +//static +bool QFileSystemEngine::fillMetaData(int fd, QFileSystemMetaData &data) +{ + data.entryFlags &= ~QFileSystemMetaData::PosixStatFlags; + data.knownFlagsMask |= QFileSystemMetaData::PosixStatFlags; + + QT_STATBUF statBuffer; + if (QT_FSTAT(fd, &statBuffer) == 0) { + data.fillFromStatBuf(statBuffer); + return true; + } + + return false; +} + +void QFileSystemMetaData::fillFromStatBuf(const QT_STATBUF &statBuffer) +{ + // Permissions + if (statBuffer.st_mode & S_IRUSR) + entryFlags |= QFileSystemMetaData::OwnerReadPermission; + if (statBuffer.st_mode & S_IWUSR) + entryFlags |= QFileSystemMetaData::OwnerWritePermission; + if (statBuffer.st_mode & S_IXUSR) + entryFlags |= QFileSystemMetaData::OwnerExecutePermission; + + if (statBuffer.st_mode & S_IRGRP) + entryFlags |= QFileSystemMetaData::GroupReadPermission; + if (statBuffer.st_mode & S_IWGRP) + entryFlags |= QFileSystemMetaData::GroupWritePermission; + if (statBuffer.st_mode & S_IXGRP) + entryFlags |= QFileSystemMetaData::GroupExecutePermission; + + if (statBuffer.st_mode & S_IROTH) + entryFlags |= QFileSystemMetaData::OtherReadPermission; + if (statBuffer.st_mode & S_IWOTH) + entryFlags |= QFileSystemMetaData::OtherWritePermission; + if (statBuffer.st_mode & S_IXOTH) + entryFlags |= QFileSystemMetaData::OtherExecutePermission; + + // Type + if ((statBuffer.st_mode & S_IFMT) == S_IFREG) + entryFlags |= QFileSystemMetaData::FileType; + else if ((statBuffer.st_mode & S_IFMT) == S_IFDIR) + entryFlags |= QFileSystemMetaData::DirectoryType; + else + entryFlags |= QFileSystemMetaData::SequentialType; + + // Attributes + entryFlags |= QFileSystemMetaData::ExistsAttribute; + size_ = statBuffer.st_size; +#if !defined(QWS) && !defined(Q_WS_QPA) && defined(Q_OS_MAC) \ + && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 + if (statBuffer.st_flags & UF_HIDDEN) { + entryFlags |= QFileSystemMetaData::HiddenAttribute; + knownFlagsMask |= QFileSystemMetaData::HiddenAttribute; + } +#endif + + // Times +#ifdef Q_OS_SYMBIAN + modificationTime_ = qt_symbian_time_t_To_TTime(statBuffer.st_mtime); +#else + creationTime_ = statBuffer.st_ctime ? statBuffer.st_ctime : statBuffer.st_mtime; + modificationTime_ = statBuffer.st_mtime; + accessTime_ = statBuffer.st_atime; + userId_ = statBuffer.st_uid; + groupId_ = statBuffer.st_gid; +#endif +} + +void QFileSystemMetaData::fillFromDirEnt(const QT_DIRENT &entry) +{ + // ### This will clear all entry flags and knownFlagsMask + switch (entry.d_type) + { + case DT_DIR: + knownFlagsMask = QFileSystemMetaData::LinkType + | QFileSystemMetaData::FileType + | QFileSystemMetaData::DirectoryType + | QFileSystemMetaData::SequentialType + | QFileSystemMetaData::ExistsAttribute; + + entryFlags = QFileSystemMetaData::DirectoryType + | QFileSystemMetaData::ExistsAttribute; + + break; + + case DT_BLK: + case DT_CHR: + case DT_FIFO: + case DT_SOCK: + // ### System attribute + knownFlagsMask = QFileSystemMetaData::LinkType + | QFileSystemMetaData::FileType + | QFileSystemMetaData::DirectoryType + | QFileSystemMetaData::BundleType + | QFileSystemMetaData::AliasType + | QFileSystemMetaData::SequentialType + | QFileSystemMetaData::ExistsAttribute; + + entryFlags = QFileSystemMetaData::SequentialType + | QFileSystemMetaData::ExistsAttribute; + + break; + + case DT_LNK: + knownFlagsMask = QFileSystemMetaData::LinkType; + entryFlags = QFileSystemMetaData::LinkType; + break; + + case DT_REG: + knownFlagsMask = QFileSystemMetaData::LinkType + | QFileSystemMetaData::FileType + | QFileSystemMetaData::DirectoryType + | QFileSystemMetaData::BundleType + | QFileSystemMetaData::SequentialType + | QFileSystemMetaData::ExistsAttribute; + + entryFlags = QFileSystemMetaData::FileType + | QFileSystemMetaData::ExistsAttribute; + + break; + + case DT_UNKNOWN: + default: + clear(); + } +} + +#endif + +//static +QString QFileSystemEngine::resolveUserName(const QFileSystemEntry &entry, QFileSystemMetaData &metaData) +{ +#if defined (Q_OS_SYMBIAN) + Q_UNUSED(entry); + Q_UNUSED(metaData); + return QString(); +#elif defined(Q_OS_WIN) + Q_UNUSED(metaData); + return QFileSystemEngine::owner(entry, QAbstractFileEngine::OwnerUser); +#else //(Q_OS_UNIX) + if (!metaData.hasFlags(QFileSystemMetaData::UserId)) + QFileSystemEngine::fillMetaData(entry, metaData, QFileSystemMetaData::UserId); + return resolveUserName(metaData.userId()); +#endif +} + +//static +QString QFileSystemEngine::resolveGroupName(const QFileSystemEntry &entry, QFileSystemMetaData &metaData) +{ +#if defined (Q_OS_SYMBIAN) + Q_UNUSED(entry); + Q_UNUSED(metaData); + return QString(); +#elif defined(Q_OS_WIN) + Q_UNUSED(metaData); + return QFileSystemEngine::owner(entry, QAbstractFileEngine::OwnerGroup); +#else //(Q_OS_UNIX) + if (!metaData.hasFlags(QFileSystemMetaData::GroupId)) + QFileSystemEngine::fillMetaData(entry, metaData, QFileSystemMetaData::GroupId); + return resolveGroupName(metaData.groupId()); +#endif +} + +QT_END_NAMESPACE diff --git a/src/corelib/io/qfilesystemengine_mac.cpp b/src/corelib/io/qfilesystemengine_mac.cpp new file mode 100644 index 0000000..30d7fa5 --- /dev/null +++ b/src/corelib/io/qfilesystemengine_mac.cpp @@ -0,0 +1,48 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qfilesystemengine_p.h" + +QT_BEGIN_NAMESPACE + +// Mac-specific implementations only! + +QT_END_NAMESPACE diff --git a/src/corelib/io/qfilesystemengine_p.h b/src/corelib/io/qfilesystemengine_p.h new file mode 100644 index 0000000..a3ec0ab --- /dev/null +++ b/src/corelib/io/qfilesystemengine_p.h @@ -0,0 +1,133 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QFILESYSTEMENGINE_P_H_INCLUDED +#define QFILESYSTEMENGINE_P_H_INCLUDED + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qfile.h" +#include "qfilesystementry_p.h" +#include "qfilesystemmetadata_p.h" +#include <QtCore/private/qsystemerror_p.h> + +QT_BEGIN_NAMESPACE + +class QFileSystemEngine +{ +public: + static bool isCaseSensitive(); + + static QFileSystemEntry getLinkTarget(const QFileSystemEntry &link, QFileSystemMetaData &data); + static QFileSystemEntry canonicalName(const QFileSystemEntry &entry, QFileSystemMetaData &data); + static QFileSystemEntry absoluteName(const QFileSystemEntry &entry); + static QString resolveUserName(const QFileSystemEntry &entry, QFileSystemMetaData &data); + static QString resolveGroupName(const QFileSystemEntry &entry, QFileSystemMetaData &data); + +#if defined(Q_OS_UNIX) && !defined(Q_OS_SYMBIAN) + static QString resolveUserName(uint userId); + static QString resolveGroupName(uint groupId); +#endif + +#if !defined(QWS) && !defined(Q_WS_QPA) && defined(Q_OS_MAC) + static QString bundleName(const QFileSystemEntry &entry); +#else + static QString bundleName(const QFileSystemEntry &entry) { Q_UNUSED(entry) return QString(); } +#endif + + static bool fillMetaData(const QFileSystemEntry &entry, QFileSystemMetaData &data, + QFileSystemMetaData::MetaDataFlags what); +#if defined(Q_OS_UNIX) + static bool fillMetaData(int fd, QFileSystemMetaData &data); // what = PosixStatFlags +#endif +#if defined(Q_OS_WIN) + + static bool uncListSharesOnServer(const QString &server, QStringList *list); //Used also by QFSFileEngineIterator::hasNext() + static bool fillMetaData(int fd, QFileSystemMetaData &data, + QFileSystemMetaData::MetaDataFlags what); + static bool fillMetaData(HANDLE fHandle, QFileSystemMetaData &data, + QFileSystemMetaData::MetaDataFlags what); + static bool fillPermissions(const QFileSystemEntry &entry, QFileSystemMetaData &data, + QFileSystemMetaData::MetaDataFlags what); + static QString owner(const QFileSystemEntry &entry, QAbstractFileEngine::FileOwner own); + static QString nativeAbsoluteFilePath(const QString &path); +#endif + //homePath, rootPath and tempPath shall return clean paths + static QString homePath(); + static QString rootPath(); + static QString tempPath(); + + static bool createDirectory(const QFileSystemEntry &entry, bool createParents); + static bool removeDirectory(const QFileSystemEntry &entry, bool removeEmptyParents); + + static bool createLink(const QFileSystemEntry &source, const QFileSystemEntry &target, QSystemError &error); + + static bool copyFile(const QFileSystemEntry &source, const QFileSystemEntry &target, QSystemError &error); + static bool renameFile(const QFileSystemEntry &source, const QFileSystemEntry &target, QSystemError &error); + static bool removeFile(const QFileSystemEntry &entry, QSystemError &error); + + static bool setPermissions(const QFileSystemEntry &entry, QFile::Permissions permissions, QSystemError &error, + QFileSystemMetaData *data = 0); + + static bool setCurrentPath(const QFileSystemEntry &entry); + static QFileSystemEntry currentPath(); + + static QAbstractFileEngine *resolveEntryAndCreateLegacyEngine(QFileSystemEntry &entry, + QFileSystemMetaData &data); +private: + static QString slowCanonicalized(const QString &path); +#if defined(Q_OS_WIN) + static void clearWinStatData(QFileSystemMetaData &data); +#endif +}; + +QT_END_NAMESPACE + +#endif // include guard diff --git a/src/corelib/io/qfilesystemengine_symbian.cpp b/src/corelib/io/qfilesystemengine_symbian.cpp new file mode 100644 index 0000000..84c3aa1 --- /dev/null +++ b/src/corelib/io/qfilesystemengine_symbian.cpp @@ -0,0 +1,408 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qfilesystemengine_p.h" +#include "qfsfileengine.h" +#include <QtCore/private/qcore_symbian_p.h> +#include <QtCore/qcoreapplication.h> + +#include <f32file.h> +#include <pathinfo.h> +#include <wchar.h> + +QT_BEGIN_NAMESPACE + +bool QFileSystemEngine::isCaseSensitive() +{ + return false; +} + +//TODO: resolve this with QDir::cleanPath, without breaking the behaviour of that +//function which is documented only by autotest +//input: a dirty absolute path, e.g. c:/../../foo/./ +//output: a clean absolute path, e.g. c:/foo/ +static QString symbianCleanAbsolutePath(const QString& path) +{ + bool isDir = path.endsWith(QLatin1Char('/')); + //using SkipEmptyParts flag to eliminate duplicated slashes + QStringList components = path.split(QLatin1Char('/'), QString::SkipEmptyParts); + int cdups = 0; + for(int i=components.count() - 1; i>=0; --i) { + if(components.at(i) == QLatin1String("..")) { + components.removeAt(i); + cdups++; + } + else if(components.at(i) == QLatin1String(".")) { + components.removeAt(i); + } + else if(cdups && i > 0) { + --cdups; + components.removeAt(i); + } + } + QString result = components.join(QLatin1String("/")); + if ((isDir&& !result.endsWith(QLatin1Char('/'))) + || (result.length() == 2 && result.at(1).unicode() == ':')) + result.append(QLatin1Char('/')); + return result; +} + +//static +QFileSystemEntry QFileSystemEngine::getLinkTarget(const QFileSystemEntry &link, QFileSystemMetaData &data) +{ + Q_UNUSED(data); + return link; +} + +//static +QFileSystemEntry QFileSystemEngine::canonicalName(const QFileSystemEntry &entry, QFileSystemMetaData &data) +{ + if (entry.isEmpty() || entry.isRoot()) + return entry; + + QFileSystemEntry result = absoluteName(entry); + if (!data.hasFlags(QFileSystemMetaData::ExistsAttribute)) + fillMetaData(result, data, QFileSystemMetaData::ExistsAttribute); + if (!data.exists()) { + // file doesn't exist + return QFileSystemEntry(); + } else { + return result; + } +} + +//static +QFileSystemEntry QFileSystemEngine::absoluteName(const QFileSystemEntry &entry) +{ + QString orig = entry.filePath(); + const bool isAbsolute = entry.isAbsolute(); + const bool isDirty = (orig.contains(QLatin1String("/../")) || orig.contains(QLatin1String("/./")) || + orig.contains(QLatin1String("//")) || + orig.endsWith(QLatin1String("/..")) || orig.endsWith(QLatin1String("/."))); + if (isAbsolute && !isDirty) + return entry; + + const bool isRelative = entry.isRelative(); + const bool needsDrive = (!orig.isEmpty() && orig.at(0).unicode() == '/'); + const bool isDriveLetter = !needsDrive && !isAbsolute && !isRelative && orig.length() == 2; + const bool isDriveRelative = !needsDrive && !isAbsolute && !isRelative && orig.length() > 2; + + QString result; + if (needsDrive || isDriveLetter || isDriveRelative || !isAbsolute || orig.isEmpty()) { + QFileSystemEntry cur(currentPath()); + if(needsDrive) + result = cur.filePath().left(2); + else if(isDriveRelative && cur.filePath().at(0) != orig.at(0)) + result = orig.left(2); // for BC, see tst_QFileInfo::absolutePath(<not current drive>:my.dll) + else + result = cur.filePath(); + if(isDriveLetter) { + result[0] = orig.at(0); //copy drive letter + orig.clear(); + } + if(isDriveRelative) { + orig = orig.mid(2); //discard the drive specifier from orig + } + } + if (!orig.isEmpty() && !(orig.length() == 1 && orig.at(0).unicode() == '.')) { + if (!result.isEmpty() && !result.endsWith(QLatin1Char('/'))) + result.append(QLatin1Char('/')); + result.append(orig); + } + + return QFileSystemEntry(symbianCleanAbsolutePath(result), QFileSystemEntry::FromInternalPath()); +} + +void QFileSystemMetaData::fillFromTEntry(const TEntry& entry) +{ + entryFlags &= ~(QFileSystemMetaData::SymbianTEntryFlags); + knownFlagsMask |= QFileSystemMetaData::SymbianTEntryFlags; + //Symbian doesn't have unix type file permissions + entryFlags |= QFileSystemMetaData::ReadPermissions; + if(!entry.IsReadOnly()) { + entryFlags |= QFileSystemMetaData::WritePermissions; + } + //set the type + if(entry.IsDir()) + entryFlags |= (QFileSystemMetaData::DirectoryType | QFileSystemMetaData::ExecutePermissions); + else + entryFlags |= QFileSystemMetaData::FileType; + + //set the attributes + entryFlags |= QFileSystemMetaData::ExistsAttribute; + if(entry.IsHidden()) + entryFlags |= QFileSystemMetaData::HiddenAttribute; + +#ifdef SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API + size_ = entry.FileSize(); +#else + size_ = (TUint)(entry.iSize); +#endif + + modificationTime_ = entry.iModified; +} + +void QFileSystemMetaData::fillFromVolumeInfo(const TVolumeInfo& info) +{ + entryFlags &= ~(QFileSystemMetaData::SymbianTEntryFlags); + knownFlagsMask |= QFileSystemMetaData::SymbianTEntryFlags; + entryFlags |= QFileSystemMetaData::ExistsAttribute; + entryFlags |= QFileSystemMetaData::Permissions; + if(info.iDrive.iDriveAtt & KDriveAttRom) { + entryFlags &= ~(QFileSystemMetaData::WritePermissions); + } + entryFlags |= QFileSystemMetaData::DirectoryType; + size_ = info.iSize; + modificationTime_ = qt_symbian_time_t_To_TTime(0); +} + +//static +bool QFileSystemEngine::fillMetaData(const QFileSystemEntry &entry, QFileSystemMetaData &data, QFileSystemMetaData::MetaDataFlags what) +{ + if (what & QFileSystemMetaData::SymbianTEntryFlags) { + RFs& fs(qt_s60GetRFs()); + TInt err; + QFileSystemEntry absentry(absoluteName(entry)); + if (entry.isEmpty()) { + err = KErrNotFound; + } else if (absentry.isRoot()) { + //Root directories don't have an entry, and Entry() returns KErrBadName. + //Therefore get information about the volume instead. + TInt drive; + err = RFs::CharToDrive(TChar(absentry.nativeFilePath().at(0).unicode()), drive); + if (!err) { + TVolumeInfo info; + err = fs.Volume(info, drive); + if (!err) + data.fillFromVolumeInfo(info); + } + } else { + TEntry ent; + err = fs.Entry(qt_QString2TPtrC(absentry.nativeFilePath()), ent); + if (!err) + data.fillFromTEntry(ent); + } + if (err) { + data.size_ = 0; + data.modificationTime_ = TTime(0); + data.entryFlags &= ~(QFileSystemMetaData::SymbianTEntryFlags); + } + //files in /sys/bin on any drive are executable, even though we don't normally have permission to check whether they exist or not + if(absentry.filePath().midRef(1,10).compare(QLatin1String(":/sys/bin/"), Qt::CaseInsensitive) == 0) + data.entryFlags |= QFileSystemMetaData::ExecutePermissions; + } + return data.hasFlags(what); +} + +//static +bool QFileSystemEngine::createDirectory(const QFileSystemEntry &entry, bool createParents) +{ + QString abspath = absoluteName(entry).nativeFilePath(); + if (!abspath.endsWith(QLatin1Char('\\'))) + abspath.append(QLatin1Char('\\')); + TInt r; + if (createParents) + r = qt_s60GetRFs().MkDirAll(qt_QString2TPtrC(abspath)); + else + r = qt_s60GetRFs().MkDir(qt_QString2TPtrC(abspath)); + if (createParents && r == KErrAlreadyExists) + return true; //# Qt5 - QDir::mkdir returns false for existing dir, QDir::mkpath returns true (should be made consistent in Qt 5) + return (r == KErrNone); +} + +//static +bool QFileSystemEngine::removeDirectory(const QFileSystemEntry &entry, bool removeEmptyParents) +{ + QString abspath = absoluteName(entry).nativeFilePath(); + if (!abspath.endsWith(QLatin1Char('\\'))) + abspath.append(QLatin1Char('\\')); + TPtrC dir(qt_QString2TPtrC(abspath)); + RFs& fs = qt_s60GetRFs(); + bool ok = false; + //behaviour of FS file engine: + //returns true if the directory could be removed + //success/failure of removing parent directories does not matter + while (KErrNone == fs.RmDir(dir)) { + ok = true; + if (!removeEmptyParents) + break; + //RFs::RmDir treats "c:\foo\bar" and "c:\foo\" the same, so it is sufficient to remove the last \ to the end + dir.Set(dir.Left(dir.LocateReverse(TChar('\\')))); + } + return ok; +} + +//static +bool QFileSystemEngine::createLink(const QFileSystemEntry &source, const QFileSystemEntry &target, QSystemError &error) +{ + Q_UNUSED(source) + Q_UNUSED(target) + error = QSystemError(KErrNotSupported, QSystemError::NativeError); + return false; +} + +//static +bool QFileSystemEngine::copyFile(const QFileSystemEntry &source, const QFileSystemEntry &target, QSystemError &error) +{ + //CFileMan is allocated each time because it is not thread-safe + CFileMan *fm = 0; + TRAPD(err, fm = CFileMan::NewL(qt_s60GetRFs())); + if (err == KErrNone) { + err = fm->Copy(qt_QString2TPtrC(absoluteName(source).nativeFilePath()), qt_QString2TPtrC(absoluteName(target).nativeFilePath()), 0); + delete fm; + } + if (err == KErrNone) + return true; + error = QSystemError(err, QSystemError::NativeError); + return false; +} + +//static +bool QFileSystemEngine::renameFile(const QFileSystemEntry &source, const QFileSystemEntry &target, QSystemError &error) +{ + QString sourcepath = absoluteName(source).nativeFilePath(); + QString targetpath = absoluteName(target).nativeFilePath(); + RFs& fs(qt_s60GetRFs()); + TInt err = fs.Rename(qt_QString2TPtrC(sourcepath), qt_QString2TPtrC(targetpath)); + if (err == KErrNone) + return true; + error = QSystemError(err, QSystemError::NativeError); + return false; +} + +//static +bool QFileSystemEngine::removeFile(const QFileSystemEntry &entry, QSystemError &error) +{ + QString targetpath = absoluteName(entry).nativeFilePath(); + RFs& fs(qt_s60GetRFs()); + TInt err = fs.Delete(qt_QString2TPtrC(targetpath)); + if (err == KErrNone) + return true; + error = QSystemError(err, QSystemError::NativeError); + return false; +} + +//static +bool QFileSystemEngine::setPermissions(const QFileSystemEntry &entry, QFile::Permissions permissions, QSystemError &error, QFileSystemMetaData *data) +{ + QString targetpath = absoluteName(entry).nativeFilePath(); + TUint setmask = 0; + TUint clearmask = 0; + RFs& fs(qt_s60GetRFs()); + if (permissions & (QFile::WriteOwner | QFile::WriteUser | QFile::WriteGroup | QFile::WriteOther)) + clearmask = KEntryAttReadOnly; //if anyone can write, it's not read-only + else + setmask = KEntryAttReadOnly; + TInt err = fs.SetAtt(qt_QString2TPtrC(targetpath), setmask, clearmask); + if (data && !err) { + data->entryFlags &= ~QFileSystemMetaData::Permissions; + data->entryFlags |= QFileSystemMetaData::MetaDataFlag(uint(permissions)); + data->knownFlagsMask |= QFileSystemMetaData::Permissions; + } + if (err == KErrNone) + return true; + error = QSystemError(err, QSystemError::NativeError); + return false; +} + +QString QFileSystemEngine::homePath() +{ + QString home = QDir::fromNativeSeparators(qt_TDesC2QString(PathInfo::PhoneMemoryRootPath())); + if(home.endsWith(QLatin1Char('/'))) + home.chop(1); + return home; +} + +QString QFileSystemEngine::rootPath() +{ + TChar drive; + TInt err = RFs::DriveToChar(RFs::GetSystemDrive(), drive); //RFs::GetSystemDriveChar not supported on S60 3.1 + Q_ASSERT(err == KErrNone); //RFs::GetSystemDrive() shall always return a convertible drive number on a valid OS configuration + return QString(QChar(drive)).append(QLatin1String(":/")); +} + +QString QFileSystemEngine::tempPath() +{ + return rootPath().append(QLatin1String("system/temp")); +} + +//static +bool QFileSystemEngine::setCurrentPath(const QFileSystemEntry &entry) +{ + QFileSystemMetaData meta; + QFileSystemEntry absname = absoluteName(entry); + fillMetaData(absname, meta, QFileSystemMetaData::ExistsAttribute | QFileSystemMetaData::DirectoryType); + if(!(meta.exists() && meta.isDirectory())) + return false; + + RFs& fs = qt_s60GetRFs(); + QString abspath = absname.nativeFilePath(); + if(!abspath.endsWith(QLatin1Char('\\'))) + abspath.append(QLatin1Char('\\')); + TInt r = fs.SetSessionPath(qt_QString2TPtrC(abspath)); + //SetSessionPath succeeds for non existent directory, which is why it's checked above + if (r == KErrNone) { + __ASSERT_COMPILE(sizeof(wchar_t) == sizeof(unsigned short)); + //attempt to set open C to the same path + r = ::wchdir(reinterpret_cast<const wchar_t *>(absname.filePath().utf16())); + if (r < 0) + qWarning("failed to sync path to open C"); + return true; + } + return false; +} + +//static +QFileSystemEntry QFileSystemEngine::currentPath() +{ + TFileName fn; + QFileSystemEntry ret; + TInt r = qt_s60GetRFs().SessionPath(fn); + if(r == KErrNone) { + //remove terminating slash from non root paths (session path is clean, absolute and always ends in a \) + if(fn.Length() > 3 && fn[fn.Length() - 1] == '\\') + fn.SetLength(fn.Length() - 1); + ret = QFileSystemEntry(qt_TDesC2QString(fn), QFileSystemEntry::FromNativePath()); + } + return ret; +} + +QT_END_NAMESPACE diff --git a/src/corelib/io/qfilesystemengine_unix.cpp b/src/corelib/io/qfilesystemengine_unix.cpp new file mode 100644 index 0000000..40fb0c0 --- /dev/null +++ b/src/corelib/io/qfilesystemengine_unix.cpp @@ -0,0 +1,655 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qplatformdefs.h" +#include "qfilesystemengine_p.h" +#include "qplatformdefs.h" +#include "qfsfileengine.h" +#include "qfile.h" + +#include <QtCore/qvarlengtharray.h> + +#include <stdlib.h> // for realpath() +#include <unistd.h> +#include <stdio.h> +#include <errno.h> + + +#if defined(Q_OS_MAC) +# include <QtCore/private/qcore_mac_p.h> +#endif + +QT_BEGIN_NAMESPACE + +#if !defined(QWS) && !defined(Q_WS_QPA) && defined(Q_OS_MAC) +static inline bool _q_isMacHidden(const char *nativePath) +{ + OSErr err; + + FSRef fsRef; + err = FSPathMakeRefWithOptions(reinterpret_cast<const UInt8 *>(nativePath), + kFSPathMakeRefDoNotFollowLeafSymlink, &fsRef, 0); + if (err != noErr) + return false; + + FSCatalogInfo catInfo; + err = FSGetCatalogInfo(&fsRef, kFSCatInfoFinderInfo, &catInfo, NULL, NULL, NULL); + if (err != noErr) + return false; + + FileInfo * const fileInfo = reinterpret_cast<FileInfo*>(&catInfo.finderInfo); + return (fileInfo->finderFlags & kIsInvisible); +} +#else +static inline bool _q_isMacHidden(const char *nativePath) +{ + Q_UNUSED(nativePath); + // no-op + return false; +} +#endif + +bool QFileSystemEngine::isCaseSensitive() +{ + return true; +} + +//static +QFileSystemEntry QFileSystemEngine::getLinkTarget(const QFileSystemEntry &link, QFileSystemMetaData &data) +{ +#if defined(__GLIBC__) && !defined(PATH_MAX) +#define PATH_CHUNK_SIZE 256 + char *s = 0; + int len = -1; + int size = PATH_CHUNK_SIZE; + + while (1) { + s = (char *) ::realloc(s, size); + Q_CHECK_PTR(s); + len = ::readlink(link.nativeFilePath().constData(), s, size); + if (len < 0) { + ::free(s); + break; + } + if (len < size) { + break; + } + size *= 2; + } +#else + char s[PATH_MAX+1]; + int len = readlink(link.nativeFilePath().constData(), s, PATH_MAX); +#endif + if (len > 0) { + QString ret; + if (!data.hasFlags(QFileSystemMetaData::DirectoryType)) + fillMetaData(link, data, QFileSystemMetaData::DirectoryType); + if (data.isDirectory() && s[0] != '/') { + QDir parent(link.filePath()); + parent.cdUp(); + ret = parent.path(); + if (!ret.isEmpty() && !ret.endsWith(QLatin1Char('/'))) + ret += QLatin1Char('/'); + } + s[len] = '\0'; + ret += QFile::decodeName(QByteArray(s)); +#if defined(__GLIBC__) && !defined(PATH_MAX) + ::free(s); +#endif + + if (!ret.startsWith(QLatin1Char('/'))) { + if (link.filePath().startsWith(QLatin1Char('/'))) { + ret.prepend(link.filePath().left(link.filePath().lastIndexOf(QLatin1Char('/'))) + + QLatin1Char('/')); + } else { + ret.prepend(QDir::currentPath() + QLatin1Char('/')); + } + } + ret = QDir::cleanPath(ret); + if (ret.size() > 1 && ret.endsWith(QLatin1Char('/'))) + ret.chop(1); + return QFileSystemEntry(ret); + } +#if !defined(QWS) && !defined(Q_WS_QPA) && defined(Q_OS_MAC) + { + FSRef fref; + if (FSPathMakeRef((const UInt8 *)QFile::encodeName(QDir::cleanPath(link.filePath())).data(), &fref, 0) == noErr) { + // TODO get the meta data info from the QFileSystemMetaData object + Boolean isAlias, isFolder; + if (FSResolveAliasFile(&fref, true, &isFolder, &isAlias) == noErr && isAlias) { + AliasHandle alias; + if (FSNewAlias(0, &fref, &alias) == noErr && alias) { + QCFString cfstr; + if (FSCopyAliasInfo(alias, 0, 0, &cfstr, 0, 0) == noErr) + return QFileSystemEntry(QCFString::toQString(cfstr)); + } + } + } + } +#endif + return QFileSystemEntry(); +} + +//static +QFileSystemEntry QFileSystemEngine::canonicalName(const QFileSystemEntry &entry, QFileSystemMetaData &data) +{ + if (entry.isEmpty() || entry.isRoot()) + return entry; + +#ifdef __UCLIBC__ + return QFileSystemEntry::slowCanonicalName(entry); +#else + char *ret = 0; +# if defined(Q_OS_MAC) && !defined(QT_NO_CORESERVICES) + // Mac OS X 10.5.x doesn't support the realpath(X,0) extension we use here. + if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_6) { + ret = realpath(entry.nativeFilePath().constData(), (char*)0); + } else { + // on 10.5 we can use FSRef to resolve the file path. + QString path = QDir::cleanPath(entry.filePath()); + FSRef fsref; + if (FSPathMakeRef((const UInt8 *)path.toUtf8().data(), &fsref, 0) == noErr) { + CFURLRef urlref = CFURLCreateFromFSRef(NULL, &fsref); + CFStringRef canonicalPath = CFURLCopyFileSystemPath(urlref, kCFURLPOSIXPathStyle); + QString ret = QCFString::toQString(canonicalPath); + CFRelease(canonicalPath); + CFRelease(urlref); + return QFileSystemEntry(ret); + } + } +# else + ret = realpath(entry.nativeFilePath().constData(), (char*)0); +# endif + if (ret) { + data.knownFlagsMask |= QFileSystemMetaData::ExistsAttribute; + data.entryFlags |= QFileSystemMetaData::ExistsAttribute; + QString canonicalPath = QDir::cleanPath(QString::fromLocal8Bit(ret)); + free(ret); + return QFileSystemEntry(canonicalPath); + } else if (errno == ENOENT) { // file doesn't exist + data.knownFlagsMask |= QFileSystemMetaData::ExistsAttribute; + data.entryFlags &= ~(QFileSystemMetaData::ExistsAttribute); + return QFileSystemEntry(); + } + return entry; +#endif +} + +//static +QFileSystemEntry QFileSystemEngine::absoluteName(const QFileSystemEntry &entry) +{ + if (entry.isAbsolute()) + return entry; + + QByteArray orig = entry.nativeFilePath(); + QByteArray result; + if (orig.isEmpty() || !orig.startsWith('/')) { + QFileSystemEntry cur(currentPath()); + result = cur.nativeFilePath(); + } + if (!orig.isEmpty() && !(orig.length() == 1 && orig[0] == '.')) { + if (!result.isEmpty() && !result.endsWith('/')) + result.append('/'); + result.append(orig); + } + + if (result.length() == 1 && result[0] == '/') + return QFileSystemEntry(result, QFileSystemEntry::FromNativePath()); + const bool isDir = result.endsWith('/'); + + /* as long as QDir::cleanPath() operates on a QString we have to convert to a string here. + * ideally we never convert to a string since that loses information. Please fix after + * we get a QByteArray version of QDir::cleanPath() + */ + QFileSystemEntry resultingEntry(result, QFileSystemEntry::FromNativePath()); + QString stringVersion = QDir::cleanPath(resultingEntry.filePath()); + if (isDir) + stringVersion.append(QLatin1Char('/')); + return QFileSystemEntry(stringVersion); +} + +//static +QString QFileSystemEngine::resolveUserName(uint userId) +{ +#if !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_OPENBSD) + int size_max = sysconf(_SC_GETPW_R_SIZE_MAX); + if (size_max == -1) + size_max = 1024; + QVarLengthArray<char, 1024> buf(size_max); +#endif + + struct passwd *pw = 0; +#if !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_OPENBSD) + struct passwd entry; + getpwuid_r(userId, &entry, buf.data(), buf.size(), &pw); +#else + pw = getpwuid(userId); +#endif + if (pw) + return QFile::decodeName(QByteArray(pw->pw_name)); + return QString(); +} + +//static +QString QFileSystemEngine::resolveGroupName(uint groupId) +{ +#if !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_OPENBSD) + int size_max = sysconf(_SC_GETPW_R_SIZE_MAX); + if (size_max == -1) + size_max = 1024; + QVarLengthArray<char, 1024> buf(size_max); +#endif + + struct group *gr = 0; +#if !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_OPENBSD) + size_max = sysconf(_SC_GETGR_R_SIZE_MAX); + if (size_max == -1) + size_max = 1024; + buf.resize(size_max); + struct group entry; + // Some large systems have more members than the POSIX max size + // Loop over by doubling the buffer size (upper limit 250k) + for (unsigned size = size_max; size < 256000; size += size) + { + buf.resize(size); + // ERANGE indicates that the buffer was too small + if (!getgrgid_r(groupId, &entry, buf.data(), buf.size(), &gr) + || errno != ERANGE) + break; + } +#else + gr = getgrgid(groupId); +#endif + if (gr) + return QFile::decodeName(QByteArray(gr->gr_name)); + return QString(); +} + +#if !defined(QWS) && !defined(Q_WS_QPA) && defined(Q_OS_MAC) +//static +QString QFileSystemEngine::bundleName(const QFileSystemEntry &entry) +{ + QCFType<CFURLRef> url = CFURLCreateWithFileSystemPath(0, QCFString(entry.filePath()), + kCFURLPOSIXPathStyle, true); + if (QCFType<CFDictionaryRef> dict = CFBundleCopyInfoDictionaryForURL(url)) { + if (CFTypeRef name = (CFTypeRef)CFDictionaryGetValue(dict, kCFBundleNameKey)) { + if (CFGetTypeID(name) == CFStringGetTypeID()) + return QCFString::toQString((CFStringRef)name); + } + } + return QString(); +} +#endif + +//static +bool QFileSystemEngine::fillMetaData(const QFileSystemEntry &entry, QFileSystemMetaData &data, + QFileSystemMetaData::MetaDataFlags what) +{ +#if !defined(QWS) && !defined(Q_WS_QPA) && defined(Q_OS_MAC) + if (what & QFileSystemMetaData::BundleType) { + if (!data.hasFlags(QFileSystemMetaData::DirectoryType)) + what |= QFileSystemMetaData::DirectoryType; + } +#endif + +#if !defined(QWS) && !defined(Q_WS_QPA) && defined(Q_OS_MAC) \ + && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 + if (what & QFileSystemMetaData::HiddenAttribute) { + // Mac OS >= 10.5: st_flags & UF_HIDDEN + what |= QFileSystemMetaData::PosixStatFlags; + } +#endif + + if (what & QFileSystemMetaData::PosixStatFlags) + what |= QFileSystemMetaData::PosixStatFlags; + + if (what & QFileSystemMetaData::ExistsAttribute) { + // FIXME: Would other queries being performed provide this bit? + what |= QFileSystemMetaData::PosixStatFlags; + } + + data.entryFlags &= ~what; + + const char * nativeFilePath; + int nativeFilePathLength; + { + const QByteArray &path = entry.nativeFilePath(); + nativeFilePath = path.constData(); + nativeFilePathLength = path.size(); + } + + bool entryExists = true; // innocent until proven otherwise + + QT_STATBUF statBuffer; + bool statBufferValid = false; + if (what & QFileSystemMetaData::LinkType) { + if (QT_LSTAT(nativeFilePath, &statBuffer) == 0) { + if (S_ISLNK(statBuffer.st_mode)) { + data.entryFlags |= QFileSystemMetaData::LinkType; + } else { + statBufferValid = true; + data.entryFlags &= ~QFileSystemMetaData::PosixStatFlags; + } + } else { + entryExists = false; + } + + data.knownFlagsMask |= QFileSystemMetaData::LinkType; + } + + if (statBufferValid || (what & QFileSystemMetaData::PosixStatFlags)) { + if (entryExists && !statBufferValid) + statBufferValid = (QT_STAT(nativeFilePath, &statBuffer) == 0); + + if (statBufferValid) + data.fillFromStatBuf(statBuffer); + else { + entryExists = false; + data.creationTime_ = 0; + data.modificationTime_ = 0; + data.accessTime_ = 0; + data.size_ = 0; + data.userId_ = (uint) -2; + data.groupId_ = (uint) -2; + } + + // reset the mask + data.knownFlagsMask |= QFileSystemMetaData::PosixStatFlags + | QFileSystemMetaData::ExistsAttribute; + } + +#if !defined(QWS) && !defined(Q_WS_QPA) && defined(Q_OS_MAC) + if (what & QFileSystemMetaData::AliasType) + { + if (entryExists) { + FSRef fref; + if (FSPathMakeRef((const UInt8 *)nativeFilePath, &fref, NULL) == noErr) { + Boolean isAlias, isFolder; + if (FSIsAliasFile(&fref, &isAlias, &isFolder) == noErr) { + if (isAlias) + data.entryFlags |= QFileSystemMetaData::AliasType; + } + } + } + data.knownFlagsMask |= QFileSystemMetaData::AliasType; + } +#endif + + if (what & QFileSystemMetaData::UserPermissions) { + // calculate user permissions + + if (entryExists) { + if (what & QFileSystemMetaData::UserReadPermission) { + if (QT_ACCESS(nativeFilePath, R_OK) == 0) + data.entryFlags |= QFileSystemMetaData::UserReadPermission; + } + if (what & QFileSystemMetaData::UserWritePermission) { + if (QT_ACCESS(nativeFilePath, W_OK) == 0) + data.entryFlags |= QFileSystemMetaData::UserWritePermission; + } + if (what & QFileSystemMetaData::UserExecutePermission) { + if (QT_ACCESS(nativeFilePath, X_OK) == 0) + data.entryFlags |= QFileSystemMetaData::UserExecutePermission; + } + } + data.knownFlagsMask |= (what & QFileSystemMetaData::UserPermissions); + } + + if (what & QFileSystemMetaData::HiddenAttribute + && !data.isHidden()) { + QString fileName = entry.fileName(); + if ((fileName.size() > 0 && fileName.at(0) == QLatin1Char('.')) + || (entryExists && _q_isMacHidden(nativeFilePath))) + data.entryFlags |= QFileSystemMetaData::HiddenAttribute; + data.knownFlagsMask |= QFileSystemMetaData::HiddenAttribute; + } + +#if !defined(QWS) && !defined(Q_WS_QPA) && defined(Q_OS_MAC) + if (what & QFileSystemMetaData::BundleType) { + if (entryExists && data.isDirectory()) { + QCFType<CFStringRef> path = CFStringCreateWithBytes(0, + (const UInt8*)nativeFilePath, nativeFilePathLength, + kCFStringEncodingUTF8, false); + QCFType<CFURLRef> url = CFURLCreateWithFileSystemPath(0, path, + kCFURLPOSIXPathStyle, true); + + UInt32 type, creator; + if (CFBundleGetPackageInfoInDirectory(url, &type, &creator)) + data.entryFlags |= QFileSystemMetaData::BundleType; + } + + data.knownFlagsMask |= QFileSystemMetaData::BundleType; + } +#endif + + return data.hasFlags(what); +} + +//static +bool QFileSystemEngine::createDirectory(const QFileSystemEntry &entry, bool createParents) +{ + QString dirName = entry.filePath(); + if (createParents) { + dirName = QDir::cleanPath(dirName); + for (int oldslash = -1, slash=0; slash != -1; oldslash = slash) { + slash = dirName.indexOf(QDir::separator(), oldslash+1); + if (slash == -1) { + if (oldslash == dirName.length()) + break; + slash = dirName.length(); + } + if (slash) { + QByteArray chunk = QFile::encodeName(dirName.left(slash)); + QT_STATBUF st; + if (QT_STAT(chunk, &st) != -1) { + if ((st.st_mode & S_IFMT) != S_IFDIR) + return false; + } else if (QT_MKDIR(chunk, 0777) != 0) { + return false; + } + } + } + return true; + } +#if defined(Q_OS_DARWIN) // Mac X doesn't support trailing /'s + if (dirName.endsWith(QLatin1Char('/'))) + dirName.chop(1); +#endif + return (QT_MKDIR(QFile::encodeName(dirName), 0777) == 0); +} + +//static +bool QFileSystemEngine::removeDirectory(const QFileSystemEntry &entry, bool removeEmptyParents) +{ + if (removeEmptyParents) { + QString dirName = QDir::cleanPath(entry.filePath()); + for (int oldslash = 0, slash=dirName.length(); slash > 0; oldslash = slash) { + QByteArray chunk = QFile::encodeName(dirName.left(slash)); + QT_STATBUF st; + if (QT_STAT(chunk, &st) != -1) { + if ((st.st_mode & S_IFMT) != S_IFDIR) + return false; + if (::rmdir(chunk) != 0) + return oldslash != 0; + } else { + return false; + } + slash = dirName.lastIndexOf(QDir::separator(), oldslash-1); + } + return true; + } + return rmdir(QFile::encodeName(entry.filePath())) == 0; +} + +//static +bool QFileSystemEngine::createLink(const QFileSystemEntry &source, const QFileSystemEntry &target, QSystemError &error) +{ + if (::symlink(source.nativeFilePath().constData(), target.nativeFilePath().constData()) == 0) + return true; + error = QSystemError(errno, QSystemError::StandardLibraryError); + return false; +} + +//static +bool QFileSystemEngine::copyFile(const QFileSystemEntry &source, const QFileSystemEntry &target, QSystemError &error) +{ + Q_UNUSED(source); + Q_UNUSED(target); + // # we can implement this using sendfile(2) + //when this function returns false, block copy is used in QFile which sets the error code. + return false; +} + +//static +bool QFileSystemEngine::renameFile(const QFileSystemEntry &source, const QFileSystemEntry &target, QSystemError &error) +{ + if (::rename(source.nativeFilePath().constData(), target.nativeFilePath().constData()) == 0) + return true; + error = QSystemError(errno, QSystemError::StandardLibraryError); + return false; +} + +//static +bool QFileSystemEngine::removeFile(const QFileSystemEntry &entry, QSystemError &error) +{ + if (unlink(entry.nativeFilePath().constData()) == 0) + return true; + error = QSystemError(errno, QSystemError::StandardLibraryError); + return false; + +} + +//static +bool QFileSystemEngine::setPermissions(const QFileSystemEntry &entry, QFile::Permissions permissions, QSystemError &error, QFileSystemMetaData *data) +{ + mode_t mode = 0; + if (permissions & QFile::ReadOwner) + mode |= S_IRUSR; + if (permissions & QFile::WriteOwner) + mode |= S_IWUSR; + if (permissions & QFile::ExeOwner) + mode |= S_IXUSR; + if (permissions & QFile::ReadUser) + mode |= S_IRUSR; + if (permissions & QFile::WriteUser) + mode |= S_IWUSR; + if (permissions & QFile::ExeUser) + mode |= S_IXUSR; + if (permissions & QFile::ReadGroup) + mode |= S_IRGRP; + if (permissions & QFile::WriteGroup) + mode |= S_IWGRP; + if (permissions & QFile::ExeGroup) + mode |= S_IXGRP; + if (permissions & QFile::ReadOther) + mode |= S_IROTH; + if (permissions & QFile::WriteOther) + mode |= S_IWOTH; + if (permissions & QFile::ExeOther) + mode |= S_IXOTH; + + bool success = ::chmod(entry.nativeFilePath().constData(), mode) == 0; + if (success && data) { + data->entryFlags &= ~QFileSystemMetaData::Permissions; + data->entryFlags |= QFileSystemMetaData::MetaDataFlag(uint(permissions)); + data->knownFlagsMask |= QFileSystemMetaData::Permissions; + } + if (!success) + error = QSystemError(errno, QSystemError::StandardLibraryError); + return success; +} + +QString QFileSystemEngine::homePath() +{ + QString home = QFile::decodeName(qgetenv("HOME")); + if (home.isNull()) + home = rootPath(); + return QDir::cleanPath(home); +} + +QString QFileSystemEngine::rootPath() +{ + return QLatin1String("/"); +} + +QString QFileSystemEngine::tempPath() +{ + QString temp = QFile::decodeName(qgetenv("TMPDIR")); + if (temp.isEmpty()) + temp = QLatin1String("/tmp/"); + return QDir::cleanPath(temp); +} + +bool QFileSystemEngine::setCurrentPath(const QFileSystemEntry &path) +{ + int r; + r = QT_CHDIR(path.nativeFilePath()); + return r >= 0; +} + +QFileSystemEntry QFileSystemEngine::currentPath() +{ + QFileSystemEntry result; + QT_STATBUF st; + if (QT_STAT(".", &st) == 0) { +#if defined(__GLIBC__) && !defined(PATH_MAX) + char *currentName = ::get_current_dir_name(); + if (currentName) { + result = QFile::decodeName(QByteArray(currentName)); + ::free(currentName); + } +#else + char currentName[PATH_MAX+1]; + if (::getcwd(currentName, PATH_MAX)) + result = QFileSystemEntry(QByteArray(currentName), QFileSystemEntry::FromNativePath()); +# if defined(QT_DEBUG) + if (result.isEmpty()) + qWarning("QFSFileEngine::currentPath: getcwd() failed"); +# endif +#endif + } else { +# if defined(QT_DEBUG) + qWarning("QFSFileEngine::currentPath: stat(\".\") failed"); +# endif + } + return result; +} +QT_END_NAMESPACE diff --git a/src/corelib/io/qfilesystemengine_win.cpp b/src/corelib/io/qfilesystemengine_win.cpp new file mode 100644 index 0000000..19c94e5 --- /dev/null +++ b/src/corelib/io/qfilesystemengine_win.cpp @@ -0,0 +1,1218 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qfilesystemengine_p.h" + +#define _POSIX_ +#include "qplatformdefs.h" +#include "qabstractfileengine.h" +#include "private/qfsfileengine_p.h" +#include <private/qsystemlibrary_p.h> +#include <qdebug.h> + +#include "qfile.h" +#include "qdir.h" +#include "private/qmutexpool_p.h" +#include "qvarlengtharray.h" +#include "qdatetime.h" +#include "qt_windows.h" + +#if !defined(Q_OS_WINCE) +# include <sys/types.h> +# include <direct.h> +# include <winioctl.h> +#else +# include <types.h> +#endif +#include <objbase.h> +#include <shlobj.h> +#include <initguid.h> +#include <accctrl.h> +#include <ctype.h> +#include <limits.h> +#define SECURITY_WIN32 +#include <security.h> + +#ifndef SPI_GETPLATFORMTYPE +#define SPI_GETPLATFORMTYPE 257 +#endif + +#ifndef PATH_MAX +#define PATH_MAX FILENAME_MAX +#endif + +#ifndef _INTPTR_T_DEFINED +#ifdef _WIN64 +typedef __int64 intptr_t; +#else +#ifdef _W64 +typedef _W64 int intptr_t; +#else +typedef INT_PTR intptr_t; +#endif +#endif +#define _INTPTR_T_DEFINED +#endif + +#ifndef INVALID_FILE_ATTRIBUTES +# define INVALID_FILE_ATTRIBUTES (DWORD (-1)) +#endif + +#if !defined(Q_OS_WINCE) +# if !defined(REPARSE_DATA_BUFFER_HEADER_SIZE) +typedef struct _REPARSE_DATA_BUFFER { + ULONG ReparseTag; + USHORT ReparseDataLength; + USHORT Reserved; + union { + struct { + USHORT SubstituteNameOffset; + USHORT SubstituteNameLength; + USHORT PrintNameOffset; + USHORT PrintNameLength; + ULONG Flags; + WCHAR PathBuffer[1]; + } SymbolicLinkReparseBuffer; + struct { + USHORT SubstituteNameOffset; + USHORT SubstituteNameLength; + USHORT PrintNameOffset; + USHORT PrintNameLength; + WCHAR PathBuffer[1]; + } MountPointReparseBuffer; + struct { + UCHAR DataBuffer[1]; + } GenericReparseBuffer; + }; +} REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER; +# define REPARSE_DATA_BUFFER_HEADER_SIZE FIELD_OFFSET(REPARSE_DATA_BUFFER, GenericReparseBuffer) +# endif // !defined(REPARSE_DATA_BUFFER_HEADER_SIZE) + +# ifndef MAXIMUM_REPARSE_DATA_BUFFER_SIZE +# define MAXIMUM_REPARSE_DATA_BUFFER_SIZE 16384 +# endif +# ifndef IO_REPARSE_TAG_SYMLINK +# define IO_REPARSE_TAG_SYMLINK (0xA000000CL) +# endif +# ifndef FSCTL_GET_REPARSE_POINT +# define FSCTL_GET_REPARSE_POINT CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 42, METHOD_BUFFERED, FILE_ANY_ACCESS) +# endif +#endif // !defined(Q_OS_WINCE) + +QT_BEGIN_NAMESPACE + +Q_CORE_EXPORT int qt_ntfs_permission_lookup = 0; + +#if defined(Q_OS_WINCE) +static QString qfsPrivateCurrentDir = QLatin1String(""); +// As none of the functions we try to resolve do exist on Windows CE +// we use QT_NO_LIBRARY to shorten everything up a little bit. +#define QT_NO_LIBRARY 1 +#endif + +#if !defined(QT_NO_LIBRARY) +QT_BEGIN_INCLUDE_NAMESPACE +typedef DWORD (WINAPI *PtrGetNamedSecurityInfoW)(LPWSTR, SE_OBJECT_TYPE, SECURITY_INFORMATION, PSID*, PSID*, PACL*, PACL*, PSECURITY_DESCRIPTOR*); +static PtrGetNamedSecurityInfoW ptrGetNamedSecurityInfoW = 0; +typedef BOOL (WINAPI *PtrLookupAccountSidW)(LPCWSTR, PSID, LPWSTR, LPDWORD, LPWSTR, LPDWORD, PSID_NAME_USE); +static PtrLookupAccountSidW ptrLookupAccountSidW = 0; +typedef VOID (WINAPI *PtrBuildTrusteeWithSidW)(PTRUSTEE_W, PSID); +static PtrBuildTrusteeWithSidW ptrBuildTrusteeWithSidW = 0; +typedef DWORD (WINAPI *PtrGetEffectiveRightsFromAclW)(PACL, PTRUSTEE_W, OUT PACCESS_MASK); +static PtrGetEffectiveRightsFromAclW ptrGetEffectiveRightsFromAclW = 0; +static TRUSTEE_W currentUserTrusteeW; +static TRUSTEE_W worldTrusteeW; + +typedef BOOL (WINAPI *PtrGetUserProfileDirectoryW)(HANDLE, LPWSTR, LPDWORD); +static PtrGetUserProfileDirectoryW ptrGetUserProfileDirectoryW = 0; +typedef BOOL (WINAPI *PtrGetVolumePathNamesForVolumeNameW)(LPCWSTR,LPWSTR,DWORD,PDWORD); +static PtrGetVolumePathNamesForVolumeNameW ptrGetVolumePathNamesForVolumeNameW = 0; +QT_END_INCLUDE_NAMESPACE + + +static void resolveLibs() +{ + static bool triedResolve = false; + if (!triedResolve) { + // need to resolve the security info functions + + // protect initialization +#ifndef QT_NO_THREAD + QMutexLocker locker(QMutexPool::globalInstanceGet(&triedResolve)); + // check triedResolve again, since another thread may have already + // done the initialization + if (triedResolve) { + // another thread did initialize the security function pointers, + // so we shouldn't do it again. + return; + } +#endif + + triedResolve = true; +#if !defined(Q_OS_WINCE) + HINSTANCE advapiHnd = QSystemLibrary::load(L"advapi32"); + if (advapiHnd) { + ptrGetNamedSecurityInfoW = (PtrGetNamedSecurityInfoW)GetProcAddress(advapiHnd, "GetNamedSecurityInfoW"); + ptrLookupAccountSidW = (PtrLookupAccountSidW)GetProcAddress(advapiHnd, "LookupAccountSidW"); + ptrBuildTrusteeWithSidW = (PtrBuildTrusteeWithSidW)GetProcAddress(advapiHnd, "BuildTrusteeWithSidW"); + ptrGetEffectiveRightsFromAclW = (PtrGetEffectiveRightsFromAclW)GetProcAddress(advapiHnd, "GetEffectiveRightsFromAclW"); + } + if (ptrBuildTrusteeWithSidW) { + // Create TRUSTEE for current user + HANDLE hnd = ::GetCurrentProcess(); + HANDLE token = 0; + if (::OpenProcessToken(hnd, TOKEN_QUERY, &token)) { + TOKEN_USER tu; + DWORD retsize; + if (::GetTokenInformation(token, TokenUser, &tu, sizeof(tu), &retsize)) + ptrBuildTrusteeWithSidW(¤tUserTrusteeW, tu.User.Sid); + ::CloseHandle(token); + } + + typedef BOOL (WINAPI *PtrAllocateAndInitializeSid)(PSID_IDENTIFIER_AUTHORITY, BYTE, DWORD, DWORD, DWORD, DWORD, DWORD, DWORD, DWORD, DWORD, PSID*); + PtrAllocateAndInitializeSid ptrAllocateAndInitializeSid = (PtrAllocateAndInitializeSid)GetProcAddress(advapiHnd, "AllocateAndInitializeSid"); + typedef PVOID (WINAPI *PtrFreeSid)(PSID); + PtrFreeSid ptrFreeSid = (PtrFreeSid)GetProcAddress(advapiHnd, "FreeSid"); + if (ptrAllocateAndInitializeSid && ptrFreeSid) { + // Create TRUSTEE for Everyone (World) + SID_IDENTIFIER_AUTHORITY worldAuth = { SECURITY_WORLD_SID_AUTHORITY }; + PSID pWorld = 0; + if (ptrAllocateAndInitializeSid(&worldAuth, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &pWorld)) + ptrBuildTrusteeWithSidW(&worldTrusteeW, pWorld); + ptrFreeSid(pWorld); + } + } + HINSTANCE userenvHnd = QSystemLibrary::load(L"userenv"); + if (userenvHnd) + ptrGetUserProfileDirectoryW = (PtrGetUserProfileDirectoryW)GetProcAddress(userenvHnd, "GetUserProfileDirectoryW"); + HINSTANCE kernel32 = LoadLibrary(L"kernel32"); + if(kernel32) + ptrGetVolumePathNamesForVolumeNameW = (PtrGetVolumePathNamesForVolumeNameW)GetProcAddress(kernel32, "GetVolumePathNamesForVolumeNameW"); +#endif + } +} +#endif // QT_NO_LIBRARY + +typedef DWORD (WINAPI *PtrNetShareEnum)(LPWSTR, DWORD, LPBYTE*, DWORD, LPDWORD, LPDWORD, LPDWORD); +static PtrNetShareEnum ptrNetShareEnum = 0; +typedef DWORD (WINAPI *PtrNetApiBufferFree)(LPVOID); +static PtrNetApiBufferFree ptrNetApiBufferFree = 0; +typedef struct _SHARE_INFO_1 { + LPWSTR shi1_netname; + DWORD shi1_type; + LPWSTR shi1_remark; +} SHARE_INFO_1; + + +static bool resolveUNCLibs() +{ + static bool triedResolve = false; + if (!triedResolve) { +#ifndef QT_NO_THREAD + QMutexLocker locker(QMutexPool::globalInstanceGet(&triedResolve)); + if (triedResolve) { + return ptrNetShareEnum && ptrNetApiBufferFree; + } +#endif + triedResolve = true; +#if !defined(Q_OS_WINCE) + HINSTANCE hLib = QSystemLibrary::load(L"Netapi32"); + if (hLib) { + ptrNetShareEnum = (PtrNetShareEnum)GetProcAddress(hLib, "NetShareEnum"); + if (ptrNetShareEnum) + ptrNetApiBufferFree = (PtrNetApiBufferFree)GetProcAddress(hLib, "NetApiBufferFree"); + } +#endif + } + return ptrNetShareEnum && ptrNetApiBufferFree; +} + +static QString readSymLink(const QFileSystemEntry &link) +{ + QString result; +#if !defined(Q_OS_WINCE) + HANDLE handle = CreateFile((wchar_t*)link.nativeFilePath().utf16(), + FILE_READ_EA, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + 0, + OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, + 0); + if (handle != INVALID_HANDLE_VALUE) { + DWORD bufsize = MAXIMUM_REPARSE_DATA_BUFFER_SIZE; + REPARSE_DATA_BUFFER *rdb = (REPARSE_DATA_BUFFER*)qMalloc(bufsize); + DWORD retsize = 0; + if (::DeviceIoControl(handle, FSCTL_GET_REPARSE_POINT, 0, 0, rdb, bufsize, &retsize, 0)) { + if (rdb->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT) { + int length = rdb->MountPointReparseBuffer.SubstituteNameLength / sizeof(wchar_t); + int offset = rdb->MountPointReparseBuffer.SubstituteNameOffset / sizeof(wchar_t); + const wchar_t* PathBuffer = &rdb->MountPointReparseBuffer.PathBuffer[offset]; + result = QString::fromWCharArray(PathBuffer, length); + } else if (rdb->ReparseTag == IO_REPARSE_TAG_SYMLINK) { + int length = rdb->SymbolicLinkReparseBuffer.SubstituteNameLength / sizeof(wchar_t); + int offset = rdb->SymbolicLinkReparseBuffer.SubstituteNameOffset / sizeof(wchar_t); + const wchar_t* PathBuffer = &rdb->SymbolicLinkReparseBuffer.PathBuffer[offset]; + result = QString::fromWCharArray(PathBuffer, length); + } + // cut-off "//?/" and "/??/" + if (result.size() > 4 && result.at(0) == QLatin1Char('\\') && result.at(2) == QLatin1Char('?') && result.at(3) == QLatin1Char('\\')) + result = result.mid(4); + } + qFree(rdb); + CloseHandle(handle); + +#if !defined(QT_NO_LIBRARY) + resolveLibs(); + if (ptrGetVolumePathNamesForVolumeNameW) { + QRegExp matchVolName(QLatin1String("^Volume\\{([a-z]|[0-9]|-)+\\}\\\\"), Qt::CaseInsensitive); + if(matchVolName.indexIn(result) == 0) { + DWORD len; + wchar_t buffer[MAX_PATH]; + QString volumeName = result.mid(0, matchVolName.matchedLength()).prepend(QLatin1String("\\\\?\\")); + if(ptrGetVolumePathNamesForVolumeNameW((wchar_t*)volumeName.utf16(), buffer, MAX_PATH, &len) != 0) + result.replace(0,matchVolName.matchedLength(), QString::fromWCharArray(buffer)); + } + } +#endif + } +#else + Q_UNUSED(link); +#endif // Q_OS_WINCE + return result; +} + +static QString readLink(const QFileSystemEntry &link) +{ +#if !defined(Q_OS_WINCE) +#if !defined(QT_NO_LIBRARY) && !defined(Q_CC_MWERKS) + QString ret; + + bool neededCoInit = false; + IShellLink *psl; // pointer to IShellLink i/f + WIN32_FIND_DATA wfd; + wchar_t szGotPath[MAX_PATH]; + + // Get pointer to the IShellLink interface. + HRESULT hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID *)&psl); + + if (hres == CO_E_NOTINITIALIZED) { // COM was not initialized + neededCoInit = true; + CoInitialize(NULL); + hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, + IID_IShellLink, (LPVOID *)&psl); + } + if (SUCCEEDED(hres)) { // Get pointer to the IPersistFile interface. + IPersistFile *ppf; + hres = psl->QueryInterface(IID_IPersistFile, (LPVOID *)&ppf); + if (SUCCEEDED(hres)) { + hres = ppf->Load((LPOLESTR)link.nativeFilePath().utf16(), STGM_READ); + //The original path of the link is retrieved. If the file/folder + //was moved, the return value still have the old path. + if (SUCCEEDED(hres)) { + if (psl->GetPath(szGotPath, MAX_PATH, &wfd, SLGP_UNCPRIORITY) == NOERROR) + ret = QString::fromWCharArray(szGotPath); + } + ppf->Release(); + } + psl->Release(); + } + if (neededCoInit) + CoUninitialize(); + + return ret; +#else + Q_UNUSED(link); + return QString(); +#endif // QT_NO_LIBRARY +#else + wchar_t target[MAX_PATH]; + QString result; + if (SHGetShortcutTarget((wchar_t*)QFileInfo(link.filePath()).absoluteFilePath().replace(QLatin1Char('/'),QLatin1Char('\\')).utf16(), target, MAX_PATH)) { + result = QString::fromWCharArray(target); + if (result.startsWith(QLatin1Char('"'))) + result.remove(0,1); + if (result.endsWith(QLatin1Char('"'))) + result.remove(result.size()-1,1); + } + return result; +#endif // Q_OS_WINCE +} + +static bool uncShareExists(const QString &server) +{ + // This code assumes the UNC path is always like \\?\UNC\server... + QStringList parts = server.split(QLatin1Char('\\'), QString::SkipEmptyParts); + if (parts.count() >= 3) { + QStringList shares; + if (QFileSystemEngine::uncListSharesOnServer(QLatin1String("\\\\") + parts.at(2), &shares)) + return parts.count() >= 4 ? shares.contains(parts.at(3), Qt::CaseInsensitive) : true; + } + return false; +} + +static inline bool getFindData(QString path, WIN32_FIND_DATA &findData) +{ + // path should not end with a trailing slash + while (path.endsWith(QLatin1Char('\\'))) + path.chop(1); + + // can't handle drives + if (!path.endsWith(QLatin1Char(':'))) { + HANDLE hFind = ::FindFirstFile((wchar_t*)path.utf16(), &findData); + if (hFind != INVALID_HANDLE_VALUE) { + ::FindClose(hFind); + return true; + } + } + + return false; +} + +bool QFileSystemEngine::uncListSharesOnServer(const QString &server, QStringList *list) +{ + if (resolveUNCLibs()) { + SHARE_INFO_1 *BufPtr, *p; + DWORD res; + DWORD er = 0, tr = 0, resume = 0, i; + do { + res = ptrNetShareEnum((wchar_t*)server.utf16(), 1, (LPBYTE *)&BufPtr, DWORD(-1), &er, &tr, &resume); + if (res == ERROR_SUCCESS || res == ERROR_MORE_DATA) { + p = BufPtr; + for (i = 1; i <= er; ++i) { + if (list && p->shi1_type == 0) + list->append(QString::fromWCharArray(p->shi1_netname)); + p++; + } + } + ptrNetApiBufferFree(BufPtr); + } while (res == ERROR_MORE_DATA); + return res == ERROR_SUCCESS; + } + return false; +} + +void QFileSystemEngine::clearWinStatData(QFileSystemMetaData &data) +{ + data.size_ = 0; + data.fileAttribute_ = 0; + data.creationTime_ = FILETIME(); + data.lastAccessTime_ = FILETIME(); + data.lastWriteTime_ = FILETIME(); +} + +bool QFileSystemEngine::isCaseSensitive() +{ + return false; +} + +//static +QFileSystemEntry QFileSystemEngine::getLinkTarget(const QFileSystemEntry &link, + QFileSystemMetaData &data) +{ + if (data.missingFlags(QFileSystemMetaData::LinkType)) + QFileSystemEngine::fillMetaData(link, data, QFileSystemMetaData::LinkType); + + QString ret; + if (data.isLnkFile()) + ret = readLink(link); + else if (data.isLink()) + ret = readSymLink(link); + return QFileSystemEntry(ret); +} + +//static +QFileSystemEntry QFileSystemEngine::canonicalName(const QFileSystemEntry &entry, QFileSystemMetaData &data) +{ + if (data.missingFlags(QFileSystemMetaData::ExistsAttribute)) + QFileSystemEngine::fillMetaData(entry, data, QFileSystemMetaData::ExistsAttribute); + + if (data.exists()) + return QFileSystemEntry(slowCanonicalized(absoluteName(entry).filePath())); + else + return QFileSystemEntry(); +} + +//static +QString QFileSystemEngine::nativeAbsoluteFilePath(const QString &path) +{ + // can be //server or //server/share + QString absPath; +#if !defined(Q_OS_WINCE) + QVarLengthArray<wchar_t, MAX_PATH> buf(qMax(MAX_PATH, path.size() + 1)); + wchar_t *fileName = 0; + DWORD retLen = GetFullPathName((wchar_t*)path.utf16(), buf.size(), buf.data(), &fileName); + if (retLen > (DWORD)buf.size()) { + buf.resize(retLen); + retLen = GetFullPathName((wchar_t*)path.utf16(), buf.size(), buf.data(), &fileName); + } + if (retLen != 0) + absPath = QString::fromWCharArray(buf.data(), retLen); +#else + if (path.startsWith(QLatin1Char('/')) || path.startsWith(QLatin1Char('\\'))) + absPath = QDir::toNativeSeparators(path); + else + absPath = QDir::toNativeSeparators(QDir::cleanPath(qfsPrivateCurrentDir + QLatin1Char('/') + path)); +#endif + // This is really ugly, but GetFullPathName strips off whitespace at the end. + // If you for instance write ". " in the lineedit of QFileDialog, + // (which is an invalid filename) this function will strip the space off and viola, + // the file is later reported as existing. Therefore, we re-add the whitespace that + // was at the end of path in order to keep the filename invalid. + if (!path.isEmpty() && path.at(path.size() - 1) == QLatin1Char(' ')) + absPath.append(QLatin1Char(' ')); + return absPath; +} + +//static +QFileSystemEntry QFileSystemEngine::absoluteName(const QFileSystemEntry &entry) +{ + QString ret; + + if (!entry.isRelative()) { +#if !defined(Q_OS_WINCE) + if (entry.isAbsolute() + && !entry.filePath().contains(QLatin1String("/../")) + && !entry.filePath().contains(QLatin1String("/./")) + && !entry.filePath().endsWith(QLatin1String("/..")) + && !entry.filePath().endsWith(QLatin1String("/."))) { + ret = entry.filePath(); + } else { + ret = QDir::fromNativeSeparators(nativeAbsoluteFilePath(entry.filePath())); + } +#else + ret = entry.filePath(); +#endif + } else { + ret = QDir::cleanPath(QDir::currentPath() + QLatin1Char('/') + entry.filePath()); + } + + // The path should be absolute at this point. + // From the docs : + // Absolute paths begin with the directory separator "/" + // (optionally preceded by a drive specification under Windows). + if (ret.at(0) != QLatin1Char('/')) { + Q_ASSERT(ret.length() >= 2); + Q_ASSERT(ret.at(0).isLetter()); + Q_ASSERT(ret.at(1) == QLatin1Char(':')); + + // Force uppercase drive letters. + ret[0] = ret.at(0).toUpper(); + } + return QFileSystemEntry(ret); +} + +//static +QString QFileSystemEngine::owner(const QFileSystemEntry &entry, QAbstractFileEngine::FileOwner own) +{ + QString name; +#if !defined(QT_NO_LIBRARY) + extern int qt_ntfs_permission_lookup; + if((qt_ntfs_permission_lookup > 0) && (QSysInfo::WindowsVersion & QSysInfo::WV_NT_based)) { + resolveLibs(); + if (ptrGetNamedSecurityInfoW && ptrLookupAccountSidW) { + PSID pOwner = 0; + PSECURITY_DESCRIPTOR pSD; + if (ptrGetNamedSecurityInfoW((wchar_t*)entry.nativeFilePath().utf16(), SE_FILE_OBJECT, + own == QAbstractFileEngine::OwnerGroup ? GROUP_SECURITY_INFORMATION : OWNER_SECURITY_INFORMATION, + own == QAbstractFileEngine::OwnerUser ? &pOwner : 0, own == QAbstractFileEngine::OwnerGroup ? &pOwner : 0, + 0, 0, &pSD) == ERROR_SUCCESS) { + DWORD lowner = 64; + DWORD ldomain = 64; + QVarLengthArray<wchar_t, 64> owner(lowner); + QVarLengthArray<wchar_t, 64> domain(ldomain); + SID_NAME_USE use = SidTypeUnknown; + // First call, to determine size of the strings (with '\0'). + if (!ptrLookupAccountSidW(NULL, pOwner, (LPWSTR)owner.data(), &lowner, + (LPWSTR)domain.data(), &ldomain, (SID_NAME_USE*)&use)) { + if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { + if (lowner > (DWORD)owner.size()) + owner.resize(lowner); + if (ldomain > (DWORD)domain.size()) + domain.resize(ldomain); + // Second call, try on resized buf-s + if (!ptrLookupAccountSidW(NULL, pOwner, (LPWSTR)owner.data(), &lowner, + (LPWSTR)domain.data(), &ldomain, (SID_NAME_USE*)&use)) { + lowner = 0; + } + } else { + lowner = 0; + } + } + if (lowner != 0) + name = QString::fromWCharArray(owner.data()); + LocalFree(pSD); + } + } + } +#else + Q_UNUSED(own); +#endif + return name; +} + +//static +bool QFileSystemEngine::fillPermissions(const QFileSystemEntry &entry, QFileSystemMetaData &data, + QFileSystemMetaData::MetaDataFlags what) +{ + QAbstractFileEngine::FileFlags ret = 0; + +#if !defined(QT_NO_LIBRARY) + if((qt_ntfs_permission_lookup > 0) && (QSysInfo::WindowsVersion & QSysInfo::WV_NT_based)) { + resolveLibs(); + if(ptrGetNamedSecurityInfoW && ptrBuildTrusteeWithSidW && ptrGetEffectiveRightsFromAclW) { + enum { ReadMask = 0x00000001, WriteMask = 0x00000002, ExecMask = 0x00000020 }; + + QString fname = entry.filePath(); + PSID pOwner = 0; + PSID pGroup = 0; + PACL pDacl; + PSECURITY_DESCRIPTOR pSD; + DWORD res = ptrGetNamedSecurityInfoW((wchar_t*)fname.utf16(), SE_FILE_OBJECT, + OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION, + &pOwner, &pGroup, &pDacl, 0, &pSD); + if(res == ERROR_SUCCESS) { + ACCESS_MASK access_mask; + TRUSTEE_W trustee; + if (what & QFileSystemMetaData::UserPermissions) { // user + data.knownFlagsMask |= QFileSystemMetaData::UserPermissions; + if(ptrGetEffectiveRightsFromAclW(pDacl, ¤tUserTrusteeW, &access_mask) != ERROR_SUCCESS) + access_mask = (ACCESS_MASK)-1; + if(access_mask & ReadMask) + data.entryFlags |= QFileSystemMetaData::UserReadPermission; + if(access_mask & WriteMask) + data.entryFlags|= QFileSystemMetaData::UserWritePermission; + if(access_mask & ExecMask) + data.entryFlags|= QFileSystemMetaData::UserExecutePermission; + } + if (what & QFileSystemMetaData::OwnerPermissions) { // owner + data.knownFlagsMask |= QFileSystemMetaData::OwnerPermissions; + ptrBuildTrusteeWithSidW(&trustee, pOwner); + if(ptrGetEffectiveRightsFromAclW(pDacl, &trustee, &access_mask) != ERROR_SUCCESS) + access_mask = (ACCESS_MASK)-1; + if(access_mask & ReadMask) + data.entryFlags |= QFileSystemMetaData::OwnerReadPermission; + if(access_mask & WriteMask) + data.entryFlags |= QFileSystemMetaData::OwnerWritePermission; + if(access_mask & ExecMask) + data.entryFlags |= QFileSystemMetaData::OwnerExecutePermission; + } + if (what & QFileSystemMetaData::GroupPermissions) { // group + data.knownFlagsMask |= QFileSystemMetaData::GroupPermissions; + ptrBuildTrusteeWithSidW(&trustee, pGroup); + if(ptrGetEffectiveRightsFromAclW(pDacl, &trustee, &access_mask) != ERROR_SUCCESS) + access_mask = (ACCESS_MASK)-1; + if(access_mask & ReadMask) + data.entryFlags |= QFileSystemMetaData::GroupReadPermission; + if(access_mask & WriteMask) + data.entryFlags |= QFileSystemMetaData::GroupWritePermission; + if(access_mask & ExecMask) + data.entryFlags |= QFileSystemMetaData::GroupExecutePermission; + } + if (what & QFileSystemMetaData::OtherPermissions) { // other (world) + data.knownFlagsMask |= QFileSystemMetaData::OtherPermissions; + if(ptrGetEffectiveRightsFromAclW(pDacl, &worldTrusteeW, &access_mask) != ERROR_SUCCESS) + access_mask = (ACCESS_MASK)-1; // ### + if(access_mask & ReadMask) + data.entryFlags |= QFileSystemMetaData::OtherReadPermission; + if(access_mask & WriteMask) + data.entryFlags |= QFileSystemMetaData::OtherWritePermission; + if(access_mask & ExecMask) + data.entryFlags |= QFileSystemMetaData::OwnerExecutePermission; + } + LocalFree(pSD); + } + } + } else +#endif + { + //### what to do with permissions if we don't use NTFS + // for now just add all permissions and what about exe missions ?? + // also qt_ntfs_permission_lookup is now not set by default ... should it ? + data.entryFlags |= QFileSystemMetaData::OwnerReadPermission + | QFileSystemMetaData::GroupReadPermission + | QFileSystemMetaData::OtherReadPermission; + + if (!(data.fileAttribute_ & FILE_ATTRIBUTE_READONLY)) { + data.entryFlags |= QFileSystemMetaData::OwnerWritePermission + | QFileSystemMetaData::GroupWritePermission + | QFileSystemMetaData::OtherWritePermission; + } + + QString fname = entry.filePath(); + QString ext = fname.right(4).toLower(); + if (data.isDirectory() || + ext == QLatin1String(".exe") || ext == QLatin1String(".com") || ext == QLatin1String(".bat") || + ext == QLatin1String(".pif") || ext == QLatin1String(".cmd")) { + data.entryFlags |= QFileSystemMetaData::OwnerExecutePermission | QFileSystemMetaData::GroupExecutePermission + | QFileSystemMetaData::OtherExecutePermission | QFileSystemMetaData::UserExecutePermission; + } + data.knownFlagsMask |= QFileSystemMetaData::OwnerPermissions | QFileSystemMetaData::GroupPermissions + | QFileSystemMetaData::OtherPermissions | QFileSystemMetaData::UserExecutePermission; + // calculate user permissions + if (what & QFileSystemMetaData::UserReadPermission) { + if (::_waccess((wchar_t*)entry.nativeFilePath().utf16(), R_OK) == 0) + data.entryFlags |= QFileSystemMetaData::UserReadPermission; + data.knownFlagsMask |= QFileSystemMetaData::UserReadPermission; + } + if (what & QFileSystemMetaData::UserWritePermission) { + if (::_waccess((wchar_t*)entry.nativeFilePath().utf16(), W_OK) == 0) + data.entryFlags |= QFileSystemMetaData::UserWritePermission; + data.knownFlagsMask |= QFileSystemMetaData::UserReadPermission; + } + } + + return data.hasFlags(what); +} + +static bool tryDriveUNCFallback(const QFileSystemEntry &fname, QFileSystemMetaData &data) +{ + bool entryExists = false; + DWORD fileAttrib = 0; +#if !defined(Q_OS_WINCE) + if (fname.isDriveRoot()) { + // a valid drive ?? + DWORD drivesBitmask = ::GetLogicalDrives(); + int drivebit = 1 << (fname.filePath().at(0).toUpper().unicode() - QLatin1Char('A').unicode()); + if (drivesBitmask & drivebit) { + fileAttrib = FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_SYSTEM; + entryExists = true; + } + } else { +#endif + const QString &path = fname.nativeFilePath(); + bool is_dir = false; + if (path.startsWith(QLatin1String("\\\\?\\UNC"))) { + // UNC - stat doesn't work for all cases (Windows bug) + int s = path.indexOf(path.at(0),7); + if (s > 0) { + // "\\?\UNC\server\..." + s = path.indexOf(path.at(0),s+1); + if (s > 0) { + // "\\?\UNC\server\share\..." + if (s == path.size() - 1) { + // "\\?\UNC\server\share\" + is_dir = true; + } else { + // "\\?\UNC\server\share\notfound" + } + } else { + // "\\?\UNC\server\share" + is_dir = true; + } + } else { + // "\\?\UNC\server" + is_dir = true; + } + } + if (is_dir && uncShareExists(path)) { + // looks like a UNC dir, is a dir. + fileAttrib = FILE_ATTRIBUTE_DIRECTORY; + entryExists = true; + } +#if !defined(Q_OS_WINCE) + } +#endif + if (entryExists) + data.fillFromFileAttribute(fileAttrib); + return entryExists; +} + +static bool tryFindFallback(const QFileSystemEntry &fname, QFileSystemMetaData &data) +{ + bool filledData = false; + // This assumes the last call to a Windows API failed. + int errorCode = GetLastError(); + if (errorCode == ERROR_ACCESS_DENIED || errorCode == ERROR_SHARING_VIOLATION) { + WIN32_FIND_DATA findData; + if (getFindData(fname.nativeFilePath(), findData) + && findData.dwFileAttributes != INVALID_FILE_ATTRIBUTES) { + data.fillFromFindData(findData, true, fname.isDriveRoot()); + filledData = true; + } + } + return filledData; +} + +#if !defined(Q_OS_WINCE) +//static +bool QFileSystemEngine::fillMetaData(int fd, QFileSystemMetaData &data, + QFileSystemMetaData::MetaDataFlags what) +{ + HANDLE fHandle = (HANDLE)_get_osfhandle(fd); + if (fHandle != INVALID_HANDLE_VALUE) { + return fillMetaData(fHandle, data, what); + } + return false; +} +#endif + +//static +bool QFileSystemEngine::fillMetaData(HANDLE fHandle, QFileSystemMetaData &data, + QFileSystemMetaData::MetaDataFlags what) +{ + data.entryFlags &= ~what; + clearWinStatData(data); + BY_HANDLE_FILE_INFORMATION fileInfo; + UINT oldmode = SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX); + if (GetFileInformationByHandle(fHandle , &fileInfo)) { + data.fillFromFindInfo(fileInfo); + } + SetErrorMode(oldmode); + return data.hasFlags(what); +} + +//static +bool QFileSystemEngine::fillMetaData(const QFileSystemEntry &entry, QFileSystemMetaData &data, + QFileSystemMetaData::MetaDataFlags what) +{ + what |= QFileSystemMetaData::WinLnkType | QFileSystemMetaData::WinStatFlags; + data.entryFlags &= ~what; + + QFileSystemEntry fname; + data.knownFlagsMask |= QFileSystemMetaData::WinLnkType; + if(entry.filePath().endsWith(QLatin1String(".lnk"))) { + data.entryFlags |= QFileSystemMetaData::WinLnkType; + fname = QFileSystemEntry(readLink(entry)); + } else { + fname = entry; + } + + if (fname.isEmpty()) { + data.knownFlagsMask |= what; + clearWinStatData(data); + return false; + } + + if (what & QFileSystemMetaData::WinStatFlags) { + UINT oldmode = SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX); + clearWinStatData(data); + WIN32_FIND_DATA findData; + // The memory structure for WIN32_FIND_DATA is same as WIN32_FILE_ATTRIBUTE_DATA + // for all members used by fillFindData(). + bool ok = ::GetFileAttributesEx((wchar_t*)fname.nativeFilePath().utf16(), GetFileExInfoStandard, + reinterpret_cast<WIN32_FILE_ATTRIBUTE_DATA *>(&findData)); + if (ok) { + data.fillFromFindData(findData, false, fname.isDriveRoot()); + } else { + if (!tryFindFallback(fname, data)) + tryDriveUNCFallback(fname, data); + } + SetErrorMode(oldmode); + } + + if (what & QFileSystemMetaData::Permissions) + fillPermissions(fname, data, what); + if ((what & QFileSystemMetaData::LinkType) + && data.missingFlags(QFileSystemMetaData::LinkType)) { + data.knownFlagsMask |= QFileSystemMetaData::LinkType; + if (data.fileAttribute_ & FILE_ATTRIBUTE_REPARSE_POINT) { + WIN32_FIND_DATA findData; + if (getFindData(fname.nativeFilePath(), findData)) + data.fillFromFindData(findData, true); + } + } + data.knownFlagsMask |= what; + return data.hasFlags(what); +} + +static inline bool mkDir(const QString &path) +{ +#if defined(Q_OS_WINCE) + // Unfortunately CreateDirectory returns true for paths longer than + // 256, but does not create a directory. It starts to fail, when + // path length > MAX_PATH, which is 260 usually on CE. + // This only happens on a Windows Mobile device. Windows CE seems + // not to be affected by this. + static int platformId = 0; + if (platformId == 0) { + wchar_t platformString[64]; + if (SystemParametersInfo(SPI_GETPLATFORMTYPE, sizeof(platformString)/sizeof(*platformString),platformString,0)) { + if (0 == wcscmp(platformString, L"PocketPC") || 0 == wcscmp(platformString, L"Smartphone")) + platformId = 1; + else + platformId = 2; + } + } + if (platformId == 1 && QFSFileEnginePrivate::longFileName(path).size() > 256) + return false; +#endif + return ::CreateDirectory((wchar_t*)QFSFileEnginePrivate::longFileName(path).utf16(), 0); +} + +static inline bool rmDir(const QString &path) +{ + return ::RemoveDirectory((wchar_t*)QFSFileEnginePrivate::longFileName(path).utf16()); +} + +static bool isDirPath(const QString &dirPath, bool *existed) +{ + QString path = dirPath; + if (path.length() == 2 && path.at(1) == QLatin1Char(':')) + path += QLatin1Char('\\'); + + DWORD fileAttrib = ::GetFileAttributes((wchar_t*)QFSFileEnginePrivate::longFileName(path).utf16()); + if (fileAttrib == INVALID_FILE_ATTRIBUTES) { + int errorCode = GetLastError(); + if (errorCode == ERROR_ACCESS_DENIED || errorCode == ERROR_SHARING_VIOLATION) { + WIN32_FIND_DATA findData; + if (getFindData(QFSFileEnginePrivate::longFileName(path), findData)) + fileAttrib = findData.dwFileAttributes; + } + } + + if (existed) + *existed = fileAttrib != INVALID_FILE_ATTRIBUTES; + + if (fileAttrib == INVALID_FILE_ATTRIBUTES) + return false; + + return fileAttrib & FILE_ATTRIBUTE_DIRECTORY; +} + +//static +bool QFileSystemEngine::createDirectory(const QFileSystemEntry &entry, bool createParents) +{ + QString dirName = entry.filePath(); + if (createParents) { + dirName = QDir::toNativeSeparators(QDir::cleanPath(dirName)); + // We spefically search for / so \ would break it.. + int oldslash = -1; + if (dirName.startsWith(QLatin1String("\\\\"))) { + // Don't try to create the root path of a UNC path; + // CreateDirectory() will just return ERROR_INVALID_NAME. + for (int i = 0; i < dirName.size(); ++i) { + if (dirName.at(i) != QDir::separator()) { + oldslash = i; + break; + } + } + if (oldslash != -1) + oldslash = dirName.indexOf(QDir::separator(), oldslash); + } + for (int slash=0; slash != -1; oldslash = slash) { + slash = dirName.indexOf(QDir::separator(), oldslash+1); + if (slash == -1) { + if (oldslash == dirName.length()) + break; + slash = dirName.length(); + } + if (slash) { + QString chunk = dirName.left(slash); + bool existed = false; + if (!isDirPath(chunk, &existed)) { + if (!existed) { + if (!mkDir(chunk)) + return false; + } else { + return false; + } + } + } + } + return true; + } + return mkDir(entry.filePath()); +} + +//static +bool QFileSystemEngine::removeDirectory(const QFileSystemEntry &entry, bool removeEmptyParents) +{ + QString dirName = entry.filePath(); + if (removeEmptyParents) { + dirName = QDir::toNativeSeparators(QDir::cleanPath(dirName)); + for (int oldslash = 0, slash=dirName.length(); slash > 0; oldslash = slash) { + QString chunk = dirName.left(slash); + if (chunk.length() == 2 && chunk.at(0).isLetter() && chunk.at(1) == QLatin1Char(':')) + break; + if (!isDirPath(chunk, 0)) + return false; + if (!rmDir(chunk)) + return oldslash != 0; + slash = dirName.lastIndexOf(QDir::separator(), oldslash-1); + } + return true; + } + return rmDir(entry.filePath()); +} + +//static +QString QFileSystemEngine::rootPath() +{ +#if defined(Q_OS_WINCE) + QString ret = QLatin1String("/"); +#elif defined(Q_FS_FAT) + QString ret = QString::fromLatin1(qgetenv("SystemDrive").constData()); + if (ret.isEmpty()) + ret = QLatin1String("c:"); + ret.append(QLatin1Char('/')); +#elif defined(Q_OS_OS2EMX) + char dir[4]; + _abspath(dir, QLatin1String("/"), _MAX_PATH); + QString ret(dir); +#endif + return ret; +} + +//static +QString QFileSystemEngine::homePath() +{ + QString ret; +#if !defined(QT_NO_LIBRARY) + resolveLibs(); + if (ptrGetUserProfileDirectoryW) { + HANDLE hnd = ::GetCurrentProcess(); + HANDLE token = 0; + BOOL ok = ::OpenProcessToken(hnd, TOKEN_QUERY, &token); + if (ok) { + DWORD dwBufferSize = 0; + // First call, to determine size of the strings (with '\0'). + ok = ptrGetUserProfileDirectoryW(token, NULL, &dwBufferSize); + if (!ok && dwBufferSize != 0) { // We got the required buffer size + wchar_t *userDirectory = new wchar_t[dwBufferSize]; + // Second call, now we can fill the allocated buffer. + ok = ptrGetUserProfileDirectoryW(token, userDirectory, &dwBufferSize); + if (ok) + ret = QString::fromWCharArray(userDirectory); + delete [] userDirectory; + } + ::CloseHandle(token); + } + } +#endif + if (ret.isEmpty() || !QFile::exists(ret)) { + ret = QString::fromLocal8Bit(qgetenv("USERPROFILE").constData()); + if (ret.isEmpty() || !QFile::exists(ret)) { + ret = QString::fromLocal8Bit(qgetenv("HOMEDRIVE").constData()) + + QString::fromLocal8Bit(qgetenv("HOMEPATH").constData()); + if (ret.isEmpty() || !QFile::exists(ret)) { + ret = QString::fromLocal8Bit(qgetenv("HOME").constData()); + if (ret.isEmpty() || !QFile::exists(ret)) { +#if defined(Q_OS_WINCE) + ret = QLatin1String("\\My Documents"); + if (!QFile::exists(ret)) +#endif + ret = rootPath(); + } + } + } + } + return QDir::fromNativeSeparators(ret); +} + +QString QFileSystemEngine::tempPath() +{ + QString ret; + wchar_t tempPath[MAX_PATH]; + DWORD len = GetTempPath(MAX_PATH, tempPath); + if (len) + ret = QString::fromWCharArray(tempPath, len); + if (!ret.isEmpty()) { + while (ret.endsWith(QLatin1Char('\\'))) + ret.chop(1); + ret = QDir::fromNativeSeparators(ret); + } + if (ret.isEmpty()) { +#if !defined(Q_OS_WINCE) + ret = QLatin1String("c:/tmp"); +#else + ret = QLatin1String("/Temp"); +#endif + } + return ret; +} + +bool QFileSystemEngine::setCurrentPath(const QFileSystemEntry &entry) +{ + QFileSystemMetaData meta; + fillMetaData(entry, meta, QFileSystemMetaData::ExistsAttribute | QFileSystemMetaData::DirectoryType); + if(!(meta.exists() && meta.isDirectory())) + return false; + +#if !defined(Q_OS_WINCE) + //TODO: this should really be using nativeFilePath(), but that returns a path in long format \\?\c:\foo + //which causes many problems later on when it's returned through currentPath() + return ::SetCurrentDirectory(reinterpret_cast<const wchar_t*>(QDir::toNativeSeparators(entry.filePath()).utf16())) != 0; +#else + qfsPrivateCurrentDir = entry.filePath(); + return true; +#endif +} + +QFileSystemEntry QFileSystemEngine::currentPath() +{ + QString ret; +#if !defined(Q_OS_WINCE) + DWORD size = 0; + wchar_t currentName[PATH_MAX]; + size = ::GetCurrentDirectory(PATH_MAX, currentName); + if (size != 0) { + if (size > PATH_MAX) { + wchar_t *newCurrentName = new wchar_t[size]; + if (::GetCurrentDirectory(PATH_MAX, newCurrentName) != 0) + ret = QString::fromWCharArray(newCurrentName, size); + delete [] newCurrentName; + } else { + ret = QString::fromWCharArray(currentName, size); + } + } + if (ret.length() >= 2 && ret[1] == QLatin1Char(':')) + ret[0] = ret.at(0).toUpper(); // Force uppercase drive letters. +#else + Q_UNUSED(fileName); + //TODO - a race condition exists when using currentPath / setCurrentPath from multiple threads + if (qfsPrivateCurrentDir.isEmpty()) + qfsPrivateCurrentDir = QCoreApplication::applicationDirPath(); + + ret = qfsPrivateCurrentDir; +#endif + return QFileSystemEntry(ret, QFileSystemEntry::FromNativePath()); +} + +//static +bool QFileSystemEngine::createLink(const QFileSystemEntry &source, const QFileSystemEntry &target, QSystemError &error) +{ + Q_ASSERT(false); + Q_UNUSED(source) + Q_UNUSED(target) + Q_UNUSED(error) + + return false; // TODO implement; - code needs to be moved from qfsfileengine_win.cpp +} + +//static +bool QFileSystemEngine::copyFile(const QFileSystemEntry &source, const QFileSystemEntry &target, QSystemError &error) +{ + bool ret = ::CopyFile((wchar_t*)source.nativeFilePath().utf16(), + (wchar_t*)target.nativeFilePath().utf16(), true) != 0; + if(!ret) + error = QSystemError(::GetLastError(), QSystemError::NativeError); + return ret; +} + +//static +bool QFileSystemEngine::renameFile(const QFileSystemEntry &source, const QFileSystemEntry &target, QSystemError &error) +{ + bool ret = ::MoveFile((wchar_t*)source.nativeFilePath().utf16(), + (wchar_t*)target.nativeFilePath().utf16()) != 0; + if(!ret) + error = QSystemError(::GetLastError(), QSystemError::NativeError); + return ret; +} + +//static +bool QFileSystemEngine::removeFile(const QFileSystemEntry &entry, QSystemError &error) +{ + bool ret = ::DeleteFile((wchar_t*)entry.nativeFilePath().utf16()) != 0; + if(!ret) + error = QSystemError(::GetLastError(), QSystemError::NativeError); + return ret; +} + +//static +bool QFileSystemEngine::setPermissions(const QFileSystemEntry &entry, QFile::Permissions permissions, QSystemError &error, + QFileSystemMetaData *data) +{ + Q_UNUSED(data); + int mode = 0; + + if (permissions & QFile::ReadOwner || permissions & QFile::ReadUser + || permissions & QFile::ReadGroup || permissions & QFile::ReadOther) + mode |= _S_IREAD; + if (permissions & QFile::WriteOwner || permissions & QFile::WriteUser + || permissions & QFile::WriteGroup || permissions & QFile::WriteOther) + mode |= _S_IWRITE; + + if (mode == 0) // not supported + return false; + + bool ret = (::_wchmod((wchar_t*)entry.nativeFilePath().utf16(), mode) == 0); + if(!ret) + error = QSystemError(errno, QSystemError::StandardLibraryError); + return ret; +} + +static inline QDateTime fileTimeToQDateTime(const FILETIME *time) +{ + QDateTime ret; + +#if defined(Q_OS_WINCE) + SYSTEMTIME systime; + FILETIME ftime; + systime.wYear = 1970; + systime.wMonth = 1; + systime.wDay = 1; + systime.wHour = 0; + systime.wMinute = 0; + systime.wSecond = 0; + systime.wMilliseconds = 0; + systime.wDayOfWeek = 4; + SystemTimeToFileTime(&systime, &ftime); + unsigned __int64 acttime = (unsigned __int64)time->dwHighDateTime << 32 | time->dwLowDateTime; + FileTimeToSystemTime(time, &systime); + unsigned __int64 time1970 = (unsigned __int64)ftime.dwHighDateTime << 32 | ftime.dwLowDateTime; + unsigned __int64 difftime = acttime - time1970; + difftime /= 10000000; + ret.setTime_t((unsigned int)difftime); +#else + SYSTEMTIME sTime, lTime; + FileTimeToSystemTime(time, &sTime); + SystemTimeToTzSpecificLocalTime(0, &sTime, &lTime); + ret.setDate(QDate(lTime.wYear, lTime.wMonth, lTime.wDay)); + ret.setTime(QTime(lTime.wHour, lTime.wMinute, lTime.wSecond, lTime.wMilliseconds)); +#endif + + return ret; +} + +QDateTime QFileSystemMetaData::creationTime() const +{ + return fileTimeToQDateTime(&creationTime_); +} +QDateTime QFileSystemMetaData::modificationTime() const +{ + return fileTimeToQDateTime(&lastWriteTime_); +} +QDateTime QFileSystemMetaData::accessTime() const +{ + return fileTimeToQDateTime(&lastAccessTime_); +} + +QT_END_NAMESPACE diff --git a/src/corelib/io/qfilesystementry.cpp b/src/corelib/io/qfilesystementry.cpp new file mode 100644 index 0000000..d4c6d0a --- /dev/null +++ b/src/corelib/io/qfilesystementry.cpp @@ -0,0 +1,383 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qfilesystementry_p.h" + +#include <QtCore/qdir.h> +#include <QtCore/qfile.h> +#include <QtCore/private/qfsfileengine_p.h> +#ifdef Q_OS_WIN +#include <QtCore/qstringbuilder.h> +#endif + +QT_BEGIN_NAMESPACE + +#ifdef Q_OS_WIN +static bool isUncRoot(const QString &server) +{ + QString localPath = QDir::toNativeSeparators(server); + if (!localPath.startsWith(QLatin1String("\\\\"))) + return false; + + int idx = localPath.indexOf(QLatin1Char('\\'), 2); + if (idx == -1 || idx + 1 == localPath.length()) + return true; + + localPath = localPath.right(localPath.length() - idx - 1).trimmed(); + return localPath.isEmpty(); +} + +static inline QString fixIfRelativeUncPath(const QString &path) +{ + QString currentPath = QDir::currentPath(); + if (currentPath.startsWith(QLatin1String("//"))) + return currentPath % QChar(QLatin1Char('/')) % path; + return path; +} +#endif + +QFileSystemEntry::QFileSystemEntry() + : m_lastSeparator(0), + m_firstDotInFileName(0), + m_lastDotInFileName(0) +{ +} + +/*! + \internal + Use this constructor when the path is supplied by user code, as it may contain a mix + of '/' and the native separator. + */ +QFileSystemEntry::QFileSystemEntry(const QString &filePath) + : m_filePath(QDir::fromNativeSeparators(filePath)), + m_lastSeparator(-2), + m_firstDotInFileName(-2), + m_lastDotInFileName(0) +{ +} + +/*! + \internal + Use this constructor when the path is guaranteed to be in internal format, i.e. all + directory separators are '/' and not the native separator. + */ +QFileSystemEntry::QFileSystemEntry(const QString &filePath, FromInternalPath /* dummy */) + : m_filePath(filePath), + m_lastSeparator(-2), + m_firstDotInFileName(-2), + m_lastDotInFileName(0) +{ +} + +/*! + \internal + Use this constructor when the path comes from a native API + */ +QFileSystemEntry::QFileSystemEntry(const NativePath &nativeFilePath, FromNativePath /* dummy */) + : m_nativeFilePath(nativeFilePath), + m_lastSeparator(-2), + m_firstDotInFileName(-2), + m_lastDotInFileName(0) +{ +} + +QFileSystemEntry::QFileSystemEntry(const QString &filePath, const NativePath &nativeFilePath) + : m_filePath(QDir::fromNativeSeparators(filePath)), + m_nativeFilePath(nativeFilePath), + m_lastSeparator(-2), + m_firstDotInFileName(-2), + m_lastDotInFileName(0) +{ +} + +QString QFileSystemEntry::filePath() const +{ + resolveFilePath(); + return m_filePath; +} + +QFileSystemEntry::NativePath QFileSystemEntry::nativeFilePath() const +{ + resolveNativeFilePath(); + return m_nativeFilePath; +} + +void QFileSystemEntry::resolveFilePath() const +{ + if (m_filePath.isEmpty() && !m_nativeFilePath.isEmpty()) { +#if defined(QFILESYSTEMENTRY_NATIVE_PATH_IS_UTF16) + m_filePath = QDir::fromNativeSeparators(m_nativeFilePath); +#ifdef Q_OS_WIN + if (m_filePath.startsWith(QLatin1String("//?/UNC/"))) + m_filePath = m_filePath.remove(2,6); + if (m_filePath.startsWith(QLatin1String("//?/"))) + m_filePath = m_filePath.remove(0,4); +#endif +#else + m_filePath = QDir::fromNativeSeparators(QFile::decodeName(m_nativeFilePath)); +#endif + } +} + +void QFileSystemEntry::resolveNativeFilePath() const +{ + if (!m_filePath.isEmpty() && m_nativeFilePath.isEmpty()) { +#ifdef Q_OS_WIN + QString filePath = m_filePath; + if (isRelative()) + filePath = fixIfRelativeUncPath(m_filePath); + m_nativeFilePath = QFSFileEnginePrivate::longFileName(QDir::toNativeSeparators(filePath)); +#elif defined(QFILESYSTEMENTRY_NATIVE_PATH_IS_UTF16) + m_nativeFilePath = QDir::toNativeSeparators(m_filePath); +#else + m_nativeFilePath = QFile::encodeName(QDir::toNativeSeparators(m_filePath)); +#endif + } +} + +QString QFileSystemEntry::fileName() const +{ + findLastSeparator(); +#if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN) + if (m_lastSeparator == -1 && m_filePath.length() >= 2 && m_filePath.at(1) == QLatin1Char(':')) + return m_filePath.mid(2); +#endif + return m_filePath.mid(m_lastSeparator + 1); +} + +QString QFileSystemEntry::path() const +{ + findLastSeparator(); + if (m_lastSeparator == -1) { +#if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN) + if (m_filePath.length() >= 2 && m_filePath.at(1) == QLatin1Char(':')) + return m_filePath.left(2); +#endif + return QString(QLatin1Char('.')); + } + if (m_lastSeparator == 0) + return QString(QLatin1Char('/')); +#if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN) + if (m_lastSeparator == 2 && m_filePath.at(1) == QLatin1Char(':')) + return m_filePath.left(m_lastSeparator + 1); +#endif + return m_filePath.left(m_lastSeparator); +} + +QString QFileSystemEntry::baseName() const +{ + findFileNameSeparators(); +#if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN) + if (m_lastSeparator == -1 && m_filePath.length() >= 2 && m_filePath.at(1) == QLatin1Char(':')) + return m_filePath.mid(2); +#endif + int length = -1; + if (m_firstDotInFileName >= 0) { + length = m_firstDotInFileName; + if (m_lastSeparator != -1) // avoid off by one + length--; + } + return m_filePath.mid(m_lastSeparator + 1, length); +} + +QString QFileSystemEntry::completeBaseName() const +{ + findFileNameSeparators(); +#if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN) + if (m_lastSeparator == -1 && m_filePath.length() >= 2 && m_filePath.at(1) == QLatin1Char(':')) + return m_filePath.mid(2); +#endif + int length = -1; + if (m_firstDotInFileName >= 0) { + length = m_firstDotInFileName + m_lastDotInFileName; + if (m_lastSeparator != -1) // avoid off by one + length--; + } + return m_filePath.mid(m_lastSeparator + 1, length); +} + +QString QFileSystemEntry::suffix() const +{ + findFileNameSeparators(); + + if (m_lastDotInFileName == -1) + return QString(); + + return m_filePath.mid(qMax((qint16)0, m_lastSeparator) + m_firstDotInFileName + m_lastDotInFileName + 1); +} + +QString QFileSystemEntry::completeSuffix() const +{ + findFileNameSeparators(); + if (m_firstDotInFileName == -1) + return QString(); + + return m_filePath.mid(qMax((qint16)0, m_lastSeparator) + m_firstDotInFileName + 1); +} + +#if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN) +bool QFileSystemEntry::isRelative() const +{ + resolveFilePath(); + return (m_filePath.isEmpty() || (!m_filePath.isEmpty() && (m_filePath[0].unicode() != '/') + && (!(m_filePath.length() >= 2 && m_filePath[1].unicode() == ':')))); +} + +bool QFileSystemEntry::isAbsolute() const +{ + resolveFilePath(); + return (!m_filePath.isEmpty() && ((m_filePath.length() >= 3 + && (m_filePath[0].isLetter() && m_filePath[1].unicode() == ':' && m_filePath[2].unicode() == '/')) +#ifdef Q_OS_WIN + || (m_filePath.length() >= 2 && (m_filePath.at(0) == QLatin1Char('/') && m_filePath.at(1) == QLatin1Char('/'))) +#endif + )); +} +#else +bool QFileSystemEntry::isRelative() const +{ + return !isAbsolute(); +} + +bool QFileSystemEntry::isAbsolute() const +{ + resolveFilePath(); + return (!m_filePath.isEmpty() && (m_filePath[0].unicode() == '/')); +} +#endif + +#if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN) +bool QFileSystemEntry::isDriveRoot() const +{ + resolveFilePath(); + return (m_filePath.length() == 3 + && m_filePath.at(0).isLetter() && m_filePath.at(1) == QLatin1Char(':') + && m_filePath.at(2) == QLatin1Char('/')); +} +#endif + +bool QFileSystemEntry::isRoot() const +{ + resolveFilePath(); + if (m_filePath == QLatin1String("/") +#if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN) + || isDriveRoot() +#if defined(Q_OS_WIN) + || isUncRoot(m_filePath) +#endif +#endif + ) + return true; + + return false; +} + +bool QFileSystemEntry::isEmpty() const +{ + resolveNativeFilePath(); + return m_nativeFilePath.isEmpty(); +} + +// private methods + +void QFileSystemEntry::findLastSeparator() const +{ + if (m_lastSeparator == -2) { + resolveFilePath(); + m_lastSeparator = -1; + for (int i = m_filePath.size() - 1; i >= 0; --i) { + if (m_filePath[i].unicode() == '/') { + m_lastSeparator = i; + break; + } + } + } +} + +void QFileSystemEntry::findFileNameSeparators() const +{ + if (m_firstDotInFileName == -2) { + resolveFilePath(); + int firstDotInFileName = -1; + int lastDotInFileName = -1; + int lastSeparator = m_lastSeparator; + + int stop; + if (lastSeparator < 0) { + lastSeparator = -1; + stop = 0; + } else { + stop = lastSeparator; + } + + int i = m_filePath.size() - 1; + for (; i >= stop; --i) { + if (m_filePath[i].unicode() == '.') { + firstDotInFileName = lastDotInFileName = i; + break; + } else if (m_filePath[i].unicode() == '/') { + lastSeparator = i; + break; + } + } + + if (lastSeparator != i) { + for (--i; i >= stop; --i) { + if (m_filePath[i].unicode() == '.') + firstDotInFileName = i; + else if (m_filePath[i].unicode() == '/') { + lastSeparator = i; + break; + } + } + } + m_lastSeparator = lastSeparator; + m_firstDotInFileName = firstDotInFileName == -1 ? -1 : firstDotInFileName - qMax(0, lastSeparator); + if (lastDotInFileName == -1) + m_lastDotInFileName = -1; + else if (firstDotInFileName == lastDotInFileName) + m_lastDotInFileName = 0; + else + m_lastDotInFileName = lastDotInFileName - firstDotInFileName; + } +} + +QT_END_NAMESPACE diff --git a/src/corelib/io/qfilesystementry_p.h b/src/corelib/io/qfilesystementry_p.h new file mode 100644 index 0000000..2ce0a83 --- /dev/null +++ b/src/corelib/io/qfilesystementry_p.h @@ -0,0 +1,126 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QFILESYSTEMENTRY_P_H_INCLUDED +#define QFILESYSTEMENTRY_P_H_INCLUDED + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtCore/qstring.h> +#include <QtCore/qbytearray.h> + +#if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN) +#define QFILESYSTEMENTRY_NATIVE_PATH_IS_UTF16 +#endif + +QT_BEGIN_NAMESPACE + +class QFileSystemEntry +{ +public: + +#ifndef QFILESYSTEMENTRY_NATIVE_PATH_IS_UTF16 + typedef QByteArray NativePath; +#else + typedef QString NativePath; +#endif + struct FromNativePath{}; + struct FromInternalPath{}; + + QFileSystemEntry(); + explicit QFileSystemEntry(const QString &filePath); + + QFileSystemEntry(const QString &filePath, FromInternalPath dummy); + QFileSystemEntry(const NativePath &nativeFilePath, FromNativePath dummy); + QFileSystemEntry(const QString &filePath, const NativePath &nativeFilePath); + + QString filePath() const; + QString fileName() const; + QString path() const; + NativePath nativeFilePath() const; + QString baseName() const; + QString completeBaseName() const; + QString suffix() const; + QString completeSuffix() const; + bool isAbsolute() const; + bool isRelative() const; + +#if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN) + bool isDriveRoot() const; +#endif + bool isRoot() const; + + bool isEmpty() const; + void clear() + { + *this = QFileSystemEntry(); + } + +private: + // creates the QString version out of the bytearray version + void resolveFilePath() const; + // creates the bytearray version out of the QString version + void resolveNativeFilePath() const; + // resolves the separator + void findLastSeparator() const; + // resolves the dots and the separator + void findFileNameSeparators() const; + + mutable QString m_filePath; // always has slashes as separator + mutable NativePath m_nativeFilePath; // native encoding and separators + + mutable qint16 m_lastSeparator; // index in m_filePath of last separator + mutable qint16 m_firstDotInFileName; // index after m_filePath for first dot (.) + mutable qint16 m_lastDotInFileName; // index after m_firstDotInFileName for last dot (.) +}; + +QT_END_NAMESPACE + +#endif // include guard diff --git a/src/corelib/io/qfilesystemiterator_p.h b/src/corelib/io/qfilesystemiterator_p.h new file mode 100644 index 0000000..66f4b1e --- /dev/null +++ b/src/corelib/io/qfilesystemiterator_p.h @@ -0,0 +1,115 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QFILESYSTEMITERATOR_P_H_INCLUDED +#define QFILESYSTEMITERATOR_P_H_INCLUDED + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtCore/qglobal.h> +#include <QtCore/qdir.h> +#include <QtCore/qdiriterator.h> +#include <QtCore/qstringlist.h> + +#include <QtCore/private/qfilesystementry_p.h> +#include <QtCore/private/qfilesystemmetadata_p.h> + +// Platform-specific headers +#if defined(Q_OS_WIN) +#elif defined (Q_OS_SYMBIAN) +#include <f32file.h> +#else +#include <QtCore/qscopedpointer.h> +#endif + +QT_BEGIN_NAMESPACE + +class QFileSystemIterator +{ +public: + QFileSystemIterator(const QFileSystemEntry &entry, QDir::Filters filters, + const QStringList &nameFilters, QDirIterator::IteratorFlags flags + = QDirIterator::FollowSymlinks | QDirIterator::Subdirectories); + ~QFileSystemIterator(); + + bool advance(QFileSystemEntry &fileEntry, QFileSystemMetaData &metaData); + +private: + QFileSystemEntry::NativePath nativePath; + + // Platform-specific data +#if defined(Q_OS_WIN) + QFileSystemEntry::NativePath dirPath; + HANDLE findFileHandle; + QStringList uncShares; + bool uncFallback; + int uncShareIndex; + bool onlyDirs; +#elif defined (Q_OS_SYMBIAN) + RDir dirHandle; + TEntryArray entries; + TInt lastError; + TInt entryIndex; +#else + QT_DIR *dir; + QT_DIRENT *dirEntry; +#if defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_CYGWIN) + // for readdir_r + QScopedPointer<QT_DIRENT, QScopedPointerPodDeleter> mt_file; +#endif + int lastError; +#endif + + Q_DISABLE_COPY(QFileSystemIterator) +}; + +QT_END_NAMESPACE + +#endif // include guard diff --git a/src/corelib/io/qfilesystemiterator_symbian.cpp b/src/corelib/io/qfilesystemiterator_symbian.cpp new file mode 100644 index 0000000..e316526 --- /dev/null +++ b/src/corelib/io/qfilesystemiterator_symbian.cpp @@ -0,0 +1,129 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qfilesystemiterator_p.h" +#include "qfilesystemengine_p.h" +#include <QtCore/private/qcore_symbian_p.h> + +QT_BEGIN_NAMESPACE + +QFileSystemIterator::QFileSystemIterator(const QFileSystemEntry &path, QDir::Filters filters, + const QStringList &nameFilters, QDirIterator::IteratorFlags iteratorFlags) + : lastError(KErrNone), entryIndex(-1) +{ + RFs& fs = qt_s60GetRFs(); + + nativePath = path.nativeFilePath(); + if (!nativePath.endsWith(QLatin1Char('\\'))) + nativePath.append(QLatin1Char('\\')); + + QString absPath = QFileSystemEngine::absoluteName(path).nativeFilePath(); + + if (!absPath.endsWith(QLatin1Char('\\'))) + absPath.append(QLatin1Char('\\')); + + int pathLen = absPath.length(); + if (pathLen > KMaxFileName) { + lastError = KErrBadName; + return; + } + + //set up server side filtering to reduce IPCs + //RDir won't accept all valid name filters e.g. "*. bar" + if (nameFilters.count() == 1 && !(filters & QDir::AllDirs) && iteratorFlags + == QDirIterator::NoIteratorFlags && pathLen + nameFilters[0].length() + <= KMaxFileName) { + //server side supports one mask - skip this for recursive mode or if only files should be filtered + absPath.append(nameFilters[0]); + } + + TUint symbianMask = 0; + if ((filters & QDir::Dirs) || (filters & QDir::AllDirs) || (iteratorFlags + & QDirIterator::Subdirectories)) + symbianMask |= KEntryAttDir; //include directories + if (filters & QDir::Hidden) + 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) + symbianMask = KEntryAttMatchExclude | KEntryAttReadOnly; + else if ((filters & QDir::PermissionMask) == QDir::Readable) + symbianMask = KEntryAttMatchExclusive | KEntryAttReadOnly; + } + + lastError = dirHandle.Open(fs, qt_QString2TPtrC(absPath), symbianMask); +} + +QFileSystemIterator::~QFileSystemIterator() +{ + dirHandle.Close(); +} + +bool QFileSystemIterator::advance(QFileSystemEntry &fileEntry, QFileSystemMetaData &metaData) +{ + //1st time, lastError is result of dirHandle.Open(), entries.Count() is 0 and entryIndex is -1 so initial read is triggered + //subsequent times, read is triggered each time we reach the end of the entry list + //final time, lastError is KErrEof so we don't need to read anymore. + ++entryIndex; + if (lastError == KErrNone && entryIndex >= entries.Count()) { + lastError = dirHandle.Read(entries); + entryIndex = 0; + } + + //each call to advance() gets the next entry from the entry list. + //from the final (or only) read call, KErrEof is returned together with a full buffer so we still need to go through the list + if ((lastError == KErrNone || lastError == KErrEof) && entryIndex < entries.Count()) { + Q_ASSERT(entryIndex >= 0); + const TEntry &entry(entries[entryIndex]); + fileEntry = QFileSystemEntry(nativePath + qt_TDesC2QString(entry.iName), QFileSystemEntry::FromNativePath()); + metaData.fillFromTEntry(entry); + return true; + } + + //TODO: error reporting, to allow user to distinguish empty directory from error condition. + + return false; +} + +QT_END_NAMESPACE diff --git a/src/corelib/io/qfilesystemiterator_unix.cpp b/src/corelib/io/qfilesystemiterator_unix.cpp new file mode 100644 index 0000000..00ccd41 --- /dev/null +++ b/src/corelib/io/qfilesystemiterator_unix.cpp @@ -0,0 +1,113 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qplatformdefs.h" +#include "qfilesystemiterator_p.h" + +#include <stdlib.h> +#include <errno.h> + +QT_BEGIN_NAMESPACE + +QFileSystemIterator::QFileSystemIterator(const QFileSystemEntry &entry, QDir::Filters filters, + const QStringList &nameFilters, QDirIterator::IteratorFlags flags) + : nativePath(entry.nativeFilePath()) + , dir(0) + , dirEntry(0) + , lastError(0) +{ + Q_UNUSED(filters) + Q_UNUSED(nameFilters) + Q_UNUSED(flags) + + if ((dir = QT_OPENDIR(nativePath.constData())) == 0) { + lastError = errno; + } else { + + if (!nativePath.endsWith('/')) + nativePath.append('/'); + +#if defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_CYGWIN) + // ### Race condition; we should use fpathconf and dirfd(). + size_t maxPathName = ::pathconf(nativePath.constData(), _PC_NAME_MAX); + if (maxPathName == size_t(-1)) + maxPathName = FILENAME_MAX; + maxPathName += sizeof(QT_DIRENT) + 1; + + QT_DIRENT *p = reinterpret_cast<QT_DIRENT*>(::malloc(maxPathName)); + Q_CHECK_PTR(p); + + mt_file.reset(p); +#endif + } +} + +QFileSystemIterator::~QFileSystemIterator() +{ + if (dir) + QT_CLOSEDIR(dir); +} + +bool QFileSystemIterator::advance(QFileSystemEntry &fileEntry, QFileSystemMetaData &metaData) +{ + if (!dir) + return false; + +#if defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_CYGWIN) + lastError = QT_READDIR_R(dir, mt_file.data(), &dirEntry); + if (lastError) + return false; +#else + // ### add local lock to prevent breaking reentrancy + dirEntry = QT_READDIR(dir); +#endif // _POSIX_THREAD_SAFE_FUNCTIONS + + if (dirEntry) { + fileEntry = QFileSystemEntry(nativePath + QByteArray(dirEntry->d_name), QFileSystemEntry::FromNativePath()); + metaData.fillFromDirEnt(*dirEntry); + return true; + } + + lastError = errno; + return false; +} + +QT_END_NAMESPACE diff --git a/src/corelib/io/qfilesystemiterator_win.cpp b/src/corelib/io/qfilesystemiterator_win.cpp new file mode 100644 index 0000000..b5fce12 --- /dev/null +++ b/src/corelib/io/qfilesystemiterator_win.cpp @@ -0,0 +1,148 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#if _WIN32_WINNT < 0x0500 +#undef _WIN32_WINNT +#define _WIN32_WINNT 0x0500 +#endif + +#include "qfilesystemiterator_p.h" +#include "qfilesystemengine_p.h" +#include "qplatformdefs.h" + +#include <QtCore/qt_windows.h> + +QT_BEGIN_NAMESPACE + +bool done = true; + +QFileSystemIterator::QFileSystemIterator(const QFileSystemEntry &entry, QDir::Filters filters, + const QStringList &nameFilters, QDirIterator::IteratorFlags flags) + : nativePath(entry.nativeFilePath()) + , dirPath(entry.filePath()) + , findFileHandle(INVALID_HANDLE_VALUE) + , uncFallback(false) + , uncShareIndex(0) + , onlyDirs(false) +{ + Q_UNUSED(nameFilters) + Q_UNUSED(flags) + if (nativePath.endsWith(QLatin1String(".lnk"))) { + QFileSystemMetaData metaData; + QFileSystemEntry link = QFileSystemEngine::getLinkTarget(entry, metaData); + nativePath = link.nativeFilePath(); + } + if (!nativePath.endsWith(QLatin1Char('\\'))) + nativePath.append(QLatin1Char('\\')); + nativePath.append(QLatin1Char('*')); + if (!dirPath.endsWith(QLatin1Char('/'))) + dirPath.append(QLatin1Char('/')); + if ((filters & (QDir::Dirs|QDir::Drives)) && (!(filters & (QDir::Files)))) + onlyDirs = true; +} + +QFileSystemIterator::~QFileSystemIterator() +{ + if (findFileHandle != INVALID_HANDLE_VALUE) + FindClose(findFileHandle); +} + +bool QFileSystemIterator::advance(QFileSystemEntry &fileEntry, QFileSystemMetaData &metaData) +{ + bool haveData = false; + WIN32_FIND_DATA findData; + + if (findFileHandle == INVALID_HANDLE_VALUE && !uncFallback) { + haveData = true; + int infoLevel = 0 ; // FindExInfoStandard; + DWORD dwAdditionalFlags = 0; + if (QSysInfo::windowsVersion() >= QSysInfo::WV_WINDOWS7) { + dwAdditionalFlags = 2; // FIND_FIRST_EX_LARGE_FETCH + infoLevel = 1 ; // FindExInfoBasic; + } + int searchOps = 0; // FindExSearchNameMatch + if (onlyDirs) + searchOps = 1 ; // FindExSearchLimitToDirectories + findFileHandle = FindFirstFileEx((const wchar_t *)nativePath.utf16(), FINDEX_INFO_LEVELS(infoLevel), &findData, + FINDEX_SEARCH_OPS(searchOps), 0, dwAdditionalFlags); + if (findFileHandle == INVALID_HANDLE_VALUE) { + if (nativePath.startsWith(QLatin1String("\\\\?\\UNC\\"))) { + QStringList parts = nativePath.split(QLatin1Char('\\'), QString::SkipEmptyParts); + if (parts.count() == 4 && QFileSystemEngine::uncListSharesOnServer( + QLatin1String("\\\\") + parts.at(2), &uncShares)) { + if (uncShares.isEmpty()) + return false; // No shares found in the server + else + uncFallback = true; + } + } + } + } + if (findFileHandle == INVALID_HANDLE_VALUE && !uncFallback) + return false; + // Retrieve the new file information. + if (!haveData) { + if (uncFallback) { + if (++uncShareIndex >= uncShares.count()) + return false; + } else { + if (!FindNextFile(findFileHandle, &findData)) + return false; + } + } + // Create the new file system entry & meta data. + if (uncFallback) { + fileEntry = QFileSystemEntry(dirPath + uncShares.at(uncShareIndex)); + metaData.fillFromFileAttribute(FILE_ATTRIBUTE_DIRECTORY); + return true; + } else { + QString fileName = QString::fromWCharArray(findData.cFileName); + fileEntry = QFileSystemEntry(dirPath + fileName); + metaData = QFileSystemMetaData(); + if (!fileName.endsWith(QLatin1String(".lnk"))) { + metaData.fillFromFindData(findData, true); + } + return true; + } + return false; +} + +QT_END_NAMESPACE diff --git a/src/corelib/io/qfilesystemmetadata_p.h b/src/corelib/io/qfilesystemmetadata_p.h new file mode 100644 index 0000000..7f75b05 --- /dev/null +++ b/src/corelib/io/qfilesystemmetadata_p.h @@ -0,0 +1,400 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QFILESYSTEMMETADATA_P_H_INCLUDED +#define QFILESYSTEMMETADATA_P_H_INCLUDED + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qplatformdefs.h" +#include <QtCore/qglobal.h> +#include <QtCore/qdatetime.h> +#include <QtCore/qabstractfileengine.h> + +// Platform-specific includes +#if defined(Q_OS_WIN) +#ifndef IO_REPARSE_TAG_SYMLINK +#define IO_REPARSE_TAG_SYMLINK (0xA000000CL) +#endif +#elif defined(Q_OS_SYMBIAN) +#include <f32file.h> +#include <QtCore/private/qdatetime_p.h> +#endif + +QT_BEGIN_NAMESPACE + +class QFileSystemEngine; + +class QFileSystemMetaData +{ +public: + QFileSystemMetaData() + : knownFlagsMask(0) + { + } + + enum MetaDataFlag { + // Permissions, overlaps with QFile::Permissions + OtherReadPermission = 0x00000004, OtherWritePermission = 0x00000002, OtherExecutePermission = 0x00000001, + GroupReadPermission = 0x00000040, GroupWritePermission = 0x00000020, GroupExecutePermission = 0x00000010, + UserReadPermission = 0x00000400, UserWritePermission = 0x00000200, UserExecutePermission = 0x00000100, + OwnerReadPermission = 0x00004000, OwnerWritePermission = 0x00002000, OwnerExecutePermission = 0x00001000, + + OtherPermissions = OtherReadPermission | OtherWritePermission | OtherExecutePermission, + GroupPermissions = GroupReadPermission | GroupWritePermission | GroupExecutePermission, + UserPermissions = UserReadPermission | UserWritePermission | UserExecutePermission, + OwnerPermissions = OwnerReadPermission | OwnerWritePermission | OwnerExecutePermission, + + ReadPermissions = OtherReadPermission | GroupReadPermission | UserReadPermission | OwnerReadPermission, + WritePermissions = OtherWritePermission | GroupWritePermission | UserWritePermission | OwnerWritePermission, + ExecutePermissions = OtherExecutePermission | GroupExecutePermission | UserExecutePermission | OwnerExecutePermission, + + Permissions = OtherPermissions | GroupPermissions | UserPermissions | OwnerPermissions, + + // Type +#ifdef Q_OS_SYMBIAN + LinkType = 0, +#else + LinkType = 0x00010000, +#endif + FileType = 0x00020000, + DirectoryType = 0x00040000, +#if !defined(QWS) && !defined(Q_WS_QPA) && defined(Q_OS_MAC) + BundleType = 0x00080000, + AliasType = 0x08000000, +#else + BundleType = 0x0, + AliasType = 0x0, +#endif +#if defined(Q_OS_WIN) + WinLnkType = 0x08000000, // Note: Uses the same position for AliasType on Mac +#else + WinLnkType = 0x0, +#endif + SequentialType = 0x00800000, // Note: overlaps with QAbstractFileEngine::RootFlag + + LegacyLinkType = LinkType | AliasType | WinLnkType, + + Type = LinkType | FileType | DirectoryType | BundleType | SequentialType | AliasType, + + // Attributes + HiddenAttribute = 0x00100000, + SizeAttribute = 0x00200000, // Note: overlaps with QAbstractFileEngine::LocalDiskFlag + ExistsAttribute = 0x00400000, + + Attributes = HiddenAttribute | SizeAttribute | ExistsAttribute, + + // Times + CreationTime = 0x01000000, // Note: overlaps with QAbstractFileEngine::Refresh + ModificationTime = 0x02000000, + AccessTime = 0x04000000, + + Times = CreationTime | ModificationTime | AccessTime, + + // Owner IDs + UserId = 0x10000000, + GroupId = 0x20000000, + + OwnerIds = UserId | GroupId, + + PosixStatFlags = QFileSystemMetaData::OtherPermissions + | QFileSystemMetaData::GroupPermissions + | QFileSystemMetaData::OwnerPermissions + | QFileSystemMetaData::FileType + | QFileSystemMetaData::DirectoryType + | QFileSystemMetaData::SequentialType + | QFileSystemMetaData::SizeAttribute + | QFileSystemMetaData::Times + | QFileSystemMetaData::OwnerIds, + + SymbianTEntryFlags = QFileSystemMetaData::Permissions + | QFileSystemMetaData::FileType + | QFileSystemMetaData::DirectoryType + | QFileSystemMetaData::SequentialType + | QFileSystemMetaData::Attributes + | QFileSystemMetaData::Times, +#if defined(Q_OS_WIN) + WinStatFlags = QFileSystemMetaData::FileType + | QFileSystemMetaData::DirectoryType + | QFileSystemMetaData::HiddenAttribute + | QFileSystemMetaData::ExistsAttribute + | QFileSystemMetaData::SizeAttribute + | QFileSystemMetaData::Times, +#endif + + AllMetaDataFlags = 0xFFFFFFFF + + }; + Q_DECLARE_FLAGS(MetaDataFlags, MetaDataFlag) + + bool hasFlags(MetaDataFlags flags) const + { + return ((knownFlagsMask & flags) == flags); + } + + MetaDataFlags missingFlags(MetaDataFlags flags) + { + return flags & ~knownFlagsMask; + } + + void clear() + { + knownFlagsMask = 0; + } + + void clearFlags(MetaDataFlags flags = AllMetaDataFlags) + { + knownFlagsMask &= ~flags; + } + + bool exists() const { return (entryFlags & ExistsAttribute); } + + bool isLink() const { return (entryFlags & LinkType); } + bool isFile() const { return (entryFlags & FileType); } + bool isDirectory() const { return (entryFlags & DirectoryType); } + bool isBundle() const; + bool isAlias() const; + bool isLegacyLink() const { return (entryFlags & LegacyLinkType); } + bool isSequential() const { return (entryFlags & SequentialType); } + bool isHidden() const { return (entryFlags & HiddenAttribute); } +#if defined(Q_OS_WIN) + bool isLnkFile() const { return (entryFlags & WinLnkType); } +#else + bool isLnkFile() const { return false; } +#endif + + qint64 size() const { return size_; } + + QFile::Permissions permissions() const { return QFile::Permissions(Permissions & entryFlags); } + + QDateTime creationTime() const; + QDateTime modificationTime() const; + QDateTime accessTime() const; + + QDateTime fileTime(QAbstractFileEngine::FileTime time) const; + uint userId() const; + uint groupId() const; + uint ownerId(QAbstractFileEngine::FileOwner owner) const; + +#ifdef Q_OS_UNIX + void fillFromStatBuf(const QT_STATBUF &statBuffer); + void fillFromDirEnt(const QT_DIRENT &statBuffer); +#endif +#ifdef Q_OS_SYMBIAN + void fillFromTEntry(const TEntry& entry); + void fillFromVolumeInfo(const TVolumeInfo& info); +#endif + +#if defined(Q_OS_WIN) + inline void fillFromFileAttribute(DWORD fileAttribute, bool isDriveRoot = false); + inline void fillFromFindData(WIN32_FIND_DATA &findData, bool setLinkType = false, bool isDriveRoot = false); + inline void fillFromFindInfo(BY_HANDLE_FILE_INFORMATION &fileInfo); +#endif +private: + friend class QFileSystemEngine; + + MetaDataFlags knownFlagsMask; + MetaDataFlags entryFlags; + + qint64 size_; + + // Platform-specific data goes here: +#if defined(Q_OS_WIN) + DWORD fileAttribute_; + FILETIME creationTime_; + FILETIME lastAccessTime_; + FILETIME lastWriteTime_; +#elif defined(Q_OS_SYMBIAN) + TTime modificationTime_; +#else + time_t creationTime_; + time_t modificationTime_; + time_t accessTime_; + + uint userId_; + uint groupId_; +#endif + +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS(QFileSystemMetaData::MetaDataFlags) + +#if !defined(QWS) && !defined(Q_WS_QPA) && defined(Q_OS_MAC) +inline bool QFileSystemMetaData::isBundle() const { return (entryFlags & BundleType); } +inline bool QFileSystemMetaData::isAlias() const { return (entryFlags & AliasType); } +#else +inline bool QFileSystemMetaData::isBundle() const { return false; } +inline bool QFileSystemMetaData::isAlias() const { return false; } +#endif + +#if (defined(Q_OS_UNIX) && !defined (Q_OS_SYMBIAN)) || defined (Q_OS_WIN) +inline QDateTime QFileSystemMetaData::fileTime(QAbstractFileEngine::FileTime time) const +{ + switch (time) { + case QAbstractFileEngine::ModificationTime: + return modificationTime(); + + case QAbstractFileEngine::AccessTime: + return accessTime(); + + case QAbstractFileEngine::CreationTime: + return creationTime(); + } + + return QDateTime(); +} +#endif + +#if defined(Q_OS_UNIX) && !defined (Q_OS_SYMBIAN) +inline QDateTime QFileSystemMetaData::creationTime() const { return QDateTime::fromTime_t(creationTime_); } +inline QDateTime QFileSystemMetaData::modificationTime() const { return QDateTime::fromTime_t(modificationTime_); } +inline QDateTime QFileSystemMetaData::accessTime() const { return QDateTime::fromTime_t(accessTime_); } + +inline uint QFileSystemMetaData::userId() const { return userId_; } +inline uint QFileSystemMetaData::groupId() const { return groupId_; } + +inline uint QFileSystemMetaData::ownerId(QAbstractFileEngine::FileOwner owner) const +{ + if (owner == QAbstractFileEngine::OwnerUser) + return userId(); + else + return groupId(); +} +#endif + +#ifdef Q_OS_SYMBIAN +inline QDateTime QFileSystemMetaData::creationTime() const { return modificationTime(); } +inline QDateTime QFileSystemMetaData::modificationTime() const { return qt_symbian_TTime_To_QDateTime(modificationTime_); } +inline QDateTime QFileSystemMetaData::accessTime() const { return modificationTime(); } + +inline QDateTime QFileSystemMetaData::fileTime(QAbstractFileEngine::FileTime time) const +{ + Q_UNUSED(time); + return modificationTime(); +} +inline uint QFileSystemMetaData::userId() const { return (uint) -2; } +inline uint QFileSystemMetaData::groupId() const { return (uint) -2; } +inline uint QFileSystemMetaData::ownerId(QAbstractFileEngine::FileOwner owner) const +{ + Q_UNUSED(owner); + return (uint) -2; +} +#endif + +#if defined(Q_OS_WIN) +inline uint QFileSystemMetaData::userId() const { return (uint) -2; } +inline uint QFileSystemMetaData::groupId() const { return (uint) -2; } +inline uint QFileSystemMetaData::ownerId(QAbstractFileEngine::FileOwner owner) const +{ + if (owner == QAbstractFileEngine::OwnerUser) + return userId(); + else + return groupId(); +} + +inline void QFileSystemMetaData::fillFromFileAttribute(DWORD fileAttribute,bool isDriveRoot) +{ + fileAttribute_ = fileAttribute; + // Ignore the hidden attribute for drives. + if (!isDriveRoot && (fileAttribute_ & FILE_ATTRIBUTE_HIDDEN)) + entryFlags |= HiddenAttribute; + entryFlags |= ((fileAttribute & FILE_ATTRIBUTE_DIRECTORY) ? DirectoryType: FileType); + entryFlags |= ExistsAttribute; + knownFlagsMask |= FileType | DirectoryType | HiddenAttribute | ExistsAttribute; +} + +inline void QFileSystemMetaData::fillFromFindData(WIN32_FIND_DATA &findData, bool setLinkType, bool isDriveRoot) +{ + fillFromFileAttribute(findData.dwFileAttributes, isDriveRoot); + creationTime_ = findData.ftCreationTime; + lastAccessTime_ = findData.ftLastAccessTime; + lastWriteTime_ = findData.ftLastWriteTime; + if (fileAttribute_ & FILE_ATTRIBUTE_DIRECTORY) { + size_ = 0; + } else { + size_ = findData.nFileSizeHigh; + size_ <<= 32; + size_ += findData.nFileSizeLow; + } + knownFlagsMask |= Times | SizeAttribute; + if (setLinkType) { + knownFlagsMask |= LinkType; + entryFlags &= ~LinkType; +#if !defined(Q_OS_WINCE) + if ((fileAttribute_ & FILE_ATTRIBUTE_REPARSE_POINT) + && (findData.dwReserved0 == IO_REPARSE_TAG_SYMLINK + || findData.dwReserved0 == IO_REPARSE_TAG_MOUNT_POINT)) { + entryFlags |= LinkType; + } +#endif + + } +} + +inline void QFileSystemMetaData::fillFromFindInfo(BY_HANDLE_FILE_INFORMATION &fileInfo) +{ + fillFromFileAttribute(fileInfo.dwFileAttributes); + creationTime_ = fileInfo.ftCreationTime; + lastAccessTime_ = fileInfo.ftLastAccessTime; + lastWriteTime_ = fileInfo.ftLastWriteTime; + if (fileAttribute_ & FILE_ATTRIBUTE_DIRECTORY) { + size_ = 0; + } else { + size_ = fileInfo.nFileSizeHigh; + size_ <<= 32; + size_ += fileInfo.nFileSizeLow; + } + knownFlagsMask |= Times | SizeAttribute; +} +#endif + +QT_END_NAMESPACE + +#endif // include guard diff --git a/src/corelib/io/qfsfileengine.cpp b/src/corelib/io/qfsfileengine.cpp index 62b9981..ae301f7 100644 --- a/src/corelib/io/qfsfileengine.cpp +++ b/src/corelib/io/qfsfileengine.cpp @@ -41,6 +41,7 @@ #include "qfsfileengine_p.h" #include "qfsfileengine_iterator_p.h" +#include "qfilesystemengine_p.h" #include "qdatetime.h" #include "qdiriterator.h" #include "qset.h" @@ -119,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; @@ -133,117 +137,13 @@ void QFSFileEnginePrivate::init() } /*! - \internal - - Returns the canonicalized form of \a path (i.e., with all symlinks - resolved, and all redundant path elements removed. -*/ -QString QFSFileEnginePrivate::canonicalized(const QString &path) -{ - if (path.isEmpty()) - return path; - - // FIXME let's see if this stuff works, then we might be able to remove some of the other code. -#if defined(Q_OS_UNIX) && !defined(Q_OS_SYMBIAN) - if (path.size() == 1 && path.at(0) == QLatin1Char('/')) - return path; -#endif -#if defined(Q_OS_LINUX) || defined(Q_OS_SYMBIAN) || defined(Q_OS_MAC) - // ... but Linux with uClibc does not have it -#if !defined(__UCLIBC__) - char *ret = 0; -#if defined(Q_OS_MAC) && !defined(QT_NO_CORESERVICES) - // Mac OS X 10.5.x doesn't support the realpath(X,0) extension we use here. - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_6) { - ret = realpath(path.toLocal8Bit().constData(), (char*)0); - } else { - // on 10.5 we can use FSRef to resolve the file path. - FSRef fsref; - if (FSPathMakeRef((const UInt8 *)QDir::cleanPath(path).toUtf8().data(), &fsref, 0) == noErr) { - CFURLRef urlref = CFURLCreateFromFSRef(NULL, &fsref); - CFStringRef canonicalPath = CFURLCopyFileSystemPath(urlref, kCFURLPOSIXPathStyle); - QString ret = QCFString::toQString(canonicalPath); - CFRelease(canonicalPath); - CFRelease(urlref); - return ret; - } - } -#else - ret = realpath(path.toLocal8Bit().constData(), (char*)0); -#endif - if (ret) { - QString canonicalPath = QDir::cleanPath(QString::fromLocal8Bit(ret)); - free(ret); - return canonicalPath; - } -#endif -#endif - - QFileInfo fi; - const QChar slash(QLatin1Char('/')); - QString tmpPath = path; - int separatorPos = 0; - QSet<QString> nonSymlinks; - QSet<QString> known; - - known.insert(path); - do { -#ifdef Q_OS_WIN - if (separatorPos == 0) { - if (tmpPath.size() >= 2 && tmpPath.at(0) == slash && tmpPath.at(1) == slash) { - // UNC, skip past the first two elements - separatorPos = tmpPath.indexOf(slash, 2); - } else if (tmpPath.size() >= 3 && tmpPath.at(1) == QLatin1Char(':') && tmpPath.at(2) == slash) { - // volume root, skip since it can not be a symlink - separatorPos = 2; - } - } - if (separatorPos != -1) -#endif - separatorPos = tmpPath.indexOf(slash, separatorPos + 1); - QString prefix = separatorPos == -1 ? tmpPath : tmpPath.left(separatorPos); - if ( -#ifdef Q_OS_SYMBIAN - // Symbian doesn't support directory symlinks, so do not check for link unless we - // are handling the last path element. This not only slightly improves performance, - // but also saves us from lot of unnecessary platform security check failures - // when dealing with files under *:/private directories. - separatorPos == -1 && -#endif - !nonSymlinks.contains(prefix)) { - fi.setFile(prefix); - if (fi.isSymLink()) { - QString target = fi.symLinkTarget(); - if(QFileInfo(target).isRelative()) - target = fi.absolutePath() + slash + target; - if (separatorPos != -1) { - if (fi.isDir() && !target.endsWith(slash)) - target.append(slash); - target.append(tmpPath.mid(separatorPos)); - } - tmpPath = QDir::cleanPath(target); - separatorPos = 0; - - if (known.contains(tmpPath)) - return QString(); - known.insert(tmpPath); - } else { - nonSymlinks.insert(prefix); - } - } - } while (separatorPos != -1); - - return QDir::cleanPath(tmpPath); -} - -/*! Constructs a QFSFileEngine for the file name \a file. */ -QFSFileEngine::QFSFileEngine(const QString &file) : QAbstractFileEngine(*new QFSFileEnginePrivate) +QFSFileEngine::QFSFileEngine(const QString &file) + : QAbstractFileEngine(*new QFSFileEnginePrivate) { Q_D(QFSFileEngine); - d->filePath = QDir::fromNativeSeparators(file); - d->nativeInitFileName(); + d->fileEntry = QFileSystemEntry(file); } /*! @@ -292,8 +192,7 @@ void QFSFileEngine::setFileName(const QString &file) { Q_D(QFSFileEngine); d->init(); - d->filePath = QDir::fromNativeSeparators(file); - d->nativeInitFileName(); + d->fileEntry = QFileSystemEntry(file); } /*! @@ -302,7 +201,7 @@ void QFSFileEngine::setFileName(const QString &file) bool QFSFileEngine::open(QIODevice::OpenMode openMode) { Q_D(QFSFileEngine); - if (d->filePath.isEmpty()) { + if (d->fileEntry.isEmpty()) { qWarning("QFSFileEngine::open: No file name specified"); setError(QFile::OpenError, QLatin1String("No file name specified")); return false; @@ -344,8 +243,7 @@ bool QFSFileEngine::open(QIODevice::OpenMode openMode, FILE *fh) d->openMode = openMode; d->lastFlushFailed = false; d->closeFileHandle = false; - d->nativeFilePath.clear(); - d->filePath.clear(); + d->fileEntry.clear(); d->tried_stat = 0; d->fd = -1; @@ -401,8 +299,7 @@ bool QFSFileEngine::open(QIODevice::OpenMode openMode, int fd) d->openMode = openMode; d->lastFlushFailed = false; d->closeFileHandle = false; - d->nativeFilePath.clear(); - d->filePath.clear(); + d->fileEntry.clear(); d->fh = 0; d->fd = -1; d->tried_stat = 0; @@ -458,7 +355,12 @@ bool QFSFileEngine::close() bool QFSFileEnginePrivate::closeFdFh() { Q_Q(QFSFileEngine); - if (fd == -1 && !fh) + if (fd == -1 && !fh +#ifdef Q_OS_SYMBIAN + && !symbianFile.SubSessionHandle() + && fileHandleForMaps == -1 +#endif + ) return false; // Flush the file if it's buffered, and if the last flush didn't fail. @@ -466,10 +368,24 @@ 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; do { +#ifdef Q_OS_SYMBIAN + if (symbianFile.SubSessionHandle()) { + symbianFile.Close(); + ret = 0; + } else +#endif if (fh) { // Close buffered file. ret = fclose(fh) != 0 ? -1 : 0; @@ -549,28 +465,19 @@ qint64 QFSFileEngine::size() const /*! \internal */ +#ifndef Q_OS_WIN qint64 QFSFileEnginePrivate::sizeFdFh() const { Q_Q(const QFSFileEngine); - // ### Fix this function, it should not stat unless the file is closed. - QT_STATBUF st; - int ret = 0; const_cast<QFSFileEngine *>(q)->flush(); - if (fh && nativeFilePath.isEmpty()) { - // Buffered stdlib mode. - // ### This should really be an ftell - ret = QT_FSTAT(QT_FILENO(fh), &st); - } else if (fd == -1) { - // Stateless stat. - ret = QT_STAT(nativeFilePath.constData(), &st); - } else { - // Unbuffered stdio mode. - ret = QT_FSTAT(fd, &st); - } - if (ret == -1) + + tried_stat = 0; + metaData.clearFlags(QFileSystemMetaData::SizeAttribute); + if (!doStat(QFileSystemMetaData::SizeAttribute)) return 0; - return st.st_size; + return metaData.size(); } +#endif /*! \reimp @@ -877,18 +784,14 @@ bool QFSFileEngine::isSequential() const /*! \internal */ +#ifdef Q_OS_UNIX bool QFSFileEnginePrivate::isSequentialFdFh() const { - if (!tried_stat) - doStat(); - if (could_stat) { -#ifdef Q_OS_UNIX - return (st.st_mode & S_IFMT) != S_IFREG; - // ### WINDOWS! -#endif - } + if (doStat(QFileSystemMetaData::SequentialType)) + return metaData.isSequential(); return true; } +#endif /*! \reimp diff --git a/src/corelib/io/qfsfileengine_iterator.cpp b/src/corelib/io/qfsfileengine_iterator.cpp index 7e7d70a..f6f08c7 100644 --- a/src/corelib/io/qfsfileengine_iterator.cpp +++ b/src/corelib/io/qfsfileengine_iterator.cpp @@ -40,6 +40,7 @@ ****************************************************************************/ #include "qfsfileengine_iterator_p.h" +#include "qfileinfo_p.h" #include "qvariant.h" #ifndef QT_NO_FSFILEENGINE @@ -48,13 +49,23 @@ QT_BEGIN_NAMESPACE QFSFileEngineIterator::QFSFileEngineIterator(QDir::Filters filters, const QStringList &filterNames) : QAbstractFileEngineIterator(filters, filterNames) + , done(false) { - newPlatformSpecifics(); } QFSFileEngineIterator::~QFSFileEngineIterator() { - deletePlatformSpecifics(); +} + +bool QFSFileEngineIterator::hasNext() const +{ + if (!done && !nativeIterator) { + nativeIterator.reset(new QFileSystemIterator(QFileSystemEntry(path()), + filters(), nameFilters())); + advance(); + } + + return !done; } QString QFSFileEngineIterator::next() @@ -66,14 +77,28 @@ QString QFSFileEngineIterator::next() return currentFilePath(); } +void QFSFileEngineIterator::advance() const +{ + currentInfo = nextInfo; + + QFileSystemEntry entry; + QFileSystemMetaData data; + if (nativeIterator->advance(entry, data)) { + nextInfo = QFileInfo(new QFileInfoPrivate(entry, data)); + } else { + done = true; + nativeIterator.reset(); + } +} + QString QFSFileEngineIterator::currentFileName() const { - return currentEntry; + return currentInfo.fileName(); } QFileInfo QFSFileEngineIterator::currentFileInfo() const { - return QAbstractFileEngineIterator::currentFileInfo(); + return currentInfo; } QT_END_NAMESPACE diff --git a/src/corelib/io/qfsfileengine_iterator_p.h b/src/corelib/io/qfsfileengine_iterator_p.h index be670e0..ac9598d 100644 --- a/src/corelib/io/qfsfileengine_iterator_p.h +++ b/src/corelib/io/qfsfileengine_iterator_p.h @@ -54,6 +54,7 @@ // #include "qabstractfileengine.h" +#include "qfilesystemiterator_p.h" #include "qdir.h" #ifndef QT_NO_FSFILEENGINE @@ -76,13 +77,11 @@ public: QFileInfo currentFileInfo() const; private: - QFSFileEngineIteratorPlatformSpecificData *platform; - friend class QFSFileEngineIteratorPlatformSpecificData; - void newPlatformSpecifics(); - void deletePlatformSpecifics(); - void advance(); - - QString currentEntry; + void advance() const; + mutable QScopedPointer<QFileSystemIterator> nativeIterator; + mutable QFileInfo currentInfo; + mutable QFileInfo nextInfo; + mutable bool done; }; QT_END_NAMESPACE diff --git a/src/corelib/io/qfsfileengine_iterator_unix.cpp b/src/corelib/io/qfsfileengine_iterator_unix.cpp deleted file mode 100644 index bfdb03e..0000000 --- a/src/corelib/io/qfsfileengine_iterator_unix.cpp +++ /dev/null @@ -1,140 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qplatformdefs.h" -#include "qfsfileengine_iterator_p.h" - -#include <QtCore/qvariant.h> - -#ifndef QT_NO_FSFILEENGINE - -QT_BEGIN_NAMESPACE - -class QFSFileEngineIteratorPlatformSpecificData -{ -public: - inline QFSFileEngineIteratorPlatformSpecificData() - : dir(0), dirEntry(0), done(false) -#if defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_CYGWIN) && !defined(Q_OS_SYMBIAN) - , mt_file(0) -#endif - {} - - QT_DIR *dir; - QT_DIRENT *dirEntry; - bool done; - -#if defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_CYGWIN) && !defined(Q_OS_SYMBIAN) - // for readdir_r - QT_DIRENT *mt_file; -#endif -}; - -void QFSFileEngineIterator::advance() -{ - currentEntry = platform->dirEntry ? QFile::decodeName(QByteArray(platform->dirEntry->d_name)) : QString(); - - if (!platform->dir) - return; - -#if defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_CYGWIN) && !defined(Q_OS_SYMBIAN) - if (QT_READDIR_R(platform->dir, platform->mt_file, &platform->dirEntry) != 0) - platform->done = true; -#else - // ### add local lock to prevent breaking reentrancy - platform->dirEntry = QT_READDIR(platform->dir); -#endif // _POSIX_THREAD_SAFE_FUNCTIONS - if (!platform->dirEntry) { - QT_CLOSEDIR(platform->dir); - platform->dir = 0; - platform->done = true; -#if defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_CYGWIN) && !defined(Q_OS_SYMBIAN) - delete [] platform->mt_file; - platform->mt_file = 0; -#endif - } -} - -void QFSFileEngineIterator::newPlatformSpecifics() -{ - platform = new QFSFileEngineIteratorPlatformSpecificData; -} - -void QFSFileEngineIterator::deletePlatformSpecifics() -{ - if (platform->dir) { - QT_CLOSEDIR(platform->dir); -#if defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_CYGWIN) && !defined(Q_OS_SYMBIAN) - delete [] platform->mt_file; - platform->mt_file = 0; -#endif - } - delete platform; - platform = 0; -} - -bool QFSFileEngineIterator::hasNext() const -{ - if (!platform->done && !platform->dir) { - QFSFileEngineIterator *that = const_cast<QFSFileEngineIterator *>(this); - if ((that->platform->dir = QT_OPENDIR(QFile::encodeName(path()).data())) == 0) { - that->platform->done = true; - } else { - // ### Race condition; we should use fpathconf and dirfd(). - long maxPathName = ::pathconf(QFile::encodeName(path()).data(), _PC_NAME_MAX); - if ((int) maxPathName == -1) - maxPathName = FILENAME_MAX; - maxPathName += sizeof(QT_DIRENT) + 1; -#if defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_CYGWIN) && !defined(Q_OS_SYMBIAN) - if (that->platform->mt_file) - delete [] that->platform->mt_file; - that->platform->mt_file = (QT_DIRENT *)new char[maxPathName]; -#endif - - that->advance(); - } - } - return !platform->done; -} - -QT_END_NAMESPACE - -#endif // QT_NO_FSFILEENGINE diff --git a/src/corelib/io/qfsfileengine_iterator_win.cpp b/src/corelib/io/qfsfileengine_iterator_win.cpp deleted file mode 100644 index 7181025..0000000 --- a/src/corelib/io/qfsfileengine_iterator_win.cpp +++ /dev/null @@ -1,161 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qfsfileengine_iterator_p.h" -#include "qfsfileengine_p.h" -#include "qplatformdefs.h" - -#include <QtCore/qvariant.h> - -QT_BEGIN_NAMESPACE - -class QFSFileEngineIteratorPlatformSpecificData -{ -public: - inline QFSFileEngineIteratorPlatformSpecificData() - : uncShareIndex(-1), findFileHandle(INVALID_HANDLE_VALUE), - done(false), uncFallback(false) - {} - - QFSFileEngineIterator *it; - - QStringList uncShares; - int uncShareIndex; - - HANDLE findFileHandle; - WIN32_FIND_DATA findData; - bool done; - bool uncFallback; - - void saveCurrentFileName(); -}; - -void QFSFileEngineIteratorPlatformSpecificData::saveCurrentFileName() -{ - if (uncFallback) { - // Windows share / UNC path - it->currentEntry = uncShares.at(uncShareIndex - 1); - } else { - // Local directory - it->currentEntry = QString::fromWCharArray(findData.cFileName); - } -} - -void QFSFileEngineIterator::advance() -{ - platform->saveCurrentFileName(); - - if (platform->done) - return; - - if (platform->uncFallback) { - ++platform->uncShareIndex; - } else if (platform->findFileHandle != INVALID_HANDLE_VALUE) { - if (!FindNextFile(platform->findFileHandle, &platform->findData)) { - platform->done = true; - FindClose(platform->findFileHandle); - } - } -} - -void QFSFileEngineIterator::newPlatformSpecifics() -{ - platform = new QFSFileEngineIteratorPlatformSpecificData; - platform->it = this; -} - -void QFSFileEngineIterator::deletePlatformSpecifics() -{ - delete platform; - platform = 0; -} - -bool QFSFileEngineIterator::hasNext() const -{ - if (platform->done) - return false; - - if (platform->uncFallback) - return platform->uncShareIndex > 0 && platform->uncShareIndex <= platform->uncShares.size(); - - if (platform->findFileHandle == INVALID_HANDLE_VALUE) { - QString path = this->path(); - // Local directory - if (path.endsWith(QLatin1String(".lnk"))) - path = QFileInfo(path).readLink(); - - if (!path.endsWith(QLatin1Char('/'))) - path.append(QLatin1Char('/')); - path.append(QLatin1String("*.*")); - - QString fileName = QFSFileEnginePrivate::longFileName(path); - platform->findFileHandle = FindFirstFile((const wchar_t *)fileName.utf16(), &platform->findData); - - if (platform->findFileHandle == INVALID_HANDLE_VALUE) { - if (path.startsWith(QLatin1String("//"))) { - path = this->path(); - // UNC - QStringList parts = QDir::toNativeSeparators(path).split(QLatin1Char('\\'), QString::SkipEmptyParts); - - if (parts.count() == 1 && QFSFileEnginePrivate::uncListSharesOnServer(QLatin1String("\\\\") + parts.at(0), - &platform->uncShares)) { - if (platform->uncShares.isEmpty()) { - platform->done = true; - } else { - platform->uncShareIndex = 1; - } - platform->uncFallback = true; - } else { - platform->done = true; - } - } else { - platform->done = true; - } - } - - if (!platform->done && (!platform->uncFallback || !platform->uncShares.isEmpty())) - platform->saveCurrentFileName(); - } - - return !platform->done; -} - -QT_END_NAMESPACE diff --git a/src/corelib/io/qfsfileengine_p.h b/src/corelib/io/qfsfileengine_p.h index e9e55f3..7c088b8 100644 --- a/src/corelib/io/qfsfileengine_p.h +++ b/src/corelib/io/qfsfileengine_p.h @@ -56,8 +56,14 @@ #include "qplatformdefs.h" #include "QtCore/qfsfileengine.h" #include "private/qabstractfileengine_p.h" +#include <QtCore/private/qfilesystementry_p.h> +#include <QtCore/private/qfilesystemmetadata_p.h> #include <qhash.h> +#ifdef Q_OS_SYMBIAN +#include <f32file.h> +#endif + #ifndef QT_NO_FSFILEENGINE QT_BEGIN_NAMESPACE @@ -74,13 +80,10 @@ public: #ifdef Q_WS_WIN static QString longFileName(const QString &path); #endif - static QString canonicalized(const QString &path); - QString filePath; - QByteArray nativeFilePath; + QFileSystemEntry fileEntry; QIODevice::OpenMode openMode; - void nativeInitFileName(); bool nativeOpen(QIODevice::OpenMode openMode); bool openFh(QIODevice::OpenMode flags, FILE *fh); bool openFd(QIODevice::OpenMode flags, int fd); @@ -89,7 +92,9 @@ public: bool nativeFlush(); bool flushFh(); qint64 nativeSize() const; +#ifndef Q_OS_WIN qint64 sizeFdFh() const; +#endif qint64 nativePos() const; qint64 posFdFh() const; bool nativeSeek(qint64); @@ -102,12 +107,42 @@ public: qint64 writeFdFh(const char *data, qint64 len); int nativeHandle() const; bool nativeIsSequential() const; +#ifndef Q_OS_WIN bool isSequentialFdFh() const; +#endif uchar *map(qint64 offset, qint64 size, QFile::MemoryMapFlags flags); bool unmap(uchar *ptr); + mutable QFileSystemMetaData metaData; + FILE *fh; +#ifdef Q_OS_SYMBIAN +#ifdef SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API + RFile64 symbianFile; + TInt64 symbianFilePos; +#else + RFile symbianFile; + + /** + * The cursor position in the underlying file. This differs + * from devicePos because the latter is updated on calls to + * writeData, even if no data was physically transferred to + * the file, but instead stored in the write buffer. + * + * iFilePos is updated on calls to RFile::Read and + * RFile::Write. It is also updated on calls to seek() but + * RFile::Seek is not called when that happens because + * Symbian supports positioned reads and writes, saving a file + * server call, and because Symbian does not support seeking + * past the end of a file. + */ + TInt symbianFilePos; +#endif + mutable int fileHandleForMaps; + int getMapHandle(); +#endif + #ifdef Q_WS_WIN HANDLE fileHandle; HANDLE mapHandle; @@ -120,7 +155,6 @@ public: mutable DWORD fileAttrib; #else QHash<uchar *, QPair<int /*offset % PageSize*/, size_t /*length + offset % PageSize*/> > maps; - mutable QT_STATBUF st; #endif int fd; @@ -142,23 +176,17 @@ public: mutable uint is_link : 1; #endif - bool doStat() const; +#if defined(Q_OS_WIN) + bool doStat(QFileSystemMetaData::MetaDataFlags flags) const; +#else + bool doStat(QFileSystemMetaData::MetaDataFlags flags = QFileSystemMetaData::PosixStatFlags) const; +#endif bool isSymlink() const; #if defined(Q_OS_WIN32) int sysOpen(const QString &, int flags); #endif -#if defined(Q_OS_WIN32) || defined(Q_OS_WINCE) - static void resolveLibs(); - static bool resolveUNCLibs(); - static bool uncListSharesOnServer(const QString &server, QStringList *list); -#endif - -#ifdef Q_OS_SYMBIAN - void setSymbianError(int symbianError, QFile::FileError defaultError, QString defaultString); -#endif - protected: QFSFileEnginePrivate(); diff --git a/src/corelib/io/qfsfileengine_unix.cpp b/src/corelib/io/qfsfileengine_unix.cpp index 03e7283..1e1b35b 100644 --- a/src/corelib/io/qfsfileengine_unix.cpp +++ b/src/corelib/io/qfsfileengine_unix.cpp @@ -43,6 +43,8 @@ #include "qabstractfileengine.h" #include "private/qfsfileengine_p.h" #include "private/qcore_unix_p.h" +#include "qfilesystementry_p.h" +#include "qfilesystemengine_p.h" #ifndef QT_NO_FSFILEENGINE @@ -67,7 +69,6 @@ QT_BEGIN_NAMESPACE - #if defined(Q_OS_SYMBIAN) /*! \internal @@ -82,56 +83,25 @@ static bool isRelativePathSymbian(const QString& fileName) || (fileName.at(0) == QLatin1Char('/') && fileName.at(1) == QLatin1Char('/'))))); } -/*! - \internal - convert symbian error code to the one suitable for setError. - example usage: setSymbianError(err, QFile::CopyError, QLatin1String("copy error")) -*/ -void QFSFileEnginePrivate::setSymbianError(int symbianError, QFile::FileError defaultError, QString defaultString) -{ - Q_Q(QFSFileEngine); - switch (symbianError) { - case KErrNone: - q->setError(QFile::NoError, QLatin1String("")); - break; - case KErrAccessDenied: - q->setError(QFile::PermissionsError, QLatin1String("access denied")); - break; - case KErrPermissionDenied: - q->setError(QFile::PermissionsError, QLatin1String("permission denied")); - break; - case KErrAbort: - q->setError(QFile::AbortError, QLatin1String("aborted")); - break; - case KErrCancel: - q->setError(QFile::AbortError, QLatin1String("cancelled")); - break; - case KErrTimedOut: - q->setError(QFile::TimeOutError, QLatin1String("timed out")); - break; - default: - q->setError(defaultError, defaultString); - break; - } -} - #endif +#ifndef Q_OS_SYMBIAN /*! \internal Returns the stdlib open string corresponding to a QIODevice::OpenMode. */ -static inline QByteArray openModeToFopenMode(QIODevice::OpenMode flags, const QByteArray &fileName) +static inline QByteArray openModeToFopenMode(QIODevice::OpenMode flags, const QFileSystemEntry &fileEntry, + QFileSystemMetaData &metaData) { QByteArray mode; if ((flags & QIODevice::ReadOnly) && !(flags & QIODevice::Truncate)) { mode = "rb"; if (flags & QIODevice::WriteOnly) { - QT_STATBUF statBuf; - if (!fileName.isEmpty() - && QT_STAT(fileName, &statBuf) == 0 - && (statBuf.st_mode & S_IFMT) == S_IFREG) { + metaData.clearFlags(QFileSystemMetaData::FileType); + if (!fileEntry.isEmpty() + && QFileSystemEngine::fillMetaData(fileEntry, metaData, QFileSystemMetaData::FileType) + && metaData.isFile()) { mode += '+'; } else { mode = "wb+"; @@ -155,6 +125,7 @@ static inline QByteArray openModeToFopenMode(QIODevice::OpenMode flags, const QB return mode; } +#endif /*! \internal @@ -184,6 +155,7 @@ static inline int openModeToOpenFlags(QIODevice::OpenMode mode) return oflags; } +#ifndef Q_OS_SYMBIAN /*! \internal @@ -194,15 +166,92 @@ static inline bool setCloseOnExec(int fd) { return fd != -1 && fcntl(fd, F_SETFD, FD_CLOEXEC) != -1; } +#endif +#ifdef Q_OS_SYMBIAN /*! \internal */ -void QFSFileEnginePrivate::nativeInitFileName() +bool QFSFileEnginePrivate::nativeOpen(QIODevice::OpenMode openMode) { - nativeFilePath = QFile::encodeName(filePath); -} + Q_Q(QFSFileEngine); + + fh = 0; + fd = -1; + + QString fn(QFileSystemEngine::absoluteName(fileEntry).nativeFilePath()); + RFs& fs = qt_s60GetRFs(); + + TUint symbianMode = 0; + + if(openMode & QIODevice::ReadOnly) + symbianMode |= EFileRead; + if(openMode & QIODevice::WriteOnly) + symbianMode |= EFileWrite; + if(openMode & QIODevice::Text) + symbianMode |= EFileStreamText; + + // pre Symbian 9.4, file I/O is always unbuffered, and the enum values don't exist + if(QSysInfo::symbianVersion() >= QSysInfo::SV_9_4) { + if (openMode & QFile::Unbuffered) { + if (openMode & QIODevice::WriteOnly) + symbianMode |= 0x00001000; //EFileWriteDirectIO; + // ### Unbuffered read is not used, because it prevents file open in /resource + // ### and has no obvious benefits + } else { + if (openMode & QIODevice::WriteOnly) + symbianMode |= 0x00000800; //EFileWriteBuffered; + // use implementation defaults for read buffering + } + } + + // Until Qt supports file sharing, we can't support EFileShareReadersOrWriters safely, + // but Qt does this on other platforms and autotests rely on it. + // The reason is that Unix locks are only advisory - the application needs to test the + // lock after opening the file. Symbian and Windows locks are mandatory - opening a + // locked file will fail. + symbianMode |= EFileShareReadersOrWriters; + + TInt r; + //note QIODevice::Truncate only has meaning for read/write access + //write-only files are always truncated unless append is specified + //reference openModeToOpenFlags in qfsfileengine_unix.cpp + if ((openMode & QIODevice::Truncate) || (!(openMode & QIODevice::ReadOnly) && !(openMode & QIODevice::Append))) { + r = symbianFile.Replace(fs, qt_QString2TPtrC(fn), symbianMode); + } else { + r = symbianFile.Open(fs, qt_QString2TPtrC(fn), symbianMode); + if (r == KErrNotFound && (openMode & QIODevice::WriteOnly)) { + r = symbianFile.Create(fs, qt_QString2TPtrC(fn), symbianMode); + } + } + + if (r == KErrNone) { +#ifdef SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API + TInt64 size; +#else + TInt size; +#endif + r = symbianFile.Size(size); + if (r==KErrNone) { + if (openMode & QIODevice::Append) + symbianFilePos = size; + else + symbianFilePos = 0; + //TODO: port this (QFileSystemMetaData in open?) + //cachedSize = size; + } + } + if (r != KErrNone) { + q->setError(QFile::OpenError, QSystemError(r, QSystemError::NativeError).toString()); + symbianFile.Close(); + return false; + } + + closeFileHandle = true; + return true; +} +#else /*! \internal */ @@ -215,7 +264,7 @@ bool QFSFileEnginePrivate::nativeOpen(QIODevice::OpenMode openMode) // Try to open the file in unbuffered mode. do { - fd = QT_OPEN(nativeFilePath.constData(), flags, 0666); + fd = QT_OPEN(fileEntry.nativeFilePath().constData(), flags, 0666); } while (fd == -1 && errno == EINTR); // On failure, return and report the error. @@ -228,13 +277,11 @@ bool QFSFileEnginePrivate::nativeOpen(QIODevice::OpenMode openMode) if (!(openMode & QIODevice::WriteOnly)) { // we don't need this check if we tried to open for writing because then // we had received EISDIR anyway. - QT_STATBUF statBuf; - if (QT_FSTAT(fd, &statBuf) != -1) { - if ((statBuf.st_mode & S_IFMT) == S_IFDIR) { - q->setError(QFile::OpenError, QLatin1String("file to open is a directory")); - QT_CLOSE(fd); - return false; - } + if (QFileSystemEngine::fillMetaData(fd, metaData) + && metaData.isDirectory()) { + q->setError(QFile::OpenError, QLatin1String("file to open is a directory")); + QT_CLOSE(fd); + return false; } } @@ -254,11 +301,11 @@ bool QFSFileEnginePrivate::nativeOpen(QIODevice::OpenMode openMode) fh = 0; } else { - QByteArray fopenMode = openModeToFopenMode(openMode, nativeFilePath.constData()); + QByteArray fopenMode = openModeToFopenMode(openMode, fileEntry, metaData); // Try to open the file in buffered mode. do { - fh = QT_FOPEN(nativeFilePath.constData(), fopenMode.constData()); + fh = QT_FOPEN(fileEntry.nativeFilePath().constData(), fopenMode.constData()); } while (!fh && errno == EINTR); // On failure, return and report the error. @@ -271,13 +318,11 @@ bool QFSFileEnginePrivate::nativeOpen(QIODevice::OpenMode openMode) if (!(openMode & QIODevice::WriteOnly)) { // we don't need this check if we tried to open for writing because then // we had received EISDIR anyway. - QT_STATBUF statBuf; - if (QT_FSTAT(fileno(fh), &statBuf) != -1) { - if ((statBuf.st_mode & S_IFMT) == S_IFDIR) { - q->setError(QFile::OpenError, QLatin1String("file to open is a directory")); - fclose(fh); - return false; - } + if (QFileSystemEngine::fillMetaData(QT_FILENO(fh), metaData) + && metaData.isDirectory()) { + q->setError(QFile::OpenError, QLatin1String("file to open is a directory")); + fclose(fh); + return false; } } @@ -303,6 +348,7 @@ bool QFSFileEnginePrivate::nativeOpen(QIODevice::OpenMode openMode) closeFileHandle = true; return true; } +#endif /*! \internal @@ -318,6 +364,10 @@ bool QFSFileEnginePrivate::nativeClose() */ bool QFSFileEnginePrivate::nativeFlush() { +#ifdef Q_OS_SYMBIAN + if (symbianFile.SubSessionHandle()) + return (KErrNone == symbianFile.Flush()); +#endif return fh ? flushFh() : fd != -1; } @@ -328,6 +378,24 @@ qint64 QFSFileEnginePrivate::nativeRead(char *data, qint64 len) { Q_Q(QFSFileEngine); +#ifdef Q_OS_SYMBIAN + if (symbianFile.SubSessionHandle()) { + if(len > KMaxTInt) { + //this check is more likely to catch a corrupt length, since it isn't possible to allocate 2GB buffers (yet..) + q->setError(QFile::ReadError, QLatin1String("Maximum 2GB in single read on this platform")); + return -1; + } + TPtr8 ptr(reinterpret_cast<TUint8*>(data), static_cast<TInt>(len)); + 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 if (fh && nativeIsSequential()) { size_t readBytes = 0; int oldFlags = fcntl(QT_FILENO(fh), F_GETFL); @@ -395,6 +463,40 @@ qint64 QFSFileEnginePrivate::nativeReadLine(char *data, qint64 maxlen) */ qint64 QFSFileEnginePrivate::nativeWrite(const char *data, qint64 len) { +#ifdef Q_OS_SYMBIAN + Q_Q(QFSFileEngine); + if (symbianFile.SubSessionHandle()) { + if(len > KMaxTInt) { + //this check is more likely to catch a corrupt length, since it isn't possible to allocate 2GB buffers (yet..) + q->setError(QFile::WriteError, QLatin1String("Maximum 2GB in single write on this platform")); + return -1; + } + const TPtrC8 ptr(reinterpret_cast<const TUint8*>(data), static_cast<TInt>(len)); +#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 return writeFdFh(data, len); } @@ -403,6 +505,12 @@ qint64 QFSFileEnginePrivate::nativeWrite(const char *data, qint64 len) */ qint64 QFSFileEnginePrivate::nativePos() const { +#ifdef Q_OS_SYMBIAN + const Q_Q(QFSFileEngine); + if (symbianFile.SubSessionHandle()) { + return symbianFilePos; + } +#endif return posFdFh(); } @@ -411,6 +519,19 @@ qint64 QFSFileEnginePrivate::nativePos() const */ bool QFSFileEnginePrivate::nativeSeek(qint64 pos) { +#ifdef Q_OS_SYMBIAN + Q_Q(QFSFileEngine); + if (symbianFile.SubSessionHandle()) { +#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; + } +#endif + symbianFilePos = pos; + return true; + } +#endif return seekFdFh(pos); } @@ -422,139 +543,110 @@ 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 */ bool QFSFileEnginePrivate::nativeIsSequential() const { +#ifdef Q_OS_SYMBIAN + if (symbianFile.SubSessionHandle()) + return false; +#endif return isSequentialFdFh(); } bool QFSFileEngine::remove() { Q_D(QFSFileEngine); - bool ret = unlink(d->nativeFilePath.constData()) == 0; - if (!ret) - setError(QFile::RemoveError, qt_error_string(errno)); + QSystemError error; + bool ret = QFileSystemEngine::removeFile(d->fileEntry, error); + d->metaData.clear(); + if (!ret) { + setError(QFile::RemoveError, error.toString()); + } return ret; } bool QFSFileEngine::copy(const QString &newName) { -#if defined(Q_OS_SYMBIAN) Q_D(QFSFileEngine); - RFs rfs = qt_s60GetRFs(); - CFileMan* fm = NULL; - QString oldNative(QDir::toNativeSeparators(d->filePath)); - TPtrC oldPtr(qt_QString2TPtrC(oldNative)); - QFileInfo fi(newName); - QString absoluteNewName = fi.absoluteFilePath(); - QString newNative(QDir::toNativeSeparators(absoluteNewName)); - TPtrC newPtr(qt_QString2TPtrC(newNative)); - TRAPD (err, - fm = CFileMan::NewL(rfs); - RFile rfile; - err = rfile.Open(rfs, oldPtr, EFileShareReadersOrWriters); - if (err == KErrNone) { - err = fm->Copy(rfile, newPtr); - rfile.Close(); - } - ) // End TRAP - delete fm; - if (err == KErrNone) - return true; - d->setSymbianError(err, QFile::CopyError, QLatin1String("copy error")); - return false; -#else - Q_UNUSED(newName); - // ### Add copy code for Unix here - setError(QFile::UnspecifiedError, QLatin1String("Not implemented!")); - return false; -#endif + QSystemError error; + bool ret = QFileSystemEngine::copyFile(d->fileEntry, QFileSystemEntry(newName), error); + if (!ret) { + setError(QFile::CopyError, error.toString()); + } + return ret; } bool QFSFileEngine::rename(const QString &newName) { Q_D(QFSFileEngine); - bool ret = ::rename(d->nativeFilePath.constData(), QFile::encodeName(newName).constData()) == 0; - if (!ret) - setError(QFile::RenameError, qt_error_string(errno)); + QSystemError error; + bool ret = QFileSystemEngine::renameFile(d->fileEntry, QFileSystemEntry(newName), error); + + if (!ret) { + setError(QFile::RenameError, error.toString()); + } + return ret; } bool QFSFileEngine::link(const QString &newName) { Q_D(QFSFileEngine); - bool ret = ::symlink(d->nativeFilePath.constData(), QFile::encodeName(newName).constData()) == 0; - if (!ret) - setError(QFile::RenameError, qt_error_string(errno)); + QSystemError error; + bool ret = QFileSystemEngine::createLink(d->fileEntry, QFileSystemEntry(newName), error); + if (!ret) { + setError(QFile::RenameError, error.toString()); + } return ret; } qint64 QFSFileEnginePrivate::nativeSize() const { +#ifdef Q_OS_SYMBIAN + const Q_Q(QFSFileEngine); + if (symbianFile.SubSessionHandle()) { +#ifdef SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API + qint64 size; +#else + TInt size; +#endif + TInt err = symbianFile.Size(size); + if(err != KErrNone) { + const_cast<QFSFileEngine*>(q)->setError(QFile::PositionError, QSystemError(err, QSystemError::NativeError).toString()); + return 0; + } + return size; + } +#endif return sizeFdFh(); } bool QFSFileEngine::mkdir(const QString &name, bool createParentDirectories) const { - QString dirName = name; - if (createParentDirectories) { - dirName = QDir::cleanPath(dirName); -#if defined(Q_OS_SYMBIAN) - dirName = QDir::toNativeSeparators(dirName); -#endif - for(int oldslash = -1, slash=0; slash != -1; oldslash = slash) { - slash = dirName.indexOf(QDir::separator(), oldslash+1); - if (slash == -1) { - if (oldslash == dirName.length()) - break; - slash = dirName.length(); - } - if (slash) { - QByteArray chunk = QFile::encodeName(dirName.left(slash)); - QT_STATBUF st; - if (QT_STAT(chunk, &st) != -1) { - if ((st.st_mode & S_IFMT) != S_IFDIR) - return false; - } else if (QT_MKDIR(chunk, 0777) != 0) { - return false; - } - } - } - return true; - } -#if defined(Q_OS_DARWIN) // Mac X doesn't support trailing /'s - if (dirName.endsWith(QLatin1Char('/'))) - dirName.chop(1); -#endif - return (QT_MKDIR(QFile::encodeName(dirName), 0777) == 0); + return QFileSystemEngine::createDirectory(QFileSystemEntry(name), createParentDirectories); } bool QFSFileEngine::rmdir(const QString &name, bool recurseParentDirectories) const { - QString dirName = name; - if (recurseParentDirectories) { - dirName = QDir::cleanPath(dirName); -#if defined(Q_OS_SYMBIAN) - dirName = QDir::toNativeSeparators(dirName); -#endif - for(int oldslash = 0, slash=dirName.length(); slash > 0; oldslash = slash) { - QByteArray chunk = QFile::encodeName(dirName.left(slash)); - QT_STATBUF st; - if (QT_STAT(chunk, &st) != -1) { - if ((st.st_mode & S_IFMT) != S_IFDIR) - return false; - if (::rmdir(chunk) != 0) - return oldslash != 0; - } else { - return false; - } - slash = dirName.lastIndexOf(QDir::separator(), oldslash-1); - } - return true; - } - return ::rmdir(QFile::encodeName(dirName)) == 0; + return QFileSystemEngine::removeDirectory(QFileSystemEntry(name), recurseParentDirectories); } bool QFSFileEngine::caseSensitive() const @@ -568,94 +660,27 @@ bool QFSFileEngine::caseSensitive() const bool QFSFileEngine::setCurrentPath(const QString &path) { - int r; - r = QT_CHDIR(QFile::encodeName(path)); - return r >= 0; + return QFileSystemEngine::setCurrentPath(QFileSystemEntry(path)); } QString QFSFileEngine::currentPath(const QString &) { - QString result; - QT_STATBUF st; -#if defined(Q_OS_SYMBIAN) - char nativeCurrentName[PATH_MAX+1]; - if (::getcwd(nativeCurrentName, PATH_MAX)) - result = QDir::fromNativeSeparators(QFile::decodeName(QByteArray(nativeCurrentName))); - if (result.isEmpty()) { -# if defined(QT_DEBUG) - qWarning("QFSFileEngine::currentPath: getcwd() failed"); -# endif - } else -#endif - if (QT_STAT(".", &st) == 0) { -#if defined(__GLIBC__) && !defined(PATH_MAX) - char *currentName = ::get_current_dir_name(); - if (currentName) { - result = QFile::decodeName(QByteArray(currentName)); - ::free(currentName); - } -#elif !defined(Q_OS_SYMBIAN) - char currentName[PATH_MAX+1]; - if (::getcwd(currentName, PATH_MAX)) - result = QFile::decodeName(QByteArray(currentName)); -# if defined(QT_DEBUG) - if (result.isNull()) - qWarning("QFSFileEngine::currentPath: getcwd() failed"); -# endif -#endif - } else { -#if defined(Q_OS_SYMBIAN) - // If current dir returned by Open C doesn't exist, - // try to create it (can happen with application private dirs) - // Ignore mkdir failures; we want to be consistent with Open C - // current path regardless. - QT_MKDIR(QFile::encodeName(QLatin1String(nativeCurrentName)), 0777); -#else -# if defined(QT_DEBUG) - qWarning("QFSFileEngine::currentPath: stat(\".\") failed"); -# endif -#endif - } - return result; + return QFileSystemEngine::currentPath().filePath(); } QString QFSFileEngine::homePath() { -#if defined(Q_OS_SYMBIAN) - QString home = rootPath(); -#else - QString home = QFile::decodeName(qgetenv("HOME")); - if (home.isNull()) - home = rootPath(); -#endif - return home; + return QFileSystemEngine::homePath(); } QString QFSFileEngine::rootPath() { -#if defined(Q_OS_SYMBIAN) - TFileName symbianPath = PathInfo::PhoneMemoryRootPath(); - return QDir::cleanPath(QDir::fromNativeSeparators(qt_TDesC2QString(symbianPath))); -#else - return QLatin1String("/"); -#endif + return QFileSystemEngine::rootPath(); } QString QFSFileEngine::tempPath() { -#if defined(Q_OS_SYMBIAN) - TFileName symbianPath = PathInfo::PhoneMemoryRootPath(); - QString temp = QDir::fromNativeSeparators(qt_TDesC2QString(symbianPath)); - temp += QLatin1String( "temp/"); - - // Just to verify that folder really exist on hardware - QT_MKDIR(QFile::encodeName(temp), 0777); -#else - QString temp = QFile::decodeName(qgetenv("TMPDIR")); - if (temp.isEmpty()) - temp = QLatin1String("/tmp/"); -#endif - return temp; + return QFileSystemEngine::tempPath(); } QFileInfoList QFSFileEngine::drives() @@ -683,123 +708,30 @@ QFileInfoList QFSFileEngine::drives() return ret; } -bool QFSFileEnginePrivate::doStat() const +bool QFSFileEnginePrivate::doStat(QFileSystemMetaData::MetaDataFlags flags) const { - if (!tried_stat) { - tried_stat = true; - could_stat = false; - - if (fh && nativeFilePath.isEmpty()) { - // ### actually covers two cases: d->fh and when the file is not open - could_stat = (QT_FSTAT(QT_FILENO(fh), &st) == 0); - } else if (fd == -1) { - // ### actually covers two cases: d->fh and when the file is not open -#if defined(Q_OS_SYMBIAN) - // Optimization for Symbian where fileFlags() calls both doStat() and isSymlink(), but rarely on real links. - // When the filename is not a link, lstat will return the same info as stat, but this also removes - // any need for a further call to lstat to check if the file is a link. - need_lstat = false; - could_stat = (QT_LSTAT(nativeFilePath.constData(), &st) == 0); - is_link = could_stat ? S_ISLNK(st.st_mode) : false; - // if it turns out this was a link, we can call stat too. - if (is_link) -#endif - could_stat = (QT_STAT(nativeFilePath.constData(), &st) == 0); - } else { - could_stat = (QT_FSTAT(fd, &st) == 0); - } - } - return could_stat; -} + if (!tried_stat || !metaData.hasFlags(flags)) { + tried_stat = 1; -bool QFSFileEnginePrivate::isSymlink() const -{ - if (need_lstat) { - need_lstat = false; + int localFd = fd; + if (fh && fileEntry.isEmpty()) + localFd = QT_FILENO(fh); + if (localFd != -1) + QFileSystemEngine::fillMetaData(localFd, metaData); - QT_STATBUF st; // don't clobber our main one - is_link = (QT_LSTAT(nativeFilePath.constData(), &st) == 0) ? S_ISLNK(st.st_mode) : false; + if (metaData.missingFlags(flags) && !fileEntry.isEmpty()) + QFileSystemEngine::fillMetaData(fileEntry, metaData, metaData.missingFlags(flags)); } - return is_link; -} -#if defined(Q_OS_SYMBIAN) -static bool _q_isSymbianHidden(const QString &path, bool isDir) -{ - RFs rfs = qt_s60GetRFs(); - QFileInfo fi(path); - QString absPath = fi.absoluteFilePath(); - if (isDir && !absPath.endsWith(QLatin1Char('/'))) - absPath.append(QLatin1Char('/')); - QString native(QDir::toNativeSeparators(absPath)); - TPtrC ptr(qt_QString2TPtrC(native)); - TUint attributes; - TInt err = rfs.Att(ptr, attributes); - return (err == KErrNone && (attributes & KEntryAttHidden)); -} -#endif - -#if !defined(QWS) && !defined(Q_WS_QPA) && defined(Q_OS_MAC) -static bool _q_isMacHidden(const QString &path) -{ - OSErr err = noErr; - - FSRef fsRef; - - err = FSPathMakeRefWithOptions(reinterpret_cast<const UInt8 *>(QFile::encodeName(QDir::cleanPath(path)).constData()), - kFSPathMakeRefDoNotFollowLeafSymlink, &fsRef, 0); - if (err != noErr) - return false; - - FSCatalogInfo catInfo; - err = FSGetCatalogInfo(&fsRef, kFSCatInfoFinderInfo, &catInfo, NULL, NULL, NULL); - if (err != noErr) - return false; - - FileInfo * const fileInfo = reinterpret_cast<FileInfo*>(&catInfo.finderInfo); - bool result = (fileInfo->finderFlags & kIsInvisible); - return result; + return metaData.exists(); } -#endif -QAbstractFileEngine::FileFlags QFSFileEnginePrivate::getPermissions(QAbstractFileEngine::FileFlags type) const +bool QFSFileEnginePrivate::isSymlink() const { - QAbstractFileEngine::FileFlags ret = 0; - - if (st.st_mode & S_IRUSR) - ret |= QAbstractFileEngine::ReadOwnerPerm; - if (st.st_mode & S_IWUSR) - ret |= QAbstractFileEngine::WriteOwnerPerm; - if (st.st_mode & S_IXUSR) - ret |= QAbstractFileEngine::ExeOwnerPerm; - if (st.st_mode & S_IRGRP) - ret |= QAbstractFileEngine::ReadGroupPerm; - if (st.st_mode & S_IWGRP) - ret |= QAbstractFileEngine::WriteGroupPerm; - if (st.st_mode & S_IXGRP) - ret |= QAbstractFileEngine::ExeGroupPerm; - if (st.st_mode & S_IROTH) - ret |= QAbstractFileEngine::ReadOtherPerm; - if (st.st_mode & S_IWOTH) - ret |= QAbstractFileEngine::WriteOtherPerm; - if (st.st_mode & S_IXOTH) - ret |= QAbstractFileEngine::ExeOtherPerm; - - // calculate user permissions - if (type & QAbstractFileEngine::ReadUserPerm) { - if (QT_ACCESS(nativeFilePath.constData(), R_OK) == 0) - ret |= QAbstractFileEngine::ReadUserPerm; - } - if (type & QAbstractFileEngine::WriteUserPerm) { - if (QT_ACCESS(nativeFilePath.constData(), W_OK) == 0) - ret |= QAbstractFileEngine::WriteUserPerm; - } - if (type & QAbstractFileEngine::ExeUserPerm) { - if (QT_ACCESS(nativeFilePath.constData(), X_OK) == 0) - ret |= QAbstractFileEngine::ExeUserPerm; - } + if (!metaData.hasFlags(QFileSystemMetaData::LinkType)) + QFileSystemEngine::fillMetaData(fileEntry, metaData, QFileSystemMetaData::LinkType); - return ret; + return metaData.isLink(); } /*! @@ -808,364 +740,111 @@ QAbstractFileEngine::FileFlags QFSFileEnginePrivate::getPermissions(QAbstractFil QAbstractFileEngine::FileFlags QFSFileEngine::fileFlags(FileFlags type) const { Q_D(const QFSFileEngine); - // Force a stat, so that we're guaranteed to get up-to-date results - if (type & Refresh) { - d->tried_stat = 0; - d->need_lstat = 1; - } + + if (type & Refresh) + d->metaData.clear(); QAbstractFileEngine::FileFlags ret = 0; + if (type & FlagsMask) ret |= LocalDiskFlag; - bool exists = d->doStat(); - if (!exists && !d->isSymlink()) + + bool exists; + { + QFileSystemMetaData::MetaDataFlags queryFlags = 0; + + queryFlags |= QFileSystemMetaData::MetaDataFlags(uint(type)) + & QFileSystemMetaData::Permissions; + + if (type & TypesMask) + queryFlags |= QFileSystemMetaData::AliasType + | QFileSystemMetaData::LinkType + | QFileSystemMetaData::FileType + | QFileSystemMetaData::DirectoryType + | QFileSystemMetaData::BundleType; + + if (type & FlagsMask) + queryFlags |= QFileSystemMetaData::HiddenAttribute + | QFileSystemMetaData::ExistsAttribute; + + queryFlags |= QFileSystemMetaData::LinkType; + + exists = d->doStat(queryFlags); + } + + if (!exists && !d->metaData.isLink()) return ret; if (exists && (type & PermsMask)) - ret |= d->getPermissions(type); + ret |= FileFlags(uint(d->metaData.permissions())); + if (type & TypesMask) { -#if !defined(QWS) && !defined(Q_WS_QPA) && defined(Q_OS_MAC) - bool foundAlias = false; - { - FSRef fref; - if (FSPathMakeRef((const UInt8 *)QFile::encodeName(QDir::cleanPath(d->filePath)).data(), - &fref, NULL) == noErr) { - Boolean isAlias, isFolder; - if (FSIsAliasFile(&fref, &isAlias, &isFolder) == noErr && isAlias) { - foundAlias = true; - ret |= LinkType; - } - } - } - if (!foundAlias) -#endif - { - if ((type & LinkType) && d->isSymlink()) + if (d->metaData.isAlias()) { + ret |= LinkType; + } else { + if ((type & LinkType) && d->metaData.isLink()) ret |= LinkType; - if (exists && (d->st.st_mode & S_IFMT) == S_IFREG) - ret |= FileType; - else if (exists && (d->st.st_mode & S_IFMT) == S_IFDIR) - ret |= DirectoryType; -#if !defined(QWS) && defined(Q_OS_MAC) - if ((ret & DirectoryType) && (type & BundleType)) { - QCFType<CFURLRef> url = CFURLCreateWithFileSystemPath(0, QCFString(d->filePath), - kCFURLPOSIXPathStyle, true); - UInt32 type, creator; - if (CFBundleGetPackageInfoInDirectory(url, &type, &creator)) - ret |= BundleType; + if (exists) { + if (d->metaData.isFile()) { + ret |= FileType; + } else if (d->metaData.isDirectory()) { + ret |= DirectoryType; + if ((type & BundleType) && d->metaData.isBundle()) + ret |= BundleType; + } } -#endif } } + if (type & FlagsMask) { if (exists) ret |= ExistsFlag; -#if defined(Q_OS_SYMBIAN) - if (d->filePath == QLatin1String("/") - || (d->filePath.length() == 3 && d->filePath.at(0).isLetter() - && d->filePath.at(1) == QLatin1Char(':') && d->filePath.at(2) == QLatin1Char('/'))) { + if (d->fileEntry.isRoot()) ret |= RootFlag; - } else { - // In Symbian, all symlinks have hidden attribute for some reason; - // lets make them visible for better compatibility with other platforms. - // If somebody actually wants a hidden link, then they are out of luck. - if (!d->isSymlink() && _q_isSymbianHidden(d->filePath, ret & DirectoryType)) - ret |= HiddenFlag; - } -#else - if (d->filePath == QLatin1String("/")) { - ret |= RootFlag; - } else { - QString baseName = fileName(BaseName); - if ((baseName.size() > 0 && baseName.at(0) == QLatin1Char('.')) -# if !defined(QWS) && !defined(Q_WS_QPA) && defined(Q_OS_MAC) - || _q_isMacHidden(d->filePath) -# if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 - || d->st.st_flags & UF_HIDDEN -# endif // MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 -# endif - ) { - ret |= HiddenFlag; - } - } -#endif + else if (d->metaData.isHidden()) + ret |= HiddenFlag; } - return ret; -} - -#if defined(Q_OS_SYMBIAN) -QString QFSFileEngine::fileName(FileName file) const -{ - Q_D(const QFSFileEngine); - const QLatin1Char slashChar('/'); - if(file == BaseName) { - int slash = d->filePath.lastIndexOf(slashChar); - if(slash == -1) { - int colon = d->filePath.lastIndexOf(QLatin1Char(':')); - if(colon != -1) - return d->filePath.mid(colon + 1); - return d->filePath; - } - return d->filePath.mid(slash + 1); - } else if(file == PathName) { - if(!d->filePath.size()) - return d->filePath; - - int slash = d->filePath.lastIndexOf(slashChar); - if(slash == -1) { - if(d->filePath.length() >= 2 && d->filePath.at(1) == QLatin1Char(':')) - return d->filePath.left(2); - return QLatin1String("."); - } else { - if(!slash) - return QLatin1String("/"); - if(slash == 2 && d->filePath.length() >= 2 && d->filePath.at(1) == QLatin1Char(':')) - slash++; - return d->filePath.left(slash); - } - } else if(file == AbsoluteName || file == AbsolutePathName) { - QString ret; - if (!isRelativePathSymbian(d->filePath)) { - if (d->filePath.size() > 2 && d->filePath.at(1) == QLatin1Char(':') - && d->filePath.at(2) != slashChar){ - // It's a drive-relative path, so C:a.txt -> C:/currentpath/a.txt, - // or if it's different drive than current, Z:a.txt -> Z:/a.txt - QString currentPath = QDir::currentPath(); - if (0 == currentPath.left(1).compare(d->filePath.left(1), Qt::CaseInsensitive)) - ret = currentPath + slashChar + d->filePath.mid(2); - else - ret = d->filePath.left(2) + slashChar + d->filePath.mid(2); - } else if (d->filePath.startsWith(slashChar)) { - // It's a absolute path to the current drive, so /a.txt -> C:/a.txt - ret = QDir::currentPath().left(2) + d->filePath; - } else { - ret = d->filePath; - } - } else { - ret = QDir::currentPath() + slashChar + d->filePath; - } - - // The path should be absolute at this point. - // From the docs : - // Absolute paths begin with the directory separator "/" - // (optionally preceded by a drive specification under Windows). - if (ret.at(0) != slashChar) { - Q_ASSERT(ret.length() >= 2); - Q_ASSERT(ret.at(0).isLetter()); - Q_ASSERT(ret.at(1) == QLatin1Char(':')); - - // Force uppercase drive letters. - ret[0] = ret.at(0).toUpper(); - } - - // Clean up the path - bool isDir = ret.endsWith(slashChar); - ret = QDir::cleanPath(ret); - if (isDir && !ret.endsWith(slashChar)) - ret += slashChar; - if (file == AbsolutePathName) { - int slash = ret.lastIndexOf(slashChar); - if (slash < 0) - return ret; - else if (ret.at(0) != slashChar && slash == 2) - return ret.left(3); // include the slash - else - return ret.left(slash > 0 ? slash : 1); - } - return ret; - } else if(file == CanonicalName || file == CanonicalPathName) { - if (!(fileFlags(ExistsFlag) & ExistsFlag)) - return QString(); - - QString ret = QFSFileEnginePrivate::canonicalized(fileName(AbsoluteName)); - if (file == CanonicalPathName && !ret.isEmpty()) { - int slash = ret.lastIndexOf(slashChar); - if (slash == -1) - ret = QDir::fromNativeSeparators(QDir::currentPath()); - else if (slash == 0) - ret = QLatin1String("/"); - ret = ret.left(slash); - } - return ret; - } else if(file == LinkName) { - if (d->isSymlink()) { - char s[PATH_MAX+1]; - int len = readlink(d->nativeFilePath.constData(), s, PATH_MAX); - if (len > 0) { - s[len] = '\0'; - QString ret = QFile::decodeName(QByteArray(s)); - - if (isRelativePathSymbian(ret)) { - if (!isRelativePathSymbian(d->filePath)) { - ret.prepend(d->filePath.left(d->filePath.lastIndexOf(slashChar)) - + slashChar); - } else { - ret.prepend(QDir::currentPath() + slashChar); - } - } - ret = QDir::cleanPath(ret); - if (ret.size() > 1 && ret.endsWith(slashChar)) - ret.chop(1); - return ret; - } - } - return QString(); - } else if(file == BundleName) { - return QString(); - } - return d->filePath; + return ret; } -#else - QString QFSFileEngine::fileName(FileName file) const { Q_D(const QFSFileEngine); if (file == BundleName) { -#if !defined(QWS) && defined(Q_OS_MAC) - QCFType<CFURLRef> url = CFURLCreateWithFileSystemPath(0, QCFString(d->filePath), - kCFURLPOSIXPathStyle, true); - if (QCFType<CFDictionaryRef> dict = CFBundleCopyInfoDictionaryForURL(url)) { - if (CFTypeRef name = (CFTypeRef)CFDictionaryGetValue(dict, kCFBundleNameKey)) { - if (CFGetTypeID(name) == CFStringGetTypeID()) - return QCFString::toQString((CFStringRef)name); - } - } -#endif - return QString(); + return QFileSystemEngine::bundleName(d->fileEntry); } else if (file == BaseName) { - int slash = d->filePath.lastIndexOf(QLatin1Char('/')); - if (slash != -1) - return d->filePath.mid(slash + 1); + return d->fileEntry.fileName(); } else if (file == PathName) { - int slash = d->filePath.lastIndexOf(QLatin1Char('/')); - if (slash == -1) - return QLatin1String("."); - else if (!slash) - return QLatin1String("/"); - return d->filePath.left(slash); + return d->fileEntry.path(); } else if (file == AbsoluteName || file == AbsolutePathName) { - QString ret; - if (d->filePath.isEmpty() || !d->filePath.startsWith(QLatin1Char('/'))) - ret = QDir::currentPath(); - if (!d->filePath.isEmpty() && d->filePath != QLatin1String(".")) { - if (!ret.isEmpty() && !ret.endsWith(QLatin1Char('/'))) - ret += QLatin1Char('/'); - ret += d->filePath; - } - if (ret == QLatin1String("/")) - return ret; - bool isDir = ret.endsWith(QLatin1Char('/')); - ret = QDir::cleanPath(ret); - if (isDir) - ret += QLatin1Char('/'); + QFileSystemEntry entry(QFileSystemEngine::absoluteName(d->fileEntry)); if (file == AbsolutePathName) { - int slash = ret.lastIndexOf(QLatin1Char('/')); - if (slash == -1) - return QDir::currentPath(); - else if (!slash) - return QLatin1String("/"); - return ret.left(slash); + return entry.path(); } - return ret; + return entry.filePath(); } else if (file == CanonicalName || file == CanonicalPathName) { - if (!(fileFlags(ExistsFlag) & ExistsFlag)) - return QString(); - - QString ret = QFSFileEnginePrivate::canonicalized(fileName(AbsoluteName)); - if (file == CanonicalPathName && !ret.isEmpty()) { - int slash = ret.lastIndexOf(QLatin1Char('/')); - if (slash == -1) - ret = QDir::currentPath(); - else if (slash == 0) - ret = QLatin1String("/"); - ret = ret.left(slash); - } - return ret; + QFileSystemEntry entry(QFileSystemEngine::canonicalName(d->fileEntry, d->metaData)); + if (file == CanonicalPathName) + return entry.path(); + return entry.filePath(); } else if (file == LinkName) { if (d->isSymlink()) { -#if defined(__GLIBC__) && !defined(PATH_MAX) -#define PATH_CHUNK_SIZE 256 - char *s = 0; - int len = -1; - int size = PATH_CHUNK_SIZE; - - while (1) { - s = (char *) ::realloc(s, size); - Q_CHECK_PTR(s); - len = ::readlink(d->nativeFilePath.constData(), s, size); - if (len < 0) { - ::free(s); - break; - } - if (len < size) { - break; - } - size *= 2; - } -#else - char s[PATH_MAX+1]; - int len = readlink(d->nativeFilePath.constData(), s, PATH_MAX); -#endif - if (len > 0) { - QString ret; - if (d->doStat() && S_ISDIR(d->st.st_mode) && s[0] != '/') { - QDir parent(d->filePath); - parent.cdUp(); - ret = parent.path(); - if (!ret.isEmpty() && !ret.endsWith(QLatin1Char('/'))) - ret += QLatin1Char('/'); - } - s[len] = '\0'; - ret += QFile::decodeName(QByteArray(s)); -#if defined(__GLIBC__) && !defined(PATH_MAX) - ::free(s); -#endif - - if (!ret.startsWith(QLatin1Char('/'))) { - if (d->filePath.startsWith(QLatin1Char('/'))) { - ret.prepend(d->filePath.left(d->filePath.lastIndexOf(QLatin1Char('/'))) - + QLatin1Char('/')); - } else { - ret.prepend(QDir::currentPath() + QLatin1Char('/')); - } - } - ret = QDir::cleanPath(ret); - if (ret.size() > 1 && ret.endsWith(QLatin1Char('/'))) - ret.chop(1); - return ret; - } - } -#if !defined(QWS) && !defined(Q_WS_QPA) && defined(Q_OS_MAC) - { - FSRef fref; - if (FSPathMakeRef((const UInt8 *)QFile::encodeName(QDir::cleanPath(d->filePath)).data(), &fref, 0) == noErr) { - Boolean isAlias, isFolder; - if (FSResolveAliasFile(&fref, true, &isFolder, &isAlias) == noErr && isAlias) { - AliasHandle alias; - if (FSNewAlias(0, &fref, &alias) == noErr && alias) { - QCFString cfstr; - if (FSCopyAliasInfo(alias, 0, 0, &cfstr, 0, 0) == noErr) - return QCFString::toQString(cfstr); - } - } - } + QFileSystemEntry entry = QFileSystemEngine::getLinkTarget(d->fileEntry, d->metaData); + return entry.filePath(); } -#endif return QString(); } - return d->filePath; + return d->fileEntry.filePath(); } -#endif // Q_OS_SYMBIAN bool QFSFileEngine::isRelativePath() const { Q_D(const QFSFileEngine); #if defined(Q_OS_SYMBIAN) - return isRelativePathSymbian(d->filePath); + return isRelativePathSymbian(d->fileEntry.filePath()); #else - return d->filePath.length() ? d->filePath[0] != QLatin1Char('/') : true; + return d->fileEntry.filePath().length() ? d->fileEntry.filePath()[0] != QLatin1Char('/') : true; #endif } @@ -1173,101 +852,73 @@ uint QFSFileEngine::ownerId(FileOwner own) const { Q_D(const QFSFileEngine); static const uint nobodyID = (uint) -2; - if (d->doStat()) { - if (own == OwnerUser) - return d->st.st_uid; - else - return d->st.st_gid; - } + + if (d->doStat(QFileSystemMetaData::OwnerIds)) + return d->metaData.ownerId(own); + return nobodyID; } QString QFSFileEngine::owner(FileOwner own) const { -#if !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_OPENBSD) - int size_max = sysconf(_SC_GETPW_R_SIZE_MAX); - if (size_max == -1) - size_max = 1024; - QVarLengthArray<char, 1024> buf(size_max); -#endif - - if (own == OwnerUser) { - struct passwd *pw = 0; -#if !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_OPENBSD) - struct passwd entry; - getpwuid_r(ownerId(own), &entry, buf.data(), buf.size(), &pw); -#else - pw = getpwuid(ownerId(own)); -#endif - if (pw) - return QFile::decodeName(QByteArray(pw->pw_name)); - } else if (own == OwnerGroup) { -#if !defined(Q_OS_SYMBIAN) - struct group *gr = 0; -#if !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_OPENBSD) - size_max = sysconf(_SC_GETGR_R_SIZE_MAX); - if (size_max == -1) - size_max = 1024; - buf.resize(size_max); - struct group entry; - // Some large systems have more members than the POSIX max size - // Loop over by doubling the buffer size (upper limit 250k) - for (unsigned size = size_max; size < 256000; size += size) - { - buf.resize(size); - // ERANGE indicates that the buffer was too small - if (!getgrgid_r(ownerId(own), &entry, buf.data(), buf.size(), &gr) - || errno != ERANGE) - break; - } +#ifndef Q_OS_SYMBIAN + if (own == OwnerUser) + return QFileSystemEngine::resolveUserName(ownerId(own)); + return QFileSystemEngine::resolveGroupName(ownerId(own)); #else - gr = getgrgid(ownerId(own)); -#endif - if (gr) - return QFile::decodeName(QByteArray(gr->gr_name)); -#endif - } return QString(); +#endif } bool QFSFileEngine::setPermissions(uint perms) { Q_D(QFSFileEngine); + QSystemError error; + if (!QFileSystemEngine::setPermissions(d->fileEntry, QFile::Permissions(perms), error, 0)) { + setError(QFile::PermissionsError, error.toString()); + return false; + } + return true; +} + +#ifdef Q_OS_SYMBIAN +bool QFSFileEngine::setSize(qint64 size) +{ + Q_D(QFSFileEngine); bool ret = false; - mode_t mode = 0; - if (perms & ReadOwnerPerm) - mode |= S_IRUSR; - if (perms & WriteOwnerPerm) - mode |= S_IWUSR; - if (perms & ExeOwnerPerm) - mode |= S_IXUSR; - if (perms & ReadUserPerm) - mode |= S_IRUSR; - if (perms & WriteUserPerm) - mode |= S_IWUSR; - if (perms & ExeUserPerm) - mode |= S_IXUSR; - if (perms & ReadGroupPerm) - mode |= S_IRGRP; - if (perms & WriteGroupPerm) - mode |= S_IWGRP; - if (perms & ExeGroupPerm) - mode |= S_IXGRP; - if (perms & ReadOtherPerm) - mode |= S_IROTH; - if (perms & WriteOtherPerm) - mode |= S_IWOTH; - if (perms & ExeOtherPerm) - mode |= S_IXOTH; - if (d->fd != -1) - ret = fchmod(d->fd, mode) == 0; - else - ret = ::chmod(d->nativeFilePath.constData(), mode) == 0; - if (!ret) - setError(QFile::PermissionsError, qt_error_string(errno)); + TInt err = KErrNone; + 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; + else if (d->fh) + ret = QT_FTRUNCATE(QT_FILENO(d->fh), size) == 0; + else { + RFile tmp; + QString symbianFilename(d->fileEntry.nativeFilePath()); + err = tmp.Open(qt_s60GetRFs(), qt_QString2TPtrC(symbianFilename), EFileWrite); + if (err == KErrNone) + { + err = tmp.SetSize(size); + tmp.Close(); + } + ret = (err == KErrNone); + } + if (!ret) { + QSystemError error; + if (err) + error = QSystemError(err, QSystemError::NativeError); + else + error = QSystemError(errno, QSystemError::StandardLibraryError); + setError(QFile::ResizeError, error.toString()); + } return ret; } - +#else bool QFSFileEngine::setSize(qint64 size) { Q_D(QFSFileEngine); @@ -1277,25 +928,21 @@ bool QFSFileEngine::setSize(qint64 size) else if (d->fh) ret = QT_FTRUNCATE(QT_FILENO(d->fh), size) == 0; else - ret = QT_TRUNCATE(d->nativeFilePath.constData(), size) == 0; + ret = QT_TRUNCATE(d->fileEntry.nativeFilePath().constData(), size) == 0; if (!ret) setError(QFile::ResizeError, qt_error_string(errno)); return ret; } +#endif QDateTime QFSFileEngine::fileTime(FileTime time) const { Q_D(const QFSFileEngine); - QDateTime ret; - if (d->doStat()) { - if (time == CreationTime) - ret.setTime_t(d->st.st_ctime ? d->st.st_ctime : d->st.st_mtime); - else if (time == ModificationTime) - ret.setTime_t(d->st.st_mtime); - else if (time == AccessTime) - ret.setTime_t(d->st.st_atime); - } - return ret; + + if (d->doStat(QFileSystemMetaData::Times)) + return d->metaData.fileTime(time); + + return QDateTime(); } uchar *QFSFileEnginePrivate::map(qint64 offset, qint64 size, QFile::MemoryMapFlags flags) @@ -1315,8 +962,8 @@ uchar *QFSFileEnginePrivate::map(qint64 offset, qint64 size, QFile::MemoryMapFla // If we know the mapping will extend beyond EOF, fail early to avoid // undefined behavior. Otherwise, let mmap have its say. - if (doStat() - && (QT_OFF_T(size) > st.st_size - QT_OFF_T(offset))) + if (doStat(QFileSystemMetaData::SizeAttribute) + && (QT_OFF_T(size) > metaData.size() - QT_OFF_T(offset))) qWarning("QFSFileEngine::map: Mapping a file beyond its size is not portable"); int access = 0; @@ -1338,7 +985,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; diff --git a/src/corelib/io/qfsfileengine_win.cpp b/src/corelib/io/qfsfileengine_win.cpp index 71b10b4..3b6e80c 100644 --- a/src/corelib/io/qfsfileengine_win.cpp +++ b/src/corelib/io/qfsfileengine_win.cpp @@ -43,7 +43,7 @@ #include "qplatformdefs.h" #include "qabstractfileengine.h" #include "private/qfsfileengine_p.h" -#include <private/qsystemlibrary_p.h> +#include "qfilesystemengine_p.h" #include <qdebug.h> #include "qfile.h" @@ -69,239 +69,12 @@ #define SECURITY_WIN32 #include <security.h> -#ifndef SPI_GETPLATFORMTYPE -#define SPI_GETPLATFORMTYPE 257 -#endif - #ifndef PATH_MAX #define PATH_MAX FILENAME_MAX #endif -#ifndef _INTPTR_T_DEFINED -#ifdef _WIN64 -typedef __int64 intptr_t; -#else -#ifdef _W64 -typedef _W64 int intptr_t; -#else -typedef INT_PTR intptr_t; -#endif -#endif -#define _INTPTR_T_DEFINED -#endif - -#ifndef INVALID_FILE_ATTRIBUTES -# define INVALID_FILE_ATTRIBUTES (DWORD (-1)) -#endif - -#if !defined(Q_OS_WINCE) -# if !defined(REPARSE_DATA_BUFFER_HEADER_SIZE) -typedef struct _REPARSE_DATA_BUFFER { - ULONG ReparseTag; - USHORT ReparseDataLength; - USHORT Reserved; - union { - struct { - USHORT SubstituteNameOffset; - USHORT SubstituteNameLength; - USHORT PrintNameOffset; - USHORT PrintNameLength; - ULONG Flags; - WCHAR PathBuffer[1]; - } SymbolicLinkReparseBuffer; - struct { - USHORT SubstituteNameOffset; - USHORT SubstituteNameLength; - USHORT PrintNameOffset; - USHORT PrintNameLength; - WCHAR PathBuffer[1]; - } MountPointReparseBuffer; - struct { - UCHAR DataBuffer[1]; - } GenericReparseBuffer; - }; -} REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER; -# define REPARSE_DATA_BUFFER_HEADER_SIZE FIELD_OFFSET(REPARSE_DATA_BUFFER, GenericReparseBuffer) -# endif // !defined(REPARSE_DATA_BUFFER_HEADER_SIZE) - -# ifndef MAXIMUM_REPARSE_DATA_BUFFER_SIZE -# define MAXIMUM_REPARSE_DATA_BUFFER_SIZE 16384 -# endif -# ifndef IO_REPARSE_TAG_SYMLINK -# define IO_REPARSE_TAG_SYMLINK (0xA000000CL) -# endif -# ifndef FSCTL_GET_REPARSE_POINT -# define FSCTL_GET_REPARSE_POINT CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 42, METHOD_BUFFERED, FILE_ANY_ACCESS) -# endif -#endif // !defined(Q_OS_WINCE) - QT_BEGIN_NAMESPACE -static QString readLink(const QString &link); - -Q_CORE_EXPORT int qt_ntfs_permission_lookup = 0; - -#if defined(Q_OS_WINCE) -static QString qfsPrivateCurrentDir = QLatin1String(""); -// As none of the functions we try to resolve do exist on Windows CE -// we use QT_NO_LIBRARY to shorten everything up a little bit. -#define QT_NO_LIBRARY 1 -#endif - -#if !defined(QT_NO_LIBRARY) -QT_BEGIN_INCLUDE_NAMESPACE -typedef DWORD (WINAPI *PtrGetNamedSecurityInfoW)(LPWSTR, SE_OBJECT_TYPE, SECURITY_INFORMATION, PSID*, PSID*, PACL*, PACL*, PSECURITY_DESCRIPTOR*); -static PtrGetNamedSecurityInfoW ptrGetNamedSecurityInfoW = 0; -typedef BOOL (WINAPI *PtrLookupAccountSidW)(LPCWSTR, PSID, LPWSTR, LPDWORD, LPWSTR, LPDWORD, PSID_NAME_USE); -static PtrLookupAccountSidW ptrLookupAccountSidW = 0; -typedef VOID (WINAPI *PtrBuildTrusteeWithSidW)(PTRUSTEE_W, PSID); -static PtrBuildTrusteeWithSidW ptrBuildTrusteeWithSidW = 0; -typedef DWORD (WINAPI *PtrGetEffectiveRightsFromAclW)(PACL, PTRUSTEE_W, OUT PACCESS_MASK); -static PtrGetEffectiveRightsFromAclW ptrGetEffectiveRightsFromAclW = 0; -static TRUSTEE_W currentUserTrusteeW; -static TRUSTEE_W worldTrusteeW; - -typedef BOOL (WINAPI *PtrGetUserProfileDirectoryW)(HANDLE, LPWSTR, LPDWORD); -static PtrGetUserProfileDirectoryW ptrGetUserProfileDirectoryW = 0; -typedef BOOL (WINAPI *PtrGetVolumePathNamesForVolumeNameW)(LPCWSTR,LPWSTR,DWORD,PDWORD); -static PtrGetVolumePathNamesForVolumeNameW ptrGetVolumePathNamesForVolumeNameW = 0; -QT_END_INCLUDE_NAMESPACE - - -void QFSFileEnginePrivate::resolveLibs() -{ - static bool triedResolve = false; - if (!triedResolve) { - // need to resolve the security info functions - - // protect initialization -#ifndef QT_NO_THREAD - QMutexLocker locker(QMutexPool::globalInstanceGet(&triedResolve)); - // check triedResolve again, since another thread may have already - // done the initialization - if (triedResolve) { - // another thread did initialize the security function pointers, - // so we shouldn't do it again. - return; - } -#endif - - triedResolve = true; -#if !defined(Q_OS_WINCE) - HINSTANCE advapiHnd = QSystemLibrary::load(L"advapi32"); - if (advapiHnd) { - ptrGetNamedSecurityInfoW = (PtrGetNamedSecurityInfoW)GetProcAddress(advapiHnd, "GetNamedSecurityInfoW"); - ptrLookupAccountSidW = (PtrLookupAccountSidW)GetProcAddress(advapiHnd, "LookupAccountSidW"); - ptrBuildTrusteeWithSidW = (PtrBuildTrusteeWithSidW)GetProcAddress(advapiHnd, "BuildTrusteeWithSidW"); - ptrGetEffectiveRightsFromAclW = (PtrGetEffectiveRightsFromAclW)GetProcAddress(advapiHnd, "GetEffectiveRightsFromAclW"); - } - if (ptrBuildTrusteeWithSidW) { - // Create TRUSTEE for current user - HANDLE hnd = ::GetCurrentProcess(); - HANDLE token = 0; - if (::OpenProcessToken(hnd, TOKEN_QUERY, &token)) { - TOKEN_USER tu; - DWORD retsize; - if (::GetTokenInformation(token, TokenUser, &tu, sizeof(tu), &retsize)) - ptrBuildTrusteeWithSidW(¤tUserTrusteeW, tu.User.Sid); - ::CloseHandle(token); - } - - typedef BOOL (WINAPI *PtrAllocateAndInitializeSid)(PSID_IDENTIFIER_AUTHORITY, BYTE, DWORD, DWORD, DWORD, DWORD, DWORD, DWORD, DWORD, DWORD, PSID*); - PtrAllocateAndInitializeSid ptrAllocateAndInitializeSid = (PtrAllocateAndInitializeSid)GetProcAddress(advapiHnd, "AllocateAndInitializeSid"); - typedef PVOID (WINAPI *PtrFreeSid)(PSID); - PtrFreeSid ptrFreeSid = (PtrFreeSid)GetProcAddress(advapiHnd, "FreeSid"); - if (ptrAllocateAndInitializeSid && ptrFreeSid) { - // Create TRUSTEE for Everyone (World) - SID_IDENTIFIER_AUTHORITY worldAuth = { SECURITY_WORLD_SID_AUTHORITY }; - PSID pWorld = 0; - if (ptrAllocateAndInitializeSid(&worldAuth, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &pWorld)) - ptrBuildTrusteeWithSidW(&worldTrusteeW, pWorld); - ptrFreeSid(pWorld); - } - } - HINSTANCE userenvHnd = QSystemLibrary::load(L"userenv"); - if (userenvHnd) - ptrGetUserProfileDirectoryW = (PtrGetUserProfileDirectoryW)GetProcAddress(userenvHnd, "GetUserProfileDirectoryW"); - HINSTANCE kernel32 = LoadLibrary(L"kernel32"); - if(kernel32) - ptrGetVolumePathNamesForVolumeNameW = (PtrGetVolumePathNamesForVolumeNameW)GetProcAddress(kernel32, "GetVolumePathNamesForVolumeNameW"); -#endif - } -} -#endif // QT_NO_LIBRARY - -typedef DWORD (WINAPI *PtrNetShareEnum)(LPWSTR, DWORD, LPBYTE*, DWORD, LPDWORD, LPDWORD, LPDWORD); -static PtrNetShareEnum ptrNetShareEnum = 0; -typedef DWORD (WINAPI *PtrNetApiBufferFree)(LPVOID); -static PtrNetApiBufferFree ptrNetApiBufferFree = 0; -typedef struct _SHARE_INFO_1 { - LPWSTR shi1_netname; - DWORD shi1_type; - LPWSTR shi1_remark; -} SHARE_INFO_1; - - -bool QFSFileEnginePrivate::resolveUNCLibs() -{ - static bool triedResolve = false; - if (!triedResolve) { -#ifndef QT_NO_THREAD - QMutexLocker locker(QMutexPool::globalInstanceGet(&triedResolve)); - if (triedResolve) { - return ptrNetShareEnum && ptrNetApiBufferFree; - } -#endif - triedResolve = true; -#if !defined(Q_OS_WINCE) - HINSTANCE hLib = QSystemLibrary::load(L"Netapi32"); - if (hLib) { - ptrNetShareEnum = (PtrNetShareEnum)GetProcAddress(hLib, "NetShareEnum"); - if (ptrNetShareEnum) - ptrNetApiBufferFree = (PtrNetApiBufferFree)GetProcAddress(hLib, "NetApiBufferFree"); - } -#endif - } - return ptrNetShareEnum && ptrNetApiBufferFree; -} - -bool QFSFileEnginePrivate::uncListSharesOnServer(const QString &server, QStringList *list) -{ - if (resolveUNCLibs()) { - SHARE_INFO_1 *BufPtr, *p; - DWORD res; - DWORD er = 0, tr = 0, resume = 0, i; - do { - res = ptrNetShareEnum((wchar_t*)server.utf16(), 1, (LPBYTE *)&BufPtr, DWORD(-1), &er, &tr, &resume); - if (res == ERROR_SUCCESS || res == ERROR_MORE_DATA) { - p = BufPtr; - for (i = 1; i <= er; ++i) { - if (list && p->shi1_type == 0) - list->append(QString::fromWCharArray(p->shi1_netname)); - p++; - } - } - ptrNetApiBufferFree(BufPtr); - } while (res == ERROR_MORE_DATA); - return res == ERROR_SUCCESS; - } - return false; -} - -static bool isUncRoot(const QString &server) -{ - QString localPath = QDir::toNativeSeparators(server); - if (!localPath.startsWith(QLatin1String("\\\\"))) - return false; - - int idx = localPath.indexOf(QLatin1Char('\\'), 2); - if (idx == -1 || idx + 1 == localPath.length()) - return true; - - localPath = localPath.right(localPath.length() - idx - 1).trimmed(); - return localPath.isEmpty(); -} - #if !defined(Q_OS_WINCE) static inline bool isUncPath(const QString &path) { @@ -311,73 +84,6 @@ static inline bool isUncPath(const QString &path) } #endif -static inline bool isRelativePath(const QString &path) -{ - // drive, e.g. "a:", or UNC root, e.q. "//" - return !(path.startsWith(QLatin1Char('/')) - || (path.length() >= 2 - && ((path.at(0).isLetter() && path.at(1) == QLatin1Char(':')) - || (path.at(0) == QLatin1Char('/') && path.at(1) == QLatin1Char('/'))))); -} - -static QString fixIfRelativeUncPath(const QString &path) -{ - if (isRelativePath(path)) { - QString currentPath = QDir::currentPath() + QLatin1Char('/'); - if (currentPath.startsWith(QLatin1String("//"))) - return QString(path).prepend(currentPath); - } - return path; -} - -// can be //server or //server/share -static bool uncShareExists(const QString &server) -{ - QStringList parts = server.split(QLatin1Char('\\'), QString::SkipEmptyParts); - if (parts.count()) { - QStringList shares; - if (QFSFileEnginePrivate::uncListSharesOnServer(QLatin1String("\\\\") + parts.at(0), &shares)) - return parts.count() >= 2 ? shares.contains(parts.at(1), Qt::CaseInsensitive) : true; - } - return false; -} - -static inline bool isDriveRoot(const QString &path) -{ - return (path.length() == 3 - && path.at(0).isLetter() && path.at(1) == QLatin1Char(':') - && path.at(2) == QLatin1Char('/')); -} - -static QString nativeAbsoluteFilePath(const QString &path) -{ - QString absPath; -#if !defined(Q_OS_WINCE) - QVarLengthArray<wchar_t, MAX_PATH> buf(qMax(MAX_PATH, path.size() + 1)); - wchar_t *fileName = 0; - DWORD retLen = GetFullPathName((wchar_t*)path.utf16(), buf.size(), buf.data(), &fileName); - if (retLen > (DWORD)buf.size()) { - buf.resize(retLen); - retLen = GetFullPathName((wchar_t*)path.utf16(), buf.size(), buf.data(), &fileName); - } - if (retLen != 0) - absPath = QString::fromWCharArray(buf.data(), retLen); -#else - if (path.startsWith(QLatin1Char('/')) || path.startsWith(QLatin1Char('\\'))) - absPath = QDir::toNativeSeparators(path); - else - absPath = QDir::toNativeSeparators(QDir::cleanPath(qfsPrivateCurrentDir + QLatin1Char('/') + path)); -#endif - // This is really ugly, but GetFullPathName strips off whitespace at the end. - // If you for instance write ". " in the lineedit of QFileDialog, - // (which is an invalid filename) this function will strip the space off and viola, - // the file is later reported as existing. Therefore, we re-add the whitespace that - // was at the end of path in order to keep the filename invalid. - if (!path.isEmpty() && path.at(path.size() - 1) == QLatin1Char(' ')) - absPath.append(QLatin1Char(' ')); - return absPath; -} - /*! \internal */ @@ -386,7 +92,7 @@ QString QFSFileEnginePrivate::longFileName(const QString &path) if (path.startsWith(QLatin1String("\\\\.\\"))) return path; - QString absPath = nativeAbsoluteFilePath(path); + QString absPath = QFileSystemEngine::nativeAbsoluteFilePath(path); #if !defined(Q_OS_WINCE) QString prefix = QLatin1String("\\\\?\\"); if (isUncPath(absPath)) { @@ -402,15 +108,6 @@ QString QFSFileEnginePrivate::longFileName(const QString &path) /* \internal */ -void QFSFileEnginePrivate::nativeInitFileName() -{ - QString path = longFileName(QDir::toNativeSeparators(fixIfRelativeUncPath(filePath))); - nativeFilePath = QByteArray((const char *)path.utf16(), path.size() * 2 + 1); -} - -/* - \internal -*/ bool QFSFileEnginePrivate::nativeOpen(QIODevice::OpenMode openMode) { Q_Q(QFSFileEngine); @@ -428,9 +125,8 @@ bool QFSFileEnginePrivate::nativeOpen(QIODevice::OpenMode openMode) // WriteOnly can create files, ReadOnly cannot. DWORD creationDisp = (openMode & QIODevice::WriteOnly) ? OPEN_ALWAYS : OPEN_EXISTING; - // Create the file handle. - fileHandle = CreateFile((const wchar_t*)nativeFilePath.constData(), + fileHandle = CreateFile((const wchar_t*)fileEntry.nativeFilePath().utf16(), accessRights, shareMode, &securityAtts, @@ -520,17 +216,9 @@ qint64 QFSFileEnginePrivate::nativeSize() const // ### Don't flush; for buffered files, we should get away with ftell. thatQ->flush(); -#if !defined(Q_OS_WINCE) - // stdlib/stdio mode. - if (fh || fd != -1) { - qint64 fileSize = _filelengthi64(fh ? QT_FILENO(fh) : fd); - if (fileSize == -1) { - fileSize = 0; - thatQ->setError(QFile::UnspecifiedError, qt_error_string(errno)); - } - return fileSize; - } -#else // Q_OS_WINCE + // Always retrive the current information + metaData.clearFlags(QFileSystemMetaData::SizeAttribute); +#if defined(Q_OS_WINCE) // Buffered stdlib mode. if (fh) { QT_OFF_T oldPos = QT_FTELL(fh); @@ -543,70 +231,22 @@ qint64 QFSFileEnginePrivate::nativeSize() const } return fileSize; } -#endif - - // Not-open mode, where the file name is known: We'll check the - // file system directly. - if (openMode == QIODevice::NotOpen && !nativeFilePath.isEmpty()) { - WIN32_FILE_ATTRIBUTE_DATA attribData; - bool ok = ::GetFileAttributesEx((const wchar_t*)nativeFilePath.constData(), - GetFileExInfoStandard, &attribData); - if (!ok) { - int errorCode = GetLastError(); - if (errorCode == ERROR_ACCESS_DENIED || errorCode == ERROR_SHARING_VIOLATION) { - QByteArray path = nativeFilePath; - // path for the FindFirstFile should not end with a trailing slash - while (!path.isEmpty() && reinterpret_cast<const wchar_t *>( - path.constData() + path.length())[-1] == '\\') - path.chop(2); - - // FindFirstFile can not handle drives - if (!path.isEmpty() && reinterpret_cast<const wchar_t *>( - path.constData() + path.length())[-1] != ':') { - WIN32_FIND_DATA findData; - HANDLE hFind = ::FindFirstFile((const wchar_t*)path.constData(), - &findData); - if (hFind != INVALID_HANDLE_VALUE) { - ::FindClose(hFind); - ok = true; - attribData.nFileSizeHigh = findData.nFileSizeHigh; - attribData.nFileSizeLow = findData.nFileSizeLow; - } - } - } - } - if (ok) { - qint64 size = attribData.nFileSizeHigh; - size <<= 32; - size += attribData.nFileSizeLow; - return size; - } - thatQ->setError(QFile::UnspecifiedError, qt_error_string()); - return 0; - } - -#if defined(Q_OS_WINCE) - // Unbuffed stdio mode if (fd != -1) { thatQ->setError(QFile::UnspecifiedError, QLatin1String("Not implemented!")); return 0; } #endif + bool filled = false; + if (fileHandle != INVALID_HANDLE_VALUE && openMode != QIODevice::NotOpen ) + filled = QFileSystemEngine::fillMetaData(fileHandle, metaData, + QFileSystemMetaData::SizeAttribute); + else + filled = doStat(QFileSystemMetaData::SizeAttribute); - // Windows native mode. - if (fileHandle == INVALID_HANDLE_VALUE) - return 0; - - BY_HANDLE_FILE_INFORMATION fileInfo; - if (!GetFileInformationByHandle(fileHandle, &fileInfo)) { - thatQ->setError(QFile::UnspecifiedError, qt_error_string()); - return 0; + if (!filled) { + thatQ->setError(QFile::UnspecifiedError, qt_error_string(errno)); } - - qint64 size = fileInfo.nFileSizeHigh; - size <<= 32; - size += fileInfo.nFileSizeLow; - return size; + return metaData.size(); } /* @@ -840,159 +480,41 @@ bool QFSFileEnginePrivate::nativeIsSequential() const bool QFSFileEngine::remove() { Q_D(QFSFileEngine); - bool ret = ::DeleteFile((wchar_t*)QFSFileEnginePrivate::longFileName(d->filePath).utf16()) != 0; + QSystemError error; + bool ret = QFileSystemEngine::removeFile(d->fileEntry, error); if (!ret) - setError(QFile::RemoveError, qt_error_string()); + setError(QFile::RemoveError, error.toString()); return ret; } bool QFSFileEngine::copy(const QString ©Name) { Q_D(QFSFileEngine); - bool ret = ::CopyFile((wchar_t*)QFSFileEnginePrivate::longFileName(d->filePath).utf16(), - (wchar_t*)QFSFileEnginePrivate::longFileName(copyName).utf16(), true) != 0; + QSystemError error; + bool ret = QFileSystemEngine::copyFile(d->fileEntry, QFileSystemEntry(copyName), error); if (!ret) - setError(QFile::CopyError, qt_error_string()); + setError(QFile::CopyError, error.toString()); return ret; } bool QFSFileEngine::rename(const QString &newName) { Q_D(QFSFileEngine); - bool ret = ::MoveFile((wchar_t*)QFSFileEnginePrivate::longFileName(d->filePath).utf16(), - (wchar_t*)QFSFileEnginePrivate::longFileName(newName).utf16()) != 0; + QSystemError error; + bool ret = QFileSystemEngine::renameFile(d->fileEntry, QFileSystemEntry(newName), error); if (!ret) - setError(QFile::RenameError, qt_error_string()); + setError(QFile::RenameError, error.toString()); return ret; } -static inline bool mkDir(const QString &path) -{ -#if defined(Q_OS_WINCE) - // Unfortunately CreateDirectory returns true for paths longer than - // 256, but does not create a directory. It starts to fail, when - // path length > MAX_PATH, which is 260 usually on CE. - // This only happens on a Windows Mobile device. Windows CE seems - // not to be affected by this. - static int platformId = 0; - if (platformId == 0) { - wchar_t platformString[64]; - if (SystemParametersInfo(SPI_GETPLATFORMTYPE, sizeof(platformString)/sizeof(*platformString),platformString,0)) { - if (0 == wcscmp(platformString, L"PocketPC") || 0 == wcscmp(platformString, L"Smartphone")) - platformId = 1; - else - platformId = 2; - } - } - if (platformId == 1 && QFSFileEnginePrivate::longFileName(path).size() > 256) - return false; -#endif - return ::CreateDirectory((wchar_t*)QFSFileEnginePrivate::longFileName(path).utf16(), 0); -} - -static inline bool rmDir(const QString &path) -{ - return ::RemoveDirectory((wchar_t*)QFSFileEnginePrivate::longFileName(path).utf16()); -} - -static bool isDirPath(const QString &dirPath, bool *existed) -{ - QString path = dirPath; - if (path.length() == 2 && path.at(1) == QLatin1Char(':')) - path += QLatin1Char('\\'); - - DWORD fileAttrib = ::GetFileAttributes((wchar_t*)QFSFileEnginePrivate::longFileName(path).utf16()); - if (fileAttrib == INVALID_FILE_ATTRIBUTES) { - int errorCode = GetLastError(); - if (errorCode == ERROR_ACCESS_DENIED || errorCode == ERROR_SHARING_VIOLATION) { - // path for the FindFirstFile should not end with a trailing slash - while (path.endsWith(QLatin1Char('\\'))) - path.chop(1); - - // FindFirstFile can not handle drives - if (!path.endsWith(QLatin1Char(':'))) { - WIN32_FIND_DATA findData; - HANDLE hFind = ::FindFirstFile((wchar_t*)QFSFileEnginePrivate::longFileName(path).utf16(), - &findData); - if (hFind != INVALID_HANDLE_VALUE) { - ::FindClose(hFind); - fileAttrib = findData.dwFileAttributes; - } - } - } - } - - if (existed) - *existed = fileAttrib != INVALID_FILE_ATTRIBUTES; - - if (fileAttrib == INVALID_FILE_ATTRIBUTES) - return false; - - return fileAttrib & FILE_ATTRIBUTE_DIRECTORY; -} - bool QFSFileEngine::mkdir(const QString &name, bool createParentDirectories) const { - QString dirName = name; - if (createParentDirectories) { - dirName = QDir::toNativeSeparators(QDir::cleanPath(dirName)); - // We spefically search for / so \ would break it.. - int oldslash = -1; - if (dirName.startsWith(QLatin1String("\\\\"))) { - // Don't try to create the root path of a UNC path; - // CreateDirectory() will just return ERROR_INVALID_NAME. - for (int i = 0; i < dirName.size(); ++i) { - if (dirName.at(i) != QDir::separator()) { - oldslash = i; - break; - } - } - if (oldslash != -1) - oldslash = dirName.indexOf(QDir::separator(), oldslash); - } - for (int slash=0; slash != -1; oldslash = slash) { - slash = dirName.indexOf(QDir::separator(), oldslash+1); - if (slash == -1) { - if (oldslash == dirName.length()) - break; - slash = dirName.length(); - } - if (slash) { - QString chunk = dirName.left(slash); - bool existed = false; - if (!isDirPath(chunk, &existed)) { - if (!existed) { - if (!mkDir(chunk)) - return false; - } else { - return false; - } - } - } - } - return true; - } - return mkDir(name); + return QFileSystemEngine::createDirectory(QFileSystemEntry(name), createParentDirectories); } bool QFSFileEngine::rmdir(const QString &name, bool recurseParentDirectories) const { - QString dirName = name; - if (recurseParentDirectories) { - dirName = QDir::toNativeSeparators(QDir::cleanPath(dirName)); - for (int oldslash = 0, slash=dirName.length(); slash > 0; oldslash = slash) { - QString chunk = dirName.left(slash); - if (chunk.length() == 2 && chunk.at(0).isLetter() && chunk.at(1) == QLatin1Char(':')) - break; - if (!isDirPath(chunk, 0)) - return false; - if (!rmDir(chunk)) - return oldslash != 0; - slash = dirName.lastIndexOf(QDir::separator(), oldslash-1); - } - return true; - } - return rmDir(name); + return QFileSystemEngine::removeDirectory(QFileSystemEntry(name), recurseParentDirectories); } bool QFSFileEngine::caseSensitive() const @@ -1002,15 +524,7 @@ bool QFSFileEngine::caseSensitive() const bool QFSFileEngine::setCurrentPath(const QString &path) { - if (!QDir(path).exists()) - return false; - -#if !defined(Q_OS_WINCE) - return ::SetCurrentDirectory((wchar_t*)path.utf16()) != 0; -#else - qfsPrivateCurrentDir = QFSFileEnginePrivate::longFileName(path); - return true; -#endif + return QFileSystemEngine::setCurrentPath(QFileSystemEntry(path)); } QString QFSFileEngine::currentPath(const QString &fileName) @@ -1029,115 +543,30 @@ QString QFSFileEngine::currentPath(const QString &fileName) } if (ret.isEmpty()) { //just the pwd - DWORD size = 0; - wchar_t currentName[PATH_MAX]; - size = ::GetCurrentDirectory(PATH_MAX, currentName); - if (size != 0) { - if (size > PATH_MAX) { - wchar_t *newCurrentName = new wchar_t[size]; - if (::GetCurrentDirectory(PATH_MAX, newCurrentName) != 0) - ret = QString::fromWCharArray(newCurrentName); - delete [] newCurrentName; - } else { - ret = QString::fromWCharArray(currentName); - } - } + ret = QFileSystemEngine::currentPath().filePath(); } if (ret.length() >= 2 && ret[1] == QLatin1Char(':')) ret[0] = ret.at(0).toUpper(); // Force uppercase drive letters. - return QDir::fromNativeSeparators(ret); + return ret; #else Q_UNUSED(fileName); - if (qfsPrivateCurrentDir.isEmpty()) - qfsPrivateCurrentDir = QCoreApplication::applicationDirPath(); - - return QDir::fromNativeSeparators(qfsPrivateCurrentDir); + return QFileSystemEngine::currentPath(); #endif } QString QFSFileEngine::homePath() { - QString ret; -#if !defined(QT_NO_LIBRARY) - QFSFileEnginePrivate::resolveLibs(); - if (ptrGetUserProfileDirectoryW) { - HANDLE hnd = ::GetCurrentProcess(); - HANDLE token = 0; - BOOL ok = ::OpenProcessToken(hnd, TOKEN_QUERY, &token); - if (ok) { - DWORD dwBufferSize = 0; - // First call, to determine size of the strings (with '\0'). - ok = ptrGetUserProfileDirectoryW(token, NULL, &dwBufferSize); - if (!ok && dwBufferSize != 0) { // We got the required buffer size - wchar_t *userDirectory = new wchar_t[dwBufferSize]; - // Second call, now we can fill the allocated buffer. - ok = ptrGetUserProfileDirectoryW(token, userDirectory, &dwBufferSize); - if (ok) - ret = QString::fromWCharArray(userDirectory); - - delete [] userDirectory; - } - ::CloseHandle(token); - } - } -#endif - if (ret.isEmpty() || !QFile::exists(ret)) { - ret = QString::fromLocal8Bit(qgetenv("USERPROFILE").constData()); - if (ret.isEmpty() || !QFile::exists(ret)) { - ret = QString::fromLocal8Bit(qgetenv("HOMEDRIVE").constData()) + QString::fromLocal8Bit(qgetenv("HOMEPATH").constData()); - if (ret.isEmpty() || !QFile::exists(ret)) { - ret = QString::fromLocal8Bit(qgetenv("HOME").constData()); - if (ret.isEmpty() || !QFile::exists(ret)) { -#if defined(Q_OS_WINCE) - ret = QLatin1String("\\My Documents"); - if (!QFile::exists(ret)) -#endif - ret = rootPath(); - } - } - } - } - return QDir::fromNativeSeparators(ret); + return QFileSystemEngine::homePath(); } QString QFSFileEngine::rootPath() { -#if defined(Q_OS_WINCE) - QString ret = QLatin1String("/"); -#elif defined(Q_FS_FAT) - QString ret = QString::fromLatin1(qgetenv("SystemDrive").constData()); - if (ret.isEmpty()) - ret = QLatin1String("c:"); - ret.append(QLatin1Char('/')); -#elif defined(Q_OS_OS2EMX) - char dir[4]; - _abspath(dir, QLatin1String("/"), _MAX_PATH); - QString ret(dir); -#endif - return ret; + return QFileSystemEngine::rootPath(); } QString QFSFileEngine::tempPath() { - QString ret; - { - wchar_t tempPath[MAX_PATH]; - if (GetTempPath(MAX_PATH, tempPath)) - ret = QString::fromWCharArray(tempPath); - if (!ret.isEmpty()) { - while (ret.endsWith(QLatin1Char('\\'))) - ret.chop(1); - ret = QDir::fromNativeSeparators(ret); - } - } - if (ret.isEmpty()) { -#if !defined(Q_OS_WINCE) - ret = QLatin1String("c:/tmp"); -#else - ret = QLatin1String("/Temp"); -#endif - } - return ret; + return QFileSystemEngine::tempPath(); } QFileInfoList QFSFileEngine::drives() @@ -1167,232 +596,25 @@ QFileInfoList QFSFileEngine::drives() #endif } -bool QFSFileEnginePrivate::doStat() const +bool QFSFileEnginePrivate::doStat(QFileSystemMetaData::MetaDataFlags flags) const { - if (!tried_stat) { + if (!tried_stat || !metaData.hasFlags(flags)) { tried_stat = true; - could_stat = false; - - if (filePath.isEmpty()) - return could_stat; - - QString fname; - if(filePath.endsWith(QLatin1String(".lnk"))) { - fname = readLink(filePath); - if(fname.isEmpty()) - return could_stat; - } - else - fname = filePath; - fname = fixIfRelativeUncPath(fname); - - UINT oldmode = SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX); - - if (fd != -1) { -#if !defined(Q_OS_WINCE) - HANDLE fh = (HANDLE)_get_osfhandle(fd); - if (fh != INVALID_HANDLE_VALUE) { - BY_HANDLE_FILE_INFORMATION fileInfo; - if (GetFileInformationByHandle(fh, &fileInfo)) { - could_stat = true; - fileAttrib = fileInfo.dwFileAttributes; - } - } -#else - DWORD tmpAttributes = GetFileAttributes((wchar_t*)QFSFileEnginePrivate::longFileName(fname).utf16()); - if (tmpAttributes != -1) { - fileAttrib = tmpAttributes; - could_stat = true; - } -#endif - } else { - fileAttrib = GetFileAttributes((wchar_t*)QFSFileEnginePrivate::longFileName(fname).utf16()); - if (fileAttrib == INVALID_FILE_ATTRIBUTES) { - int errorCode = GetLastError(); - if (errorCode == ERROR_ACCESS_DENIED || errorCode == ERROR_SHARING_VIOLATION) { - QString path = QDir::toNativeSeparators(fname); - // path for the FindFirstFile should not end with a trailing slash - while (path.endsWith(QLatin1Char('\\'))) - path.chop(1); - - // FindFirstFile can not handle drives - if (!path.endsWith(QLatin1Char(':'))) { - WIN32_FIND_DATA findData; - HANDLE hFind = ::FindFirstFile((wchar_t*)QFSFileEnginePrivate::longFileName(path).utf16(), - &findData); - if (hFind != INVALID_HANDLE_VALUE) { - ::FindClose(hFind); - fileAttrib = findData.dwFileAttributes; - } - } - } - } - could_stat = fileAttrib != INVALID_FILE_ATTRIBUTES; - if (!could_stat) { #if !defined(Q_OS_WINCE) - if (isDriveRoot(fname)) { - // a valid drive ?? - DWORD drivesBitmask = ::GetLogicalDrives(); - int drivebit = 1 << (fname.at(0).toUpper().unicode() - QLatin1Char('A').unicode()); - if (drivesBitmask & drivebit) { - fileAttrib = FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_SYSTEM; - could_stat = true; - } - } else { + int localFd = fd; + if (fh && fileEntry.isEmpty()) + localFd = QT_FILENO(fh); + if (localFd != -1) + QFileSystemEngine::fillMetaData(localFd, metaData, flags); #endif - QString path = QDir::toNativeSeparators(fname); - bool is_dir = false; - if (path.startsWith(QLatin1String("\\\\"))) { - // UNC - stat doesn't work for all cases (Windows bug) - int s = path.indexOf(path.at(0),2); - if (s > 0) { - // "\\server\..." - s = path.indexOf(path.at(0),s+1); - if (s > 0) { - // "\\server\share\..." - if (s == path.size() - 1) { - // "\\server\share\" - is_dir = true; - } else { - // "\\server\share\notfound" - } - } else { - // "\\server\share" - is_dir = true; - } - } else { - // "\\server" - is_dir = true; - } - } - if (is_dir && uncShareExists(path)) { - // looks like a UNC dir, is a dir. - fileAttrib = FILE_ATTRIBUTE_DIRECTORY; - could_stat = true; - } -#if !defined(Q_OS_WINCE) - } -#endif - } - } - - SetErrorMode(oldmode); + if (metaData.missingFlags(flags) && !fileEntry.isEmpty()) + QFileSystemEngine::fillMetaData(fileEntry, metaData, metaData.missingFlags(flags)); } - return could_stat; -} - -static QString readSymLink(const QString &link) -{ - QString result; -#if !defined(Q_OS_WINCE) - HANDLE handle = CreateFile((wchar_t*)QFSFileEnginePrivate::longFileName(link).utf16(), - FILE_READ_EA, - FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, - 0, - OPEN_EXISTING, - FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, - 0); - if (handle != INVALID_HANDLE_VALUE) { - DWORD bufsize = MAXIMUM_REPARSE_DATA_BUFFER_SIZE; - REPARSE_DATA_BUFFER *rdb = (REPARSE_DATA_BUFFER*)qMalloc(bufsize); - DWORD retsize = 0; - if (::DeviceIoControl(handle, FSCTL_GET_REPARSE_POINT, 0, 0, rdb, bufsize, &retsize, 0)) { - if (rdb->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT) { - int length = rdb->MountPointReparseBuffer.SubstituteNameLength / sizeof(wchar_t); - int offset = rdb->MountPointReparseBuffer.SubstituteNameOffset / sizeof(wchar_t); - const wchar_t* PathBuffer = &rdb->MountPointReparseBuffer.PathBuffer[offset]; - result = QString::fromWCharArray(PathBuffer, length); - } else if (rdb->ReparseTag == IO_REPARSE_TAG_SYMLINK) { - int length = rdb->SymbolicLinkReparseBuffer.SubstituteNameLength / sizeof(wchar_t); - int offset = rdb->SymbolicLinkReparseBuffer.SubstituteNameOffset / sizeof(wchar_t); - const wchar_t* PathBuffer = &rdb->SymbolicLinkReparseBuffer.PathBuffer[offset]; - result = QString::fromWCharArray(PathBuffer, length); - } - // cut-off "//?/" and "/??/" - if (result.size() > 4 && result.at(0) == QLatin1Char('\\') && result.at(2) == QLatin1Char('?') && result.at(3) == QLatin1Char('\\')) - result = result.mid(4); - } - qFree(rdb); - CloseHandle(handle); - -#if !defined(QT_NO_LIBRARY) - QFSFileEnginePrivate::resolveLibs(); - if (ptrGetVolumePathNamesForVolumeNameW) { - QRegExp matchVolName(QLatin1String("^Volume\\{([a-z]|[0-9]|-)+\\}\\\\"), Qt::CaseInsensitive); - if(matchVolName.indexIn(result) == 0) { - DWORD len; - wchar_t buffer[MAX_PATH]; - QString volumeName = result.mid(0, matchVolName.matchedLength()).prepend(QLatin1String("\\\\?\\")); - if(ptrGetVolumePathNamesForVolumeNameW((wchar_t*)volumeName.utf16(), buffer, MAX_PATH, &len) != 0) - result.replace(0,matchVolName.matchedLength(), QString::fromWCharArray(buffer)); - } - } -#endif - } -#else - Q_UNUSED(link); -#endif // Q_OS_WINCE - return result; + return metaData.exists(); } -static QString readLink(const QString &link) -{ -#if !defined(Q_OS_WINCE) -#if !defined(QT_NO_LIBRARY) && !defined(Q_CC_MWERKS) - QString ret; - - bool neededCoInit = false; - IShellLink *psl; // pointer to IShellLink i/f - WIN32_FIND_DATA wfd; - wchar_t szGotPath[MAX_PATH]; - - // Get pointer to the IShellLink interface. - HRESULT hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID *)&psl); - - if (hres == CO_E_NOTINITIALIZED) { // COM was not initialized - neededCoInit = true; - CoInitialize(NULL); - hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, - IID_IShellLink, (LPVOID *)&psl); - } - if (SUCCEEDED(hres)) { // Get pointer to the IPersistFile interface. - IPersistFile *ppf; - hres = psl->QueryInterface(IID_IPersistFile, (LPVOID *)&ppf); - if (SUCCEEDED(hres)) { - hres = ppf->Load((LPOLESTR)link.utf16(), STGM_READ); - //The original path of the link is retrieved. If the file/folder - //was moved, the return value still have the old path. - if (SUCCEEDED(hres)) { - if (psl->GetPath(szGotPath, MAX_PATH, &wfd, SLGP_UNCPRIORITY) == NOERROR) - ret = QString::fromWCharArray(szGotPath); - } - ppf->Release(); - } - psl->Release(); - } - if (neededCoInit) - CoUninitialize(); - - return ret; -#else - Q_UNUSED(link); - return QString(); -#endif // QT_NO_LIBRARY -#else - wchar_t target[MAX_PATH]; - QString result; - if (SHGetShortcutTarget((wchar_t*)QFileInfo(link).absoluteFilePath().replace(QLatin1Char('/'),QLatin1Char('\\')).utf16(), target, MAX_PATH)) { - result = QString::fromWCharArray(target); - if (result.startsWith(QLatin1Char('"'))) - result.remove(0,1); - if (result.endsWith(QLatin1Char('"'))) - result.remove(result.size()-1,1); - } - return result; -#endif // Q_OS_WINCE -} bool QFSFileEngine::link(const QString &newName) { @@ -1457,191 +679,63 @@ bool QFSFileEngine::link(const QString &newName) #endif // Q_OS_WINCE } -QAbstractFileEngine::FileFlags QFSFileEnginePrivate::getPermissions(QAbstractFileEngine::FileFlags type) const +/*! + \reimp +*/ +QAbstractFileEngine::FileFlags QFSFileEngine::fileFlags(QAbstractFileEngine::FileFlags type) const { + Q_D(const QFSFileEngine); + + if (type & Refresh) + d->metaData.clear(); + QAbstractFileEngine::FileFlags ret = 0; -#if !defined(QT_NO_LIBRARY) - if((qt_ntfs_permission_lookup > 0) && (QSysInfo::WindowsVersion & QSysInfo::WV_NT_based)) { - resolveLibs(); - if(ptrGetNamedSecurityInfoW && ptrBuildTrusteeWithSidW && ptrGetEffectiveRightsFromAclW) { - enum { ReadMask = 0x00000001, WriteMask = 0x00000002, ExecMask = 0x00000020 }; - - QString fname = filePath.endsWith(QLatin1String(".lnk")) ? readLink(filePath) : filePath; - PSID pOwner = 0; - PSID pGroup = 0; - PACL pDacl; - PSECURITY_DESCRIPTOR pSD; - DWORD res = ptrGetNamedSecurityInfoW((wchar_t*)fname.utf16(), SE_FILE_OBJECT, - OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION, - &pOwner, &pGroup, &pDacl, 0, &pSD); - if(res == ERROR_SUCCESS) { - ACCESS_MASK access_mask; - TRUSTEE_W trustee; - if (type & 0x0700) { // user - if(ptrGetEffectiveRightsFromAclW(pDacl, ¤tUserTrusteeW, &access_mask) != ERROR_SUCCESS) - access_mask = (ACCESS_MASK)-1; - if(access_mask & ReadMask) - ret |= QAbstractFileEngine::ReadUserPerm; - if(access_mask & WriteMask) - ret |= QAbstractFileEngine::WriteUserPerm; - if(access_mask & ExecMask) - ret |= QAbstractFileEngine::ExeUserPerm; - } - if (type & 0x7000) { // owner - ptrBuildTrusteeWithSidW(&trustee, pOwner); - if(ptrGetEffectiveRightsFromAclW(pDacl, &trustee, &access_mask) != ERROR_SUCCESS) - access_mask = (ACCESS_MASK)-1; - if(access_mask & ReadMask) - ret |= QAbstractFileEngine::ReadOwnerPerm; - if(access_mask & WriteMask) - ret |= QAbstractFileEngine::WriteOwnerPerm; - if(access_mask & ExecMask) - ret |= QAbstractFileEngine::ExeOwnerPerm; - } - if (type & 0x0070) { // group - ptrBuildTrusteeWithSidW(&trustee, pGroup); - if(ptrGetEffectiveRightsFromAclW(pDacl, &trustee, &access_mask) != ERROR_SUCCESS) - access_mask = (ACCESS_MASK)-1; - if(access_mask & ReadMask) - ret |= QAbstractFileEngine::ReadGroupPerm; - if(access_mask & WriteMask) - ret |= QAbstractFileEngine::WriteGroupPerm; - if(access_mask & ExecMask) - ret |= QAbstractFileEngine::ExeGroupPerm; - } - if (type & 0x0007) { // other (world) - if(ptrGetEffectiveRightsFromAclW(pDacl, &worldTrusteeW, &access_mask) != ERROR_SUCCESS) - access_mask = (ACCESS_MASK)-1; // ### - if(access_mask & ReadMask) - ret |= QAbstractFileEngine::ReadOtherPerm; - if(access_mask & WriteMask) - ret |= QAbstractFileEngine::WriteOtherPerm; - if(access_mask & ExecMask) - ret |= QAbstractFileEngine::ExeOtherPerm; - } - LocalFree(pSD); - } - } - } else -#endif + if (type & FlagsMask) + ret |= LocalDiskFlag; + + bool exists; { - //### what to do with permissions if we don't use NTFS - // for now just add all permissions and what about exe missions ?? - // also qt_ntfs_permission_lookup is now not set by default ... should it ? - ret |= QAbstractFileEngine::ReadOwnerPerm | QAbstractFileEngine::ReadGroupPerm - | QAbstractFileEngine::ReadOtherPerm; - - if (!(fileAttrib & FILE_ATTRIBUTE_READONLY)) { - ret |= QAbstractFileEngine::WriteOwnerPerm | QAbstractFileEngine::WriteGroupPerm - | QAbstractFileEngine::WriteOtherPerm; - } + QFileSystemMetaData::MetaDataFlags queryFlags = 0; - QString fname = filePath.endsWith(QLatin1String(".lnk")) ? readLink(filePath) : filePath; - QString ext = fname.right(4).toLower(); - if ((fileAttrib & FILE_ATTRIBUTE_DIRECTORY) || - ext == QLatin1String(".exe") || ext == QLatin1String(".com") || ext == QLatin1String(".bat") || - ext == QLatin1String(".pif") || ext == QLatin1String(".cmd")) { - ret |= QAbstractFileEngine::ExeOwnerPerm | QAbstractFileEngine::ExeGroupPerm - | QAbstractFileEngine::ExeOtherPerm | QAbstractFileEngine::ExeUserPerm; - } + queryFlags |= QFileSystemMetaData::MetaDataFlags(uint(type)) + & QFileSystemMetaData::Permissions; - // calculate user permissions - if (type & QAbstractFileEngine::ReadUserPerm) { - if (::_waccess((wchar_t*)longFileName(fname).utf16(), R_OK) == 0) - ret |= QAbstractFileEngine::ReadUserPerm; - } - if (type & QAbstractFileEngine::WriteUserPerm) { - if (::_waccess((wchar_t*)longFileName(fname).utf16(), W_OK) == 0) - ret |= QAbstractFileEngine::WriteUserPerm; - } - } - return ret; -} + // AliasType and BundleType are 0x0 + if (type & TypesMask) + queryFlags |= QFileSystemMetaData::AliasType + | QFileSystemMetaData::LinkType + | QFileSystemMetaData::FileType + | QFileSystemMetaData::DirectoryType + | QFileSystemMetaData::BundleType; -/*! - \internal -*/ -bool QFSFileEnginePrivate::isSymlink() const -{ -#if !defined(Q_OS_WINCE) - if (need_lstat) { - need_lstat = false; - is_link = false; - - if (fileAttrib & FILE_ATTRIBUTE_REPARSE_POINT) { - QString path = QDir::toNativeSeparators(filePath); - // path for the FindFirstFile should not end with a trailing slash - while (path.endsWith(QLatin1Char('\\'))) - path.chop(1); - - WIN32_FIND_DATA findData; - HANDLE hFind = ::FindFirstFile((wchar_t*)QFSFileEnginePrivate::longFileName(path).utf16(), - &findData); - if (hFind != INVALID_HANDLE_VALUE) { - ::FindClose(hFind); - if ((findData.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) - && (findData.dwReserved0 == IO_REPARSE_TAG_SYMLINK || findData.dwReserved0 == IO_REPARSE_TAG_MOUNT_POINT)) { - is_link = true; - } - } - } - } - return is_link; -#else - return false; -#endif // Q_OS_WINCE -} + if (type & FlagsMask) + queryFlags |= QFileSystemMetaData::HiddenAttribute + | QFileSystemMetaData::ExistsAttribute; -/*! - \reimp -*/ -QAbstractFileEngine::FileFlags QFSFileEngine::fileFlags(QAbstractFileEngine::FileFlags type) const -{ - Q_D(const QFSFileEngine); - QAbstractFileEngine::FileFlags ret = 0; - // Force a stat, so that we're guaranteed to get up-to-date results - if (type & Refresh) { - d->tried_stat = 0; -#if !defined(Q_OS_WINCE) - d->need_lstat = 1; -#endif - } + queryFlags |= QFileSystemMetaData::LinkType; - if (type & PermsMask) { - if (d->doStat()) { - ret |= ExistsFlag; - ret |= d->getPermissions(type); - } + exists = d->doStat(queryFlags); } + + if (exists && (type & PermsMask)) + ret |= FileFlags(uint(d->metaData.permissions())); + if (type & TypesMask) { - if (d->filePath.endsWith(QLatin1String(".lnk"))) { + if ((type & LinkType) && d->metaData.isLegacyLink()) ret |= LinkType; - QString l = readLink(d->filePath); - if (!l.isEmpty()) { - bool existed = false; - if (isDirPath(l, &existed) && existed) - ret |= DirectoryType; - else if (existed) - ret |= FileType; - } - } else if (d->doStat()) { - if ((type & LinkType) && d->isSymlink()) - ret |= LinkType; - if (d->fileAttrib & FILE_ATTRIBUTE_DIRECTORY) { - ret |= DirectoryType; - } else { - ret |= FileType; - } + if (d->metaData.isDirectory()) { + ret |= DirectoryType; + } else { + ret |= FileType; } } if (type & FlagsMask) { - ret |= LocalDiskFlag; - if (d->doStat()) { + if (d->metaData.exists()) { ret |= ExistsFlag; - if (d->filePath == QLatin1String("/") || isDriveRoot(d->filePath) || isUncRoot(d->filePath)) + if (d->fileEntry.isRoot()) ret |= RootFlag; - else if (d->fileAttrib & FILE_ATTRIBUTE_HIDDEN) + else if (d->metaData.isHidden()) ret |= HiddenFlag; } } @@ -1652,50 +746,28 @@ QString QFSFileEngine::fileName(FileName file) const { Q_D(const QFSFileEngine); if (file == BaseName) { - int slash = d->filePath.lastIndexOf(QLatin1Char('/')); - if (slash == -1) { - int colon = d->filePath.lastIndexOf(QLatin1Char(':')); - if (colon != -1) - return d->filePath.mid(colon + 1); - return d->filePath; - } - return d->filePath.mid(slash + 1); + return d->fileEntry.fileName(); } else if (file == PathName) { - if (!d->filePath.size()) - return d->filePath; - - int slash = d->filePath.lastIndexOf(QLatin1Char('/')); - if (slash == -1) { - if (d->filePath.length() >= 2 && d->filePath.at(1) == QLatin1Char(':')) - return d->filePath.left(2); - return QString(QLatin1Char('.')); - } else { - if (!slash) - return QString(QLatin1Char('/')); - if (slash == 2 && d->filePath.length() >= 2 && d->filePath.at(1) == QLatin1Char(':')) - slash++; - return d->filePath.left(slash); - } + return d->fileEntry.path(); } else if (file == AbsoluteName || file == AbsolutePathName) { QString ret; if (!isRelativePath()) { #if !defined(Q_OS_WINCE) - if (d->filePath.startsWith(QLatin1Char('/')) || // It's a absolute path to the current drive, so \a.txt -> Z:\a.txt - d->filePath.size() == 2 || // It's a drive letter that needs to get a working dir appended - (d->filePath.size() > 2 && d->filePath.at(2) != QLatin1Char('/')) || // It's a drive-relative path, so Z:a.txt -> Z:\currentpath\a.txt - d->filePath.contains(QLatin1String("/../")) || d->filePath.contains(QLatin1String("/./")) || - d->filePath.endsWith(QLatin1String("/..")) || d->filePath.endsWith(QLatin1String("/."))) + if (d->fileEntry.filePath().startsWith(QLatin1Char('/')) || // It's a absolute path to the current drive, so \a.txt -> Z:\a.txt + d->fileEntry.filePath().size() == 2 || // It's a drive letter that needs to get a working dir appended + (d->fileEntry.filePath().size() > 2 && d->fileEntry.filePath().at(2) != QLatin1Char('/')) || // It's a drive-relative path, so Z:a.txt -> Z:\currentpath\a.txt + d->fileEntry.filePath().contains(QLatin1String("/../")) || d->fileEntry.filePath().contains(QLatin1String("/./")) || + d->fileEntry.filePath().endsWith(QLatin1String("/..")) || d->fileEntry.filePath().endsWith(QLatin1String("/."))) { - ret = QDir::fromNativeSeparators(nativeAbsoluteFilePath(d->filePath)); - } else { - ret = d->filePath; - } -#else - ret = d->filePath; + ret = QDir::fromNativeSeparators(QFileSystemEngine::nativeAbsoluteFilePath(d->fileEntry.filePath())); + } else #endif + { + ret = d->fileEntry.filePath(); + } } else { - ret = QDir::cleanPath(QDir::currentPath() + QLatin1Char('/') + d->filePath); + ret = QDir::cleanPath(QDir::currentPath() + QLatin1Char('/') + d->fileEntry.filePath()); } // The path should be absolute at this point. @@ -1724,38 +796,24 @@ QString QFSFileEngine::fileName(FileName file) const } else if (file == CanonicalName || file == CanonicalPathName) { if (!(fileFlags(ExistsFlag) & ExistsFlag)) return QString(); + QFileSystemEntry entry(QFileSystemEngine::canonicalName(QFileSystemEntry(fileName(AbsoluteName)), d->metaData)); - QString ret = QFSFileEnginePrivate::canonicalized(fileName(AbsoluteName)); - if (!ret.isEmpty() && file == CanonicalPathName) { - int slash = ret.lastIndexOf(QLatin1Char('/')); - if (slash == -1) - ret = QDir::currentPath(); - else if (slash == 0) - ret = QString(QLatin1Char('/')); - ret = ret.left(slash); - } - return ret; + if (file == CanonicalPathName) + return entry.path(); + return entry.filePath(); } else if (file == LinkName) { - QString ret; - if (d->filePath.endsWith(QLatin1String(".lnk"))) - ret = readLink(d->filePath); - else if (d->doStat() && d->isSymlink()) - ret = readSymLink(d->filePath); - return QDir::fromNativeSeparators(ret); + return QFileSystemEngine::getLinkTarget(d->fileEntry, d->metaData).filePath(); } else if (file == BundleName) { return QString(); } - return d->filePath; + return d->fileEntry.filePath(); } bool QFSFileEngine::isRelativePath() const { Q_D(const QFSFileEngine); // drive, e.g. "a:", or UNC root, e.q. "//" - return !(d->filePath.startsWith(QLatin1Char('/')) - || (d->filePath.length() >= 2 - && ((d->filePath.at(0).isLetter() && d->filePath.at(1) == QLatin1Char(':')) - || (d->filePath.at(0) == QLatin1Char('/') && d->filePath.at(1) == QLatin1Char('/'))))); + return d->fileEntry.isRelative(); } uint QFSFileEngine::ownerId(FileOwner /*own*/) const @@ -1766,69 +824,17 @@ uint QFSFileEngine::ownerId(FileOwner /*own*/) const QString QFSFileEngine::owner(FileOwner own) const { - QString name; -#if !defined(QT_NO_LIBRARY) Q_D(const QFSFileEngine); - if((qt_ntfs_permission_lookup > 0) && (QSysInfo::WindowsVersion & QSysInfo::WV_NT_based)) { - QFSFileEnginePrivate::resolveLibs(); - if (ptrGetNamedSecurityInfoW && ptrLookupAccountSidW) { - PSID pOwner = 0; - PSECURITY_DESCRIPTOR pSD; - if (ptrGetNamedSecurityInfoW((wchar_t*)d->filePath.utf16(), SE_FILE_OBJECT, - own == OwnerGroup ? GROUP_SECURITY_INFORMATION : OWNER_SECURITY_INFORMATION, - own == OwnerUser ? &pOwner : 0, own == OwnerGroup ? &pOwner : 0, - 0, 0, &pSD) == ERROR_SUCCESS) { - DWORD lowner = 64; - DWORD ldomain = 64; - QVarLengthArray<wchar_t, 64> owner(lowner); - QVarLengthArray<wchar_t, 64> domain(ldomain); - SID_NAME_USE use = SidTypeUnknown; - // First call, to determine size of the strings (with '\0'). - if (!ptrLookupAccountSidW(NULL, pOwner, (LPWSTR)owner.data(), &lowner, - (LPWSTR)domain.data(), &ldomain, (SID_NAME_USE*)&use)) { - if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { - if (lowner > (DWORD)owner.size()) - owner.resize(lowner); - if (ldomain > (DWORD)domain.size()) - domain.resize(ldomain); - // Second call, try on resized buf-s - if (!ptrLookupAccountSidW(NULL, pOwner, (LPWSTR)owner.data(), &lowner, - (LPWSTR)domain.data(), &ldomain, (SID_NAME_USE*)&use)) { - lowner = 0; - } - } else { - lowner = 0; - } - } - if (lowner != 0) - name = QString::fromWCharArray(owner.data()); - LocalFree(pSD); - } - } - } -#else - Q_UNUSED(own); -#endif - return name; + return QFileSystemEngine::owner(d->fileEntry, own); } bool QFSFileEngine::setPermissions(uint perms) { Q_D(QFSFileEngine); - bool ret = false; - int mode = 0; - - if (perms & QFile::ReadOwner || perms & QFile::ReadUser || perms & QFile::ReadGroup || perms & QFile::ReadOther) - mode |= _S_IREAD; - if (perms & QFile::WriteOwner || perms & QFile::WriteUser || perms & QFile::WriteGroup || perms & QFile::WriteOther) - mode |= _S_IWRITE; - - if (mode == 0) // not supported - return false; - - ret = ::_wchmod((wchar_t*)QFSFileEnginePrivate::longFileName(d->filePath).utf16(), mode) == 0; + QSystemError error; + bool ret = QFileSystemEngine::setPermissions(d->fileEntry, QFile::Permissions(perms), error); if (!ret) - setError(QFile::PermissionsError, qt_error_string(errno)); + setError(QFile::PermissionsError, error.toString()); return ret; } @@ -1836,12 +842,16 @@ bool QFSFileEngine::setSize(qint64 size) { Q_D(QFSFileEngine); - if (d->fileHandle != INVALID_HANDLE_VALUE || d->fd != -1) { + if (d->fileHandle != INVALID_HANDLE_VALUE || d->fd != -1 || d->fh) { // resize open file HANDLE fh = d->fileHandle; #if !defined(Q_OS_WINCE) - if (fh == INVALID_HANDLE_VALUE) - fh = (HANDLE)_get_osfhandle(d->fd); + if (fh == INVALID_HANDLE_VALUE) { + if (d->fh) + fh = (HANDLE)_get_osfhandle(QT_FILENO(d->fh)); + else + fh = (HANDLE)_get_osfhandle(d->fd); + } #endif if (fh == INVALID_HANDLE_VALUE) return false; @@ -1856,9 +866,9 @@ bool QFSFileEngine::setSize(qint64 size) return false; } - if (!d->nativeFilePath.isEmpty()) { + if (!d->fileEntry.isEmpty()) { // resize file on disk - QFile file(d->filePath); + QFile file(d->fileEntry.filePath()); if (file.open(QFile::ReadWrite)) { bool ret = file.resize(size); if (!ret) @@ -1870,94 +880,14 @@ bool QFSFileEngine::setSize(qint64 size) } -static inline QDateTime fileTimeToQDateTime(const FILETIME *time) -{ - QDateTime ret; - -#if defined(Q_OS_WINCE) - SYSTEMTIME systime; - FILETIME ftime; - systime.wYear = 1970; - systime.wMonth = 1; - systime.wDay = 1; - systime.wHour = 0; - systime.wMinute = 0; - systime.wSecond = 0; - systime.wMilliseconds = 0; - systime.wDayOfWeek = 4; - SystemTimeToFileTime(&systime, &ftime); - unsigned __int64 acttime = (unsigned __int64)time->dwHighDateTime << 32 | time->dwLowDateTime; - FileTimeToSystemTime(time, &systime); - unsigned __int64 time1970 = (unsigned __int64)ftime.dwHighDateTime << 32 | ftime.dwLowDateTime; - unsigned __int64 difftime = acttime - time1970; - difftime /= 10000000; - ret.setTime_t((unsigned int)difftime); -#else - SYSTEMTIME sTime, lTime; - FileTimeToSystemTime(time, &sTime); - SystemTimeToTzSpecificLocalTime(0, &sTime, &lTime); - ret.setDate(QDate(lTime.wYear, lTime.wMonth, lTime.wDay)); - ret.setTime(QTime(lTime.wHour, lTime.wMinute, lTime.wSecond, lTime.wMilliseconds)); -#endif - - return ret; -} - QDateTime QFSFileEngine::fileTime(FileTime time) const { Q_D(const QFSFileEngine); - QDateTime ret; - if (d->fd != -1) { -#if !defined(Q_OS_WINCE) - HANDLE fh = (HANDLE)_get_osfhandle(d->fd); - if (fh != INVALID_HANDLE_VALUE) { - FILETIME creationTime, lastAccessTime, lastWriteTime; - if (GetFileTime(fh, &creationTime, &lastAccessTime, &lastWriteTime)) { - if(time == CreationTime) - ret = fileTimeToQDateTime(&creationTime); - else if(time == ModificationTime) - ret = fileTimeToQDateTime(&lastWriteTime); - else if(time == AccessTime) - ret = fileTimeToQDateTime(&lastAccessTime); - } - } -#endif - } else { - WIN32_FILE_ATTRIBUTE_DATA attribData; - bool ok = ::GetFileAttributesEx((wchar_t*)QFSFileEnginePrivate::longFileName(d->filePath).utf16(), GetFileExInfoStandard, &attribData); - if (!ok) { - int errorCode = GetLastError(); - if (errorCode == ERROR_ACCESS_DENIED || errorCode == ERROR_SHARING_VIOLATION) { - QString path = QDir::toNativeSeparators(d->filePath); - // path for the FindFirstFile should not end with a trailing slash - while (path.endsWith(QLatin1Char('\\'))) - path.chop(1); - - // FindFirstFile can not handle drives - if (!path.endsWith(QLatin1Char(':'))) { - WIN32_FIND_DATA findData; - HANDLE hFind = ::FindFirstFile((wchar_t*)QFSFileEnginePrivate::longFileName(path).utf16(), - &findData); - if (hFind != INVALID_HANDLE_VALUE) { - ::FindClose(hFind); - ok = true; - attribData.ftCreationTime = findData.ftCreationTime; - attribData.ftLastWriteTime = findData.ftLastWriteTime; - attribData.ftLastAccessTime = findData.ftLastAccessTime; - } - } - } - } - if (ok) { - if(time == CreationTime) - ret = fileTimeToQDateTime(&attribData.ftCreationTime); - else if(time == ModificationTime) - ret = fileTimeToQDateTime(&attribData.ftLastWriteTime); - else if(time == AccessTime) - ret = fileTimeToQDateTime(&attribData.ftLastAccessTime); - } - } - return ret; + + if (d->doStat(QFileSystemMetaData::Times)) + return d->metaData.fileTime(time); + + return QDateTime(); } uchar *QFSFileEnginePrivate::map(qint64 offset, qint64 size, @@ -1986,7 +916,7 @@ uchar *QFSFileEnginePrivate::map(qint64 offset, qint64 size, #ifdef Q_USE_DEPRECATED_MAP_API nativeClose(); // handle automatically closed by kernel with mapHandle (below). - handle = ::CreateFileForMapping((const wchar_t*)nativeFilePath.constData(), + handle = ::CreateFileForMapping((const wchar_t*)fileEntry.nativeFilePath().utf16(), GENERIC_READ | (openMode & QIODevice::WriteOnly ? GENERIC_WRITE : 0), 0, NULL, diff --git a/src/corelib/io/qtemporaryfile.cpp b/src/corelib/io/qtemporaryfile.cpp index c34c4a4..79dfa35 100644 --- a/src/corelib/io/qtemporaryfile.cpp +++ b/src/corelib/io/qtemporaryfile.cpp @@ -295,7 +295,7 @@ public: : QFSFileEngine(), filePathIsTemplate(fileIsTemplate) { Q_D(QFSFileEngine); - d->filePath = file; + d->fileEntry = QFileSystemEntry(file); if (!filePathIsTemplate) QFSFileEngine::setFileName(file); @@ -325,6 +325,9 @@ bool QTemporaryFileEngine::isReallyOpen() Q_D(QFSFileEngine); if (!((0 == d->fh) && (-1 == d->fd) +#if defined (Q_OS_SYMBIAN) + && (0 == d->symbianFile.SubSessionHandle()) +#endif #if defined Q_OS_WIN && (INVALID_HANDLE_VALUE == d->fileHandle) #endif @@ -346,7 +349,7 @@ void QTemporaryFileEngine::setFileTemplate(const QString &fileTemplate) { Q_D(QFSFileEngine); if (filePathIsTemplate) - d->filePath = fileTemplate; + d->fileEntry = QFileSystemEntry(fileTemplate); } bool QTemporaryFileEngine::open(QIODevice::OpenMode openMode) @@ -359,7 +362,7 @@ bool QTemporaryFileEngine::open(QIODevice::OpenMode openMode) if (!filePathIsTemplate) return QFSFileEngine::open(openMode); - QString qfilename = d->filePath; + QString qfilename = d->fileEntry.filePath(); if(!qfilename.contains(QLatin1String("XXXXXX"))) qfilename += QLatin1String(".XXXXXX"); @@ -377,9 +380,8 @@ bool QTemporaryFileEngine::open(QIODevice::OpenMode openMode) d->closeFileHandle = true; // Restore the file names (open() resets them). - d->filePath = QString::fromLocal8Bit(filename); //changed now! + d->fileEntry = QFileSystemEntry(QString::fromLocal8Bit(filename)); //note that filename is NOT a native path filePathIsTemplate = false; - d->nativeInitFileName(); delete [] filename; return true; } @@ -395,9 +397,8 @@ bool QTemporaryFileEngine::open(QIODevice::OpenMode openMode) return false; } - QString template_ = d->filePath; - d->filePath = QString::fromLocal8Bit(filename); - d->nativeInitFileName(); + QString template_ = d->fileEntry.filePath(); + d->fileEntry = QFileSystemEntry(QString::fromLocal8Bit(filename)); delete [] filename; if (QFSFileEngine::open(openMode)) { @@ -405,8 +406,7 @@ bool QTemporaryFileEngine::open(QIODevice::OpenMode openMode) return true; } - d->filePath = template_; - d->nativeFilePath.clear(); + d->fileEntry = QFileSystemEntry(template_); return false; #endif } @@ -418,7 +418,7 @@ bool QTemporaryFileEngine::remove() // we must explicitly call QFSFileEngine::close() before we remove it. QFSFileEngine::close(); if (QFSFileEngine::remove()) { - d->filePath.clear(); + d->fileEntry.clear(); return true; } return false; diff --git a/src/corelib/kernel/kernel.pri b/src/corelib/kernel/kernel.pri index 1e27c31..93818d1 100644 --- a/src/corelib/kernel/kernel.pri +++ b/src/corelib/kernel/kernel.pri @@ -1,81 +1,83 @@ # Qt core object module HEADERS += \ - kernel/qabstracteventdispatcher.h \ + kernel/qabstracteventdispatcher.h \ kernel/qabstractitemmodel.h \ kernel/qabstractitemmodel_p.h \ - kernel/qbasictimer.h \ - kernel/qeventloop.h\ - kernel/qpointer.h \ + kernel/qbasictimer.h \ + kernel/qeventloop.h\ + kernel/qpointer.h \ kernel/qcorecmdlineargs_p.h \ - kernel/qcoreapplication.h \ - kernel/qcoreevent.h \ - kernel/qmetaobject.h \ - kernel/qmetatype.h \ - kernel/qmimedata.h \ - kernel/qobject.h \ - kernel/qobjectdefs.h \ - kernel/qsignalmapper.h \ - kernel/qsocketnotifier.h \ - kernel/qtimer.h \ - kernel/qtranslator.h \ + kernel/qcoreapplication.h \ + kernel/qcoreevent.h \ + kernel/qmetaobject.h \ + kernel/qmetatype.h \ + kernel/qmimedata.h \ + kernel/qobject.h \ + kernel/qobjectdefs.h \ + kernel/qsignalmapper.h \ + kernel/qsocketnotifier.h \ + kernel/qtimer.h \ + kernel/qtranslator.h \ kernel/qtranslator_p.h \ kernel/qvariant.h \ - kernel/qabstracteventdispatcher_p.h \ - kernel/qcoreapplication_p.h \ - kernel/qobjectcleanuphandler.h \ + kernel/qabstracteventdispatcher_p.h \ + kernel/qcoreapplication_p.h \ + kernel/qobjectcleanuphandler.h \ kernel/qvariant_p.h \ kernel/qmetaobject_p.h \ kernel/qobject_p.h \ - kernel/qcoreglobaldata_p.h \ - kernel/qsharedmemory.h \ + kernel/qcoreglobaldata_p.h \ + kernel/qsharedmemory.h \ kernel/qsharedmemory_p.h \ kernel/qsystemsemaphore.h \ kernel/qsystemsemaphore_p.h \ kernel/qfunctions_p.h \ - kernel/qmath.h + kernel/qmath.h \ + kernel/qsystemerror_p.h SOURCES += \ - kernel/qabstracteventdispatcher.cpp \ + kernel/qabstracteventdispatcher.cpp \ kernel/qabstractitemmodel.cpp \ - kernel/qbasictimer.cpp \ - kernel/qeventloop.cpp \ - kernel/qcoreapplication.cpp \ - kernel/qcoreevent.cpp \ - kernel/qmetaobject.cpp \ - kernel/qmetatype.cpp \ - kernel/qmimedata.cpp \ - kernel/qobject.cpp \ - kernel/qobjectcleanuphandler.cpp \ - kernel/qsignalmapper.cpp \ - kernel/qsocketnotifier.cpp \ - kernel/qtimer.cpp \ - kernel/qtranslator.cpp \ - kernel/qvariant.cpp \ + kernel/qbasictimer.cpp \ + kernel/qeventloop.cpp \ + kernel/qcoreapplication.cpp \ + kernel/qcoreevent.cpp \ + kernel/qmetaobject.cpp \ + kernel/qmetatype.cpp \ + kernel/qmimedata.cpp \ + kernel/qobject.cpp \ + kernel/qobjectcleanuphandler.cpp \ + kernel/qsignalmapper.cpp \ + kernel/qsocketnotifier.cpp \ + kernel/qtimer.cpp \ + kernel/qtranslator.cpp \ + kernel/qvariant.cpp \ kernel/qcoreglobaldata.cpp \ kernel/qsharedmemory.cpp \ kernel/qsystemsemaphore.cpp \ kernel/qpointer.cpp \ - kernel/qmath.cpp + kernel/qmath.cpp \ + kernel/qsystemerror.cpp win32 { - SOURCES += \ - kernel/qeventdispatcher_win.cpp \ - kernel/qcoreapplication_win.cpp \ - kernel/qwineventnotifier_p.cpp \ + SOURCES += \ + kernel/qeventdispatcher_win.cpp \ + kernel/qcoreapplication_win.cpp \ + kernel/qwineventnotifier_p.cpp \ kernel/qsharedmemory_win.cpp \ kernel/qsystemsemaphore_win.cpp - HEADERS += \ - kernel/qeventdispatcher_win_p.h \ - kernel/qwineventnotifier_p.h + HEADERS += \ + kernel/qeventdispatcher_win_p.h \ + kernel/qwineventnotifier_p.h } wince*: { - SOURCES += \ - kernel/qfunctions_wince.cpp - HEADERS += \ - kernel/qfunctions_wince.h + SOURCES += \ + kernel/qfunctions_wince.cpp + HEADERS += \ + kernel/qfunctions_wince.h } mac:!embedded:!qpa{ @@ -85,18 +87,18 @@ mac:!embedded:!qpa{ mac:!nacl { SOURCES += \ - kernel/qcore_mac.cpp + kernel/qcore_mac.cpp } unix:!symbian { - SOURCES += \ + SOURCES += \ kernel/qcore_unix.cpp \ kernel/qcrashhandler.cpp \ kernel/qsharedmemory_unix.cpp \ kernel/qsystemsemaphore_unix.cpp - HEADERS += \ + HEADERS += \ kernel/qcore_unix_p.h \ - kernel/qcrashhandler_p.h + kernel/qcrashhandler_p.h contains(QT_CONFIG, glib) { SOURCES += \ @@ -115,7 +117,7 @@ unix:!symbian { } symbian { - SOURCES += \ + SOURCES += \ kernel/qcore_unix.cpp \ kernel/qcrashhandler.cpp \ kernel/qeventdispatcher_symbian.cpp \ @@ -123,7 +125,7 @@ symbian { kernel/qsharedmemory_symbian.cpp \ kernel/qsystemsemaphore_symbian.cpp - HEADERS += \ + HEADERS += \ kernel/qcore_unix_p.h \ kernel/qcrashhandler_p.h \ kernel/qeventdispatcher_symbian_p.h \ @@ -131,9 +133,9 @@ symbian { } vxworks { - SOURCES += \ - kernel/qfunctions_vxworks.cpp - HEADERS += \ - kernel/qfunctions_vxworks.h + SOURCES += \ + kernel/qfunctions_vxworks.cpp + HEADERS += \ + kernel/qfunctions_vxworks.h } diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index a8dc491..0f95ee0 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -71,6 +71,7 @@ # include <e32ldr.h> # include "qeventdispatcher_symbian_p.h" # include "private/qcore_symbian_p.h" +# include "private/qfilesystemengine_p.h" #elif defined(Q_OS_UNIX) # if !defined(QT_NO_GLIB) # include "qeventdispatcher_glib_p.h" @@ -567,6 +568,12 @@ void QCoreApplication::init() Q_ASSERT_X(!self, "QCoreApplication", "there should be only one application object"); QCoreApplication::self = this; +#ifdef Q_OS_SYMBIAN + //ensure temp and working directories exist + QFileSystemEngine::createDirectory(QFileSystemEntry(QFileSystemEngine::tempPath()), true); + QFileSystemEngine::createDirectory(QFileSystemEntry(QFileSystemEngine::currentPath()), true); +#endif + #ifndef QT_NO_THREAD QThread::initialize(); #endif diff --git a/src/corelib/kernel/qsystemerror.cpp b/src/corelib/kernel/qsystemerror.cpp new file mode 100644 index 0000000..953ed95 --- /dev/null +++ b/src/corelib/kernel/qsystemerror.cpp @@ -0,0 +1,220 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <qglobal.h> +#include "qsystemerror_p.h" +#if !defined(Q_OS_WINCE) +# include <errno.h> +# if defined(Q_CC_MSVC) +# include <crtdbg.h> +# endif +#endif +#ifdef Q_OS_WIN +#include <windows.h> +#endif + +QT_BEGIN_NAMESPACE + +#if !defined(Q_OS_WIN) && !defined(QT_NO_THREAD) && !defined(Q_OS_INTEGRITY) && !defined(Q_OS_QNX) && \ + defined(_POSIX_THREAD_SAFE_FUNCTIONS) && _POSIX_VERSION >= 200112L +namespace { + // There are two incompatible versions of strerror_r: + // a) the XSI/POSIX.1 version, which returns an int, + // indicating success or not + // b) the GNU version, which returns a char*, which may or may not + // be the beginning of the buffer we used + // The GNU libc manpage for strerror_r says you should use the the XSI + // version in portable code. However, it's impossible to do that if + // _GNU_SOURCE is defined so we use C++ overloading to decide what to do + // depending on the return type + static inline QString fromstrerror_helper(int, const QByteArray &buf) + { + return QString::fromLocal8Bit(buf); + } + static inline QString fromstrerror_helper(const char *str, const QByteArray &) + { + return QString::fromLocal8Bit(str); + } +} +#endif + +static QString standardLibraryErrorString(int errorCode) +{ + const char *s = 0; + QString ret; + switch (errorCode) { + case 0: + break; + case EACCES: + s = QT_TRANSLATE_NOOP("QIODevice", "Permission denied"); + break; + case EMFILE: + s = QT_TRANSLATE_NOOP("QIODevice", "Too many open files"); + break; + case ENOENT: + s = QT_TRANSLATE_NOOP("QIODevice", "No such file or directory"); + break; + case ENOSPC: + s = QT_TRANSLATE_NOOP("QIODevice", "No space left on device"); + break; + default: { + #if !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && _POSIX_VERSION >= 200112L && !defined(Q_OS_INTEGRITY) && !defined(Q_OS_QNX) + QByteArray buf(1024, '\0'); + ret = fromstrerror_helper(strerror_r(errorCode, buf.data(), buf.size()), buf); + #else + ret = QString::fromLocal8Bit(strerror(errorCode)); + #endif + break; } + } + if (s) { + // ######## this breaks moc build currently + // ret = QCoreApplication::translate("QIODevice", s); + ret = QString::fromLatin1(s); + } + return ret.trimmed(); +} + +#ifdef Q_OS_WIN +static QString windowsErrorString(int errorCode) +{ + QString ret; + wchar_t *string = 0; + FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM, + NULL, + errorCode, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPWSTR)&string, + 0, + NULL); + ret = QString::fromWCharArray(string); + LocalFree((HLOCAL)string); + + if (ret.isEmpty() && errorCode == ERROR_MOD_NOT_FOUND) + ret = QString::fromLatin1("The specified module could not be found."); + return ret; +} +#endif + +#ifdef Q_OS_SYMBIAN +static QString symbianErrorString(int errorCode) +{ + switch (errorCode) { + case KErrNotFound: + return QLatin1String("not found"); + case KErrCancel: + return QLatin1String("cancelled"); + case KErrNoMemory: + return QLatin1String("out of memory"); + case KErrNotSupported: + return QLatin1String("not supported"); + case KErrBadHandle: + return QLatin1String("bad handle"); //KERN-EXEC 0 panic is more likely + case KErrAlreadyExists: + return QLatin1String("already exists"); + case KErrPathNotFound: + return QLatin1String("path not found"); + case KErrInUse: + return QLatin1String("in use"); + case KErrNotReady: + return QLatin1String("not ready (e.g. FS dismounted, no memory card)"); + case KErrCorrupt: + return QLatin1String("corrupt"); + case KErrAccessDenied: + return QLatin1String("access denied"); + case KErrLocked: + return QLatin1String("locked"); + case KErrWrite: + return QLatin1String("incomplete write error"); + case KErrDisMounted: + return QLatin1String("file system dismounted during operation"); //i.e. a forcible dismount was done while we had files open + case KErrEof: + return QLatin1String("end of file"); + case KErrDiskFull: + return QLatin1String("no space in file system"); + case KErrBadName: + return QLatin1String("invalid filename"); + case KErrTimedOut: + return QLatin1String("timed out"); + case KErrBadDescriptor: + return QLatin1String("bad descriptor (passed address on stack to async call?)"); + case KErrAbort: + return QLatin1String("aborted"); + case KErrTooBig: + return QLatin1String("too big"); //e.g. trying to open a >2GB file with 32 bit API + case KErrBadPower: + return QLatin1String("insufficient power"); + case KErrDirFull: + return QLatin1String("no space in directory table"); + case KErrHardwareNotAvailable: + return QLatin1String("hardware not available"); + case KErrSessionClosed: + return QLatin1String("session closed"); + case KErrPermissionDenied: + return QLatin1String("permission denied"); + default: + return QString(QLatin1String("symbian error %d")).arg(errorCode); + } +} +#endif + +QString QSystemError::toString() +{ + switch(errorScope) { + case NativeError: +#if defined (Q_OS_WIN) + return windowsErrorString(errorCode); +#elif defined (Q_OS_SYMBIAN) + return symbianErrorString(errorCode); +#else + //unix: fall through as native and standard library are the same +#endif + case StandardLibraryError: + return standardLibraryErrorString(errorCode); + default: + qWarning("invalid error scope"); + //fall through + case NoError: + return QLatin1String("No error"); + } +} + +QT_END_NAMESPACE + diff --git a/src/corelib/kernel/qsystemerror_p.h b/src/corelib/kernel/qsystemerror_p.h new file mode 100644 index 0000000..c2a13a8 --- /dev/null +++ b/src/corelib/kernel/qsystemerror_p.h @@ -0,0 +1,107 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QSYSTEMERROR_P_H +#define QSYSTEMERROR_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <qstring.h> + +QT_BEGIN_NAMESPACE + +class Q_CORE_EXPORT QSystemError +{ +public: + enum ErrorScope + { + NoError, + StandardLibraryError, + NativeError + }; + + inline QSystemError(int error, ErrorScope scope); + inline QSystemError(); + + QString toString(); + inline ErrorScope scope(); + inline int error(); + + //data members + int errorCode; + ErrorScope errorScope; +}; + +QSystemError::QSystemError(int error, QSystemError::ErrorScope scope) +: errorCode(error), errorScope(scope) +{ + +} + +QSystemError::QSystemError() +: errorCode(0), errorScope(NoError) +{ + +} + +QSystemError::ErrorScope QSystemError::scope() +{ + return errorScope; +} + +int QSystemError::error() +{ + return errorCode; +} + + +QT_END_NAMESPACE + +#endif // QSYSTEMERROR_P_H diff --git a/src/corelib/tools/qdatetime.cpp b/src/corelib/tools/qdatetime.cpp index c252e64..6a20c7a 100644 --- a/src/corelib/tools/qdatetime.cpp +++ b/src/corelib/tools/qdatetime.cpp @@ -5838,6 +5838,41 @@ bool operator==(const QDateTimeParser::SectionNode &s1, const QDateTimeParser::S return (s1.type == s2.type) && (s1.pos == s2.pos) && (s1.count == s2.count); } +#ifdef Q_OS_SYMBIAN +const static TTime UnixEpochOffset(I64LIT(0xdcddb30f2f8000)); +const static TInt64 MinimumMillisecondTime(KMinTInt64 / 1000); +const static TInt64 MaximumMillisecondTime(KMaxTInt64 / 1000); +QDateTime qt_symbian_TTime_To_QDateTime(const TTime& time) +{ + TTimeIntervalMicroSeconds absolute = time.MicroSecondsFrom(UnixEpochOffset); + + return QDateTime::fromMSecsSinceEpoch(absolute.Int64() / 1000); +} + +TTime qt_symbian_QDateTime_To_TTime(const QDateTime& datetime) +{ + qint64 absolute = datetime.toMSecsSinceEpoch(); + if(absolute > MaximumMillisecondTime) + return TTime(KMaxTInt64); + if(absolute < MinimumMillisecondTime) + return TTime(KMinTInt64); + return TTime(absolute * 1000); +} + +time_t qt_symbian_TTime_To_time_t(const TTime& time) +{ + TTimeIntervalSeconds interval; + TInt err = time.SecondsFrom(UnixEpochOffset, interval); + if (err || interval.Int() < 0) + return (time_t) 0; + return (time_t) interval.Int(); +} + +TTime qt_symbian_time_t_To_TTime(time_t time) +{ + return UnixEpochOffset + TTimeIntervalSeconds(time); +} +#endif //Q_OS_SYMBIAN #endif // QT_BOOTSTRAPPED diff --git a/src/corelib/tools/qdatetime_p.h b/src/corelib/tools/qdatetime_p.h index f10785e..8355ef7 100644 --- a/src/corelib/tools/qdatetime_p.h +++ b/src/corelib/tools/qdatetime_p.h @@ -275,6 +275,12 @@ Q_CORE_EXPORT bool operator==(const QDateTimeParser::SectionNode &s1, const QDat Q_DECLARE_OPERATORS_FOR_FLAGS(QDateTimeParser::Sections) Q_DECLARE_OPERATORS_FOR_FLAGS(QDateTimeParser::FieldInfo) +#ifdef Q_OS_SYMBIAN +QDateTime qt_symbian_TTime_To_QDateTime(const TTime& time); +TTime qt_symbian_QDateTime_To_TTime(const QDateTime& datetime); +time_t qt_symbian_TTime_To_time_t(const TTime& time); +TTime qt_symbian_time_t_To_TTime(time_t time); +#endif //Q_OS_SYMBIAN #endif // QT_BOOTSTRAPPED diff --git a/src/declarative/qml/qdeclarativeglobal_p.h b/src/declarative/qml/qdeclarativeglobal_p.h index 31fbb1e..b8428b8 100644 --- a/src/declarative/qml/qdeclarativeglobal_p.h +++ b/src/declarative/qml/qdeclarativeglobal_p.h @@ -65,7 +65,7 @@ QT_MODULE(Declarative) } #ifdef Q_OS_SYMBIAN -#define Q_DECLARATIVE_PRIVATE_EXPORT +#define Q_DECLARATIVE_PRIVATE_EXPORT Q_AUTOTEST_EXPORT #else #define Q_DECLARATIVE_PRIVATE_EXPORT Q_DECLARATIVE_EXPORT #endif diff --git a/src/gui/dialogs/qfilesystemmodel.cpp b/src/gui/dialogs/qfilesystemmodel.cpp index 5002beb..6552370 100644 --- a/src/gui/dialogs/qfilesystemmodel.cpp +++ b/src/gui/dialogs/qfilesystemmodel.cpp @@ -1313,7 +1313,7 @@ QString QFileSystemModelPrivate::filePath(const QModelIndex &index) const if ((fullPath.length() > 2) && fullPath[0] == QLatin1Char('/') && fullPath[1] == QLatin1Char('/')) fullPath = fullPath.mid(1); #endif -#if defined(Q_OS_WIN) +#if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN) if (fullPath.length() == 2 && fullPath.endsWith(QLatin1Char(':'))) fullPath.append(QLatin1Char('/')); #endif diff --git a/src/gui/kernel/qapplication_s60.cpp b/src/gui/kernel/qapplication_s60.cpp index f352871..5f01bcb 100644 --- a/src/gui/kernel/qapplication_s60.cpp +++ b/src/gui/kernel/qapplication_s60.cpp @@ -1614,6 +1614,9 @@ extern void qt_cleanup_symbianFontDatabaseExtras(); // qfontdatabase_s60.cpp *****************************************************************************/ void qt_cleanup() { +#ifdef Q_WS_S60 + S60->setButtonGroupContainer(0); +#endif if(qt_S60Beep) { delete qt_S60Beep; qt_S60Beep = 0; diff --git a/src/s60installs/bwins/QtCoreu.def b/src/s60installs/bwins/QtCoreu.def index b678b4e..84aa246 100644 --- a/src/s60installs/bwins/QtCoreu.def +++ b/src/s60installs/bwins/QtCoreu.def @@ -4585,4 +4585,9 @@ EXPORTS ?advance@QAnimationDriver@@QAEXXZ @ 4584 NONAME ; void QAnimationDriver::advance(void) ?start@QAnimationDriver@@AAEXXZ @ 4585 NONAME ; void QAnimationDriver::start(void) ?unlockInline@QMutex@@QAEXXZ @ 4586 NONAME ; void QMutex::unlockInline(void) - + ??0QSystemError@@QAE@HW4ErrorScope@0@@Z @ 4587 NONAME ; QSystemError::QSystemError(int, enum QSystemError::ErrorScope) + ??0QSystemError@@QAE@XZ @ 4588 NONAME ; QSystemError::QSystemError(void) + ?error@QSystemError@@QAEHXZ @ 4589 NONAME ; int QSystemError::error(void) + ?scope@QSystemError@@QAE?AW4ErrorScope@1@XZ @ 4590 NONAME ; enum QSystemError::ErrorScope QSystemError::scope(void) + ?toString@QSystemError@@QAE?AVQString@@XZ @ 4591 NONAME ; class QString QSystemError::toString(void) + ??0QFileInfo@@QAE@PAVQFileInfoPrivate@@@Z @ 4592 NONAME ; QFileInfo::QFileInfo(class QFileInfoPrivate *) diff --git a/src/s60installs/eabi/QtCoreu.def b/src/s60installs/eabi/QtCoreu.def index 02e72a1..130d9c0 100644 --- a/src/s60installs/eabi/QtCoreu.def +++ b/src/s60installs/eabi/QtCoreu.def @@ -3791,4 +3791,8 @@ EXPORTS _ZTV13QUnifiedTimer @ 3790 NONAME _ZTV16QAnimationDriver @ 3791 NONAME _ZTV23QAnimationDriverPrivate @ 3792 NONAME + _ZN12QSystemError8toStringEv @ 3793 NONAME + _ZN5QChar21currentUnicodeVersionEv @ 3794 NONAME + _ZN9QFileInfoC1EP16QFileInfoPrivate @ 3795 NONAME + _ZN9QFileInfoC2EP16QFileInfoPrivate @ 3796 NONAME diff --git a/src/s60installs/eabi/QtDeclarativeu.def b/src/s60installs/eabi/QtDeclarativeu.def index 396c133..b0efab4 100644 --- a/src/s60installs/eabi/QtDeclarativeu.def +++ b/src/s60installs/eabi/QtDeclarativeu.def @@ -1747,8 +1747,8 @@ EXPORTS _ZN21QDeclarativeListModelC1EPKS_P32QDeclarativeListModelWorkerAgent @ 1746 NONAME ABSENT _ZN21QDeclarativeListModelC2EPKS_P32QDeclarativeListModelWorkerAgent @ 1747 NONAME ABSENT _ZNK21QDeclarativeListModel14inWorkerThreadEv @ 1748 NONAME ABSENT - _ZN23QDeclarativeDebugHelper15getScriptEngineEP18QDeclarativeEngine @ 1749 NONAME ABSENT - _ZN23QDeclarativeDebugHelper26setAnimationSlowDownFactorEf @ 1750 NONAME ABSENT + _ZN23QDeclarativeDebugHelper15getScriptEngineEP18QDeclarativeEngine @ 1749 NONAME + _ZN23QDeclarativeDebugHelper26setAnimationSlowDownFactorEf @ 1750 NONAME _ZN17QDeclarativeTimer10classBeginEv @ 1751 NONAME ABSENT _ZN17QDeclarativeTimer10setRunningEb @ 1752 NONAME ABSENT _ZN17QDeclarativeTimer11qt_metacallEN11QMetaObject4CallEiPPv @ 1753 NONAME ABSENT @@ -1883,6 +1883,6 @@ EXPORTS _ZThn8_N29QDeclarativeAbstractAnimation9setTargetERK20QDeclarativeProperty @ 1882 NONAME ABSENT _ZThn8_N29QDeclarativeAbstractAnimationD0Ev @ 1883 NONAME ABSENT _ZThn8_N29QDeclarativeAbstractAnimationD1Ev @ 1884 NONAME ABSENT - _ZN23QDeclarativeDebugHelper15enableDebuggingEv @ 1885 NONAME ABSENT + _ZN23QDeclarativeDebugHelper15enableDebuggingEv @ 1885 NONAME _ZN27QDeclarativePropertyPrivate7connectEPK7QObjectiS2_iiPi @ 1886 NONAME ABSENT diff --git a/src/s60installs/eabi/QtGuiu.def b/src/s60installs/eabi/QtGuiu.def index 703d11b..926ed52 100644 --- a/src/s60installs/eabi/QtGuiu.def +++ b/src/s60installs/eabi/QtGuiu.def @@ -12105,7 +12105,7 @@ EXPORTS _ZN15QStaticTextItemD1Ev @ 12104 NONAME _ZN15QStaticTextItemD2Ev @ 12105 NONAME _ZN19QEventDispatcherS6031reactivateDeferredActiveObjectsEv @ 12106 NONAME - _Z18qt_addBitmapToPathffPKhiiiP12QPainterPath @ 12107 NONAME ABSENT + _Z18qt_addBitmapToPathffPKhiiiP12QPainterPath @ 12107 NONAME _Z22qt_fontdata_from_indexi @ 12108 NONAME _ZN10QBlittable4lockEv @ 12109 NONAME _ZN10QBlittable6unlockEv @ 12110 NONAME diff --git a/src/tools/bootstrap/bootstrap.pro b/src/tools/bootstrap/bootstrap.pro index 27b7336..9e5845c 100644 --- a/src/tools/bootstrap/bootstrap.pro +++ b/src/tools/bootstrap/bootstrap.pro @@ -59,6 +59,8 @@ SOURCES += \ ../../corelib/io/qdiriterator.cpp \ ../../corelib/io/qfile.cpp \ ../../corelib/io/qfileinfo.cpp \ + ../../corelib/io/qfilesystementry.cpp \ + ../../corelib/io/qfilesystemengine.cpp \ ../../corelib/io/qfsfileengine.cpp \ ../../corelib/io/qfsfileengine_iterator.cpp \ ../../corelib/io/qiodevice.cpp \ @@ -67,6 +69,7 @@ SOURCES += \ ../../corelib/io/qurl.cpp \ ../../corelib/kernel/qmetatype.cpp \ ../../corelib/kernel/qvariant.cpp \ + ../../corelib/kernel/qsystemerror.cpp \ ../../corelib/tools/qbitarray.cpp \ ../../corelib/tools/qbytearray.cpp \ ../../corelib/tools/qbytearraymatcher.cpp \ @@ -81,19 +84,22 @@ SOURCES += \ ../../corelib/tools/qvector.cpp \ ../../corelib/tools/qvsnprintf.cpp \ ../../corelib/xml/qxmlutils.cpp \ - ../../corelib/xml/qxmlstream.cpp \ + ../../corelib/xml/qxmlstream.cpp \ ../../xml/dom/qdom.cpp \ ../../xml/sax/qxml.cpp -unix:SOURCES += ../../corelib/io/qfsfileengine_unix.cpp \ - ../../corelib/io/qfsfileengine_iterator_unix.cpp +unix:SOURCES += ../../corelib/io/qfilesystemengine_unix.cpp \ + ../../corelib/io/qfilesystemiterator_unix.cpp \ + ../../corelib/io/qfsfileengine_unix.cpp -win32:SOURCES += ../../corelib/io/qfsfileengine_win.cpp \ - ../../corelib/io/qfsfileengine_iterator_win.cpp \ +win32:SOURCES += ../../corelib/io/qfilesystemengine_win.cpp \ + ../../corelib/io/qfilesystemiterator_win.cpp \ + ../../corelib/io/qfsfileengine_win.cpp \ ../../corelib/plugin/qsystemlibrary.cpp \ macx: { QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.4 #enables weak linking for 10.4 (exported) + SOURCES += ../../corelib/io/qfilesystemengine_mac.cpp SOURCES += ../../corelib/kernel/qcore_mac.cpp LIBS += -framework CoreServices } diff --git a/tests/.gitignore b/tests/.gitignore deleted file mode 100644 index b203473..0000000 --- a/tests/.gitignore +++ /dev/null @@ -1,6 +0,0 @@ -QObject.log -tst_* -!tst_*.* -tst_*.log -tst_*.debug -tst_*~ diff --git a/tests/auto/collections/tst_collections.cpp b/tests/auto/collections/tst_collections.cpp index cf9fa53..225fe79 100644 --- a/tests/auto/collections/tst_collections.cpp +++ b/tests/auto/collections/tst_collections.cpp @@ -3635,7 +3635,7 @@ template<template<class, class> class C> void QTBUG13079_collectionInsideCollect } -static quint32 qHash(const QTBUG13079_Node<QSet> &) +quint32 qHash(const QTBUG13079_Node<QSet> &) { return 0; } diff --git a/tests/auto/corelib.pro b/tests/auto/corelib.pro index d1d0940..3451b53 100644 --- a/tests/auto/corelib.pro +++ b/tests/auto/corelib.pro @@ -101,6 +101,8 @@ SUBDIRS=\ qwritelocker \ selftests \ utf8 \ + qfilesystementry \ + qabstractfileengine symbian:SUBDIRS -= \ qtconcurrentfilter \ diff --git a/tests/auto/declarative/declarative.pro b/tests/auto/declarative/declarative.pro index f0fcfa9..499c155 100644 --- a/tests/auto/declarative/declarative.pro +++ b/tests/auto/declarative/declarative.pro @@ -8,74 +8,78 @@ SUBDIRS += \ SUBDIRS += \ examples \ parserstress \ + qdeclarativecomponent \ + qdeclarativecontext \ + qdeclarativeengine \ + qdeclarativeerror \ + qdeclarativefolderlistmodel \ + qdeclarativeinfo \ + qdeclarativelayoutitem \ + qdeclarativelistreference \ + qdeclarativemoduleplugin \ + qdeclarativeparticles \ + qdeclarativepixmapcache \ + qdeclarativeqt \ + qdeclarativeview \ + qdeclarativeviewer \ + qdeclarativexmlhttprequest \ + qmlvisual \ + moduleqt47 + +contains(QT_CONFIG, private_tests) { + SUBDIRS += \ qdeclarativeanchors \ qdeclarativeanimatedimage \ qdeclarativeanimations \ qdeclarativebehaviors \ qdeclarativebinding \ qdeclarativeborderimage \ - qdeclarativecomponent \ qdeclarativeconnection \ - qdeclarativecontext \ qdeclarativedebug \ qdeclarativedebugclient \ qdeclarativedebugservice \ qdeclarativedom \ qdeclarativeecmascript \ - qdeclarativeengine \ - qdeclarativeerror \ - qdeclarativefolderlistmodel \ - qdeclarativefontloader \ qdeclarativeflickable \ qdeclarativeflipable \ qdeclarativefocusscope \ + qdeclarativefontloader \ qdeclarativegridview \ qdeclarativeimage \ qdeclarativeimageprovider \ - qdeclarativeinfo \ qdeclarativeinstruction \ qdeclarativeitem \ qdeclarativelanguage \ - qdeclarativelayoutitem \ qdeclarativelistmodel \ - qdeclarativelistreference \ qdeclarativelistview \ qdeclarativeloader \ - qdeclarativemoduleplugin \ qdeclarativemousearea \ - qdeclarativeparticles \ qdeclarativepathview \ - qdeclarativepixmapcache \ qdeclarativepositioners \ qdeclarativeproperty \ qdeclarativepropertymap \ - qdeclarativeqt \ qdeclarativerepeater \ qdeclarativesmoothedanimation \ qdeclarativespringanimation \ + qdeclarativestyledtext \ qdeclarativesqldatabase \ qdeclarativestates \ - qdeclarativestyledtext \ qdeclarativesystempalette \ qdeclarativetext \ qdeclarativetextedit \ qdeclarativetextinput \ qdeclarativetimer \ qdeclarativevaluetypes \ - qdeclarativeview \ - qdeclarativeviewer \ qdeclarativevisualdatamodel \ qdeclarativeworkerscript \ - qdeclarativexmlhttprequest \ qdeclarativexmllistmodel \ - qmlvisual \ - qpacketprotocol \ - moduleqt47 + qpacketprotocol contains(QT_CONFIG, webkit) { SUBDIRS += \ qdeclarativewebview } +} # Tests which should run in Pulse PULSE_TESTS = $$SUBDIRS diff --git a/tests/auto/declarative/examples/examples.pro b/tests/auto/declarative/examples/examples.pro index 8ed33da..dafc146 100644 --- a/tests/auto/declarative/examples/examples.pro +++ b/tests/auto/declarative/examples/examples.pro @@ -6,10 +6,12 @@ SOURCES += tst_examples.cpp include(../../../../tools/qml/qml.pri) +include(../symbianlibs.pri) + symbian: { importFiles.files = data importFiles.path = . - DEPLOYMENT = importFiles + DEPLOYMENT += importFiles } else { DEFINES += SRCDIR=\\\"$$PWD\\\" } diff --git a/tests/auto/declarative/moduleqt47/moduleqt47.pro b/tests/auto/declarative/moduleqt47/moduleqt47.pro index 808f263..ff773e8 100644 --- a/tests/auto/declarative/moduleqt47/moduleqt47.pro +++ b/tests/auto/declarative/moduleqt47/moduleqt47.pro @@ -7,7 +7,7 @@ SOURCES += tst_moduleqt47.cpp symbian: { importFiles.files = data importFiles.path = . - DEPLOYMENT = importFiles + DEPLOYMENT += importFiles } else { DEFINES += SRCDIR=\\\"$$PWD\\\" } diff --git a/tests/auto/declarative/parserstress/parserstress.pro b/tests/auto/declarative/parserstress/parserstress.pro index 1e323f7..6ef2432 100644 --- a/tests/auto/declarative/parserstress/parserstress.pro +++ b/tests/auto/declarative/parserstress/parserstress.pro @@ -7,7 +7,7 @@ SOURCES += tst_parserstress.cpp symbian: { importFiles.files = ..\\..\\qscriptjstestsuite\\tests importFiles.path = . - DEPLOYMENT = importFiles + DEPLOYMENT += importFiles } else { DEFINES += SRCDIR=\\\"$$PWD\\\" } diff --git a/tests/auto/declarative/qdeclarativeanchors/qdeclarativeanchors.pro b/tests/auto/declarative/qdeclarativeanchors/qdeclarativeanchors.pro index 141e25d..f09e8d9 100644 --- a/tests/auto/declarative/qdeclarativeanchors/qdeclarativeanchors.pro +++ b/tests/auto/declarative/qdeclarativeanchors/qdeclarativeanchors.pro @@ -6,7 +6,7 @@ macx:CONFIG -= app_bundle symbian: { importFiles.files = data importFiles.path = . - DEPLOYMENT = importFiles + DEPLOYMENT += importFiles } else { DEFINES += SRCDIR=\\\"$$PWD\\\" } diff --git a/tests/auto/declarative/qdeclarativeanimatedimage/qdeclarativeanimatedimage.pro b/tests/auto/declarative/qdeclarativeanimatedimage/qdeclarativeanimatedimage.pro index ad9509a..3d040a6 100644 --- a/tests/auto/declarative/qdeclarativeanimatedimage/qdeclarativeanimatedimage.pro +++ b/tests/auto/declarative/qdeclarativeanimatedimage/qdeclarativeanimatedimage.pro @@ -7,7 +7,7 @@ macx:CONFIG -= app_bundle symbian: { importFiles.files = data importFiles.path = . - DEPLOYMENT = importFiles + DEPLOYMENT += importFiles } else { DEFINES += SRCDIR=\\\"$$PWD\\\" } diff --git a/tests/auto/declarative/qdeclarativeanimations/qdeclarativeanimations.pro b/tests/auto/declarative/qdeclarativeanimations/qdeclarativeanimations.pro index 84cd498..d00d51a 100644 --- a/tests/auto/declarative/qdeclarativeanimations/qdeclarativeanimations.pro +++ b/tests/auto/declarative/qdeclarativeanimations/qdeclarativeanimations.pro @@ -6,7 +6,7 @@ macx:CONFIG -= app_bundle symbian: { importFiles.files = data importFiles.path = . - DEPLOYMENT = importFiles + DEPLOYMENT += importFiles } else { DEFINES += SRCDIR=\\\"$$PWD\\\" } diff --git a/tests/auto/declarative/qdeclarativebehaviors/qdeclarativebehaviors.pro b/tests/auto/declarative/qdeclarativebehaviors/qdeclarativebehaviors.pro index e4125fd..7416827 100644 --- a/tests/auto/declarative/qdeclarativebehaviors/qdeclarativebehaviors.pro +++ b/tests/auto/declarative/qdeclarativebehaviors/qdeclarativebehaviors.pro @@ -6,7 +6,7 @@ macx:CONFIG -= app_bundle symbian: { importFiles.files = data importFiles.path = . - DEPLOYMENT = importFiles + DEPLOYMENT += importFiles } else { DEFINES += SRCDIR=\\\"$$PWD\\\" } diff --git a/tests/auto/declarative/qdeclarativebinding/qdeclarativebinding.pro b/tests/auto/declarative/qdeclarativebinding/qdeclarativebinding.pro index 25bdbec..fe12635 100644 --- a/tests/auto/declarative/qdeclarativebinding/qdeclarativebinding.pro +++ b/tests/auto/declarative/qdeclarativebinding/qdeclarativebinding.pro @@ -7,7 +7,7 @@ SOURCES += tst_qdeclarativebinding.cpp symbian: { importFiles.files = data importFiles.path = . - DEPLOYMENT = importFiles + DEPLOYMENT += importFiles } else { DEFINES += SRCDIR=\\\"$$PWD\\\" } diff --git a/tests/auto/declarative/qdeclarativeborderimage/qdeclarativeborderimage.pro b/tests/auto/declarative/qdeclarativeborderimage/qdeclarativeborderimage.pro index 05d4cac..a7463e8 100644 --- a/tests/auto/declarative/qdeclarativeborderimage/qdeclarativeborderimage.pro +++ b/tests/auto/declarative/qdeclarativeborderimage/qdeclarativeborderimage.pro @@ -8,7 +8,7 @@ SOURCES += tst_qdeclarativeborderimage.cpp ../shared/testhttpserver.cpp symbian: { importFiles.files = data importFiles.path = . - DEPLOYMENT = importFiles + DEPLOYMENT += importFiles } else { DEFINES += SRCDIR=\\\"$$PWD\\\" } diff --git a/tests/auto/declarative/qdeclarativeconnection/qdeclarativeconnection.pro b/tests/auto/declarative/qdeclarativeconnection/qdeclarativeconnection.pro index c614571..6f9550d 100644 --- a/tests/auto/declarative/qdeclarativeconnection/qdeclarativeconnection.pro +++ b/tests/auto/declarative/qdeclarativeconnection/qdeclarativeconnection.pro @@ -7,7 +7,7 @@ SOURCES += tst_qdeclarativeconnection.cpp symbian: { importFiles.files = data importFiles.path = . - DEPLOYMENT = importFiles + DEPLOYMENT += importFiles } else { DEFINES += SRCDIR=\\\"$$PWD\\\" } diff --git a/tests/auto/declarative/qdeclarativedom/qdeclarativedom.pro b/tests/auto/declarative/qdeclarativedom/qdeclarativedom.pro index e8f24a5..8ac69aa 100644 --- a/tests/auto/declarative/qdeclarativedom/qdeclarativedom.pro +++ b/tests/auto/declarative/qdeclarativedom/qdeclarativedom.pro @@ -7,7 +7,7 @@ SOURCES += tst_qdeclarativedom.cpp symbian: { importFiles.files = data importFiles.path = . - DEPLOYMENT = importFiles + DEPLOYMENT += importFiles } else { DEFINES += SRCDIR=\\\"$$PWD\\\" } diff --git a/tests/auto/declarative/qdeclarativeecmascript/qdeclarativeecmascript.pro b/tests/auto/declarative/qdeclarativeecmascript/qdeclarativeecmascript.pro index e7f8636..69d25a4 100644 --- a/tests/auto/declarative/qdeclarativeecmascript/qdeclarativeecmascript.pro +++ b/tests/auto/declarative/qdeclarativeecmascript/qdeclarativeecmascript.pro @@ -15,7 +15,7 @@ INCLUDEPATH += ../shared symbian: { importFiles.files = data importFiles.path = . - DEPLOYMENT = importFiles + DEPLOYMENT += importFiles } else { DEFINES += SRCDIR=\\\"$$PWD\\\" } diff --git a/tests/auto/declarative/qdeclarativeflickable/qdeclarativeflickable.pro b/tests/auto/declarative/qdeclarativeflickable/qdeclarativeflickable.pro index 1fb99d0..c176e07 100644 --- a/tests/auto/declarative/qdeclarativeflickable/qdeclarativeflickable.pro +++ b/tests/auto/declarative/qdeclarativeflickable/qdeclarativeflickable.pro @@ -7,7 +7,7 @@ SOURCES += tst_qdeclarativeflickable.cpp symbian: { importFiles.files = data importFiles.path = . - DEPLOYMENT = importFiles + DEPLOYMENT += importFiles } else { DEFINES += SRCDIR=\\\"$$PWD\\\" } diff --git a/tests/auto/declarative/qdeclarativeflipable/qdeclarativeflipable.pro b/tests/auto/declarative/qdeclarativeflipable/qdeclarativeflipable.pro index eddd053..3b6d19a 100644 --- a/tests/auto/declarative/qdeclarativeflipable/qdeclarativeflipable.pro +++ b/tests/auto/declarative/qdeclarativeflipable/qdeclarativeflipable.pro @@ -7,7 +7,7 @@ SOURCES += tst_qdeclarativeflipable.cpp symbian: { importFiles.files = data importFiles.path = . - DEPLOYMENT = importFiles + DEPLOYMENT += importFiles } else { DEFINES += SRCDIR=\\\"$$PWD\\\" } diff --git a/tests/auto/declarative/qdeclarativefocusscope/qdeclarativefocusscope.pro b/tests/auto/declarative/qdeclarativefocusscope/qdeclarativefocusscope.pro index fd7f6b8..eab983f 100644 --- a/tests/auto/declarative/qdeclarativefocusscope/qdeclarativefocusscope.pro +++ b/tests/auto/declarative/qdeclarativefocusscope/qdeclarativefocusscope.pro @@ -6,7 +6,7 @@ macx:CONFIG -= app_bundle symbian: { importFiles.files = data importFiles.path = . - DEPLOYMENT = importFiles + DEPLOYMENT += importFiles } else { DEFINES += SRCDIR=\\\"$$PWD\\\" } diff --git a/tests/auto/declarative/qdeclarativefolderlistmodel/qdeclarativefolderlistmodel.pro b/tests/auto/declarative/qdeclarativefolderlistmodel/qdeclarativefolderlistmodel.pro index 50c7ca0..b7e5e5f 100644 --- a/tests/auto/declarative/qdeclarativefolderlistmodel/qdeclarativefolderlistmodel.pro +++ b/tests/auto/declarative/qdeclarativefolderlistmodel/qdeclarativefolderlistmodel.pro @@ -7,7 +7,7 @@ SOURCES += tst_qdeclarativefolderlistmodel.cpp symbian: { importFiles.files = data importFiles.path = . - DEPLOYMENT = importFiles + DEPLOYMENT += importFiles } else { DEFINES += SRCDIR=\\\"$$PWD\\\" } diff --git a/tests/auto/declarative/qdeclarativefontloader/qdeclarativefontloader.pro b/tests/auto/declarative/qdeclarativefontloader/qdeclarativefontloader.pro index f245a0d..357268b 100644 --- a/tests/auto/declarative/qdeclarativefontloader/qdeclarativefontloader.pro +++ b/tests/auto/declarative/qdeclarativefontloader/qdeclarativefontloader.pro @@ -8,7 +8,7 @@ SOURCES += tst_qdeclarativefontloader.cpp ../shared/testhttpserver.cpp symbian: { importFiles.files = data importFiles.path = . - DEPLOYMENT = importFiles + DEPLOYMENT += importFiles } else { DEFINES += SRCDIR=\\\"$$PWD\\\" } diff --git a/tests/auto/declarative/qdeclarativegridview/qdeclarativegridview.pro b/tests/auto/declarative/qdeclarativegridview/qdeclarativegridview.pro index b775b3d..bc196fb 100644 --- a/tests/auto/declarative/qdeclarativegridview/qdeclarativegridview.pro +++ b/tests/auto/declarative/qdeclarativegridview/qdeclarativegridview.pro @@ -7,7 +7,7 @@ SOURCES += tst_qdeclarativegridview.cpp symbian: { importFiles.files = data importFiles.path = . - DEPLOYMENT = importFiles + DEPLOYMENT += importFiles } else { DEFINES += SRCDIR=\\\"$$PWD\\\" } diff --git a/tests/auto/declarative/qdeclarativeimage/qdeclarativeimage.pro b/tests/auto/declarative/qdeclarativeimage/qdeclarativeimage.pro index c87c1d9..a22c8b5 100644 --- a/tests/auto/declarative/qdeclarativeimage/qdeclarativeimage.pro +++ b/tests/auto/declarative/qdeclarativeimage/qdeclarativeimage.pro @@ -8,7 +8,7 @@ SOURCES += tst_qdeclarativeimage.cpp ../shared/testhttpserver.cpp symbian: { importFiles.files = data importFiles.path = . - DEPLOYMENT = importFiles + DEPLOYMENT += importFiles } else { DEFINES += SRCDIR=\\\"$$PWD\\\" } diff --git a/tests/auto/declarative/qdeclarativeinfo/qdeclarativeinfo.pro b/tests/auto/declarative/qdeclarativeinfo/qdeclarativeinfo.pro index 888596f..423390f 100644 --- a/tests/auto/declarative/qdeclarativeinfo/qdeclarativeinfo.pro +++ b/tests/auto/declarative/qdeclarativeinfo/qdeclarativeinfo.pro @@ -7,7 +7,7 @@ SOURCES += tst_qdeclarativeinfo.cpp symbian: { importFiles.files = data importFiles.path = . - DEPLOYMENT = importFiles + DEPLOYMENT += importFiles } else { DEFINES += SRCDIR=\\\"$$PWD\\\" } diff --git a/tests/auto/declarative/qdeclarativeitem/qdeclarativeitem.pro b/tests/auto/declarative/qdeclarativeitem/qdeclarativeitem.pro index 0fd871e..d8007a0 100644 --- a/tests/auto/declarative/qdeclarativeitem/qdeclarativeitem.pro +++ b/tests/auto/declarative/qdeclarativeitem/qdeclarativeitem.pro @@ -7,7 +7,7 @@ SOURCES += tst_qdeclarativeitem.cpp symbian: { importFiles.files = data importFiles.path = . - DEPLOYMENT = importFiles + DEPLOYMENT += importFiles } else { DEFINES += SRCDIR=\\\"$$PWD\\\" } diff --git a/tests/auto/declarative/qdeclarativelanguage/qdeclarativelanguage.pro b/tests/auto/declarative/qdeclarativelanguage/qdeclarativelanguage.pro index aa69337..cae85a7 100644 --- a/tests/auto/declarative/qdeclarativelanguage/qdeclarativelanguage.pro +++ b/tests/auto/declarative/qdeclarativelanguage/qdeclarativelanguage.pro @@ -14,7 +14,7 @@ SOURCES += ../shared/testhttpserver.cpp symbian: { importFiles.files = data importFiles.path = . - DEPLOYMENT = importFiles + DEPLOYMENT += importFiles } else { DEFINES += SRCDIR=\\\"$$PWD\\\" } diff --git a/tests/auto/declarative/qdeclarativelayoutitem/qdeclarativelayoutitem.pro b/tests/auto/declarative/qdeclarativelayoutitem/qdeclarativelayoutitem.pro index 42d9a80..d89f16c 100644 --- a/tests/auto/declarative/qdeclarativelayoutitem/qdeclarativelayoutitem.pro +++ b/tests/auto/declarative/qdeclarativelayoutitem/qdeclarativelayoutitem.pro @@ -7,7 +7,7 @@ SOURCES += tst_qdeclarativelayoutitem.cpp symbian: { importFiles.files = data importFiles.path = . - DEPLOYMENT = importFiles + DEPLOYMENT += importFiles } else { DEFINES += SRCDIR=\\\"$$PWD\\\" } diff --git a/tests/auto/declarative/qdeclarativelistmodel/qdeclarativelistmodel.pro b/tests/auto/declarative/qdeclarativelistmodel/qdeclarativelistmodel.pro index 8a39555..b5c5cf2 100644 --- a/tests/auto/declarative/qdeclarativelistmodel/qdeclarativelistmodel.pro +++ b/tests/auto/declarative/qdeclarativelistmodel/qdeclarativelistmodel.pro @@ -8,7 +8,7 @@ SOURCES += tst_qdeclarativelistmodel.cpp symbian: { importFiles.files = data importFiles.path = . - DEPLOYMENT = importFiles + DEPLOYMENT += importFiles } else { DEFINES += SRCDIR=\\\"$$PWD\\\" } diff --git a/tests/auto/declarative/qdeclarativelistview/qdeclarativelistview.pro b/tests/auto/declarative/qdeclarativelistview/qdeclarativelistview.pro index 99eba67..468474a 100644 --- a/tests/auto/declarative/qdeclarativelistview/qdeclarativelistview.pro +++ b/tests/auto/declarative/qdeclarativelistview/qdeclarativelistview.pro @@ -7,7 +7,7 @@ SOURCES += tst_qdeclarativelistview.cpp symbian: { importFiles.files = data importFiles.path = . - DEPLOYMENT = importFiles + DEPLOYMENT += importFiles } else { DEFINES += SRCDIR=\\\"$$PWD\\\" } diff --git a/tests/auto/declarative/qdeclarativeloader/qdeclarativeloader.pro b/tests/auto/declarative/qdeclarativeloader/qdeclarativeloader.pro index 1e7808a..1ede509 100644 --- a/tests/auto/declarative/qdeclarativeloader/qdeclarativeloader.pro +++ b/tests/auto/declarative/qdeclarativeloader/qdeclarativeloader.pro @@ -10,7 +10,7 @@ SOURCES += tst_qdeclarativeloader.cpp \ symbian: { importFiles.files = data importFiles.path = . - DEPLOYMENT = importFiles + DEPLOYMENT += importFiles } else { DEFINES += SRCDIR=\\\"$$PWD\\\" } diff --git a/tests/auto/declarative/qdeclarativemoduleplugin/tst_qdeclarativemoduleplugin.pro b/tests/auto/declarative/qdeclarativemoduleplugin/tst_qdeclarativemoduleplugin.pro index ec2d25e..2e8aa75 100644 --- a/tests/auto/declarative/qdeclarativemoduleplugin/tst_qdeclarativemoduleplugin.pro +++ b/tests/auto/declarative/qdeclarativemoduleplugin/tst_qdeclarativemoduleplugin.pro @@ -6,7 +6,7 @@ CONFIG -= app_bundle symbian: { importFiles.files = data importFiles.path = . - DEPLOYMENT = importFiles + DEPLOYMENT += importFiles } else { DEFINES += SRCDIR=\\\"$$PWD\\\" } diff --git a/tests/auto/declarative/qdeclarativemousearea/qdeclarativemousearea.pro b/tests/auto/declarative/qdeclarativemousearea/qdeclarativemousearea.pro index a93f7af..ed9313f 100644 --- a/tests/auto/declarative/qdeclarativemousearea/qdeclarativemousearea.pro +++ b/tests/auto/declarative/qdeclarativemousearea/qdeclarativemousearea.pro @@ -8,7 +8,7 @@ SOURCES += tst_qdeclarativemousearea.cpp ../shared/testhttpserver.cpp symbian: { importFiles.files = data importFiles.path = . - DEPLOYMENT = importFiles + DEPLOYMENT += importFiles } else { DEFINES += SRCDIR=\\\"$$PWD\\\" } diff --git a/tests/auto/declarative/qdeclarativeparticles/qdeclarativeparticles.pro b/tests/auto/declarative/qdeclarativeparticles/qdeclarativeparticles.pro index 8f13573..2cf8268 100644 --- a/tests/auto/declarative/qdeclarativeparticles/qdeclarativeparticles.pro +++ b/tests/auto/declarative/qdeclarativeparticles/qdeclarativeparticles.pro @@ -7,7 +7,7 @@ SOURCES += tst_qdeclarativeparticles.cpp symbian: { importFiles.files = data importFiles.path = . - DEPLOYMENT = importFiles + DEPLOYMENT += importFiles } else { DEFINES += SRCDIR=\\\"$$PWD\\\" } diff --git a/tests/auto/declarative/qdeclarativepathview/qdeclarativepathview.pro b/tests/auto/declarative/qdeclarativepathview/qdeclarativepathview.pro index 4f70a6f..e0404c5 100644 --- a/tests/auto/declarative/qdeclarativepathview/qdeclarativepathview.pro +++ b/tests/auto/declarative/qdeclarativepathview/qdeclarativepathview.pro @@ -7,7 +7,7 @@ SOURCES += tst_qdeclarativepathview.cpp symbian: { importFiles.files = data importFiles.path = . - DEPLOYMENT = importFiles + DEPLOYMENT += importFiles } else { DEFINES += SRCDIR=\\\"$$PWD\\\" } diff --git a/tests/auto/declarative/qdeclarativepixmapcache/qdeclarativepixmapcache.pro b/tests/auto/declarative/qdeclarativepixmapcache/qdeclarativepixmapcache.pro index 47b1b7b..88871e9 100644 --- a/tests/auto/declarative/qdeclarativepixmapcache/qdeclarativepixmapcache.pro +++ b/tests/auto/declarative/qdeclarativepixmapcache/qdeclarativepixmapcache.pro @@ -12,7 +12,7 @@ SOURCES += ../shared/testhttpserver.cpp symbian: { importFiles.files = data importFiles.path = . - DEPLOYMENT = importFiles + DEPLOYMENT += importFiles } else { DEFINES += SRCDIR=\\\"$$PWD\\\" } diff --git a/tests/auto/declarative/qdeclarativepixmapcache/tst_qdeclarativepixmapcache.cpp b/tests/auto/declarative/qdeclarativepixmapcache/tst_qdeclarativepixmapcache.cpp index 50d0731..1a38e87 100644 --- a/tests/auto/declarative/qdeclarativepixmapcache/tst_qdeclarativepixmapcache.cpp +++ b/tests/auto/declarative/qdeclarativepixmapcache/tst_qdeclarativepixmapcache.cpp @@ -74,7 +74,9 @@ private slots: void massive(); void cancelcrash(); void shrinkcache(); +#ifndef QT_NO_CONCURRENT void networkCrash(); +#endif private: QDeclarativeEngine engine; QUrl thisfile; @@ -363,6 +365,7 @@ void createNetworkServer() eventLoop.exec(); } +#ifndef QT_NO_CONCURRENT // QT-3957 void tst_qdeclarativepixmapcache::networkCrash() { @@ -377,6 +380,7 @@ void tst_qdeclarativepixmapcache::networkCrash() } future.cancel(); } +#endif QTEST_MAIN(tst_qdeclarativepixmapcache) diff --git a/tests/auto/declarative/qdeclarativepositioners/qdeclarativepositioners.pro b/tests/auto/declarative/qdeclarativepositioners/qdeclarativepositioners.pro index e98aa5c..27e5948 100644 --- a/tests/auto/declarative/qdeclarativepositioners/qdeclarativepositioners.pro +++ b/tests/auto/declarative/qdeclarativepositioners/qdeclarativepositioners.pro @@ -6,7 +6,7 @@ macx:CONFIG -= app_bundle symbian: { importFiles.files = data importFiles.path = . - DEPLOYMENT = importFiles + DEPLOYMENT += importFiles } else { DEFINES += SRCDIR=\\\"$$PWD\\\" } diff --git a/tests/auto/declarative/qdeclarativeproperty/qdeclarativeproperty.pro b/tests/auto/declarative/qdeclarativeproperty/qdeclarativeproperty.pro index 9dd727c..1750860 100644 --- a/tests/auto/declarative/qdeclarativeproperty/qdeclarativeproperty.pro +++ b/tests/auto/declarative/qdeclarativeproperty/qdeclarativeproperty.pro @@ -7,7 +7,7 @@ SOURCES += tst_qdeclarativeproperty.cpp symbian: { importFiles.files = data importFiles.path = . - DEPLOYMENT = importFiles + DEPLOYMENT += importFiles } else { DEFINES += SRCDIR=\\\"$$PWD\\\" } diff --git a/tests/auto/declarative/qdeclarativeqt/qdeclarativeqt.pro b/tests/auto/declarative/qdeclarativeqt/qdeclarativeqt.pro index a12c439..71ff8a8 100644 --- a/tests/auto/declarative/qdeclarativeqt/qdeclarativeqt.pro +++ b/tests/auto/declarative/qdeclarativeqt/qdeclarativeqt.pro @@ -6,7 +6,7 @@ macx:CONFIG -= app_bundle symbian: { importFiles.files = data importFiles.path = . - DEPLOYMENT = importFiles + DEPLOYMENT += importFiles } else { DEFINES += SRCDIR=\\\"$$PWD\\\" } diff --git a/tests/auto/declarative/qdeclarativerepeater/qdeclarativerepeater.pro b/tests/auto/declarative/qdeclarativerepeater/qdeclarativerepeater.pro index 385b8da..5230f69 100644 --- a/tests/auto/declarative/qdeclarativerepeater/qdeclarativerepeater.pro +++ b/tests/auto/declarative/qdeclarativerepeater/qdeclarativerepeater.pro @@ -7,7 +7,7 @@ SOURCES += tst_qdeclarativerepeater.cpp symbian: { importFiles.files = data importFiles.path = . - DEPLOYMENT = importFiles + DEPLOYMENT += importFiles } else { DEFINES += SRCDIR=\\\"$$PWD\\\" } diff --git a/tests/auto/declarative/qdeclarativescriptdebugging/qdeclarativescriptdebugging.pro b/tests/auto/declarative/qdeclarativescriptdebugging/qdeclarativescriptdebugging.pro index dedb263..171f308 100644 --- a/tests/auto/declarative/qdeclarativescriptdebugging/qdeclarativescriptdebugging.pro +++ b/tests/auto/declarative/qdeclarativescriptdebugging/qdeclarativescriptdebugging.pro @@ -11,7 +11,7 @@ INCLUDEPATH += ../shared symbian: { importFiles.files = data importFiles.path = . - DEPLOYMENT = importFiles + DEPLOYMENT += importFiles } else { DEFINES += SRCDIR=\\\"$$PWD\\\" } diff --git a/tests/auto/declarative/qdeclarativesmoothedanimation/qdeclarativesmoothedanimation.pro b/tests/auto/declarative/qdeclarativesmoothedanimation/qdeclarativesmoothedanimation.pro index 69f331b..1e77d6e 100644 --- a/tests/auto/declarative/qdeclarativesmoothedanimation/qdeclarativesmoothedanimation.pro +++ b/tests/auto/declarative/qdeclarativesmoothedanimation/qdeclarativesmoothedanimation.pro @@ -7,7 +7,7 @@ SOURCES += tst_qdeclarativesmoothedanimation.cpp symbian: { importFiles.files = data importFiles.path = . - DEPLOYMENT = importFiles + DEPLOYMENT += importFiles } else { DEFINES += SRCDIR=\\\"$$PWD\\\" } diff --git a/tests/auto/declarative/qdeclarativespringanimation/qdeclarativespringanimation.pro b/tests/auto/declarative/qdeclarativespringanimation/qdeclarativespringanimation.pro index a59522b..da477fc 100644 --- a/tests/auto/declarative/qdeclarativespringanimation/qdeclarativespringanimation.pro +++ b/tests/auto/declarative/qdeclarativespringanimation/qdeclarativespringanimation.pro @@ -7,7 +7,7 @@ SOURCES += tst_qdeclarativespringanimation.cpp symbian: { importFiles.files = data importFiles.path = . - DEPLOYMENT = importFiles + DEPLOYMENT += importFiles } else { DEFINES += SRCDIR=\\\"$$PWD\\\" } diff --git a/tests/auto/declarative/qdeclarativesqldatabase/qdeclarativesqldatabase.pro b/tests/auto/declarative/qdeclarativesqldatabase/qdeclarativesqldatabase.pro index d938692..0d335a5 100644 --- a/tests/auto/declarative/qdeclarativesqldatabase/qdeclarativesqldatabase.pro +++ b/tests/auto/declarative/qdeclarativesqldatabase/qdeclarativesqldatabase.pro @@ -8,7 +8,7 @@ SOURCES += tst_qdeclarativesqldatabase.cpp symbian: { importFiles.files = data importFiles.path = . - DEPLOYMENT = importFiles + DEPLOYMENT += importFiles } else { DEFINES += SRCDIR=\\\"$$PWD\\\" } diff --git a/tests/auto/declarative/qdeclarativestates/qdeclarativestates.pro b/tests/auto/declarative/qdeclarativestates/qdeclarativestates.pro index 2f32178..4a0cc24 100644 --- a/tests/auto/declarative/qdeclarativestates/qdeclarativestates.pro +++ b/tests/auto/declarative/qdeclarativestates/qdeclarativestates.pro @@ -7,7 +7,7 @@ SOURCES += tst_qdeclarativestates.cpp symbian: { importFiles.files = data importFiles.path = . - DEPLOYMENT = importFiles + DEPLOYMENT += importFiles } else { DEFINES += SRCDIR=\\\"$$PWD\\\" } diff --git a/tests/auto/declarative/qdeclarativetext/qdeclarativetext.pro b/tests/auto/declarative/qdeclarativetext/qdeclarativetext.pro index 362886e..290cda3 100644 --- a/tests/auto/declarative/qdeclarativetext/qdeclarativetext.pro +++ b/tests/auto/declarative/qdeclarativetext/qdeclarativetext.pro @@ -12,7 +12,7 @@ SOURCES += ../shared/testhttpserver.cpp symbian: { importFiles.files = data importFiles.path = . - DEPLOYMENT = importFiles + DEPLOYMENT += importFiles } else { DEFINES += SRCDIR=\\\"$$PWD\\\" } diff --git a/tests/auto/declarative/qdeclarativetextedit/qdeclarativetextedit.pro b/tests/auto/declarative/qdeclarativetextedit/qdeclarativetextedit.pro index cf706ba..aaf753e 100644 --- a/tests/auto/declarative/qdeclarativetextedit/qdeclarativetextedit.pro +++ b/tests/auto/declarative/qdeclarativetextedit/qdeclarativetextedit.pro @@ -8,7 +8,7 @@ HEADERS += ../shared/testhttpserver.h symbian: { importFiles.files = data importFiles.path = . - DEPLOYMENT = importFiles + DEPLOYMENT += importFiles } else { DEFINES += SRCDIR=\\\"$$PWD\\\" } diff --git a/tests/auto/declarative/qdeclarativetextinput/qdeclarativetextinput.pro b/tests/auto/declarative/qdeclarativetextinput/qdeclarativetextinput.pro index 5c45f57..0fee1c9 100644 --- a/tests/auto/declarative/qdeclarativetextinput/qdeclarativetextinput.pro +++ b/tests/auto/declarative/qdeclarativetextinput/qdeclarativetextinput.pro @@ -7,7 +7,7 @@ SOURCES += tst_qdeclarativetextinput.cpp symbian: { importFiles.files = data importFiles.path = . - DEPLOYMENT = importFiles + DEPLOYMENT += importFiles } else { DEFINES += SRCDIR=\\\"$$PWD\\\" } diff --git a/tests/auto/declarative/qdeclarativevaluetypes/qdeclarativevaluetypes.pro b/tests/auto/declarative/qdeclarativevaluetypes/qdeclarativevaluetypes.pro index a208254..59b3526 100644 --- a/tests/auto/declarative/qdeclarativevaluetypes/qdeclarativevaluetypes.pro +++ b/tests/auto/declarative/qdeclarativevaluetypes/qdeclarativevaluetypes.pro @@ -10,7 +10,7 @@ SOURCES += tst_qdeclarativevaluetypes.cpp \ symbian: { importFiles.files = data importFiles.path = . - DEPLOYMENT = importFiles + DEPLOYMENT += importFiles } else { DEFINES += SRCDIR=\\\"$$PWD\\\" } diff --git a/tests/auto/declarative/qdeclarativeview/qdeclarativeview.pro b/tests/auto/declarative/qdeclarativeview/qdeclarativeview.pro index 4436d54..fc4790d 100644 --- a/tests/auto/declarative/qdeclarativeview/qdeclarativeview.pro +++ b/tests/auto/declarative/qdeclarativeview/qdeclarativeview.pro @@ -7,7 +7,7 @@ SOURCES += tst_qdeclarativeview.cpp symbian: { importFiles.files = data importFiles.path = . - DEPLOYMENT = importFiles + DEPLOYMENT += importFiles } else { DEFINES += SRCDIR=\\\"$$PWD\\\" } diff --git a/tests/auto/declarative/qdeclarativeviewer/qdeclarativeviewer.pro b/tests/auto/declarative/qdeclarativeviewer/qdeclarativeviewer.pro index 5ba416e..8d4b410 100644 --- a/tests/auto/declarative/qdeclarativeviewer/qdeclarativeviewer.pro +++ b/tests/auto/declarative/qdeclarativeviewer/qdeclarativeviewer.pro @@ -6,10 +6,12 @@ include(../../../../tools/qml/qml.pri) SOURCES += tst_qdeclarativeviewer.cpp +include(../symbianlibs.pri) + symbian: { importFiles.files = data importFiles.path = . - DEPLOYMENT = importFiles + DEPLOYMENT += importFiles } else { DEFINES += SRCDIR=\\\"$$PWD\\\" } diff --git a/tests/auto/declarative/qdeclarativevisualdatamodel/qdeclarativevisualdatamodel.pro b/tests/auto/declarative/qdeclarativevisualdatamodel/qdeclarativevisualdatamodel.pro index 16154f3..fe3d794 100644 --- a/tests/auto/declarative/qdeclarativevisualdatamodel/qdeclarativevisualdatamodel.pro +++ b/tests/auto/declarative/qdeclarativevisualdatamodel/qdeclarativevisualdatamodel.pro @@ -7,7 +7,7 @@ SOURCES += tst_qdeclarativevisualdatamodel.cpp symbian: { importFiles.files = data importFiles.path = . - DEPLOYMENT = importFiles + DEPLOYMENT += importFiles } else { DEFINES += SRCDIR=\\\"$$PWD\\\" } diff --git a/tests/auto/declarative/qdeclarativewebview/qdeclarativewebview.pro b/tests/auto/declarative/qdeclarativewebview/qdeclarativewebview.pro index cc7fa43..af13d33 100644 --- a/tests/auto/declarative/qdeclarativewebview/qdeclarativewebview.pro +++ b/tests/auto/declarative/qdeclarativewebview/qdeclarativewebview.pro @@ -8,7 +8,7 @@ SOURCES += tst_qdeclarativewebview.cpp symbian: { importFiles.files = data importFiles.path = . - DEPLOYMENT = importFiles + DEPLOYMENT += importFiles } else { DEFINES += SRCDIR=\\\"$$PWD\\\" } diff --git a/tests/auto/declarative/qdeclarativeworkerscript/qdeclarativeworkerscript.pro b/tests/auto/declarative/qdeclarativeworkerscript/qdeclarativeworkerscript.pro index eca8a68..e20c3e6 100644 --- a/tests/auto/declarative/qdeclarativeworkerscript/qdeclarativeworkerscript.pro +++ b/tests/auto/declarative/qdeclarativeworkerscript/qdeclarativeworkerscript.pro @@ -7,7 +7,7 @@ SOURCES += tst_qdeclarativeworkerscript.cpp symbian: { importFiles.files = data importFiles.path = . - DEPLOYMENT = importFiles + DEPLOYMENT += importFiles } else { DEFINES += SRCDIR=\\\"$$PWD\\\" } diff --git a/tests/auto/declarative/qdeclarativexmlhttprequest/qdeclarativexmlhttprequest.pro b/tests/auto/declarative/qdeclarativexmlhttprequest/qdeclarativexmlhttprequest.pro index fbcc597..8aefb8e 100644 --- a/tests/auto/declarative/qdeclarativexmlhttprequest/qdeclarativexmlhttprequest.pro +++ b/tests/auto/declarative/qdeclarativexmlhttprequest/qdeclarativexmlhttprequest.pro @@ -11,7 +11,7 @@ SOURCES += tst_qdeclarativexmlhttprequest.cpp \ symbian: { importFiles.files = data importFiles.path = . - DEPLOYMENT = importFiles + DEPLOYMENT += importFiles } else { DEFINES += SRCDIR=\\\"$$PWD\\\" } diff --git a/tests/auto/declarative/qdeclarativexmllistmodel/qdeclarativexmllistmodel.pro b/tests/auto/declarative/qdeclarativexmllistmodel/qdeclarativexmllistmodel.pro index 23173f3..c74b8fb 100644 --- a/tests/auto/declarative/qdeclarativexmllistmodel/qdeclarativexmllistmodel.pro +++ b/tests/auto/declarative/qdeclarativexmllistmodel/qdeclarativexmllistmodel.pro @@ -11,7 +11,7 @@ SOURCES += tst_qdeclarativexmllistmodel.cpp symbian: { importFiles.files = data importFiles.path = . - DEPLOYMENT = importFiles + DEPLOYMENT += importFiles } else { DEFINES += SRCDIR=\\\"$$PWD\\\" } diff --git a/tests/auto/declarative/qmlvisual/qmlvisual.pro b/tests/auto/declarative/qmlvisual/qmlvisual.pro index a424b8f..84df15c 100644 --- a/tests/auto/declarative/qmlvisual/qmlvisual.pro +++ b/tests/auto/declarative/qmlvisual/qmlvisual.pro @@ -19,7 +19,6 @@ symbian: { qdeclarativepathview \ qdeclarativepositioners \ qdeclarativesmoothedanimation \ - qdeclarativespringfollow \ qdeclarativetext \ qdeclarativetextedit \ qdeclarativetextinput \ @@ -27,7 +26,7 @@ symbian: { repeater \ selftest_noimages \ webview - DEPLOYMENT = importFiles + DEPLOYMENT += importFiles } else { DEFINES += QT_TEST_SOURCE_DIR=\"\\\"$$PWD\\\"\" } diff --git a/tests/auto/declarative/symbianlibs.pri b/tests/auto/declarative/symbianlibs.pri new file mode 100644 index 0000000..4452f67 --- /dev/null +++ b/tests/auto/declarative/symbianlibs.pri @@ -0,0 +1,9 @@ +#additional libs required for orientation sensor +symbian { + !contains(S60_VERSION, 3.1):!contains(S60_VERSION, 3.2) { + LIBS += -lsensrvclient -lsensrvutil + } + contains(QT_CONFIG, s60): { + LIBS += -lavkon -lcone + } +} diff --git a/tests/auto/guiapplauncher/tst_guiapplauncher.cpp b/tests/auto/guiapplauncher/tst_guiapplauncher.cpp index 4b3ce18..c223992 100644 --- a/tests/auto/guiapplauncher/tst_guiapplauncher.cpp +++ b/tests/auto/guiapplauncher/tst_guiapplauncher.cpp @@ -270,7 +270,7 @@ private: const QSharedPointer<WindowManager> m_wm; }; -// Test mask from enviroment as test lib does not allow options. +// Test mask from environment as test lib does not allow options. static inline unsigned testMask() { unsigned testMask = tst_GuiAppLauncher::TestAll; diff --git a/tests/auto/macnativeevents/tst_macnativeevents.cpp b/tests/auto/macnativeevents/tst_macnativeevents.cpp index 742267f..dce768e 100644 --- a/tests/auto/macnativeevents/tst_macnativeevents.cpp +++ b/tests/auto/macnativeevents/tst_macnativeevents.cpp @@ -488,7 +488,7 @@ void tst_MacNativeEvents::testModifierCtrlWithDontSwapCtrlAndMeta() { // On Mac, we switch the Command and Control modifier by default, so that Command // means Meta, and Control means Command. Lets check that the flag to swith off - // this behaviour works. While working on this test I realised that we actually + // this behaviour works. While working on this test I realized that we actually // don't (and never have) respected this flag for raw key events. Only for // menus, through QKeySequence. I don't want to change this behaviour now, at // least not until someone complains. So I choose to let the test just stop diff --git a/tests/auto/networkselftest/networkselftest.pro b/tests/auto/networkselftest/networkselftest.pro index b7c70a1..98e981c 100644 --- a/tests/auto/networkselftest/networkselftest.pro +++ b/tests/auto/networkselftest/networkselftest.pro @@ -6,12 +6,12 @@ QT = core network wince*: { addFiles.files = rfc3252.txt addFiles.path = . - DEPLOYMENT = addFiles + DEPLOYMENT += addFiles DEFINES += SRCDIR=\\\"\\\" } else:symbian { addFiles.files = rfc3252.txt addFiles.path = . - DEPLOYMENT = addFiles + DEPLOYMENT += addFiles } else:vxworks*: { DEFINES += SRCDIR=\\\"\\\" } else { diff --git a/tests/auto/qabstractfileengine/qabstractfileengine.pro b/tests/auto/qabstractfileengine/qabstractfileengine.pro new file mode 100644 index 0000000..870473a --- /dev/null +++ b/tests/auto/qabstractfileengine/qabstractfileengine.pro @@ -0,0 +1,6 @@ +load(qttest_p4) +QT = core + +SOURCES = tst_qabstractfileengine.cpp +RESOURCES += qabstractfileengine.qrc + diff --git a/tests/auto/qabstractfileengine/qabstractfileengine.qrc b/tests/auto/qabstractfileengine/qabstractfileengine.qrc new file mode 100644 index 0000000..5401b08 --- /dev/null +++ b/tests/auto/qabstractfileengine/qabstractfileengine.qrc @@ -0,0 +1,5 @@ +<!DOCTYPE RCC><RCC version="1.0"> +<qresource prefix="/tst_qabstractfileengine/"> + <file>resources/</file> +</qresource> +</RCC> diff --git a/tests/auto/qabstractfileengine/resources/file.txt b/tests/auto/qabstractfileengine/resources/file.txt new file mode 100644 index 0000000..8a03e0e --- /dev/null +++ b/tests/auto/qabstractfileengine/resources/file.txt @@ -0,0 +1 @@ +This is a simple text file. diff --git a/tests/auto/qabstractfileengine/tst_qabstractfileengine.cpp b/tests/auto/qabstractfileengine/tst_qabstractfileengine.cpp new file mode 100644 index 0000000..5952252 --- /dev/null +++ b/tests/auto/qabstractfileengine/tst_qabstractfileengine.cpp @@ -0,0 +1,765 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the FOO module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtCore/QAbstractFileEngine> +#include <QtCore/QFSFileEngine> + +#include <QtCore/QMutex> +#include <QtCore/QMutexLocker> +#include <QtCore/QSharedPointer> +#include <QtCore/QScopedPointer> +#include <QtCore/QHash> + +#include <QtTest/QTest> + +#include <QtCore/QDebug> + +class tst_QAbstractFileEngine + : public QObject +{ + Q_OBJECT +public slots: + void cleanupTestCase(); + +private slots: + void customHandler(); + + void fileIO_data(); + void fileIO(); + +private: + QStringList filesForRemoval; +}; + +class ReferenceFileEngine + : public QAbstractFileEngine +{ +public: + ReferenceFileEngine(const QString &fileName) + : fileName_(fileName) + , position_(-1) + , openForRead_(false) + , openForWrite_(false) + { + } + + bool open(QIODevice::OpenMode openMode) + { + Q_ASSERT(!openForRead_); + Q_ASSERT(!openForWrite_); + + openFile_ = resolveFile(openMode & QIODevice::WriteOnly); + if (!openFile_) + return false; + + position_ = 0; + if (openMode & QIODevice::ReadOnly) + openForRead_ = true; + + if (openMode & QIODevice::WriteOnly) { + openForWrite_ = true; + + QMutexLocker lock(&openFile_->mutex); + if (openMode & QIODevice::Truncate + || !(openForRead_ || openMode & QIODevice::Append)) + openFile_->content.clear(); + + if (openMode & QIODevice::Append) + position_ = openFile_->content.size(); + } + + return true; + } + + bool close() + { + openFile_.clear(); + + openForRead_ = false; + openForWrite_ = false; + position_ = -1; + + return true; + } + + qint64 size() const + { + QSharedPointer<File> file = resolveFile(false); + if (!file) + return 0; + + QMutexLocker lock(&file->mutex); + return file->content.size(); + } + + qint64 pos() const + { + Q_ASSERT(openForRead_ || openForWrite_); + return position_; + } + + bool seek(qint64 pos) + { + Q_ASSERT(openForRead_ || openForWrite_); + + if (pos >= 0) { + position_ = pos; + return true; + } + + return false; + } + + bool flush() + { + Q_ASSERT(openForRead_ || openForWrite_); + return true; + } + + bool remove() + { + QMutexLocker lock(&fileSystemMutex); + int count = fileSystem.remove(fileName_); + + return (count == 1); + } + + bool copy(const QString &newName) + { + QMutexLocker lock(&fileSystemMutex); + if (!fileSystem.contains(fileName_) + || fileSystem.contains(newName)) + return false; + + fileSystem.insert(newName, fileSystem.value(fileName_)); + return true; + } + + bool rename(const QString &newName) + { + QMutexLocker lock(&fileSystemMutex); + if (!fileSystem.contains(fileName_) + || fileSystem.contains(newName)) + return false; + + fileSystem.insert(newName, fileSystem.take(fileName_)); + return true; + } + + // bool link(const QString &newName) + // { + // Q_UNUSED(newName) + // return false; + // } + + // bool mkdir(const QString &dirName, bool createParentDirectories) const + // { + // Q_UNUSED(dirName) + // Q_UNUSED(createParentDirectories) + + // return false; + // } + + // bool rmdir(const QString &dirName, bool recurseParentDirectories) const + // { + // Q_UNUSED(dirName) + // Q_UNUSED(recurseParentDirectories) + + // return false; + // } + + bool setSize(qint64 size) + { + if (size < 0) + return false; + + QSharedPointer<File> file = resolveFile(false); + if (!file) + return false; + + QMutexLocker lock(&file->mutex); + file->content.resize(size); + + if (openForRead_ || openForWrite_) + if (position_ > size) + position_ = size; + + return (file->content.size() == size); + } + + FileFlags fileFlags(FileFlags type) const + { + QSharedPointer<File> file = resolveFile(false); + if (file) { + QMutexLocker lock(&file->mutex); + return (file->fileFlags & type); + } + + return FileFlags(); + } + + // bool setPermissions(uint perms) + // { + // Q_UNUSED(perms) + + // return false; + // } + + QString fileName(FileName file) const + { + switch (file) { + case DefaultName: + return QLatin1String("DefaultName"); + case BaseName: + return QLatin1String("BaseName"); + case PathName: + return QLatin1String("PathName"); + case AbsoluteName: + return QLatin1String("AbsoluteName"); + case AbsolutePathName: + return QLatin1String("AbsolutePathName"); + case LinkName: + return QLatin1String("LinkName"); + case CanonicalName: + return QLatin1String("CanonicalName"); + case CanonicalPathName: + return QLatin1String("CanonicalPathName"); + case BundleName: + return QLatin1String("BundleName"); + + default: + break; + } + + return QString(); + } + + uint ownerId(FileOwner owner) const + { + QSharedPointer<File> file = resolveFile(false); + if (file) { + switch (owner) { + case OwnerUser: + { + QMutexLocker lock(&file->mutex); + return file->userId; + } + case OwnerGroup: + { + QMutexLocker lock(&file->mutex); + return file->groupId; + } + } + } + + return -2; + } + + QString owner(FileOwner owner) const + { + QSharedPointer<File> file = resolveFile(false); + if (file) { + uint ownerId; + switch (owner) { + case OwnerUser: + { + QMutexLocker lock(&file->mutex); + ownerId = file->userId; + } + + { + QMutexLocker lock(&fileSystemMutex); + return fileSystemUsers.value(ownerId); + } + + case OwnerGroup: + { + QMutexLocker lock(&file->mutex); + ownerId = file->groupId; + } + + { + QMutexLocker lock(&fileSystemMutex); + return fileSystemGroups.value(ownerId); + } + } + } + + return QString(); + } + + QDateTime fileTime(FileTime time) const + { + QSharedPointer<File> file = resolveFile(false); + if (file) { + QMutexLocker lock(&file->mutex); + switch (time) { + case CreationTime: + return file->creation; + case ModificationTime: + return file->modification; + case AccessTime: + return file->access; + } + } + + return QDateTime(); + } + + void setFileName(const QString &file) + { + Q_ASSERT(!openForRead_); + Q_ASSERT(!openForWrite_); + + fileName_ = file; + } + + // typedef QAbstractFileEngineIterator Iterator; + // Iterator *beginEntryList(QDir::Filters filters, const QStringList &filterNames) + // { + // Q_UNUSED(filters) + // Q_UNUSED(filterNames) + + // return 0; + // } + + // Iterator *endEntryList() + // { + // return 0; + // } + + qint64 read(char *data, qint64 maxLen) + { + Q_ASSERT(openForRead_); + + Q_ASSERT(!openFile_.isNull()); + QMutexLocker lock(&openFile_->mutex); + qint64 readSize = qMin(openFile_->content.size() - position_, maxLen); + if (readSize < 0) + return -1; + + qMemCopy(data, openFile_->content.constData() + position_, readSize); + position_ += readSize; + + return readSize; + } + + qint64 write(const char *data, qint64 length) + { + Q_ASSERT(openForWrite_); + + if (length < 0) + return -1; + + Q_ASSERT(!openFile_.isNull()); + QMutexLocker lock(&openFile_->mutex); + if (openFile_->content.size() == position_) + openFile_->content.append(data, length); + else { + if (position_ + length > openFile_->content.size()) + openFile_->content.resize(position_ + length); + openFile_->content.replace(position_, length, data, length); + } + + qint64 writeSize = qMin(length, openFile_->content.size() - position_); + position_ += writeSize; + + return writeSize; + } + +protected: + // void setError(QFile::FileError error, const QString &str); + + struct File + { + File() + : userId(0) + , groupId(0) + , fileFlags( + ReadOwnerPerm | WriteOwnerPerm | ExeOwnerPerm + | ReadUserPerm | WriteUserPerm | ExeUserPerm + | ReadGroupPerm | WriteGroupPerm | ExeGroupPerm + | ReadOtherPerm | WriteOtherPerm | ExeOtherPerm + | FileType | ExistsFlag) + { + } + + QMutex mutex; + + uint userId, groupId; + QAbstractFileEngine::FileFlags fileFlags; + QDateTime creation, modification, access; + + QByteArray content; + }; + + QSharedPointer<File> resolveFile(bool create) const + { + if (openForRead_ || openForWrite_) { + Q_ASSERT(openFile_); + return openFile_; + } + + QMutexLocker lock(&fileSystemMutex); + if (create) { + QSharedPointer<File> &p = fileSystem[fileName_]; + if (p.isNull()) + p = QSharedPointer<File>(new File); + return p; + } + + return fileSystem.value(fileName_); + } + + static QMutex fileSystemMutex; + static QHash<uint, QString> fileSystemUsers, fileSystemGroups; + static QHash<QString, QSharedPointer<File> > fileSystem; + +private: + QString fileName_; + qint64 position_; + bool openForRead_; + bool openForWrite_; + + mutable QSharedPointer<File> openFile_; +}; + +QMutex ReferenceFileEngine::fileSystemMutex; +QHash<uint, QString> ReferenceFileEngine::fileSystemUsers, ReferenceFileEngine::fileSystemGroups; +QHash<QString, QSharedPointer<ReferenceFileEngine::File> > ReferenceFileEngine::fileSystem; + +class FileEngineHandler + : QAbstractFileEngineHandler +{ + QAbstractFileEngine *create(const QString &fileName) const + { + if (fileName.startsWith("QFSFileEngine:")) + return new QFSFileEngine(fileName.mid(14)); + if (fileName.startsWith("reference-file-engine:")) + return new ReferenceFileEngine(fileName.mid(22)); + if (fileName.startsWith("resource:")) + return QAbstractFileEngine::create(QLatin1String(":/tst_qabstractfileengine/resources/") + fileName.mid(9)); + return 0; + } +}; + +void tst_QAbstractFileEngine::cleanupTestCase() +{ + bool failed = false; + + FileEngineHandler handler; + Q_FOREACH(QString file, filesForRemoval) + if (!QFile::remove(file) + || QFile::exists(file)) { + failed = true; + qDebug() << "Couldn't remove file:" << file; + } + + QVERIFY(!failed); +} + +void tst_QAbstractFileEngine::customHandler() +{ + QScopedPointer<QAbstractFileEngine> file; + { + file.reset(QAbstractFileEngine::create("resource:file.txt")); + + QVERIFY(file); + } + + { + FileEngineHandler handler; + + QFile file("resource:file.txt"); + QVERIFY(file.exists()); + } + + { + QFile file("resource:file.txt"); + QVERIFY(!file.exists()); + } +} + +void tst_QAbstractFileEngine::fileIO_data() +{ + QTest::addColumn<QString>("fileName"); + QTest::addColumn<QByteArray>("readContent"); + QTest::addColumn<QByteArray>("writeContent"); + QTest::addColumn<bool>("fileExists"); + + QString resourceTxtFile(":/tst_qabstractfileengine/resources/file.txt"); + QByteArray readContent("This is a simple text file.\n"); + QByteArray writeContent("This contains two lines of text.\n"); + + QTest::newRow("resource") << resourceTxtFile << readContent << QByteArray() << true; + QTest::newRow("native") << "native-file.txt" << readContent << writeContent << false; + QTest::newRow("Forced QFSFileEngine") << "QFSFileEngine:QFSFileEngine-file.txt" << readContent << writeContent << false; + QTest::newRow("Custom FE") << "reference-file-engine:file.txt" << readContent << writeContent << false; + + QTest::newRow("Forced QFSFileEngine (native)") << "QFSFileEngine:native-file.txt" << readContent << writeContent << true; + QTest::newRow("native (Forced QFSFileEngine)") << "QFSFileEngine-file.txt" << readContent << writeContent << true; + QTest::newRow("Custom FE (2)") << "reference-file-engine:file.txt" << readContent << writeContent << true; +} + +void tst_QAbstractFileEngine::fileIO() +{ + QFETCH(QString, fileName); + QFETCH(QByteArray, readContent); + QFETCH(QByteArray, writeContent); + QFETCH(bool, fileExists); + + FileEngineHandler handler; + + + { + QFile file(fileName); + QCOMPARE(file.exists(), fileExists); + + if (!fileExists) { + QVERIFY(file.open(QIODevice::WriteOnly | QIODevice::Unbuffered)); + filesForRemoval.append(fileName); + + QCOMPARE(file.write(readContent), qint64(readContent.size())); + } + } + + // + // File content is: readContent + // + + qint64 fileSize = readContent.size(); + { + // Reading + QFile file(fileName); + + QVERIFY(!file.isOpen()); + QVERIFY(file.open(QIODevice::ReadOnly | QIODevice::Unbuffered)); + + QVERIFY(file.isOpen()); + QCOMPARE(file.size(), fileSize); + QCOMPARE(file.pos(), qint64(0)); + + QCOMPARE(file.size(), fileSize); + QCOMPARE(file.readAll(), readContent); + QCOMPARE(file.pos(), fileSize); + + file.close(); + QVERIFY(!file.isOpen()); + QCOMPARE(file.size(), fileSize); + } + + if (writeContent.isEmpty()) + return; + + { + // Writing / appending + QFile file(fileName); + + QVERIFY(!file.isOpen()); + QVERIFY(file.open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Unbuffered)); + + QVERIFY(file.isOpen()); + QCOMPARE(file.size(), fileSize); + QCOMPARE(file.pos(), fileSize); + + QCOMPARE(file.write(writeContent), qint64(writeContent.size())); + + fileSize += writeContent.size(); + QCOMPARE(file.pos(), fileSize); + QCOMPARE(file.size(), fileSize); + + file.close(); + QVERIFY(!file.isOpen()); + QCOMPARE(file.size(), fileSize); + } + + // + // File content is: readContent + writeContent + // + + { + // Reading and Writing + QFile file(fileName); + + QVERIFY(!file.isOpen()); + QVERIFY(file.open(QIODevice::ReadWrite | QIODevice::Unbuffered)); + + QVERIFY(file.isOpen()); + QCOMPARE(file.size(), fileSize); + QCOMPARE(file.pos(), qint64(0)); + + QCOMPARE(file.readAll(), readContent + writeContent); + QCOMPARE(file.pos(), fileSize); + QCOMPARE(file.size(), fileSize); + + QVERIFY(file.seek(writeContent.size())); + QCOMPARE(file.pos(), qint64(writeContent.size())); + QCOMPARE(file.size(), fileSize); + + QCOMPARE(file.write(readContent), qint64(readContent.size())); + QCOMPARE(file.pos(), fileSize); + QCOMPARE(file.size(), fileSize); + + QVERIFY(file.seek(0)); + QCOMPARE(file.pos(), qint64(0)); + QCOMPARE(file.size(), fileSize); + + QCOMPARE(file.write(writeContent), qint64(writeContent.size())); + QCOMPARE(file.pos(), qint64(writeContent.size())); + QCOMPARE(file.size(), fileSize); + + QVERIFY(file.seek(0)); + QCOMPARE(file.read(writeContent.size()), writeContent); + QCOMPARE(file.pos(), qint64(writeContent.size())); + QCOMPARE(file.size(), fileSize); + + QCOMPARE(file.readAll(), readContent); + QCOMPARE(file.pos(), fileSize); + QCOMPARE(file.size(), fileSize); + + file.close(); + QVERIFY(!file.isOpen()); + QCOMPARE(file.size(), fileSize); + } + + // + // File content is: writeContent + readContent + // + + { + // Writing + QFile file(fileName); + + QVERIFY(!file.isOpen()); + QVERIFY(file.open(QIODevice::ReadWrite | QIODevice::Unbuffered)); + + QVERIFY(file.isOpen()); + QCOMPARE(file.size(), fileSize); + QCOMPARE(file.pos(), qint64(0)); + + QCOMPARE(file.write(writeContent), qint64(writeContent.size())); + QCOMPARE(file.pos(), qint64(writeContent.size())); + QCOMPARE(file.size(), fileSize); + + QVERIFY(file.resize(writeContent.size())); + QCOMPARE(file.size(), qint64(writeContent.size())); + + file.close(); + QVERIFY(!file.isOpen()); + QCOMPARE(file.size(), qint64(writeContent.size())); + + QVERIFY(file.resize(fileSize)); + QCOMPARE(file.size(), fileSize); + } + + // + // File content is: writeContent + <undefined> + // File size is : (readContent + writeContent).size() + // + + { + // Writing / extending + QFile file(fileName); + + QVERIFY(!file.isOpen()); + QVERIFY(file.open(QIODevice::ReadWrite | QIODevice::Unbuffered)); + + QVERIFY(file.isOpen()); + QCOMPARE(file.size(), fileSize); + QCOMPARE(file.pos(), qint64(0)); + + QVERIFY(file.seek(1024)); + QCOMPARE(file.pos(), qint64(1024)); + QCOMPARE(file.size(), fileSize); + + fileSize = 1024 + writeContent.size(); + QCOMPARE(file.write(writeContent), qint64(writeContent.size())); + QCOMPARE(file.pos(), fileSize); + QCOMPARE(file.size(), fileSize); + + QVERIFY(file.seek(1028)); + QCOMPARE(file.pos(), qint64(1028)); + QCOMPARE(file.size(), fileSize); + + fileSize = 1028 + writeContent.size(); + QCOMPARE(file.write(writeContent), qint64(writeContent.size())); + QCOMPARE(file.pos(), fileSize); + QCOMPARE(file.size(), fileSize); + + file.close(); + QVERIFY(!file.isOpen()); + QCOMPARE(file.size(), fileSize); + } + + // + // File content is: writeContent + <undefined> + writeContent + // File size is : 1024 + writeContent.size() + // + + { + // Writing / truncating + QFile file(fileName); + + QVERIFY(!file.isOpen()); + QVERIFY(file.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Unbuffered)); + + QVERIFY(file.isOpen()); + QCOMPARE(file.size(), qint64(0)); + QCOMPARE(file.pos(), qint64(0)); + + fileSize = readContent.size(); + QCOMPARE(file.write(readContent), fileSize); + QCOMPARE(file.pos(), fileSize); + QCOMPARE(file.size(), fileSize); + + file.close(); + QVERIFY(!file.isOpen()); + QCOMPARE(file.size(), fileSize); + } + + // + // File content is: readContent + // +} + +QTEST_APPLESS_MAIN(tst_QAbstractFileEngine) +#include "tst_qabstractfileengine.moc" + diff --git a/tests/auto/qapplication/test/test.pro b/tests/auto/qapplication/test/test.pro index 4c8e9b0..73799f4 100644 --- a/tests/auto/qapplication/test/test.pro +++ b/tests/auto/qapplication/test/test.pro @@ -8,7 +8,7 @@ wince* { additional.path = desktopsettingsaware someTest.files = test.pro someTest.path = test - DEPLOYMENT = additional deploy someTest + DEPLOYMENT += additional deploy someTest } symbian: { @@ -17,7 +17,7 @@ symbian: { someTest.files = test.pro someTest.path = test windowIcon.files = ../heart.svg - DEPLOYMENT = additional deploy someTest windowIcon + DEPLOYMENT += additional deploy someTest windowIcon LIBS += -lcone -lavkon } diff --git a/tests/auto/qaudioinput/qaudioinput.pro b/tests/auto/qaudioinput/qaudioinput.pro index 922c3e4..aac7fb4 100644 --- a/tests/auto/qaudioinput/qaudioinput.pro +++ b/tests/auto/qaudioinput/qaudioinput.pro @@ -6,7 +6,7 @@ QT = core multimedia wince* { deploy.files += 4.wav - DEPLOYMENT = deploy + DEPLOYMENT += deploy DEFINES += SRCDIR=\\\"\\\" QT += gui } else { diff --git a/tests/auto/qaudiooutput/qaudiooutput.pro b/tests/auto/qaudiooutput/qaudiooutput.pro index 0bd0151..f4d840a 100644 --- a/tests/auto/qaudiooutput/qaudiooutput.pro +++ b/tests/auto/qaudiooutput/qaudiooutput.pro @@ -6,7 +6,7 @@ QT = core multimedia wince*|symbian: { deploy.files += 4.wav - DEPLOYMENT = deploy + DEPLOYMENT += deploy !symbian { DEFINES += SRCDIR=\\\"\\\" QT += gui diff --git a/tests/auto/qchar/qchar.pro b/tests/auto/qchar/qchar.pro index 9fcf132..1681220 100644 --- a/tests/auto/qchar/qchar.pro +++ b/tests/auto/qchar/qchar.pro @@ -5,7 +5,7 @@ QT = core wince*|symbian: { deploy.files += NormalizationTest.txt -DEPLOYMENT = deploy +DEPLOYMENT += deploy } symbian: { diff --git a/tests/auto/qclipboard/test/test.pro b/tests/auto/qclipboard/test/test.pro index 6e61b31..12c6b6c 100644 --- a/tests/auto/qclipboard/test/test.pro +++ b/tests/auto/qclipboard/test/test.pro @@ -28,5 +28,5 @@ wince*|symbian: { reg_resource.path = $$REG_RESOURCE_IMPORT_DIR } - DEPLOYMENT = copier paster rsc reg_resource + DEPLOYMENT += copier paster rsc reg_resource }
\ No newline at end of file diff --git a/tests/auto/qdir/qdir.pro b/tests/auto/qdir/qdir.pro index 818f52c..472e646 100644 --- a/tests/auto/qdir/qdir.pro +++ b/tests/auto/qdir/qdir.pro @@ -15,8 +15,11 @@ wince* { TARGET.CAPABILITY += AllFiles TARGET.UID3 = 0xE0340002 DEFINES += SYMBIAN_SRCDIR_UID=$$lower($$replace(TARGET.UID3,"0x","")) + LIBS += -lefsrv + INCLUDEPATH += $$MW_LAYER_SYSTEMINCLUDE } else { contains(QT_CONFIG, qt3support):QT += qt3support DEFINES += SRCDIR=\\\"$$PWD/\\\" } +CONFIG += parallel_test diff --git a/tests/auto/qdir/tst_qdir.cpp b/tests/auto/qdir/tst_qdir.cpp index 9678868..44d1fb6 100644 --- a/tests/auto/qdir/tst_qdir.cpp +++ b/tests/auto/qdir/tst_qdir.cpp @@ -57,11 +57,13 @@ #include "../../shared/filesystem.h" #if defined(Q_OS_SYMBIAN) +# include <f32file.h> # define STRINGIFY(x) #x # define TOSTRING(x) STRINGIFY(x) # define SRCDIR "C:/Private/" TOSTRING(SYMBIAN_SRCDIR_UID) "/" #elif defined(Q_OS_UNIX) # include <unistd.h> +# include <sys/stat.h> #endif #if defined(Q_OS_VXWORKS) @@ -69,7 +71,7 @@ #endif #if defined(Q_OS_SYMBIAN) -// Open C in Symbian doesn't support symbolic links to directories +#define Q_NO_SYMLINKS #define Q_NO_SYMLINKS_TO_DIRS #endif @@ -103,6 +105,8 @@ private slots: void mkdir_data(); void mkdir(); + void makedirReturnCode(); + void rmdir_data(); void rmdir(); @@ -175,10 +179,31 @@ private slots: void detachingOperations(); -#if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN) + void testCaching(); + void isRoot_data(); void isRoot(); + +#ifndef QT_NO_REGEXP + void match_data(); + void match(); #endif + + void drives(); + + void arrayOperator(); + +#ifdef QT3_SUPPORT + void setNameFilter(); +#endif + + void equalityOperator_data(); + void equalityOperator(); + + void isRelative_data(); + void isRelative(); + + void isReadable(); }; // Testing get/set functions @@ -293,6 +318,17 @@ void tst_QDir::mkdir() QVERIFY(fi.exists() && fi.isDir()); } +void tst_QDir::makedirReturnCode() +{ + QString dirName = QString::fromLatin1("makedirReturnCode"); + QDir::current().rmdir(dirName); // cleanup a previous run. + QDir dir(dirName); + QVERIFY(!dir.exists()); + QVERIFY(QDir::current().mkdir(dirName)); + QVERIFY(!QDir::current().mkdir(dirName)); // calling mkdir on an existing dir will fail. + QVERIFY(QDir::current().mkpath(dirName)); // calling mkpath on an existing dir will pass +} + void tst_QDir::rmdir_data() { QTest::addColumn<QString>("path"); @@ -597,6 +633,7 @@ void tst_QDir::entryList() expected.removeAll(".."); #endif +#ifndef Q_NO_SYMLINKS #if defined(Q_OS_WIN) // ### Sadly, this is a platform difference right now. QFile::link(SRCDIR "entryList/file", SRCDIR "entrylist/linktofile.lnk"); @@ -651,6 +688,7 @@ void tst_QDir::entryList() QFile::link("directory", SRCDIR "entrylist/linktodirectory.lnk"); QFile::link("nothing", SRCDIR "entrylist/brokenlink.lnk"); #endif +#endif //Q_NO_SYMLINKS #ifdef Q_WS_MAC if (qstrcmp(QTest::currentDataTag(), "unprintablenames") == 0) @@ -813,11 +851,19 @@ void tst_QDir::canonicalPath_data() #endif QTest::newRow("nonexistant") << "testd" << QString(); + QTest::newRow("rootPath") << QDir::rootPath() << QDir::rootPath(); + +#ifdef Q_OS_MAC + // On Mac OS X 10.5 and earlier, canonicalPath depends on cleanPath which + // is itself very broken and fundamentally wrong on "/./" which, this would + // exercise + if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_6) +#endif + QTest::newRow("rootPath + ./") << QDir::rootPath().append("./") << QDir::rootPath(); + + QTest::newRow("rootPath + ../.. ") << QDir::rootPath().append("../..") << QDir::rootPath(); #if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN) - QTest::newRow("drive:/") << QDir::rootPath() << QDir::rootPath(); QTest::newRow("drive:\\") << QDir::toNativeSeparators(QDir::rootPath()) << QDir::rootPath(); - QTest::newRow("drive:/./") << QDir::rootPath().append("./") << QDir::rootPath(); - QTest::newRow("drive:/../.. ") << QDir::rootPath().append("../..") << QDir::rootPath(); QTest::newRow("drive:\\.\\") << QDir::toNativeSeparators(QDir::rootPath().append("./")) << QDir::rootPath(); QTest::newRow("drive:\\..\\..") << QDir::toNativeSeparators(QDir::rootPath().append("../..")) << QDir::rootPath(); QTest::newRow("drive:") << QDir().canonicalPath().left(2) << QDir().canonicalPath(); @@ -890,7 +936,7 @@ void tst_QDir::current() if (!path.isEmpty()) { bool b = QDir::setCurrent(path); - // If path is non existant, then setCurrent should be false (currentDir is empty in testData) + // If path is non existent, then setCurrent should be false (currentDir is empty in testData) QVERIFY(b == !currentDir.isEmpty()); } if (!currentDir.isEmpty()) { @@ -935,6 +981,7 @@ void tst_QDir::cd() QFETCH(QString, newDir); QDir d = startDir; + bool notUsed = d.exists(); // make sure we cache this before so we can see if 'cd' fails to flush this QCOMPARE(d.cd(cdDir), successExpected); if (successExpected) QCOMPARE(d.absolutePath(), newDir); @@ -1104,24 +1151,24 @@ void tst_QDir::relativeFilePath_data() QTest::newRow("14") << "C:/foo/bar" << "/ding/dong" << "../../ding/dong"; QTest::newRow("15") << "C:/foo/bar" << "D:/ding/dong" << "D:/ding/dong"; QTest::newRow("16") << "C:" << "C:/ding/dong" << "ding/dong"; - QTest::newRow("16") << "C:/" << "C:/ding/dong" << "ding/dong"; - QTest::newRow("17") << "C:" << "C:" << ""; - QTest::newRow("18") << "C:/" << "C:" << ""; - QTest::newRow("19") << "C:" << "C:/" << ""; - QTest::newRow("20") << "C:/" << "C:/" << ""; - QTest::newRow("17") << "C:" << "C:file.txt" << "file.txt"; - QTest::newRow("18") << "C:/" << "C:file.txt" << "file.txt"; - QTest::newRow("19") << "C:" << "C:/file.txt" << "file.txt"; - QTest::newRow("20") << "C:/" << "C:/file.txt" << "file.txt"; - QTest::newRow("21") << "C:" << "D:" << "D:"; - QTest::newRow("22") << "C:" << "D:/" << "D:/"; - QTest::newRow("23") << "C:/" << "D:" << "D:"; - QTest::newRow("24") << "C:/" << "D:/" << "D:/"; + QTest::newRow("17") << "C:/" << "C:/ding/dong" << "ding/dong"; + QTest::newRow("18") << "C:" << "C:" << ""; + QTest::newRow("19") << "C:/" << "C:" << ""; + QTest::newRow("20") << "C:" << "C:/" << ""; + QTest::newRow("21") << "C:/" << "C:/" << ""; + QTest::newRow("22") << "C:" << "C:file.txt" << "file.txt"; + QTest::newRow("23") << "C:/" << "C:file.txt" << "file.txt"; + QTest::newRow("24") << "C:" << "C:/file.txt" << "file.txt"; + QTest::newRow("25") << "C:/" << "C:/file.txt" << "file.txt"; + QTest::newRow("26") << "C:" << "D:" << "D:"; + QTest::newRow("27") << "C:" << "D:/" << "D:/"; + QTest::newRow("28") << "C:/" << "D:" << "D:"; + QTest::newRow("29") << "C:/" << "D:/" << "D:/"; # if !defined(Q_OS_SYMBIAN) - QTest::newRow("25") << "C:/foo/bar" << "//anotherHost/foo/bar" << "//anotherHost/foo/bar"; - QTest::newRow("26") << "//anotherHost/foo" << "//anotherHost/foo/bar" << "bar"; - QTest::newRow("27") << "//anotherHost/foo" << "bar" << "bar"; - QTest::newRow("28") << "//anotherHost/foo" << "C:/foo/bar" << "C:/foo/bar"; + QTest::newRow("30") << "C:/foo/bar" << "//anotherHost/foo/bar" << "//anotherHost/foo/bar"; + QTest::newRow("31") << "//anotherHost/foo" << "//anotherHost/foo/bar" << "bar"; + QTest::newRow("32") << "//anotherHost/foo" << "bar" << "bar"; + QTest::newRow("33") << "//anotherHost/foo" << "C:/foo/bar" << "C:/foo/bar"; # endif #endif } @@ -1167,6 +1214,8 @@ void tst_QDir::remove() QDir dir; QVERIFY(dir.remove("remove-test")); QVERIFY(!dir.remove("/remove-test")); + QTest::ignoreMessage(QtWarningMsg, "QDir::remove: Empty or null file name"); + QVERIFY(!dir.remove("")); } void tst_QDir::rename() @@ -1179,10 +1228,18 @@ void tst_QDir::rename() QVERIFY(dir.rename("rename-test-renamed", "rename-test")); #if defined(Q_OS_MAC) QVERIFY(!dir.rename("rename-test", "/etc/rename-test-renamed")); -#elif !defined(Q_OS_WIN) && !defined(Q_OS_SYMBIAN) - // on windows/symbian this is possible - maybe make the test a bit better +#elif defined(Q_OS_SYMBIAN) + QVERIFY(!dir.rename("rename-test", "/resource/rename-test-renamed")); +#elif !defined(Q_OS_WIN) + // on windows this is possible - maybe make the test a bit better QVERIFY(!dir.rename("rename-test", "/rename-test-renamed")); #endif + QTest::ignoreMessage(QtWarningMsg, "QDir::rename: Empty or null file name(s)"); + QVERIFY(!dir.rename("rename-test", "")); + QTest::ignoreMessage(QtWarningMsg, "QDir::rename: Empty or null file name(s)"); + QVERIFY(!dir.rename("", "rename-test-renamed")); + QVERIFY(!dir.rename("some-file-that-does-not-exist", "rename-test-renamed")); + QVERIFY(dir.remove("rename-test")); } @@ -1256,12 +1313,13 @@ void tst_QDir::dotAndDotDot() { #if defined(Q_OS_WINCE) || defined(Q_OS_SYMBIAN) QSKIP("WinCE and Symbian do not have . nor ..", SkipAll); -#endif +#else QDir dir(QString(SRCDIR "testdir/")); QStringList entryList = dir.entryList(QDir::Dirs); QCOMPARE(entryList, QStringList() << QString(".") << QString("..") << QString("dir") << QString("spaces")); entryList = dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot); QCOMPARE(entryList, QStringList() << QString("dir") << QString("spaces")); +#endif } #ifdef QT3_SUPPORT @@ -1416,6 +1474,29 @@ void tst_QDir::searchPaths() for (int i = 0; i < searchPathPrefixList.count(); ++i) { QVERIFY(QDir::searchPaths(searchPathPrefixList.at(i)).isEmpty()); } + + for (int i = 0; i < searchPathPrefixList.count(); ++i) { + foreach (QString path, searchPathsList.at(i).split(",")) { + QDir::addSearchPath(searchPathPrefixList.at(i), path); + } + } + for (int i = 0; i < searchPathPrefixList.count(); ++i) { + QVERIFY(QDir::searchPaths(searchPathPrefixList.at(i)) == searchPathsList.at(i).split(",")); + } + + QCOMPARE(QFile(filename).exists(), exists); + QCOMPARE(QFileInfo(filename).exists(), exists); + + if (exists) { + QCOMPARE(QFileInfo(filename).absoluteFilePath(), expectedAbsolutePath); + } + + for (int i = 0; i < searchPathPrefixList.count(); ++i) { + QDir::setSearchPaths(searchPathPrefixList.at(i), QStringList()); + } + for (int i = 0; i < searchPathPrefixList.count(); ++i) { + QVERIFY(QDir::searchPaths(searchPathPrefixList.at(i)).isEmpty()); + } } void tst_QDir::entryListWithSearchPaths() @@ -1660,7 +1741,17 @@ void tst_QDir::detachingOperations() QCOMPARE(dir1.sorting(), sorting); } -#if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN) +void tst_QDir::testCaching() +{ + QString dirName = QString::fromLatin1("testCaching"); + QDir::current().rmdir(dirName); // cleanup a previous run. + QDir dir(dirName); + QVERIFY(!dir.exists()); + QDir::current().mkdir(dirName); + QVERIFY(QDir(dirName).exists()); // dir exists + QVERIFY(dir.exists()); // QDir doesn't cache the 'exist' between calls. +} + void tst_QDir::isRoot_data() { QTest::addColumn<QString>("path"); @@ -1670,10 +1761,23 @@ void tst_QDir::isRoot_data() QTest::newRow(QString("rootPath " + test).toLatin1()) << test << true; test = QDir::rootPath().append("./"); QTest::newRow(QString("./ appended " + test).toLatin1()) << test << false; + test = QDir(QDir::rootPath().append("./")).canonicalPath(); - QTest::newRow(QString("canonicalPath " + test).toLatin1()) << test << true; +#ifdef Q_OS_MAC + // On Mac OS X 10.5 and earlier, canonicalPath depends on cleanPath which + // is itself very broken and fundamentally wrong on "/./", which this would + // exercise + if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_6) +#endif + QTest::newRow(QString("canonicalPath " + test).toLatin1()) << test << true; + +#if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN) test = QDir::rootPath().left(2); QTest::newRow(QString("drive relative " + test).toLatin1()) << test << false; +#endif + + QTest::newRow("resources root") << ":/" << true; + QTest::newRow("resources nonroot") << ":/entrylist" << false; } void tst_QDir::isRoot() @@ -1684,7 +1788,202 @@ void tst_QDir::isRoot() QDir dir(path); QCOMPARE(dir.isRoot(),isRoot); } + +#ifndef QT_NO_REGEXP +void tst_QDir::match_data() +{ + QTest::addColumn<QString>("filter"); + QTest::addColumn<QString>("filename"); + QTest::addColumn<bool>("match"); + + QTest::newRow("single, matching") << "*.cpp" << "tst_qdir.cpp" << true; + QTest::newRow("single, not matching") << "*.cpp" << "tst_qdir.h" << false; + QTest::newRow("multi, matching") << "*.cpp;*.h" << "tst_qdir.cpp" << true; + QTest::newRow("multi, matching2") << "*.cpp;*.h" << "tst_qdir.h" << true; + QTest::newRow("multi, not matching") << "*.cpp;*.h" << "readme.txt" << false; +} + +void tst_QDir::match() +{ + QFETCH(QString, filter); + QFETCH(QString, filename); + QFETCH(bool, match); + + QCOMPARE(QDir::match(filter, filename), match); + QCOMPARE(QDir::match(filter.split(QLatin1Char(';')), filename), match); +} +#endif + +void tst_QDir::drives() +{ + QFileInfoList list(QDir::drives()); +#if defined(Q_OS_WIN) + QVERIFY(list.count() >= 1); //system + QLatin1Char systemdrive('c'); +#elif defined(Q_OS_SYMBIAN) + QVERIFY(list.count() >= 2); //system, rom + QLatin1Char romdrive('z'); + QLatin1Char systemdrive('a' + int(RFs::GetSystemDrive())); +#endif +#if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN) + QVERIFY(list.count() <= 26); + bool foundsystem = false; +#ifdef Q_OS_SYMBIAN + bool foundrom = false; #endif + foreach (QFileInfo fi, list) { + QCOMPARE(fi.absolutePath().size(), 3); //"x:/" + QCOMPARE(fi.absolutePath().at(1), QChar(QLatin1Char(':'))); + QCOMPARE(fi.absolutePath().at(2), QChar(QLatin1Char('/'))); + if (fi.absolutePath().at(0).toLower() == systemdrive) + foundsystem = true; +#ifdef Q_OS_SYMBIAN + if (fi.absolutePath().at(0).toLower() == romdrive) + foundrom = true; +#endif + } + QCOMPARE(foundsystem, true); +#ifdef Q_OS_SYMBIAN + QCOMPARE(foundrom, true); +#endif +#else + QCOMPARE(list.count(), 1); //root + QCOMPARE(list.at(0).absolutePath(), QLatin1String("/")); +#endif +} + +void tst_QDir::arrayOperator() +{ + QDir dir1(SRCDIR "entrylist/"); + QDir dir2(SRCDIR "entrylist/"); + + QStringList entries(dir1.entryList()); + int i = dir2.count(); + QCOMPARE(i, entries.count()); + --i; + for (;i>=0;--i) { + QCOMPARE(dir2[i], entries.at(i)); + } +} + +#ifdef QT3_SUPPORT +void tst_QDir::setNameFilter() +{ + QStringList filters; + filters << "*.jpg" << "*.png" << "*.gif"; + QStringList filters2; + filters2 << "*.cpp" << "*.h" << "*.c"; + + QDir dir(SRCDIR "entrylist/"); + + dir.setNameFilter(filters.join(";")); + QCOMPARE(filters, dir.nameFilters()); + QCOMPARE(filters, dir.nameFilter().split(';')); + + dir.setNameFilters(filters2); + QCOMPARE(filters2, dir.nameFilter().split(';')); + + dir.setNameFilter(filters.join(" ")); + QCOMPARE(filters, dir.nameFilters()); + QCOMPARE(filters, dir.nameFilter().split(' ')); + + dir.setNameFilters(filters2); + QCOMPARE(filters2, dir.nameFilter().split(' ')); +} +#endif + +void tst_QDir::equalityOperator_data() +{ + QTest::addColumn<QString>("leftPath"); + QTest::addColumn<QString>("leftNameFilters"); + QTest::addColumn<int>("leftSort"); + QTest::addColumn<int>("leftFilters"); + QTest::addColumn<QString>("rightPath"); + QTest::addColumn<QString>("rightNameFilters"); + QTest::addColumn<int>("rightSort"); + QTest::addColumn<int>("rightFilters"); + QTest::addColumn<bool>("expected"); + + QTest::newRow("same") << SRCDIR << "*.cpp" << int(QDir::Name) << int(QDir::Files) + << SRCDIR << "*.cpp" << int(QDir::Name) << int(QDir::Files) + << true; + + QTest::newRow("relativepaths") << "entrylist/" << "*.cpp" << int(QDir::Name) << int(QDir::Files) + << "./entrylist" << "*.cpp" << int(QDir::Name) << int(QDir::Files) + << true; + + QTest::newRow("diff-filters") << SRCDIR << "*.cpp" << int(QDir::Name) << int(QDir::Files) + << SRCDIR << "*.cpp" << int(QDir::Name) << int(QDir::Dirs) + << false; + + QTest::newRow("diff-sort") << SRCDIR << "*.cpp" << int(QDir::Name) << int(QDir::Files) + << SRCDIR << "*.cpp" << int(QDir::Time) << int(QDir::Files) + << false; + + QTest::newRow("diff-namefilters") << SRCDIR << "*.cpp" << int(QDir::Name) << int(QDir::Files) + << SRCDIR << "*.jpg" << int(QDir::Name) << int(QDir::Files) + << false; +} + +void tst_QDir::equalityOperator() +{ + QFETCH(QString, leftPath); + QFETCH(QString, leftNameFilters); + QFETCH(int, leftSort); + QFETCH(int, leftFilters); + QFETCH(QString, rightPath); + QFETCH(QString, rightNameFilters); + QFETCH(int, rightSort); + QFETCH(int, rightFilters); + QFETCH(bool, expected); + + QDir dir1(leftPath, leftNameFilters, QDir::SortFlags(leftSort), QDir::Filters(leftFilters)); + QDir dir2(rightPath, rightNameFilters, QDir::SortFlags(rightSort), QDir::Filters(rightFilters)); + + QCOMPARE((dir1 == dir2), expected); + QCOMPARE((dir2 == dir1), expected); + QCOMPARE((dir1 != dir2), !expected); + QCOMPARE((dir2 != dir1), !expected); +} + +void tst_QDir::isRelative_data() +{ + QTest::addColumn<QString>("path"); + QTest::addColumn<bool>("relative"); + + QTest::newRow(".") << "./" << true; + QTest::newRow("..") << "../" << true; + QTest::newRow("content") << "entrylist/" << true; + QTest::newRow("current") << QDir::currentPath() << false; + QTest::newRow("homepath") << QDir::homePath() << false; + QTest::newRow("temppath") << QDir::tempPath() << false; + QTest::newRow("rootpath") << QDir::rootPath() << false; + foreach (QFileInfo root, QDir::drives()) { + QTest::newRow(root.absolutePath().toLocal8Bit()) << root.absolutePath() << false; + } +} + +void tst_QDir::isRelative() +{ + QFETCH(QString, path); + QFETCH(bool, relative); + + QCOMPARE(QDir(path).isRelative(), relative); +} + +void tst_QDir::isReadable() +{ + QDir dir; + + QVERIFY(dir.isReadable()); +#if defined (Q_OS_UNIX) && !defined (Q_OS_SYMBIAN) + QVERIFY(dir.mkdir("nonreadabledir")); + QVERIFY(0 == ::chmod("nonreadabledir", 0)); + QVERIFY(!QDir("nonreadabledir").isReadable()); + QVERIFY(0 == ::chmod("nonreadabledir", S_IRUSR | S_IWUSR | S_IXUSR)); + QVERIFY(dir.rmdir("nonreadabledir")); +#endif +} QTEST_MAIN(tst_QDir) #include "tst_qdir.moc" diff --git a/tests/auto/qdiriterator/qdiriterator.pro b/tests/auto/qdiriterator/qdiriterator.pro index 140b57d..0807a18 100644 --- a/tests/auto/qdiriterator/qdiriterator.pro +++ b/tests/auto/qdiriterator/qdiriterator.pro @@ -3,11 +3,6 @@ SOURCES += tst_qdiriterator.cpp RESOURCES += qdiriterator.qrc QT = core -wince*|symbian: { - addFiles.files = entrylist recursiveDirs foo - addFiles.path = . - DEPLOYMENT += addFiles wince*mips*|wincewm50smart-msvc200*: DEFINES += WINCE_BROKEN_ITERATE=1 -} CONFIG += parallel_test diff --git a/tests/auto/qdiriterator/tst_qdiriterator.cpp b/tests/auto/qdiriterator/tst_qdiriterator.cpp index 1a873b8..3a696b5 100644 --- a/tests/auto/qdiriterator/tst_qdiriterator.cpp +++ b/tests/auto/qdiriterator/tst_qdiriterator.cpp @@ -53,10 +53,14 @@ #endif #if defined(Q_OS_SYMBIAN) -// Open C in Symbian doesn't support symbolic links to directories +#define Q_NO_SYMLINKS #define Q_NO_SYMLINKS_TO_DIRS #endif +#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) +#include "../network-settings.h" +#endif + Q_DECLARE_METATYPE(QDirIterator::IteratorFlags) Q_DECLARE_METATYPE(QDir::Filters) @@ -118,6 +122,10 @@ private slots: void longPath(); void task185502_dirorder(); void relativePaths(); +#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) + void uncPaths_data(); + void uncPaths(); +#endif }; tst_QDirIterator::tst_QDirIterator() @@ -147,6 +155,8 @@ tst_QDirIterator::tst_QDirIterator() createDirectory("foo/bar"); createFile("foo/bar/readme.txt"); + createDirectory("empty"); + #ifndef Q_NO_SYMLINKS # if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN) // ### Sadly, this is a platform difference right now. @@ -288,6 +298,20 @@ void tst_QDirIterator::iterateRelativeDirectory_data() #endif "entrylist/directory/dummy," "entrylist/writable").split(','); + + QTest::newRow("empty, default") + << QString("empty") << QDirIterator::IteratorFlags(0) + << QDir::Filters(QDir::NoFilter) << QStringList("*") +#if defined(Q_OS_SYMBIAN) || defined(Q_OS_WINCE) + << QStringList(); +#else + << QString("empty/.,empty/..").split(','); +#endif + + QTest::newRow("empty, QDir::NoDotAndDotDot") + << QString("empty") << QDirIterator::IteratorFlags(0) + << QDir::Filters(QDir::NoDotAndDotDot) << QStringList("*") + << QStringList(); } void tst_QDirIterator::iterateRelativeDirectory() @@ -532,6 +556,28 @@ void tst_QDirIterator::relativePaths() } } +#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) +void tst_QDirIterator::uncPaths_data() +{ + QTest::addColumn<QString>("dirName"); + QTest::newRow("uncserver") + <<QString("//" + QtNetworkSettings::winServerName()); + QTest::newRow("uncserver/testshare") + <<QString("//" + QtNetworkSettings::winServerName() + "/testshare"); + QTest::newRow("uncserver/testshare/tmp") + <<QString("//" + QtNetworkSettings::winServerName() + "/testshare/tmp"); +} +void tst_QDirIterator::uncPaths() +{ + QFETCH(QString, dirName); + QDirIterator iterator(dirName, QDir::AllEntries|QDir::NoDotAndDotDot, QDirIterator::Subdirectories); + while(iterator.hasNext()) { + iterator.next(); + QCOMPARE(iterator.filePath(), QDir::cleanPath(iterator.filePath())); + } +} +#endif + QTEST_MAIN(tst_QDirIterator) #include "tst_qdiriterator.moc" diff --git a/tests/auto/qdirmodel/tst_qdirmodel.cpp b/tests/auto/qdirmodel/tst_qdirmodel.cpp index 41bbd87..e252b82 100644 --- a/tests/auto/qdirmodel/tst_qdirmodel.cpp +++ b/tests/auto/qdirmodel/tst_qdirmodel.cpp @@ -583,19 +583,15 @@ void tst_QDirModel::unreadable() void tst_QDirModel::filePath() { +#ifdef Q_OS_SYMBIAN + QSKIP("OS doesn't support symbolic links", SkipAll); +#else QFile::remove(SRCDIR "test.lnk"); QVERIFY(QFile(SRCDIR "tst_qdirmodel.cpp").link(SRCDIR "test.lnk")); QDirModel model; model.setResolveSymlinks(false); QModelIndex index = model.index(SRCDIR "test.lnk"); QVERIFY(index.isValid()); -#if defined(Q_OS_SYMBIAN) - // Since model will force lowercase path in Symbian, make case insensitive compare - // Note: Windows should fail this, too, if test path has any uppercase letters. - QCOMPARE(model.filePath(index).toLower(), QString(SRCDIR).toLower() + "test.lnk"); - model.setResolveSymlinks(true); - QCOMPARE(model.filePath(index).toLower(), QString(SRCDIR).toLower() + "tst_qdirmodel.cpp"); -#else #ifndef Q_OS_WINCE QString path = SRCDIR; #else @@ -604,8 +600,8 @@ void tst_QDirModel::filePath() QCOMPARE(model.filePath(index), path + QString( "test.lnk")); model.setResolveSymlinks(true); QCOMPARE(model.filePath(index), path + QString( "tst_qdirmodel.cpp")); -#endif QFile::remove(SRCDIR "test.lnk"); +#endif } void tst_QDirModel::task196768_sorting() @@ -613,11 +609,6 @@ void tst_QDirModel::task196768_sorting() //this task showed that the persistent model indexes got corrupted when sorting QString path = SRCDIR; -#ifdef Q_OS_SYMBIAN - if(!RProcess().HasCapability(ECapabilityAllFiles)) - QEXPECT_FAIL("", "QTBUG-9746", Continue); -#endif - QDirModel model; /* QDirModel has a bug if we show the content of the subdirectory inside a hidden directory @@ -637,6 +628,11 @@ void tst_QDirModel::task196768_sorting() QCOMPARE(index.data(), index2.data()); view.setSortingEnabled(true); index2 = model.index(path); + +#ifdef Q_OS_SYMBIAN + if(!RProcess().HasCapability(ECapabilityAllFiles)) + QEXPECT_FAIL("", "QTBUG-9746", Continue); +#endif QCOMPARE(index.data(), index2.data()); } diff --git a/tests/auto/qfile/largefile/largefile.pro b/tests/auto/qfile/largefile/largefile.pro index d67cb46..6407cb6 100644 --- a/tests/auto/qfile/largefile/largefile.pro +++ b/tests/auto/qfile/largefile/largefile.pro @@ -4,3 +4,5 @@ QT = core SOURCES += tst_largefile.cpp wince*: SOURCES += $$QT_SOURCE_TREE/src/corelib/kernel/qfunctions_wince.cpp + +CONFIG += parallel_test diff --git a/tests/auto/qfile/qfile.pro b/tests/auto/qfile/qfile.pro index 727f660..f41d327 100644 --- a/tests/auto/qfile/qfile.pro +++ b/tests/auto/qfile/qfile.pro @@ -7,3 +7,4 @@ wince*|symbian:{ !symbian:SUBDIRS += largefile +CONFIG += parallel_test diff --git a/tests/auto/qfile/test/test.pro b/tests/auto/qfile/test/test.pro index c657e9a..673eacc 100644 --- a/tests/auto/qfile/test/test.pro +++ b/tests/auto/qfile/test/test.pro @@ -10,7 +10,7 @@ wince*|symbian { resour.files += ..\\resources\\file1.ext1 resour.path = resources - DEPLOYMENT = files resour + DEPLOYMENT += files resour } wince* { diff --git a/tests/auto/qfile/tst_qfile.cpp b/tests/auto/qfile/tst_qfile.cpp index ee799f3..c19079f 100644 --- a/tests/auto/qfile/tst_qfile.cpp +++ b/tests/auto/qfile/tst_qfile.cpp @@ -170,6 +170,7 @@ private slots: void encodeName(); void truncate(); void seekToPos(); + void seekAfterEndOfFile(); void FILEReadWrite(); void i18nFileName_data(); void i18nFileName(); @@ -210,6 +211,16 @@ private slots: void openStandardStreams(); + void resize_data(); + void resize(); + + void objectConstructors(); +#ifdef Q_OS_SYMBIAN + void platformSecurity_data(); + void platformSecurity(); +#endif + void caseSensitivity(); + // --- Task related tests below this line void task167217(); @@ -394,6 +405,7 @@ void tst_QFile::cleanupTestCase() QFile::remove("qfile_map_testfile"); QFile::remove("readAllBuffer.txt"); QFile::remove("qt_file.tmp"); + QFile::remove("File.txt"); } //------------------------------------------ @@ -402,7 +414,7 @@ void tst_QFile::cleanupTestCase() // attributes and the contents itself // will be changed as far as we have a // proper way to handle files in the -// testing enviroment. +// testing environment. //------------------------------------------ void tst_QFile::exists() @@ -1108,6 +1120,7 @@ void tst_QFile::permissions() QFETCH(bool, expected); QFile f(file); QCOMPARE(((f.permissions() & perms) == QFile::Permissions(perms)), expected); + QCOMPARE(((QFile::permissions(file) & perms) == QFile::Permissions(perms)), expected); } void tst_QFile::setPermissions() @@ -1285,17 +1298,32 @@ static QString getWorkingDirectoryForLink(const QString &linkFileName) void tst_QFile::link() { +#if defined(Q_OS_SYMBIAN) + QSKIP("Symbian does not support links", SkipAll); +#endif QFile::remove("myLink.lnk"); - QFileInfo info1("tst_qfile.cpp"); - QVERIFY(QFile::link("tst_qfile.cpp", "myLink.lnk")); + + QFileInfo info1(SRCDIR "tst_qfile.cpp"); + QString referenceTarget = QDir::cleanPath(info1.absoluteFilePath()); + + QVERIFY(QFile::link(SRCDIR "tst_qfile.cpp", "myLink.lnk")); + QFileInfo info2("myLink.lnk"); QVERIFY(info2.isSymLink()); - QCOMPARE(info2.symLinkTarget(), info1.absoluteFilePath()); + QCOMPARE(info2.symLinkTarget(), referenceTarget); + + QFile link("myLink.lnk"); + QVERIFY(link.open(QIODevice::ReadOnly)); + QCOMPARE(link.symLinkTarget(), referenceTarget); + link.close(); + + QCOMPARE(QFile::symLinkTarget("myLink.lnk"), referenceTarget); #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) QString wd = getWorkingDirectoryForLink(info2.absoluteFilePath()); - QCOMPARE(QDir::fromNativeSeparators(wd), info1.absolutePath()); + QCOMPARE(QDir::fromNativeSeparators(wd), QDir::cleanPath(info1.absolutePath())); #endif + QVERIFY(QFile::remove(info2.absoluteFilePath())); } @@ -1324,6 +1352,9 @@ void tst_QFile::linkToDir() void tst_QFile::absolutePathLinkToRelativePath() { +#if defined(Q_OS_SYMBIAN) + QSKIP("Symbian does not support links", SkipAll); +#endif QFile::remove("myDir/test.txt"); QFile::remove("myDir/myLink.lnk"); QDir dir; @@ -1346,6 +1377,9 @@ void tst_QFile::absolutePathLinkToRelativePath() void tst_QFile::readBrokenLink() { +#if defined(Q_OS_SYMBIAN) + QSKIP("Symbian does not support links", SkipAll); +#endif QFile::remove("myLink2.lnk"); QFileInfo info1("file12"); #if defined(Q_OS_SYMBIAN) @@ -1635,10 +1669,40 @@ void tst_QFile::seekToPos() } +void tst_QFile::seekAfterEndOfFile() +{ + QLatin1String filename("seekAfterEof.dat"); + QFile::remove(filename); + { + QFile file(filename); + QVERIFY(file.open(QFile::WriteOnly)); + file.write("abcd"); + QCOMPARE(file.size(), qint64(4)); + file.seek(8); + file.write("ijkl"); + QCOMPARE(file.size(), qint64(12)); + file.seek(4); + file.write("efgh"); + QCOMPARE(file.size(), qint64(12)); + file.seek(16); + file.write("----"); + QCOMPARE(file.size(), qint64(20)); + file.flush(); + } + + QFile file(filename); + QVERIFY(file.open(QFile::ReadOnly)); + QByteArray contents = file.readAll(); + QCOMPARE(contents.left(12), QByteArray("abcdefghijkl", 12)); + //bytes 12-15 are uninitialised so we don't care what they read as. + QCOMPARE(contents.mid(16), QByteArray("----", 4)); + file.close(); + QFile::remove(filename); +} void tst_QFile::FILEReadWrite() { - // Tests modifing a file. First creates it then reads in 4 bytes and then overwrites these + // Tests modifying a file. First creates it then reads in 4 bytes and then overwrites these // 4 bytes with new values. At the end check to see the file contains the new values. QFile::remove("FILEReadWrite.txt"); @@ -2494,10 +2558,11 @@ void tst_QFile::standarderror() void tst_QFile::handle() { -#ifndef Q_OS_WINCE + int fd; +#if !defined(Q_OS_WINCE) && !defined(Q_OS_SYMBIAN) QFile file(SRCDIR "tst_qfile.cpp"); QVERIFY(file.open(QIODevice::ReadOnly)); - int fd = int(file.handle()); + fd = int(file.handle()); QVERIFY(fd > 2); QCOMPARE(int(file.handle()), fd); char c = '\0'; @@ -2524,6 +2589,7 @@ void tst_QFile::handle() QCOMPARE(c, '*'); #endif + //test round trip of adopted stdio file handle QFile file2; FILE *fp = fopen(SRCDIR "tst_qfile.cpp", "r"); file2.open(fp, QIODevice::ReadOnly); @@ -2531,6 +2597,7 @@ void tst_QFile::handle() QCOMPARE(int(file2.handle()), int(fileno(fp))); fclose(fp); + //test round trip of adopted posix file handle #ifdef Q_OS_UNIX QFile file3; fd = QT_OPEN(SRCDIR "tst_qfile.cpp", QT_OPEN_RDONLY); @@ -2542,6 +2609,9 @@ void tst_QFile::handle() void tst_QFile::nativeHandleLeaks() { +#ifdef Q_OS_SYMBIAN + QSKIP("test assumptions invalid for symbian", SkipAll); +#else int fd1, fd2; #ifdef Q_OS_WIN @@ -2583,6 +2653,7 @@ void tst_QFile::nativeHandleLeaks() #ifdef Q_OS_WIN QCOMPARE( handle2, handle1 ); #endif +#endif } void tst_QFile::readEof_data() @@ -2898,6 +2969,7 @@ void tst_QFile::mapOpenMode() { QFETCH(int, openMode); static const qint64 fileSize = 4096; + QByteArray pattern(fileSize, 'A'); QString fileName = QDir::currentPath() + '/' + "qfile_map_testfile"; @@ -3037,5 +3109,123 @@ void tst_QFile::writeNothing() } } +void tst_QFile::resize_data() +{ + QTest::addColumn<int>("filetype"); + + QTest::newRow("native") << int(OpenQFile); + QTest::newRow("fileno") << int(OpenFd); + QTest::newRow("stream") << int(OpenStream); +} + +void tst_QFile::resize() +{ + QFETCH(int, filetype); + QString filename(QLatin1String("file.txt")); + QFile file(filename); + QVERIFY(openFile(file, QIODevice::ReadWrite, FileType(filetype))); + QVERIFY(file.resize(8)); + QCOMPARE(file.size(), qint64(8)); + closeFile(file); + QFile::resize(filename, 4); + QCOMPARE(QFileInfo(filename).size(), qint64(4)); + QVERIFY(QFile::remove(filename)); +} + +void tst_QFile::objectConstructors() +{ + QObject ob; + QFile* file1 = new QFile(SRCDIR "testfile.txt", &ob); + QFile* file2 = new QFile(&ob); + QVERIFY(file1->exists()); + QVERIFY(!file2->exists()); +} + +#ifdef Q_OS_SYMBIAN +void tst_QFile::platformSecurity_data() +{ + QTest::addColumn<QString>("file"); + QTest::addColumn<bool>("readable"); + QTest::addColumn<bool>("writable"); + + QString selfname = QCoreApplication::applicationFilePath(); + QString ownprivate = QCoreApplication::applicationDirPath(); + QString owndrive = selfname.left(2); + bool amiprivileged = RProcess().HasCapability(ECapabilityAllFiles); + QTest::newRow("resource") << owndrive + "/resource/apps/tst_qfile.rsc" << true << amiprivileged; + QTest::newRow("sys") << selfname << amiprivileged << false; + QTest::newRow("own private") << ownprivate + "/testfile.txt" << true << true; + QTest::newRow("other private") << owndrive + "/private/10003a3f/import/apps/tst_qfile_reg.rsc" << amiprivileged << amiprivileged; +} + +void tst_QFile::platformSecurity() +{ + QFETCH(QString,file); + QFETCH(bool,readable); + QFETCH(bool,writable); + + { + QFile f(file); + QCOMPARE(f.open(QIODevice::ReadOnly), readable); + } + + { + QFile f(file); + QCOMPARE(f.open(QIODevice::ReadOnly | QIODevice::Unbuffered), readable); + } + + //append mode used to avoid truncating the files. + { + QFile f(file); + QCOMPARE(f.open(QIODevice::WriteOnly | QIODevice::Append), writable); + } + + { + QFile f(file); + QCOMPARE(f.open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Unbuffered), writable); + } + + { + QFile f(file); + QCOMPARE(f.open(QIODevice::ReadWrite), writable); + } + + { + QFile f(file); + QCOMPARE(f.open(QIODevice::ReadWrite | QIODevice::Unbuffered), writable); + } +} +#endif + +void tst_QFile::caseSensitivity() +{ +#if defined(Q_OS_SYMBIAN) || defined(Q_OS_WIN) || defined(Q_OS_MAC) + const bool caseSensitive = false; +#else + const bool caseSensitive = true; +#endif + QByteArray testData("a little test"); + QString filename("File.txt"); + { + QFile f(filename); + QVERIFY(f.open(QIODevice::WriteOnly)); + QVERIFY(f.write(testData)); + f.close(); + } + QStringList alternates; + QFileInfo fi(filename); + QVERIFY(fi.exists()); + alternates << "file.txt" << "File.TXT" << "fIlE.TxT" << fi.absoluteFilePath().toUpper() << fi.absoluteFilePath().toLower(); + foreach (QString alt, alternates) { + QFileInfo fi2(alt); + QCOMPARE(fi2.exists(), !caseSensitive); + QCOMPARE(fi.size() == fi2.size(), !caseSensitive); + QFile f2(alt); + QCOMPARE(f2.open(QIODevice::ReadOnly), !caseSensitive); + if (!caseSensitive) + QCOMPARE(f2.readAll(), testData); + } +} + QTEST_MAIN(tst_QFile) #include "tst_qfile.moc" diff --git a/tests/auto/qfiledialog/resources/file.txt b/tests/auto/qfiledialog/resources/file.txt new file mode 100644 index 0000000..8a03e0e --- /dev/null +++ b/tests/auto/qfiledialog/resources/file.txt @@ -0,0 +1 @@ +This is a simple text file. diff --git a/tests/auto/qfiledialog/tst_qfiledialog.cpp b/tests/auto/qfiledialog/tst_qfiledialog.cpp index ca7c445..668a3e0 100644 --- a/tests/auto/qfiledialog/tst_qfiledialog.cpp +++ b/tests/auto/qfiledialog/tst_qfiledialog.cpp @@ -61,9 +61,13 @@ #include <qlineedit.h> #include <qlayout.h> #include "../../shared/util.h" +#if defined QT_BUILD_INTERNAL #include "../../../src/gui/dialogs/qsidebar_p.h" #include "../../../src/gui/dialogs/qfilesystemmodel_p.h" #include "../../../src/gui/dialogs/qfiledialog_p.h" +#endif +#include <QFileDialog> +#include <QFileSystemModel> #include "../network-settings.h" @@ -183,7 +187,7 @@ public: QSize sizeHint(const QStyleOptionViewItem &, const QModelIndex &) const { return QSize(); } }; -// emited any time the selection model emits current changed +// emitted any time the selection model emits current changed void tst_QFiledialog::currentChangedSignal() { QNonNativeFileDialog fd; @@ -208,7 +212,7 @@ void tst_QFiledialog::currentChangedSignal() QCOMPARE(spyCurrentChanged.count(), 1); } -// only emited from the views, sidebar, or lookin combo +// only emitted from the views, sidebar, or lookin combo void tst_QFiledialog::directoryEnteredSignal() { #if defined QT_BUILD_INTERNAL @@ -269,13 +273,13 @@ void tst_QFiledialog::filesSelectedSignal_data() QTest::newRow("existingFiles") << QFileDialog::ExistingFiles; } -// emited when the dialog closes with the selected files +// emitted when the dialog closes with the selected files void tst_QFiledialog::filesSelectedSignal() { QNonNativeFileDialog fd; fd.setViewMode(QFileDialog::List); fd.setOptions(QFileDialog::DontUseNativeDialog); - QDir testDir(SRCDIR"/../../.."); + QDir testDir(SRCDIR); fd.setDirectory(testDir); QFETCH(QFileDialog::FileMode, fileMode); fd.setFileMode(fileMode); @@ -313,7 +317,7 @@ void tst_QFiledialog::filesSelectedSignal() QCOMPARE(spyFilesSelected.count(), 1); } -// only emited when the combo box is activated +// only emitted when the combo box is activated void tst_QFiledialog::filterSelectedSignal() { QNonNativeFileDialog fd; @@ -1304,6 +1308,10 @@ QString saveName(QWidget *, const QString &, const QString &, const QString &, Q void tst_QFiledialog::hooks() { +#ifdef Q_OS_SYMBIAN + if(QSysInfo::symbianVersion() < QSysInfo::SV_SF_3) + QSKIP("writing to data exports in paged dll not supported and crashes on symbian versions prior to ^3", SkipAll); +#endif qt_filedialog_existing_directory_hook = &existing; qt_filedialog_save_filename_hook = &saveName; qt_filedialog_open_filename_hook = &openName; diff --git a/tests/auto/qfileinfo/qfileinfo.pro b/tests/auto/qfileinfo/qfileinfo.pro index 3141db6..b35b1e0 100644 --- a/tests/auto/qfileinfo/qfileinfo.pro +++ b/tests/auto/qfileinfo/qfileinfo.pro @@ -10,9 +10,11 @@ wince*:|symbian: { deploy.files += qfileinfo.qrc tst_qfileinfo.cpp res.files = resources\\file1 resources\\file1.ext1 resources\\file1.ext1.ext2 res.path = resources - DEPLOYMENT = deploy res + DEPLOYMENT += deploy res } +win32*:LIBS += -ladvapi32 -lnetapi32 + symbian { TARGET.CAPABILITY=AllFiles LIBS *= -lefsrv @@ -28,3 +30,6 @@ wince* { DEFINES += SRCDIR=\\\"$$PWD/\\\" } +contains(QT_CONFIG, qt3support): QT += qt3support + +CONFIG += parallel_test diff --git a/tests/auto/qfileinfo/tst_qfileinfo.cpp b/tests/auto/qfileinfo/tst_qfileinfo.cpp index 202f212..4d9e80b 100644 --- a/tests/auto/qfileinfo/tst_qfileinfo.cpp +++ b/tests/auto/qfileinfo/tst_qfileinfo.cpp @@ -54,11 +54,14 @@ #include <fcntl.h> #include <unistd.h> #include <sys/stat.h> +#include <sys/types.h> +#include <pwd.h> #endif #ifdef Q_OS_WIN #define _WIN32_WINNT 0x500 #include <qt_windows.h> #include <qlibrary.h> +#include <lm.h> #endif #include <qplatformdefs.h> #include <qdebug.h> @@ -72,6 +75,7 @@ #if defined(Q_OS_SYMBIAN) # define SRCDIR "" +# define NO_SYMLINKS #endif QT_BEGIN_NAMESPACE @@ -187,6 +191,13 @@ private slots: void notEqualOperator() const; void detachingOperations(); + +#if !defined(Q_OS_WINCE) && !defined(Q_OS_SYMBIAN) + void owner(); +#endif + void group(); + + void invalidState(); }; tst_QFileInfo::tst_QFileInfo() @@ -415,6 +426,7 @@ void tst_QFileInfo::exists_data() QTest::newRow("data9") << SRCDIR "resources/file?.ext1" << false; QTest::newRow("data10") << "." << true; QTest::newRow("data11") << ". " << false; + QTest::newRow("empty") << "" << false; QTest::newRow("simple dir") << SRCDIR "resources" << true; QTest::newRow("simple dir with slash") << SRCDIR "resources/" << true; @@ -517,7 +529,11 @@ void tst_QFileInfo::absFilePath() QFETCH(QString, expected); QFileInfo fi(file); +#if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN) + QVERIFY(QString::compare(fi.absoluteFilePath(), expected, Qt::CaseInsensitive) == 0); +#else QCOMPARE(fi.absoluteFilePath(), expected); +#endif } void tst_QFileInfo::canonicalPath() @@ -607,20 +623,29 @@ void tst_QFileInfo::canonicalFilePath() #ifdef Q_OS_WIN typedef BOOL (WINAPI *PtrCreateSymbolicLink)(LPTSTR, LPTSTR, DWORD); PtrCreateSymbolicLink ptrCreateSymbolicLink = - (PtrCreateSymbolicLink)QLibrary::resolve(QLatin1String("kernel32"), "CreateSymbolicLink"); + (PtrCreateSymbolicLink)QLibrary::resolve(QLatin1String("kernel32"), "CreateSymbolicLinkW"); - if (!ptrCreateSymbolicLink || - ptrCreateSymbolicLink((wchar_t*)QString("res").utf16(), (wchar_t*)QString("resources").utf16(), 1) == 0) { + if (!ptrCreateSymbolicLink) { QSKIP("Symbolic links aren't supported by FS", SkipAll); + } else { + // CreateSymbolicLink can return TRUE & still fail to create the link, + // the error code in that case is ERROR_PRIVILEGE_NOT_HELD (1314) + SetLastError(0); + BOOL ret = ptrCreateSymbolicLink((wchar_t*)QString("res").utf16(), (wchar_t*)QString("resources").utf16(), 1); + DWORD dwErr = GetLastError(); + if (!ret) + QSKIP("Symbolic links aren't supported by FS", SkipAll); + QString currentPath = QDir::currentPath(); + bool is_res_Current = QDir::setCurrent("res"); + if (!is_res_Current && dwErr == 1314) + QSKIP("Not enough privilages to create Symbolic links", SkipAll); + QCOMPARE(is_res_Current, true); + + QCOMPARE(QFileInfo("file1").canonicalFilePath(), currentPath + "/resources/file1"); + + QCOMPARE(QDir::setCurrent(currentPath), true); + QDir::current().rmdir("res"); } - - QString currentPath = QDir::currentPath(); - QCOMPARE(QDir::setCurrent("res"), true); - - QCOMPARE(QFileInfo("file1").canonicalFilePath(), currentPath + "/resources/file1"); - - QCOMPARE(QDir::setCurrent(currentPath), true); - QFile::remove("res"); #endif } @@ -698,10 +723,19 @@ void tst_QFileInfo::dir() QFETCH(QString, expected); QFileInfo fi(file); - if (absPath) + if (absPath) { QCOMPARE(fi.absolutePath(), expected); - else + QCOMPARE(fi.absoluteDir().path(), expected); +#ifdef QT3_SUPPORT + QCOMPARE(fi.dir(true).path(), expected); +#endif + } else { QCOMPARE(fi.path(), expected); + QCOMPARE(fi.dir().path(), expected); +#ifdef QT3_SUPPORT + QCOMPARE(fi.dir(false).path(), expected); +#endif + } } @@ -1089,6 +1123,7 @@ void tst_QFileInfo::fileTimes_oldFile() void tst_QFileInfo::isSymLink_data() { +#ifndef NO_SYMLINKS QFile::remove("link.lnk"); QFile::remove("brokenlink.lnk"); QFile::remove("dummyfile"); @@ -1108,10 +1143,12 @@ void tst_QFileInfo::isSymLink_data() QTest::newRow("existent file") << SRCDIR "tst_qfileinfo.cpp" << false << ""; QTest::newRow("link") << "link.lnk" << true << QFileInfo(SRCDIR "tst_qfileinfo.cpp").absoluteFilePath(); QTest::newRow("broken link") << "brokenlink.lnk" << true << QFileInfo("dummyfile").absoluteFilePath(); +#endif } void tst_QFileInfo::isSymLink() { +#ifndef NO_SYMLINKS QFETCH(QString, path); QFETCH(bool, isSymLink); QFETCH(QString, linkTarget); @@ -1119,6 +1156,9 @@ void tst_QFileInfo::isSymLink() QFileInfo fi(path); QCOMPARE(fi.isSymLink(), isSymLink); QCOMPARE(fi.symLinkTarget(), linkTarget); +#else + QSKIP("no symbolic link support on this platform", SkipAll); +#endif } void tst_QFileInfo::isHidden_data() @@ -1252,9 +1292,10 @@ void tst_QFileInfo::isLocalFs() QFileInfo info(path); QFileInfoPrivate *privateInfo = getPrivate(info); - QVERIFY(privateInfo->fileEngine); - QCOMPARE(bool(privateInfo->fileEngine->fileFlags(QAbstractFileEngine::LocalDiskFlag) - & QAbstractFileEngine::LocalDiskFlag), isLocalFs); + QCOMPARE((privateInfo->fileEngine == 0), isLocalFs); + if (privateInfo->fileEngine) + QCOMPARE(bool(privateInfo->fileEngine->fileFlags(QAbstractFileEngine::LocalDiskFlag) + & QAbstractFileEngine::LocalDiskFlag), isLocalFs); } void tst_QFileInfo::refresh() @@ -1343,8 +1384,24 @@ void tst_QFileInfo::ntfsJunctionPointsAndSymlinks_data() file.open(QIODevice::ReadWrite); file.close(); - QVERIFY(pwd.exists("abs_symlink") || createSymbolicLinkW((wchar_t*)absSymlink.utf16(),(wchar_t*)absTarget.utf16(),0x1)); - QVERIFY(pwd.exists(relSymlink) || createSymbolicLinkW((wchar_t*)relSymlink.utf16(),(wchar_t*)relTarget.utf16(),0x1)); + DWORD err = ERROR_SUCCESS ; + if (!pwd.exists("abs_symlink")) + if (!createSymbolicLinkW((wchar_t*)absSymlink.utf16(),(wchar_t*)absTarget.utf16(),0x1)) + err = GetLastError(); + if (err == ERROR_SUCCESS && !pwd.exists(relSymlink)) + if (!createSymbolicLinkW((wchar_t*)relSymlink.utf16(),(wchar_t*)relTarget.utf16(),0x1)) + err = GetLastError(); + if (err != ERROR_SUCCESS) { + wchar_t errstr[0x100]; + DWORD count = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM, + 0, err, 0, errstr, 0x100, 0); + QString error(QString::fromUtf16(errstr, count)); + qWarning() << error; + //we need at least one data set for the test not to assert fail when skipping _data function + QDir target("target"); + QTest::newRow("dummy") << target.path() << false << "" << target.canonicalPath(); + QSKIP("link not supported by FS or insufficient privilege", SkipSingle); + } QVERIFY(file.exists()); QTest::newRow("absolute dir symlink") << absSymlink << true << QDir::fromNativeSeparators(absTarget) << target.canonicalPath(); @@ -1433,10 +1490,6 @@ void tst_QFileInfo::brokenShortcut() void tst_QFileInfo::isWritable() { -#ifdef Q_OS_SYMBIAN - QSKIP("Currently skipped on Symbian OS, but surely there is a writeable file somewhere???", SkipAll); -#endif - QFile tempfile("tempfile.txt"); tempfile.open(QIODevice::WriteOnly); tempfile.write("This file is generated by the QFileInfo autotest."); @@ -1454,7 +1507,7 @@ void tst_QFileInfo::isWritable() QVERIFY(fi.exists()); QVERIFY(!fi.isWritable()); #endif -#ifdef Q_OS_UNIX +#if defined (Q_OS_UNIX) && !defined (Q_OS_SYMBIAN) if (::getuid() == 0) QVERIFY(QFileInfo("/etc/passwd").isWritable()); else @@ -1465,9 +1518,6 @@ void tst_QFileInfo::isWritable() void tst_QFileInfo::isExecutable() { #ifdef Q_OS_SYMBIAN -# if defined(Q_CC_NOKIAX86) - QSKIP("Impossible to implement reading/touching of application binaries in Symbian emulator", SkipAll); -# endif QString appPath = "c:/sys/bin/tst_qfileinfo.exe"; #else QString appPath = QCoreApplication::applicationDirPath(); @@ -1601,5 +1651,160 @@ void tst_QFileInfo::detachingOperations() QVERIFY(!info1.caching()); } +#if !defined(Q_OS_WINCE) && !defined(Q_OS_SYMBIAN) +#if defined (Q_OS_WIN) +BOOL IsUserAdmin() +{ + BOOL b; + SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY; + PSID AdministratorsGroup; + b = AllocateAndInitializeSid( + &NtAuthority, + 2, + SECURITY_BUILTIN_DOMAIN_RID, + DOMAIN_ALIAS_RID_ADMINS, + 0, 0, 0, 0, 0, 0, + &AdministratorsGroup); + if (b) { + if (!CheckTokenMembership( NULL, AdministratorsGroup, &b)) + b = FALSE; + FreeSid(AdministratorsGroup); + } + + return(b); +} +#endif + +void tst_QFileInfo::owner() +{ + QString userName; +#if defined(Q_OS_UNIX) + { + passwd *user = getpwuid(geteuid()); + QVERIFY(user); + char *usernameBuf = user->pw_name; + userName = QString::fromLocal8Bit(usernameBuf); + } +#endif +#if defined(Q_OS_WIN) + wchar_t usernameBuf[1024]; + DWORD bufSize = 1024; + if (GetUserNameW(usernameBuf, &bufSize)) { + userName = QString::fromWCharArray(usernameBuf); + if (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA && IsUserAdmin()) { + // Special case : If the user is a member of Administrators group, all files + // created by the current user are owned by the Administrators group. + LPLOCALGROUP_USERS_INFO_0 pBuf = NULL; + DWORD dwLevel = 0; + DWORD dwFlags = LG_INCLUDE_INDIRECT ; + DWORD dwPrefMaxLen = MAX_PREFERRED_LENGTH; + DWORD dwEntriesRead = 0; + DWORD dwTotalEntries = 0; + NET_API_STATUS nStatus; + nStatus = NetUserGetLocalGroups(0, usernameBuf, dwLevel, dwFlags, (LPBYTE *) &pBuf, + dwPrefMaxLen, &dwEntriesRead, &dwTotalEntries); + // Check if the current user is a member of Administrators group + if (nStatus == NERR_Success && pBuf){ + for (int i = 0; i < dwEntriesRead; i++) { + QString groupName = QString::fromWCharArray(pBuf[i].lgrui0_name); + if (!groupName.compare(QLatin1String("Administrators"))) + userName = groupName; + } + } + if (pBuf != NULL) + NetApiBufferFree(pBuf); + } + } + extern Q_CORE_EXPORT int qt_ntfs_permission_lookup; + qt_ntfs_permission_lookup = 1; +#endif + if (userName.isEmpty()) + QSKIP("Can't retrieve the user name", SkipAll); + QString fileName("ownertest.txt"); + QVERIFY(!QFile::exists(fileName) || QFile::remove(fileName)); + { + QFile testFile(fileName); + QVERIFY(testFile.open(QIODevice::WriteOnly | QIODevice::Text)); + QByteArray testData("testfile"); + QVERIFY(testFile.write(testData) != -1); + } + QFileInfo fi(fileName); + QVERIFY(fi.exists()); + QCOMPARE(fi.owner(), userName); + + QFile::remove(fileName); +#if defined(Q_OS_WIN) + qt_ntfs_permission_lookup = 0; +#endif +} +#endif + +void tst_QFileInfo::group() +{ + QString expected; +#if defined(Q_OS_UNIX) && !defined(Q_OS_SYMBIAN) + struct group *gr; + gid_t gid = getegid(); + gr = getgrgid(gid); + expected = QString::fromLocal8Bit(gr->gr_name); +#endif + + QString fileName("ownertest.txt"); + if (QFile::exists(fileName)) + QFile::remove(fileName); + QFile testFile(fileName); + QVERIFY(testFile.open(QIODevice::WriteOnly | QIODevice::Text)); + QByteArray testData("testfile"); + QVERIFY(testFile.write(testData) != -1); + testFile.close(); + QFileInfo fi(fileName); + QVERIFY(fi.exists()); + + QCOMPARE(fi.group(), expected); +} + +void tst_QFileInfo::invalidState() +{ + // Shouldn't crash; + + { + QFileInfo info; + QCOMPARE(info.size(), qint64(0)); + QVERIFY(!info.exists()); + + info.setCaching(false); + + info.created(); + info.lastRead(); + info.lastModified(); + } + + { + QFileInfo info(""); + QCOMPARE(info.size(), qint64(0)); + QVERIFY(!info.exists()); + + info.setCaching(false); + + info.created(); + info.lastRead(); + info.lastModified(); + } + + { + QFileInfo info("file-doesn't-really-exist.txt"); + QCOMPARE(info.size(), qint64(0)); + QVERIFY(!info.exists()); + + info.setCaching(false); + + info.created(); + info.lastRead(); + info.lastModified(); + } + + QVERIFY(true); +} + QTEST_MAIN(tst_QFileInfo) #include "tst_qfileinfo.moc" diff --git a/tests/auto/qfilesystementry/qfilesystementry.pro b/tests/auto/qfilesystementry/qfilesystementry.pro new file mode 100644 index 0000000..b9b43e6 --- /dev/null +++ b/tests/auto/qfilesystementry/qfilesystementry.pro @@ -0,0 +1,8 @@ +load(qttest_p4) + +SOURCES += tst_qfilesystementry.cpp \ + ../../../src/corelib/io/qfilesystementry.cpp +HEADERS += ../../../src/corelib/io/qfilesystementry_p.h +QT = core + +CONFIG += parallel_test diff --git a/tests/auto/qfilesystementry/tst_qfilesystementry.cpp b/tests/auto/qfilesystementry/tst_qfilesystementry.cpp new file mode 100644 index 0000000..4375f99 --- /dev/null +++ b/tests/auto/qfilesystementry/tst_qfilesystementry.cpp @@ -0,0 +1,387 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include <QtTest/QtTest> + +#include <QtCore/private/qfilesystementry_p.h> + +#if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN) +# define WIN_STUFF +#endif + +//TESTED_CLASS= +//TESTED_FILES= + +class tst_QFileSystemEntry : public QObject +{ + Q_OBJECT + +private slots: + void getSetCheck_data(); + void getSetCheck(); + void suffix_data(); + void suffix(); + void completeSuffix_data(); + void completeSuffix(); + void baseName_data(); + void baseName(); + void completeBaseName_data(); + void completeBaseName(); +#if defined(WIN_STUFF) + void absoluteOrRelative_data(); + void absoluteOrRelative(); +#endif +}; + +#if defined(WIN_STUFF) +void tst_QFileSystemEntry::getSetCheck_data() +{ + QTest::addColumn<QString>("nativeFilePath"); + QTest::addColumn<QString>("internalnativeFilePath"); + QTest::addColumn<QString>("filepath"); + QTest::addColumn<QString>("filename"); + QTest::addColumn<QString>("baseName"); + QTest::addColumn<QString>("completeBasename"); + QTest::addColumn<QString>("suffix"); + QTest::addColumn<QString>("completeSuffix"); + QTest::addColumn<bool>("absolute"); + QTest::addColumn<bool>("relative"); + + QString absPrefix = QLatin1String("\\\\?\\"); + QString relPrefix = absPrefix + + QDir::toNativeSeparators(QDir::currentPath()) + + QLatin1String("\\"); + + QTest::newRow("simple") + << QString("A:\\home\\qt\\in\\a\\dir.tar.gz") + << absPrefix + QString("A:\\home\\qt\\in\\a\\dir.tar.gz") + << "A:/home/qt/in/a/dir.tar.gz" + << "dir.tar.gz" << "dir" << "dir.tar" << "gz" << "tar.gz" << true << false; + + QTest::newRow("relative") + << QString("in\\a\\dir.tar.gz") + << relPrefix + QString("in\\a\\dir.tar.gz") + << "in/a/dir.tar.gz" + << "dir.tar.gz" << "dir" << "dir.tar" << "gz" << "tar.gz" << false <<true; + + QTest::newRow("noSuffix") + << QString("myDir\\myfile") + << relPrefix + QString("myDir\\myfile") + << "myDir/myfile" << "myfile" << "myfile" << "myfile" << "" << "" << false <<true; + + QTest::newRow("noLongSuffix") + << QString("myDir\\myfile.txt") + << relPrefix + QString("myDir\\myfile.txt") + << "myDir/myfile.txt" << "myfile.txt" << "myfile" << "myfile" << "txt" << "txt" << false << true; + + QTest::newRow("endingSlash") + << QString("myDir\\myfile.bla\\") + << relPrefix + QString("myDir\\myfile.bla\\") + << "myDir/myfile.bla/" << "" << "" << "" << "" << "" << false << true; + + QTest::newRow("absolutePath") + << QString("A:dir\\without\\leading\\backslash.bat") + << absPrefix + QString("A:\\dir\\without\\leading\\backslash.bat") + << "A:dir/without/leading/backslash.bat" << "backslash.bat" << "backslash" << "backslash" << "bat" << "bat" << false << false; +} + +void tst_QFileSystemEntry::getSetCheck() +{ + QFETCH(QString, nativeFilePath); + QFETCH(QString, internalnativeFilePath); + QFETCH(QString, filepath); + QFETCH(QString, filename); + QFETCH(QString, baseName); + QFETCH(QString, completeBasename); + QFETCH(QString, suffix); + QFETCH(QString, completeSuffix); + QFETCH(bool, absolute); + QFETCH(bool, relative); + + QFileSystemEntry entry1(filepath); + QCOMPARE(entry1.filePath(), filepath); + QCOMPARE(entry1.nativeFilePath().toLower(), internalnativeFilePath.toLower()); + QCOMPARE(entry1.fileName(), filename); + QCOMPARE(entry1.suffix(), suffix); + QCOMPARE(entry1.completeSuffix(), completeSuffix); + QCOMPARE(entry1.isAbsolute(), absolute); + QCOMPARE(entry1.isRelative(), relative); + QCOMPARE(entry1.baseName(), baseName); + QCOMPARE(entry1.completeBaseName(), completeBasename); + + QFileSystemEntry entry2(nativeFilePath, QFileSystemEntry::FromNativePath()); + QCOMPARE(entry2.suffix(), suffix); + QCOMPARE(entry2.completeSuffix(), completeSuffix); + QCOMPARE(entry2.isAbsolute(), absolute); + QCOMPARE(entry2.isRelative(), relative); + QCOMPARE(entry2.filePath(), filepath); + // Since this entry was created using the native path, + // the object shouldnot change nativeFilePath. + QCOMPARE(entry2.nativeFilePath(), nativeFilePath); + QCOMPARE(entry2.fileName(), filename); + QCOMPARE(entry2.baseName(), baseName); + QCOMPARE(entry2.completeBaseName(), completeBasename); +} + +#else + +void tst_QFileSystemEntry::getSetCheck_data() +{ + QTest::addColumn<QByteArray>("nativeFilePath"); + QTest::addColumn<QString>("filepath"); + QTest::addColumn<QString>("filename"); + QTest::addColumn<QString>("basename"); + QTest::addColumn<QString>("completeBasename"); + QTest::addColumn<QString>("suffix"); + QTest::addColumn<QString>("completeSuffix"); + QTest::addColumn<bool>("absolute"); + + QTest::newRow("simple") + << QByteArray("/home/qt/in/a/dir.tar.gz") + << "/home/qt/in/a/dir.tar.gz" + << "dir.tar.gz" << "dir" << "dir.tar" << "gz" << "tar.gz" << true; + QTest::newRow("relative") + << QByteArray("in/a/dir.tar.gz") + << "in/a/dir.tar.gz" + << "dir.tar.gz" << "dir" << "dir.tar" << "gz" << "tar.gz" << false; + + QTest::newRow("noSuffix") + << QByteArray("myDir/myfile") + << "myDir/myfile" << "myfile" << "myfile" << "myfile" << "" << "" << false; + + QTest::newRow("noLongSuffix") + << QByteArray("myDir/myfile.txt") + << "myDir/myfile.txt" << "myfile.txt" << "myfile" << "myfile" << "txt" << "txt" << false; + + QTest::newRow("endingSlash") + << QByteArray("myDir/myfile.bla/") + << "myDir/myfile.bla/" << "" << "" << "" << "" << "" << false; + + QTest::newRow("relativePath") + << QByteArray("A:dir/without/leading/backslash.bat") + << "A:dir/without/leading/backslash.bat" << "backslash.bat" << "backslash" << "backslash" << "bat" << "bat" << false; +} + +void tst_QFileSystemEntry::getSetCheck() +{ + QFETCH(QByteArray, nativeFilePath); + QFETCH(QString, filepath); + QFETCH(QString, filename); + QFETCH(QString, basename); + QFETCH(QString, completeBasename); + QFETCH(QString, suffix); + QFETCH(QString, completeSuffix); + QFETCH(bool, absolute); + + QFileSystemEntry entry1(filepath); + QCOMPARE(entry1.filePath(), filepath); + QCOMPARE(entry1.nativeFilePath(), nativeFilePath); + QCOMPARE(entry1.fileName(), filename); + QCOMPARE(entry1.suffix(), suffix); + QCOMPARE(entry1.completeSuffix(), completeSuffix); + QCOMPARE(entry1.isAbsolute(), absolute); + QCOMPARE(entry1.isRelative(), !absolute); + QCOMPARE(entry1.baseName(), basename); + QCOMPARE(entry1.completeBaseName(), completeBasename); + + QFileSystemEntry entry2(nativeFilePath, QFileSystemEntry::FromNativePath()); + QCOMPARE(entry2.suffix(), suffix); + QCOMPARE(entry2.completeSuffix(), completeSuffix); + QCOMPARE(entry2.isAbsolute(), absolute); + QCOMPARE(entry2.isRelative(), !absolute); + QCOMPARE(entry2.filePath(), filepath); + QCOMPARE(entry2.nativeFilePath(), nativeFilePath); + QCOMPARE(entry2.fileName(), filename); + QCOMPARE(entry2.baseName(), basename); + QCOMPARE(entry2.completeBaseName(), completeBasename); +} +#endif + +void tst_QFileSystemEntry::suffix_data() +{ + QTest::addColumn<QString>("file"); + QTest::addColumn<QString>("expected"); + + QTest::newRow("noextension0") << "file" << ""; + QTest::newRow("noextension1") << "/path/to/file" << ""; + QTest::newRow("data0") << "file.tar" << "tar"; + QTest::newRow("data1") << "file.tar.gz" << "gz"; + QTest::newRow("data2") << "/path/file/file.tar.gz" << "gz"; + QTest::newRow("data3") << "/path/file.tar" << "tar"; + QTest::newRow("hidden1") << ".ext1" << "ext1"; + QTest::newRow("hidden1") << ".ext" << "ext"; + QTest::newRow("hidden1") << ".ex" << "ex"; + QTest::newRow("hidden1") << ".e" << "e"; + QTest::newRow("hidden2") << ".ext1.ext2" << "ext2"; + QTest::newRow("hidden2") << ".ext.ext2" << "ext2"; + QTest::newRow("hidden2") << ".ex.ext2" << "ext2"; + QTest::newRow("hidden2") << ".e.ext2" << "ext2"; + QTest::newRow("hidden2") << "..ext2" << "ext2"; + QTest::newRow("dots") << "/path/file.with.dots/file..ext2" << "ext2"; + QTest::newRow("dots2") << "/path/file.with.dots/.file..ext2" << "ext2"; +} + +void tst_QFileSystemEntry::suffix() +{ + QFETCH(QString, file); + QFETCH(QString, expected); + + QFileSystemEntry fe(file); + QCOMPARE(fe.suffix(), expected); + + QFileSystemEntry fi2(file); + // first resolve the last slash + (void) fi2.path(); + QCOMPARE(fi2.suffix(), expected); +} + +void tst_QFileSystemEntry::completeSuffix_data() +{ + QTest::addColumn<QString>("file"); + QTest::addColumn<QString>("expected"); + + QTest::newRow("noextension0") << "file" << ""; + QTest::newRow("noextension1") << "/path/to/file" << ""; + QTest::newRow("data0") << "file.tar" << "tar"; + QTest::newRow("data1") << "file.tar.gz" << "tar.gz"; + QTest::newRow("data2") << "/path/file/file.tar.gz" << "tar.gz"; + QTest::newRow("data3") << "/path/file.tar" << "tar"; + QTest::newRow("dots") << "/path/file.with.dots/file..ext2" << ".ext2"; + QTest::newRow("dots2") << "/path/file.with.dots/.file..ext2" << "file..ext2"; +} + +void tst_QFileSystemEntry::completeSuffix() +{ + QFETCH(QString, file); + QFETCH(QString, expected); + + QFileSystemEntry fi(file); + QCOMPARE(fi.completeSuffix(), expected); + + QFileSystemEntry fi2(file); + // first resolve the last slash + (void) fi2.path(); + QCOMPARE(fi2.completeSuffix(), expected); +} + +void tst_QFileSystemEntry::baseName_data() +{ + QTest::addColumn<QString>("file"); + QTest::addColumn<QString>("expected"); + + QTest::newRow("data0") << "file.tar" << "file"; + QTest::newRow("data1") << "file.tar.gz" << "file"; + QTest::newRow("data2") << "/path/file/file.tar.gz" << "file"; + QTest::newRow("data3") << "/path/file.tar" << "file"; + QTest::newRow("data4") << "/path/file" << "file"; + QTest::newRow("dots") << "/path/file.with.dots/file..ext2" << "file"; + QTest::newRow("dots2") << "/path/file.with.dots/.file..ext2" << ""; +} + +void tst_QFileSystemEntry::baseName() +{ + QFETCH(QString, file); + QFETCH(QString, expected); + + QFileSystemEntry fi(file); + QCOMPARE(fi.baseName(), expected); + + QFileSystemEntry fi2(file); + // first resolve the last slash + (void) fi2.path(); + QCOMPARE(fi2.baseName(), expected); +} + +void tst_QFileSystemEntry::completeBaseName_data() +{ + QTest::addColumn<QString>("file"); + QTest::addColumn<QString>("expected"); + + QTest::newRow("data0") << "file.tar" << "file"; + QTest::newRow("data1") << "file.tar.gz" << "file.tar"; + QTest::newRow("data2") << "/path/file/file.tar.gz" << "file.tar"; + QTest::newRow("data3") << "/path/file.tar" << "file"; + QTest::newRow("data4") << "/path/file" << "file"; + QTest::newRow("dots") << "/path/file.with.dots/file..ext2" << "file."; + QTest::newRow("dots2") << "/path/file.with.dots/.file..ext2" << ".file."; +} + +void tst_QFileSystemEntry::completeBaseName() +{ + QFETCH(QString, file); + QFETCH(QString, expected); + + QFileSystemEntry fi(file); + QCOMPARE(fi.completeBaseName(), expected); + + QFileSystemEntry fi2(file); + // first resolve the last slash + (void) fi2.path(); + QCOMPARE(fi2.completeBaseName(), expected); +} + +#if defined(WIN_STUFF) +void tst_QFileSystemEntry::absoluteOrRelative_data() +{ + QTest::addColumn<QString>("path"); + QTest::addColumn<bool>("isAbsolute"); + QTest::addColumn<bool>("isRelative"); + + QTest::newRow("data0") << "file.tar" << false << true; + QTest::newRow("data1") << "/path/file/file.tar.gz" << false << false; + QTest::newRow("data1") << "C:path/file/file.tar.gz" << false << false; + QTest::newRow("data3") << "C:/path/file" << true << false; + QTest::newRow("data3") << "//machine/share" << true << false; +} + +void tst_QFileSystemEntry::absoluteOrRelative() +{ + QFETCH(QString, path); + QFETCH(bool, isAbsolute); + QFETCH(bool, isRelative); + + QFileSystemEntry fi(path); + QCOMPARE(fi.isAbsolute(), isAbsolute); + QCOMPARE(fi.isRelative(), isRelative); +} +#endif + +QTEST_MAIN(tst_QFileSystemEntry) +#include <tst_qfilesystementry.moc> diff --git a/tests/auto/qfilesystemmodel/tst_qfilesystemmodel.cpp b/tests/auto/qfilesystemmodel/tst_qfilesystemmodel.cpp index c234c96..6b63691 100644 --- a/tests/auto/qfilesystemmodel/tst_qfilesystemmodel.cpp +++ b/tests/auto/qfilesystemmodel/tst_qfilesystemmodel.cpp @@ -41,7 +41,10 @@ #include <QtTest/QtTest> +#ifdef QT_BUILD_INTERNAL #include "../../../src/gui/dialogs/qfilesystemmodel_p.h" +#endif +#include <QFileSystemModel> #include <QFileIconProvider> #include <QTreeView> #include <QHeaderView> @@ -826,8 +829,10 @@ void tst_QFileSystemModel::sort() MyFriendFileSystemModel *myModel = new MyFriendFileSystemModel(); QTreeView *tree = new QTreeView(); +#ifdef QT_BUILD_INTERNAL if (fileDialogMode) myModel->d_func()->disableRecursiveSort = true; +#endif QDir dir(QDir::tempPath()); //initialize the randomness @@ -992,8 +997,8 @@ void tst_QFileSystemModel::dirsBeforeFiles() } dir.rmdir(dirPath); } - dir.mkpath(dirPath); - QVERIFY(dir.exists()); + QVERIFY(dir.mkpath(dirPath)); + QVERIFY(QDir(dirPath).exists()); for (int i = 0; i < 3; ++i) { QLatin1Char c('a' + i); diff --git a/tests/auto/qfilesystemwatcher/qfilesystemwatcher.pro b/tests/auto/qfilesystemwatcher/qfilesystemwatcher.pro index 8b8616a..75e85a0 100644 --- a/tests/auto/qfilesystemwatcher/qfilesystemwatcher.pro +++ b/tests/auto/qfilesystemwatcher/qfilesystemwatcher.pro @@ -1,3 +1,5 @@ load(qttest_p4) SOURCES += tst_qfilesystemwatcher.cpp QT = core + +CONFIG += parallel_test diff --git a/tests/auto/qhttp/qhttp.pro b/tests/auto/qhttp/qhttp.pro index 5b102ce..49eebd5 100644 --- a/tests/auto/qhttp/qhttp.pro +++ b/tests/auto/qhttp/qhttp.pro @@ -11,7 +11,7 @@ wince*: { cgi.path = webserver/cgi-bin addFiles.files = rfc3252.txt trolltech addFiles.path = . - DEPLOYMENT = addFiles webFiles cgi + DEPLOYMENT += addFiles webFiles cgi DEFINES += SRCDIR=\\\"\\\" } else:symbian { webFiles.files = webserver/* @@ -20,7 +20,7 @@ wince*: { cgi.path = webserver/cgi-bin addFiles.files = rfc3252.txt trolltech addFiles.path = . - DEPLOYMENT = addFiles webFiles cgi + DEPLOYMENT += addFiles webFiles cgi TARGET.CAPABILITY = NetworkServices } else:vxworks*: { DEFINES += SRCDIR=\\\"\\\" diff --git a/tests/auto/qimagereader/tst_qimagereader.cpp b/tests/auto/qimagereader/tst_qimagereader.cpp index 4aff8d5..5742a97 100644 --- a/tests/auto/qimagereader/tst_qimagereader.cpp +++ b/tests/auto/qimagereader/tst_qimagereader.cpp @@ -1107,6 +1107,11 @@ void tst_QImageReader::readFromDevice() QCOMPARE(image1, expectedImage); } +#if defined (Q_OS_SYMBIAN) && defined (__WINS__) + //the emulator hangs in socket write (this is a test bug, it assumes the TCP stack can accept a whole image to its buffers) + if(imageData.size() > 16384) + QSKIP("image larger than socket buffer (test needs to be rewritten)", SkipSingle); +#endif Server server(imageData); QEventLoop loop; connect(&server, SIGNAL(ready()), &loop, SLOT(quit())); @@ -1258,7 +1263,10 @@ void tst_QImageReader::devicePosition() buf.seek(preLen); QImageReader reader(&buf, format); QCOMPARE(expected, reader.read()); - if (format != "ppm" && format != "gif") // Known not to work + if (format != "ppm" && + format != "pgm" && + format != "pbm" && + format != "gif") // Known not to work QCOMPARE(buf.pos(), qint64(preLen+imageDataSize)); } diff --git a/tests/auto/qlocalsocket/test/test.pro b/tests/auto/qlocalsocket/test/test.pro index f91fe58..b2755b5 100644 --- a/tests/auto/qlocalsocket/test/test.pro +++ b/tests/auto/qlocalsocket/test/test.pro @@ -42,7 +42,7 @@ symbian { wince*|symbian { scriptFiles.files = ../lackey/scripts/*.js scriptFiles.path = lackey/scripts - DEPLOYMENT = additionalFiles scriptFiles + DEPLOYMENT += additionalFiles scriptFiles QT += script # for easy deployment of QtScript requires(contains(QT_CONFIG,script)) diff --git a/tests/auto/qprocess/tst_qprocess.cpp b/tests/auto/qprocess/tst_qprocess.cpp index fd310f4..a497b13 100644 --- a/tests/auto/qprocess/tst_qprocess.cpp +++ b/tests/auto/qprocess/tst_qprocess.cpp @@ -1585,6 +1585,7 @@ void tst_QProcess::spaceArgsTest() #if defined(Q_OS_SYMBIAN) // Symbian test outputs to a file, so check that FILE* file = fopen("c:\\logs\\qprocess_args_test.txt","r"); + QVERIFY(file); char buf[256]; fgets(buf, 256, file); fclose(file); @@ -1614,6 +1615,7 @@ void tst_QProcess::spaceArgsTest() #if defined(Q_OS_SYMBIAN) // Symbian test outputs to a file, so check that file = fopen("c:\\logs\\qprocess_args_test.txt","r"); + QVERIFY(file); fgets(buf, 256, file); fclose(file); actual = QString::fromLatin1(buf).split("|"); @@ -1661,6 +1663,7 @@ void tst_QProcess::nativeArguments() # else FILE* file = fopen("\\temp\\qprocess_args_test.txt","r"); # endif + QVERIFY(file); char buf[256]; fgets(buf, 256, file); fclose(file); @@ -2285,7 +2288,9 @@ void tst_QProcess::detachedWorkingDirectoryAndPid() QFileInfo fi(infoFile); fi.setCaching(false); - while (fi.size() == 0) { + //The guard counter ensures the test does not hang if the sub process fails. + //Instead, the test will fail when trying to open & verify the sub process output file. + for (int guard = 0; guard < 100 && fi.size() == 0; guard++) { QTest::qSleep(100); } @@ -2397,6 +2402,7 @@ void tst_QProcess::startFinishStartFinish() #if defined(Q_OS_SYMBIAN) // Symbian test outputs to a file, so check that FILE* file = fopen("c:\\logs\\qprocess_output_test.txt","r"); + QVERIFY(file); char buf[30]; fgets(buf, 30, file); QCOMPARE(QString::fromLatin1(buf), diff --git a/tests/auto/qresourceengine/qresourceengine.pro b/tests/auto/qresourceengine/qresourceengine.pro index c0db52f..9ca6994 100644 --- a/tests/auto/qresourceengine/qresourceengine.pro +++ b/tests/auto/qresourceengine/qresourceengine.pro @@ -38,7 +38,7 @@ wince*|symbian:{ testsub.path = testqrc/test testsub2.files = testqrc/test/test/* testsub2.path = testqrc/test/test - DEPLOYMENT = deploy test alias other search1 search2 sub testsub testsub2 + DEPLOYMENT += deploy test alias other search1 search2 sub testsub testsub2 !symbian:DEFINES += SRCDIR=\\\"\\\" } else { DEFINES += SRCDIR=\\\"$$PWD/\\\" diff --git a/tests/auto/qsettings/qsettings.pro b/tests/auto/qsettings/qsettings.pro index 19513b3..fe104df 100644 --- a/tests/auto/qsettings/qsettings.pro +++ b/tests/auto/qsettings/qsettings.pro @@ -6,3 +6,5 @@ contains(QT_CONFIG, qt3support):QT += qt3support CONFIG -= debug CONFIG += release win32-msvc*:LIBS += advapi32.lib + +CONFIG += parallel_test diff --git a/tests/auto/qsound/qsound.pro b/tests/auto/qsound/qsound.pro index a1760f8..b69d084 100644 --- a/tests/auto/qsound/qsound.pro +++ b/tests/auto/qsound/qsound.pro @@ -3,7 +3,7 @@ SOURCES += tst_qsound.cpp wince*|symbian: { deploy.files += 4.wav - DEPLOYMENT = deploy + DEPLOYMENT += deploy !symbian:DEFINES += SRCDIR=\\\"\\\" } else { DEFINES += SRCDIR=\\\"$$PWD/\\\" diff --git a/tests/auto/qtemporaryfile/qtemporaryfile.pro b/tests/auto/qtemporaryfile/qtemporaryfile.pro index 543c143..64a043b 100644 --- a/tests/auto/qtemporaryfile/qtemporaryfile.pro +++ b/tests/auto/qtemporaryfile/qtemporaryfile.pro @@ -10,3 +10,5 @@ symbian { }else { DEFINES += SRCDIR=\\\"$$PWD/\\\" } + +CONFIG += parallel_test diff --git a/tests/auto/qxmlstream/qxmlstream.pro b/tests/auto/qxmlstream/qxmlstream.pro index 31d77e7..894801d 100644 --- a/tests/auto/qxmlstream/qxmlstream.pro +++ b/tests/auto/qxmlstream/qxmlstream.pro @@ -8,7 +8,7 @@ wince*|symbian: { addFiles.files = data XML-Test-Suite addFiles.path = . DEPLOYMENT += addFiles - DEFINES += SRCDIR=\\\"\\\" + wince*:DEFINES += SRCDIR=\\\"\\\" } else { DEFINES += SRCDIR=\\\"$$PWD/\\\" } diff --git a/tests/auto/qxmlstream/tst_qxmlstream.cpp b/tests/auto/qxmlstream/tst_qxmlstream.cpp index 7d5e3b7..19e4b90 100644 --- a/tests/auto/qxmlstream/tst_qxmlstream.cpp +++ b/tests/auto/qxmlstream/tst_qxmlstream.cpp @@ -55,6 +55,10 @@ //TESTED_CLASS=QXmlStreamReader QXmlStreamWriter //TESTED_FILES=corelib/xml/stream/qxmlutils.cpp corelib/xml/stream/qxmlstream.cpp corelib/xml/stream/qxmlstream_p.h +#ifdef Q_OS_SYMBIAN +#define SRCDIR "" +#endif + Q_DECLARE_METATYPE(QXmlStreamReader::ReadElementTextBehaviour) static const char *const catalogFile = SRCDIR "XML-Test-Suite/xmlconf/finalCatalog.xml"; diff --git a/tests/benchmarks/corelib/io/qdir/tree/bench_qdir_tree.cpp b/tests/benchmarks/corelib/io/qdir/tree/bench_qdir_tree.cpp index ad5ae98..84922f6 100644 --- a/tests/benchmarks/corelib/io/qdir/tree/bench_qdir_tree.cpp +++ b/tests/benchmarks/corelib/io/qdir/tree/bench_qdir_tree.cpp @@ -55,12 +55,24 @@ class bench_QDir_tree public: bench_QDir_tree() - : prefix("./test-tree/") + : prefix("./test-tree/"), + musicprefix(QLatin1String("music")), + photoprefix(QLatin1String("photos")), + sourceprefix(QLatin1String("source")), + musicsize(0), + photosize(0), + sourcesize(0) { } private: QByteArray prefix; + QString musicprefix; + QString photoprefix; + QString sourceprefix; + qint64 musicsize; + qint64 photosize; + qint64 sourcesize; private slots: void initTestCase() @@ -105,6 +117,34 @@ private slots: line.clear(); } + + //Use case: music collection - 10 files in 100 directories (albums) + QVERIFY(fs.createDirectory(musicprefix)); + for (int i=0;i<1000;i++) { + if ((i % 10) == 0) + QVERIFY(fs.createDirectory(QString("%1/directory%2").arg(musicprefix).arg(i/10))); + qint64 size = fs.createFileWithContent(QString("%1/directory%2/file%3").arg(musicprefix).arg(i/10).arg(i)); + QVERIFY(size > 0); + musicsize += size; + } + //Use case: photos - 1000 files in 1 directory + QVERIFY(fs.createDirectory(photoprefix)); + for (int i=0;i<1000;i++) { + qint64 size = fs.createFileWithContent(QString("%1/file%2").arg(photoprefix).arg(i)); + QVERIFY(size > 0); + photosize += size; + } + //Use case: source - 10 files in 10 subdirectories in 10 directories (1000 total) + QVERIFY(fs.createDirectory(sourceprefix)); + for (int i=0;i<1000;i++) { + if ((i % 100) == 0) + QVERIFY(fs.createDirectory(QString("%1/directory%2").arg(sourceprefix).arg(i/100))); + if ((i % 10) == 0) + QVERIFY(fs.createDirectory(QString("%1/directory%2/subdirectory%3").arg(sourceprefix).arg(i/100).arg(i/10))); + qint64 size = fs.createFileWithContent(QString("%1/directory%2/subdirectory%3/file%4").arg(sourceprefix).arg(i/100).arg(i/10).arg(i)); + QVERIFY(size > 0); + sourcesize += size; + } } void fileSearch_data() const @@ -154,6 +194,7 @@ private slots: QDir::AllEntries | QDir::NoDotAndDotDot | QDir::Hidden | QDir::System, QDirIterator::Subdirectories | QDirIterator::FollowSymlinks); + count = 0; while (iterator.hasNext()) { iterator.next(); ++count; @@ -165,6 +206,32 @@ private slots: QCOMPARE(count, 11963); } + void thousandFiles_data() const + { + QTest::addColumn<QString>("dirName"); + QTest::addColumn<qint64>("expectedSize"); + QTest::newRow("music") << musicprefix << musicsize; + QTest::newRow("photos") << photoprefix << photosize; + QTest::newRow("src") << sourceprefix << sourcesize; + } + + void thousandFiles() const + { + QFETCH(QString, dirName); + QFETCH(qint64, expectedSize); + QBENCHMARK { + qint64 totalsize = 0; + int count = 0; + QDirIterator iter(dirName, QDir::Files, QDirIterator::Subdirectories); + while(iter.hasNext()) { + iter.next(); + count++; + totalsize += iter.fileInfo().size(); + } + QCOMPARE(count, 1000); + QCOMPARE(totalsize, expectedSize); + } + } private: FileSystem fs; }; diff --git a/tests/benchmarks/declarative/binding/binding.pro b/tests/benchmarks/declarative/binding/binding.pro index ceaabeb..bbe8701 100644 --- a/tests/benchmarks/declarative/binding/binding.pro +++ b/tests/benchmarks/declarative/binding/binding.pro @@ -10,7 +10,7 @@ HEADERS += testtypes.h symbian { data.files = data data.path = . - DEPLOYMENT = data + DEPLOYMENT += data } else { # Define SRCDIR equal to test's source directory DEFINES += SRCDIR=\\\"$$PWD\\\" diff --git a/tests/benchmarks/declarative/qdeclarativeimage/qdeclarativeimage.pro b/tests/benchmarks/declarative/qdeclarativeimage/qdeclarativeimage.pro index c4d5609..0d7c184 100644 --- a/tests/benchmarks/declarative/qdeclarativeimage/qdeclarativeimage.pro +++ b/tests/benchmarks/declarative/qdeclarativeimage/qdeclarativeimage.pro @@ -10,7 +10,7 @@ SOURCES += tst_qdeclarativeimage.cpp symbian { importFiles.files = image.png importFiles.path = - DEPLOYMENT = importFiles + DEPLOYMENT += importFiles } else { DEFINES += SRCDIR=\\\"$$PWD\\\" } diff --git a/tests/benchmarks/declarative/script/script.pro b/tests/benchmarks/declarative/script/script.pro index d6cb708..75faa5c 100644 --- a/tests/benchmarks/declarative/script/script.pro +++ b/tests/benchmarks/declarative/script/script.pro @@ -10,7 +10,7 @@ SOURCES += tst_script.cpp symbian { importFiles.files = data importFiles.path = - DEPLOYMENT = importFiles + DEPLOYMENT += importFiles } else { DEFINES += SRCDIR=\\\"$$PWD\\\" } diff --git a/tests/shared/filesystem.h b/tests/shared/filesystem.h index 079a6dc..8274346 100644 --- a/tests/shared/filesystem.h +++ b/tests/shared/filesystem.h @@ -87,6 +87,16 @@ struct FileSystem return false; } + qint64 createFileWithContent(const QString &fileName) + { + QFile file(fileName); + if (file.open(QIODevice::WriteOnly)) { + createdFiles << fileName; + return file.write(fileName.toUtf8()); + } + return -1; + } + bool createLink(const QString &destination, const QString &linkName) { if (QFile::link(destination, linkName)) { diff --git a/tools/configure/configure.pro b/tools/configure/configure.pro index 0a49fbe..608d876 100644 --- a/tools/configure/configure.pro +++ b/tools/configure/configure.pro @@ -48,6 +48,10 @@ HEADERS = configureapp.h environment.h tools.h\ $$QT_SOURCE_TREE/src/corelib/io/qdiriterator.h \ $$QT_SOURCE_TREE/src/corelib/io/qfile.h \ $$QT_SOURCE_TREE/src/corelib/io/qfileinfo.h \ + $$QT_SOURCE_TREE/src/corelib/io/qfilesystementry_p.h \ + $$QT_SOURCE_TREE/src/corelib/io/qfilesystemengine_p.h \ + $$QT_SOURCE_TREE/src/corelib/io/qfilesystemmetadata_p.h \ + $$QT_SOURCE_TREE/src/corelib/io/qfilesystemiterator_p.h \ $$QT_SOURCE_TREE/src/corelib/io/qfsfileengine.h \ $$QT_SOURCE_TREE/src/corelib/io/qfsfileengine_iterator_p.h \ $$QT_SOURCE_TREE/src/corelib/io/qiodevice.h \ @@ -86,9 +90,13 @@ SOURCES = main.cpp configureapp.cpp environment.cpp tools.cpp \ $$QT_SOURCE_TREE/src/corelib/io/qfile.cpp \ $$QT_SOURCE_TREE/src/corelib/io/qfileinfo.cpp \ $$QT_SOURCE_TREE/src/corelib/io/qabstractfileengine.cpp \ + $$QT_SOURCE_TREE/src/corelib/io/qfilesystementry.cpp \ + $$QT_SOURCE_TREE/src/corelib/io/qfilesystemengine.cpp \ + $$QT_SOURCE_TREE/src/corelib/io/qfilesystemengine_win.cpp \ + $$QT_SOURCE_TREE/src/corelib/io/qfilesystemiterator_win.cpp \ $$QT_SOURCE_TREE/src/corelib/io/qfsfileengine.cpp \ + $$QT_SOURCE_TREE/src/corelib/io/qfsfileengine_win.cpp \ $$QT_SOURCE_TREE/src/corelib/io/qfsfileengine_iterator.cpp \ - $$QT_SOURCE_TREE/src/corelib/io/qfsfileengine_iterator_win.cpp \ $$QT_SOURCE_TREE/src/corelib/io/qiodevice.cpp \ $$QT_SOURCE_TREE/src/corelib/io/qtextstream.cpp \ $$QT_SOURCE_TREE/src/corelib/io/qtemporaryfile.cpp \ @@ -115,8 +123,6 @@ SOURCES = main.cpp configureapp.cpp environment.cpp tools.cpp \ $$QT_SOURCE_TREE/tools/shared/symbian/epocroot.cpp \ $$QT_SOURCE_TREE/tools/shared/windows/registry.cpp -win32:SOURCES += $$QT_SOURCE_TREE/src/corelib/io/qfsfileengine_win.cpp - DEFINES += COMMERCIAL_VERSION INCLUDEPATH += $$QT_SOURCE_TREE/src/corelib/arch/generic \ diff --git a/tools/qtestlib/wince/cetest/bootstrapped.pri b/tools/qtestlib/wince/cetest/bootstrapped.pri index b9c4b2b..56c8ab7 100644 --- a/tools/qtestlib/wince/cetest/bootstrapped.pri +++ b/tools/qtestlib/wince/cetest/bootstrapped.pri @@ -4,11 +4,14 @@ SOURCES += \ $$QT_SOURCE_TREE/src/corelib/tools/qstringlist.cpp \ $$QT_SOURCE_TREE/src/corelib/io/qfile.cpp \ $$QT_SOURCE_TREE/src/corelib/io/qdir.cpp \ + $$QT_SOURCE_TREE/src/corelib/io/qfilesystementry.cpp \ + $$QT_SOURCE_TREE/src/corelib/io/qfilesystemengine.cpp \ + $$QT_SOURCE_TREE/src/corelib/io/qfilesystemengine_win.cpp \ + $$QT_SOURCE_TREE/src/corelib/io/qfilesystemiterator_win.cpp \ $$QT_SOURCE_TREE/src/corelib/io/qfsfileengine.cpp \ $$QT_SOURCE_TREE/src/corelib/io/qabstractfileengine.cpp \ $$QT_SOURCE_TREE/src/corelib/io/qfsfileengine_win.cpp \ $$QT_SOURCE_TREE/src/corelib/io/qfsfileengine_iterator.cpp \ - $$QT_SOURCE_TREE/src/corelib/io/qfsfileengine_iterator_win.cpp \ $$QT_SOURCE_TREE/src/corelib/io/qfileinfo.cpp \ $$QT_SOURCE_TREE/src/corelib/io/qtemporaryfile.cpp \ $$QT_SOURCE_TREE/src/corelib/io/qdiriterator.cpp \ |