summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore14
-rw-r--r--demos/declarative/minehunt/minehunt.pro2
-rw-r--r--examples/declarative/cppextensions/imageprovider/imageprovider.pro2
-rw-r--r--examples/declarative/cppextensions/qwidgets/qwidgets.pro2
-rw-r--r--qmake/Makefile.unix32
-rw-r--r--qmake/Makefile.win326
-rw-r--r--qmake/Makefile.win32-g++24
-rw-r--r--qmake/Makefile.win32-g++-sh24
-rw-r--r--qmake/qmake.pri10
-rw-r--r--src/corelib/io/io.pri27
-rw-r--r--src/corelib/io/qabstractfileengine.cpp85
-rw-r--r--src/corelib/io/qabstractfileengine_p.h2
-rw-r--r--src/corelib/io/qdir.cpp388
-rw-r--r--src/corelib/io/qdir_p.h98
-rw-r--r--src/corelib/io/qdiriterator.cpp144
-rw-r--r--src/corelib/io/qfile.cpp22
-rw-r--r--src/corelib/io/qfileinfo.cpp234
-rw-r--r--src/corelib/io/qfileinfo.h4
-rw-r--r--src/corelib/io/qfileinfo_p.h31
-rw-r--r--src/corelib/io/qfilesystemengine.cpp385
-rw-r--r--src/corelib/io/qfilesystemengine_mac.cpp48
-rw-r--r--src/corelib/io/qfilesystemengine_p.h133
-rw-r--r--src/corelib/io/qfilesystemengine_symbian.cpp408
-rw-r--r--src/corelib/io/qfilesystemengine_unix.cpp655
-rw-r--r--src/corelib/io/qfilesystemengine_win.cpp1211
-rw-r--r--src/corelib/io/qfilesystementry.cpp383
-rw-r--r--src/corelib/io/qfilesystementry_p.h126
-rw-r--r--src/corelib/io/qfilesystemiterator_p.h115
-rw-r--r--src/corelib/io/qfilesystemiterator_symbian.cpp129
-rw-r--r--src/corelib/io/qfilesystemiterator_unix.cpp113
-rw-r--r--src/corelib/io/qfilesystemiterator_win.cpp148
-rw-r--r--src/corelib/io/qfilesystemmetadata_p.h400
-rw-r--r--src/corelib/io/qfsfileengine.cpp181
-rw-r--r--src/corelib/io/qfsfileengine_iterator.cpp33
-rw-r--r--src/corelib/io/qfsfileengine_iterator_p.h13
-rw-r--r--src/corelib/io/qfsfileengine_iterator_unix.cpp140
-rw-r--r--src/corelib/io/qfsfileengine_iterator_win.cpp161
-rw-r--r--src/corelib/io/qfsfileengine_p.h60
-rw-r--r--src/corelib/io/qfsfileengine_unix.cpp1127
-rw-r--r--src/corelib/io/qfsfileengine_win.cpp1314
-rw-r--r--src/corelib/io/qtemporaryfile.cpp22
-rw-r--r--src/corelib/kernel/kernel.pri118
-rw-r--r--src/corelib/kernel/qcoreapplication.cpp7
-rw-r--r--src/corelib/kernel/qsystemerror.cpp220
-rw-r--r--src/corelib/kernel/qsystemerror_p.h107
-rw-r--r--src/corelib/tools/qdatetime.cpp35
-rw-r--r--src/corelib/tools/qdatetime_p.h6
-rw-r--r--src/declarative/qml/qdeclarativeglobal_p.h2
-rw-r--r--src/gui/dialogs/qfilesystemmodel.cpp2
-rw-r--r--src/gui/kernel/qapplication_s60.cpp3
-rw-r--r--src/s60installs/bwins/QtCoreu.def7
-rw-r--r--src/s60installs/eabi/QtCoreu.def4
-rw-r--r--src/s60installs/eabi/QtDeclarativeu.def6
-rw-r--r--src/s60installs/eabi/QtGuiu.def2
-rw-r--r--src/tools/bootstrap/bootstrap.pro16
-rw-r--r--tests/.gitignore6
-rw-r--r--tests/auto/collections/tst_collections.cpp2
-rw-r--r--tests/auto/corelib.pro2
-rw-r--r--tests/auto/declarative/declarative.pro44
-rw-r--r--tests/auto/declarative/examples/examples.pro4
-rw-r--r--tests/auto/declarative/moduleqt47/moduleqt47.pro2
-rw-r--r--tests/auto/declarative/parserstress/parserstress.pro2
-rw-r--r--tests/auto/declarative/qdeclarativeanchors/qdeclarativeanchors.pro2
-rw-r--r--tests/auto/declarative/qdeclarativeanimatedimage/qdeclarativeanimatedimage.pro2
-rw-r--r--tests/auto/declarative/qdeclarativeanimations/qdeclarativeanimations.pro2
-rw-r--r--tests/auto/declarative/qdeclarativebehaviors/qdeclarativebehaviors.pro2
-rw-r--r--tests/auto/declarative/qdeclarativebinding/qdeclarativebinding.pro2
-rw-r--r--tests/auto/declarative/qdeclarativeborderimage/qdeclarativeborderimage.pro2
-rw-r--r--tests/auto/declarative/qdeclarativeconnection/qdeclarativeconnection.pro2
-rw-r--r--tests/auto/declarative/qdeclarativedom/qdeclarativedom.pro2
-rw-r--r--tests/auto/declarative/qdeclarativeecmascript/qdeclarativeecmascript.pro2
-rw-r--r--tests/auto/declarative/qdeclarativeflickable/qdeclarativeflickable.pro2
-rw-r--r--tests/auto/declarative/qdeclarativeflipable/qdeclarativeflipable.pro2
-rw-r--r--tests/auto/declarative/qdeclarativefocusscope/qdeclarativefocusscope.pro2
-rw-r--r--tests/auto/declarative/qdeclarativefolderlistmodel/qdeclarativefolderlistmodel.pro2
-rw-r--r--tests/auto/declarative/qdeclarativefontloader/qdeclarativefontloader.pro2
-rw-r--r--tests/auto/declarative/qdeclarativegridview/qdeclarativegridview.pro2
-rw-r--r--tests/auto/declarative/qdeclarativeimage/qdeclarativeimage.pro2
-rw-r--r--tests/auto/declarative/qdeclarativeinfo/qdeclarativeinfo.pro2
-rw-r--r--tests/auto/declarative/qdeclarativeitem/qdeclarativeitem.pro2
-rw-r--r--tests/auto/declarative/qdeclarativelanguage/qdeclarativelanguage.pro2
-rw-r--r--tests/auto/declarative/qdeclarativelayoutitem/qdeclarativelayoutitem.pro2
-rw-r--r--tests/auto/declarative/qdeclarativelistmodel/qdeclarativelistmodel.pro2
-rw-r--r--tests/auto/declarative/qdeclarativelistview/qdeclarativelistview.pro2
-rw-r--r--tests/auto/declarative/qdeclarativeloader/qdeclarativeloader.pro2
-rw-r--r--tests/auto/declarative/qdeclarativemoduleplugin/tst_qdeclarativemoduleplugin.pro2
-rw-r--r--tests/auto/declarative/qdeclarativemousearea/qdeclarativemousearea.pro2
-rw-r--r--tests/auto/declarative/qdeclarativeparticles/qdeclarativeparticles.pro2
-rw-r--r--tests/auto/declarative/qdeclarativepathview/qdeclarativepathview.pro2
-rw-r--r--tests/auto/declarative/qdeclarativepixmapcache/qdeclarativepixmapcache.pro2
-rw-r--r--tests/auto/declarative/qdeclarativepixmapcache/tst_qdeclarativepixmapcache.cpp4
-rw-r--r--tests/auto/declarative/qdeclarativepositioners/qdeclarativepositioners.pro2
-rw-r--r--tests/auto/declarative/qdeclarativeproperty/qdeclarativeproperty.pro2
-rw-r--r--tests/auto/declarative/qdeclarativeqt/qdeclarativeqt.pro2
-rw-r--r--tests/auto/declarative/qdeclarativerepeater/qdeclarativerepeater.pro2
-rw-r--r--tests/auto/declarative/qdeclarativescriptdebugging/qdeclarativescriptdebugging.pro2
-rw-r--r--tests/auto/declarative/qdeclarativesmoothedanimation/qdeclarativesmoothedanimation.pro2
-rw-r--r--tests/auto/declarative/qdeclarativespringanimation/qdeclarativespringanimation.pro2
-rw-r--r--tests/auto/declarative/qdeclarativesqldatabase/qdeclarativesqldatabase.pro2
-rw-r--r--tests/auto/declarative/qdeclarativestates/qdeclarativestates.pro2
-rw-r--r--tests/auto/declarative/qdeclarativetext/qdeclarativetext.pro2
-rw-r--r--tests/auto/declarative/qdeclarativetextedit/qdeclarativetextedit.pro2
-rw-r--r--tests/auto/declarative/qdeclarativetextinput/qdeclarativetextinput.pro2
-rw-r--r--tests/auto/declarative/qdeclarativevaluetypes/qdeclarativevaluetypes.pro2
-rw-r--r--tests/auto/declarative/qdeclarativeview/qdeclarativeview.pro2
-rw-r--r--tests/auto/declarative/qdeclarativeviewer/qdeclarativeviewer.pro4
-rw-r--r--tests/auto/declarative/qdeclarativevisualdatamodel/qdeclarativevisualdatamodel.pro2
-rw-r--r--tests/auto/declarative/qdeclarativewebview/qdeclarativewebview.pro2
-rw-r--r--tests/auto/declarative/qdeclarativeworkerscript/qdeclarativeworkerscript.pro2
-rw-r--r--tests/auto/declarative/qdeclarativexmlhttprequest/qdeclarativexmlhttprequest.pro2
-rw-r--r--tests/auto/declarative/qdeclarativexmllistmodel/qdeclarativexmllistmodel.pro2
-rw-r--r--tests/auto/declarative/qmlvisual/qmlvisual.pro3
-rw-r--r--tests/auto/declarative/symbianlibs.pri9
-rw-r--r--tests/auto/networkselftest/networkselftest.pro4
-rw-r--r--tests/auto/qabstractfileengine/qabstractfileengine.pro6
-rw-r--r--tests/auto/qabstractfileengine/qabstractfileengine.qrc5
-rw-r--r--tests/auto/qabstractfileengine/resources/file.txt1
-rw-r--r--tests/auto/qabstractfileengine/tst_qabstractfileengine.cpp765
-rw-r--r--tests/auto/qapplication/test/test.pro4
-rw-r--r--tests/auto/qaudioinput/qaudioinput.pro2
-rw-r--r--tests/auto/qaudiooutput/qaudiooutput.pro2
-rw-r--r--tests/auto/qchar/qchar.pro2
-rw-r--r--tests/auto/qclipboard/test/test.pro2
-rw-r--r--tests/auto/qdir/qdir.pro3
-rw-r--r--tests/auto/qdir/tst_qdir.cpp337
-rw-r--r--tests/auto/qdiriterator/qdiriterator.pro5
-rw-r--r--tests/auto/qdiriterator/tst_qdiriterator.cpp48
-rw-r--r--tests/auto/qdirmodel/tst_qdirmodel.cpp22
-rw-r--r--tests/auto/qfile/largefile/largefile.pro2
-rw-r--r--tests/auto/qfile/qfile.pro1
-rw-r--r--tests/auto/qfile/test/test.pro2
-rw-r--r--tests/auto/qfile/tst_qfile.cpp206
-rw-r--r--tests/auto/qfiledialog/resources/file.txt1
-rw-r--r--tests/auto/qfiledialog/tst_qfiledialog.cpp18
-rw-r--r--tests/auto/qfileinfo/qfileinfo.pro7
-rw-r--r--tests/auto/qfileinfo/tst_qfileinfo.cpp208
-rw-r--r--tests/auto/qfilesystementry/qfilesystementry.pro8
-rw-r--r--tests/auto/qfilesystementry/tst_qfilesystementry.cpp387
-rw-r--r--tests/auto/qfilesystemmodel/tst_qfilesystemmodel.cpp9
-rw-r--r--tests/auto/qfilesystemwatcher/qfilesystemwatcher.pro2
-rw-r--r--tests/auto/qhttp/qhttp.pro4
-rw-r--r--tests/auto/qimagereader/tst_qimagereader.cpp10
-rw-r--r--tests/auto/qlocalsocket/test/test.pro2
-rw-r--r--tests/auto/qprocess/tst_qprocess.cpp8
-rw-r--r--tests/auto/qresourceengine/qresourceengine.pro2
-rw-r--r--tests/auto/qsettings/qsettings.pro2
-rw-r--r--tests/auto/qsound/qsound.pro2
-rw-r--r--tests/auto/qtemporaryfile/qtemporaryfile.pro2
-rw-r--r--tests/auto/qxmlstream/qxmlstream.pro2
-rw-r--r--tests/auto/qxmlstream/tst_qxmlstream.cpp4
-rw-r--r--tests/benchmarks/corelib/io/qdir/tree/bench_qdir_tree.cpp69
-rw-r--r--tests/benchmarks/declarative/binding/binding.pro2
-rw-r--r--tests/benchmarks/declarative/qdeclarativeimage/qdeclarativeimage.pro2
-rw-r--r--tests/benchmarks/declarative/script/script.pro2
-rw-r--r--tests/shared/filesystem.h10
-rw-r--r--tools/configure/configure.pro12
-rw-r--r--tools/qtestlib/wince/cetest/bootstrapped.pri5
157 files changed, 8321 insertions, 3045 deletions
diff --git a/.gitignore b/.gitignore
index f9a4454..d446680 100644
--- a/.gitignore
+++ b/.gitignore
@@ -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 &copy)
- : QSharedData(copy)
- , path(copy.path)
- , nameFilters(copy.nameFilters)
- , sort(copy.sort)
- , filters(copy.filters)
+QDirPrivate::QDirPrivate(const QDirPrivate &copy)
+ : 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 &copy);
+
+ 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 &copy)
- : 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..39fce97
--- /dev/null
+++ b/src/corelib/io/qfilesystemengine_win.cpp
@@ -0,0 +1,1211 @@
+/****************************************************************************
+**
+** 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(&currentUserTrusteeW, 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;
+}
+
+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, &currentUserTrusteeW, &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);
+ 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..c4e11d9
--- /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(&currentUserTrusteeW, 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 &copyName)
{
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, &currentUserTrusteeW, &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/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..dc46f52 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,11 @@ void tst_QDir::canonicalPath_data()
#endif
QTest::newRow("nonexistant") << "testd" << QString();
+ QTest::newRow("rootPath") << QDir::rootPath() << QDir::rootPath();
+ 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 +928,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 +973,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 +1143,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 +1206,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 +1220,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 +1305,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 +1466,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 +1733,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");
@@ -1672,8 +1755,13 @@ void tst_QDir::isRoot_data()
QTest::newRow(QString("./ appended " + test).toLatin1()) << test << false;
test = QDir(QDir::rootPath().append("./")).canonicalPath();
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,8 +1772,203 @@ 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..2e1ab39 100644
--- a/tests/auto/qfileinfo/tst_qfileinfo.cpp
+++ b/tests/auto/qfileinfo/tst_qfileinfo.cpp
@@ -59,6 +59,7 @@
#define _WIN32_WINNT 0x500
#include <qt_windows.h>
#include <qlibrary.h>
+#include <lm.h>
#endif
#include <qplatformdefs.h>
#include <qdebug.h>
@@ -72,6 +73,7 @@
#if defined(Q_OS_SYMBIAN)
# define SRCDIR ""
+# define NO_SYMLINKS
#endif
QT_BEGIN_NAMESPACE
@@ -187,6 +189,11 @@ private slots:
void notEqualOperator() const;
void detachingOperations();
+
+#if !defined(Q_OS_WINCE) && !defined(Q_OS_SYMBIAN)
+ void owner();
+#endif
+ void group();
};
tst_QFileInfo::tst_QFileInfo()
@@ -415,6 +422,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 +525,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 +619,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 +719,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 +1119,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 +1139,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 +1152,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 +1288,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 +1380,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 +1486,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 +1503,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 +1514,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 +1647,115 @@ 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)
+ char *usernameBuf = getlogin();
+ if (usernameBuf) {
+ 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");
+ 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(userName, fi.owner());
+ if (QFile::exists(fileName))
+ 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);
+}
+
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 \