summaryrefslogtreecommitdiffstats
path: root/src/corelib/io
diff options
context:
space:
mode:
authorJoão Abecasis <joao.abecasis@nokia.com>2012-01-16 17:52:29 +0100
committerJoão Abecasis <joao.abecasis@nokia.com>2012-01-16 17:53:41 +0100
commit5b250d497fd798c476765b22a2906e1c0ff1e432 (patch)
treefd4215ca375cc2402e536bf670c2977cf64ae2ef /src/corelib/io
parent2c52e9a5c1d6ef6cbf4577430e14027375465c96 (diff)
parent7a0099183a1c107126bda3b59a47651aac612426 (diff)
Merge remote-tracking branch 'gerrit/master' into containers
Diffstat (limited to 'src/corelib/io')
-rw-r--r--src/corelib/io/io.pri57
-rw-r--r--src/corelib/io/qabstractfileengine.cpp2
-rw-r--r--src/corelib/io/qabstractfileengine.h2
-rw-r--r--src/corelib/io/qabstractfileengine_p.h2
-rw-r--r--src/corelib/io/qbuffer.cpp10
-rw-r--r--src/corelib/io/qbuffer.h2
-rw-r--r--src/corelib/io/qdatastream.cpp2
-rw-r--r--src/corelib/io/qdatastream.h2
-rw-r--r--src/corelib/io/qdatastream_p.h2
-rw-r--r--src/corelib/io/qdataurl.cpp68
-rw-r--r--src/corelib/io/qdataurl_p.h4
-rw-r--r--src/corelib/io/qdebug.cpp2
-rw-r--r--src/corelib/io/qdebug.h21
-rw-r--r--src/corelib/io/qdir.cpp4
-rw-r--r--src/corelib/io/qdir.h2
-rw-r--r--src/corelib/io/qdir_p.h2
-rw-r--r--src/corelib/io/qdiriterator.cpp2
-rw-r--r--src/corelib/io/qdiriterator.h2
-rw-r--r--src/corelib/io/qfile.cpp2
-rw-r--r--src/corelib/io/qfile.h2
-rw-r--r--src/corelib/io/qfile_p.h2
-rw-r--r--src/corelib/io/qfileinfo.cpp2
-rw-r--r--src/corelib/io/qfileinfo.h2
-rw-r--r--src/corelib/io/qfileinfo_p.h2
-rw-r--r--src/corelib/io/qfilesystemengine.cpp2
-rw-r--r--src/corelib/io/qfilesystemengine_mac.cpp2
-rw-r--r--src/corelib/io/qfilesystemengine_p.h2
-rw-r--r--src/corelib/io/qfilesystemengine_symbian.cpp406
-rw-r--r--src/corelib/io/qfilesystemengine_unix.cpp2
-rw-r--r--src/corelib/io/qfilesystemengine_win.cpp63
-rw-r--r--src/corelib/io/qfilesystementry.cpp2
-rw-r--r--src/corelib/io/qfilesystementry_p.h2
-rw-r--r--src/corelib/io/qfilesystemiterator_p.h2
-rw-r--r--src/corelib/io/qfilesystemiterator_symbian.cpp127
-rw-r--r--src/corelib/io/qfilesystemiterator_unix.cpp2
-rw-r--r--src/corelib/io/qfilesystemiterator_win.cpp2
-rw-r--r--src/corelib/io/qfilesystemmetadata_p.h2
-rw-r--r--src/corelib/io/qfilesystemwatcher.cpp371
-rw-r--r--src/corelib/io/qfilesystemwatcher.h10
-rw-r--r--src/corelib/io/qfilesystemwatcher_dnotify.cpp461
-rw-r--r--src/corelib/io/qfilesystemwatcher_fsevents.cpp492
-rw-r--r--src/corelib/io/qfilesystemwatcher_fsevents_p.h132
-rw-r--r--src/corelib/io/qfilesystemwatcher_inotify.cpp37
-rw-r--r--src/corelib/io/qfilesystemwatcher_inotify_p.h17
-rw-r--r--src/corelib/io/qfilesystemwatcher_kqueue.cpp296
-rw-r--r--src/corelib/io/qfilesystemwatcher_kqueue_p.h15
-rw-r--r--src/corelib/io/qfilesystemwatcher_p.h17
-rw-r--r--src/corelib/io/qfilesystemwatcher_polling.cpp151
-rw-r--r--src/corelib/io/qfilesystemwatcher_polling_p.h (renamed from src/corelib/io/qfilesystemwatcher_dnotify_p.h)113
-rw-r--r--src/corelib/io/qfilesystemwatcher_symbian.cpp273
-rw-r--r--src/corelib/io/qfilesystemwatcher_win.cpp35
-rw-r--r--src/corelib/io/qfilesystemwatcher_win_p.h10
-rw-r--r--src/corelib/io/qfsfileengine.cpp2
-rw-r--r--src/corelib/io/qfsfileengine.h2
-rw-r--r--src/corelib/io/qfsfileengine_iterator.cpp2
-rw-r--r--src/corelib/io/qfsfileengine_iterator_p.h2
-rw-r--r--src/corelib/io/qfsfileengine_p.h2
-rw-r--r--src/corelib/io/qfsfileengine_unix.cpp2
-rw-r--r--src/corelib/io/qfsfileengine_win.cpp5
-rw-r--r--src/corelib/io/qiodevice.cpp2
-rw-r--r--src/corelib/io/qiodevice.h2
-rw-r--r--src/corelib/io/qiodevice_p.h2
-rw-r--r--src/corelib/io/qnoncontiguousbytedevice.cpp2
-rw-r--r--src/corelib/io/qnoncontiguousbytedevice_p.h2
-rw-r--r--src/corelib/io/qprocess.cpp14
-rw-r--r--src/corelib/io/qprocess.h2
-rw-r--r--src/corelib/io/qprocess_p.h2
-rw-r--r--src/corelib/io/qprocess_symbian.cpp1072
-rw-r--r--src/corelib/io/qprocess_unix.cpp2
-rw-r--r--src/corelib/io/qprocess_win.cpp125
-rw-r--r--src/corelib/io/qprocess_wince.cpp330
-rw-r--r--src/corelib/io/qresource.cpp4
-rw-r--r--src/corelib/io/qresource.h2
-rw-r--r--src/corelib/io/qresource_iterator.cpp2
-rw-r--r--src/corelib/io/qresource_iterator_p.h2
-rw-r--r--src/corelib/io/qresource_p.h2
-rw-r--r--src/corelib/io/qsettings.cpp2
-rw-r--r--src/corelib/io/qsettings.h2
-rw-r--r--src/corelib/io/qsettings_mac.cpp2
-rw-r--r--src/corelib/io/qsettings_p.h2
-rw-r--r--src/corelib/io/qsettings_win.cpp2
-rw-r--r--src/corelib/io/qstandardpaths.cpp4
-rw-r--r--src/corelib/io/qstandardpaths.h5
-rw-r--r--src/corelib/io/qstandardpaths_mac.cpp6
-rw-r--r--src/corelib/io/qstandardpaths_unix.cpp13
-rw-r--r--src/corelib/io/qstandardpaths_win.cpp5
-rw-r--r--src/corelib/io/qtemporarydir.cpp2
-rw-r--r--src/corelib/io/qtemporarydir.h2
-rw-r--r--src/corelib/io/qtemporaryfile.cpp2
-rw-r--r--src/corelib/io/qtemporaryfile.h2
-rw-r--r--src/corelib/io/qtextstream.cpp2
-rw-r--r--src/corelib/io/qtextstream.h2
-rw-r--r--src/corelib/io/qtldurl.cpp2
-rw-r--r--src/corelib/io/qtldurl_p.h2
-rw-r--r--src/corelib/io/qurl.cpp2
-rw-r--r--src/corelib/io/qurl.h2
-rw-r--r--src/corelib/io/qwindowspipereader.cpp315
-rw-r--r--src/corelib/io/qwindowspipereader_p.h (renamed from src/corelib/io/qfilesystemwatcher_symbian_p.h)106
-rw-r--r--src/corelib/io/qwindowspipewriter.cpp2
-rw-r--r--src/corelib/io/qwindowspipewriter_p.h2
100 files changed, 1397 insertions, 3923 deletions
diff --git a/src/corelib/io/io.pri b/src/corelib/io/io.pri
index ef11621679..1d31e5d794 100644
--- a/src/corelib/io/io.pri
+++ b/src/corelib/io/io.pri
@@ -35,6 +35,7 @@ HEADERS += \
io/qfsfileengine_iterator_p.h \
io/qfilesystemwatcher.h \
io/qfilesystemwatcher_p.h \
+ io/qfilesystemwatcher_polling_p.h \
io/qfilesystementry_p.h \
io/qfilesystemengine_p.h \
io/qfilesystemmetadata_p.h \
@@ -65,36 +66,39 @@ SOURCES += \
io/qfsfileengine.cpp \
io/qfsfileengine_iterator.cpp \
io/qfilesystemwatcher.cpp \
+ io/qfilesystemwatcher_polling.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/qfilesystemwatcher_win.cpp
HEADERS += io/qfilesystemwatcher_win_p.h
+ HEADERS += io/qwindowspipereader_p.h
+ SOURCES += io/qwindowspipereader.cpp
HEADERS += io/qwindowspipewriter_p.h
SOURCES += io/qwindowspipewriter.cpp
SOURCES += io/qfilesystemengine_win.cpp
SOURCES += io/qfilesystemiterator_win.cpp
SOURCES += io/qstandardpaths_win.cpp
-} else:unix {
- SOURCES += io/qfsfileengine_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
- }
+
+ wince* {
+ SOURCES += io/qprocess_wince.cpp
+ } else {
+ SOURCES += io/qprocess_win.cpp
+ }
+} else:unix|integrity {
+ SOURCES += \
+ io/qfsfileengine_unix.cpp \
+ io/qfilesystemengine_unix.cpp \
+ io/qprocess_unix.cpp \
+ 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
+ SOURCES += io/qsettings_mac.cpp
}
macx-*: {
SOURCES += io/qstandardpaths_mac.cpp
@@ -102,14 +106,9 @@ win32 {
SOURCES += io/qstandardpaths_unix.cpp
}
- linux-*:!symbian {
- SOURCES += \
- io/qfilesystemwatcher_inotify.cpp \
- io/qfilesystemwatcher_dnotify.cpp
-
- HEADERS += \
- io/qfilesystemwatcher_inotify_p.h \
- io/qfilesystemwatcher_dnotify_p.h
+ linux-* {
+ SOURCES += io/qfilesystemwatcher_inotify.cpp
+ HEADERS += io/qfilesystemwatcher_inotify_p.h
}
!nacl {
@@ -118,17 +117,5 @@ win32 {
HEADERS += io/qfilesystemwatcher_kqueue_p.h
}
}
-
- symbian {
- SOURCES += io/qfilesystemwatcher_symbian.cpp
- HEADERS += io/qfilesystemwatcher_symbian_p.h
- INCLUDEPATH += $$MW_LAYER_SYSTEMINCLUDE
- LIBS += -lplatformenv -lesock
- }
-}
-integrity {
- SOURCES += io/qfsfileengine_unix.cpp \
- io/qfsfileengine_iterator.cpp \
- io/qfilesystemengine_unix.cpp \
- io/qfilesystemiterator_unix.cpp
}
+
diff --git a/src/corelib/io/qabstractfileengine.cpp b/src/corelib/io/qabstractfileengine.cpp
index d2b250d336..c315d33606 100644
--- a/src/corelib/io/qabstractfileengine.cpp
+++ b/src/corelib/io/qabstractfileengine.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
diff --git a/src/corelib/io/qabstractfileengine.h b/src/corelib/io/qabstractfileengine.h
index cc167a2aa6..c9bab7d435 100644
--- a/src/corelib/io/qabstractfileengine.h
+++ b/src/corelib/io/qabstractfileengine.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
diff --git a/src/corelib/io/qabstractfileengine_p.h b/src/corelib/io/qabstractfileengine_p.h
index dd9a707316..72b8339e39 100644
--- a/src/corelib/io/qabstractfileengine_p.h
+++ b/src/corelib/io/qabstractfileengine_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
diff --git a/src/corelib/io/qbuffer.cpp b/src/corelib/io/qbuffer.cpp
index 35e7b6809c..a5e605b9d5 100644
--- a/src/corelib/io/qbuffer.cpp
+++ b/src/corelib/io/qbuffer.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
@@ -143,12 +143,8 @@ QByteArray QBufferPrivate::peek(qint64 maxSize)
QBuffer emits readyRead() when new data has arrived in the
buffer. By connecting to this signal, you can use QBuffer to
- store temporary data before processing it. For example, you can
- pass the buffer to QFtp when downloading a file from an FTP
- server. Whenever a new payload of data has been downloaded,
- readyRead() is emitted, and you can process the data that just
- arrived. QBuffer also emits bytesWritten() every time new data
- has been written to the buffer.
+ store temporary data before processing it. QBuffer also emits
+ bytesWritten() every time new data has been written to the buffer.
\sa QFile, QDataStream, QTextStream, QByteArray
*/
diff --git a/src/corelib/io/qbuffer.h b/src/corelib/io/qbuffer.h
index 9227a2f3dc..b222c7d6ca 100644
--- a/src/corelib/io/qbuffer.h
+++ b/src/corelib/io/qbuffer.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
diff --git a/src/corelib/io/qdatastream.cpp b/src/corelib/io/qdatastream.cpp
index 0e0a47267a..fb2528e45f 100644
--- a/src/corelib/io/qdatastream.cpp
+++ b/src/corelib/io/qdatastream.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
diff --git a/src/corelib/io/qdatastream.h b/src/corelib/io/qdatastream.h
index 1ae0573f6c..30cf8417ad 100644
--- a/src/corelib/io/qdatastream.h
+++ b/src/corelib/io/qdatastream.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
diff --git a/src/corelib/io/qdatastream_p.h b/src/corelib/io/qdatastream_p.h
index d372d54e36..2501e98d1d 100644
--- a/src/corelib/io/qdatastream_p.h
+++ b/src/corelib/io/qdatastream_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
diff --git a/src/corelib/io/qdataurl.cpp b/src/corelib/io/qdataurl.cpp
index ed8abdd839..7e856ad647 100644
--- a/src/corelib/io/qdataurl.cpp
+++ b/src/corelib/io/qdataurl.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
@@ -51,51 +51,49 @@ QT_BEGIN_NAMESPACE
Decode a data: URL into its mimetype and payload. Returns a null string if
the URL could not be decoded.
*/
-Q_CORE_EXPORT QPair<QString, QByteArray> qDecodeDataUrl(const QUrl &uri)
+Q_CORE_EXPORT bool qDecodeDataUrl(const QUrl &uri, QString &mimeType, QByteArray &payload)
{
- QString mimeType;
- QByteArray payload;
+ if (uri.scheme() != QLatin1String("data") || !uri.host().isEmpty())
+ return false;
- if (uri.scheme() == QLatin1String("data") && uri.host().isEmpty()) {
- mimeType = QLatin1String("text/plain;charset=US-ASCII");
+ mimeType = QLatin1String("text/plain;charset=US-ASCII");
- // the following would have been the correct thing, but
- // reality often differs from the specification. People have
- // data: URIs with ? and #
- //QByteArray data = QByteArray::fromPercentEncoding(uri.encodedPath());
- QByteArray data = QByteArray::fromPercentEncoding(uri.toEncoded());
+ // the following would have been the correct thing, but
+ // reality often differs from the specification. People have
+ // data: URIs with ? and #
+ //QByteArray data = QByteArray::fromPercentEncoding(uri.encodedPath());
+ QByteArray data = QByteArray::fromPercentEncoding(uri.toEncoded());
- // remove the data: scheme
- data.remove(0, 5);
+ // remove the data: scheme
+ data.remove(0, 5);
- // parse it:
- int pos = data.indexOf(',');
- if (pos != -1) {
- payload = data.mid(pos + 1);
- data.truncate(pos);
- data = data.trimmed();
+ // parse it:
+ int pos = data.indexOf(',');
+ if (pos != -1) {
+ payload = data.mid(pos + 1);
+ data.truncate(pos);
+ data = data.trimmed();
- // find out if the payload is encoded in Base64
- if (data.endsWith(";base64")) {
- payload = QByteArray::fromBase64(payload);
- data.chop(7);
- }
+ // find out if the payload is encoded in Base64
+ if (data.endsWith(";base64")) {
+ payload = QByteArray::fromBase64(payload);
+ data.chop(7);
+ }
- if (data.toLower().startsWith("charset")) {
- int i = 7; // strlen("charset")
- while (data.at(i) == ' ')
- ++i;
- if (data.at(i) == '=')
- data.prepend("text/plain;");
- }
+ if (data.toLower().startsWith("charset")) {
+ int i = 7; // strlen("charset")
+ while (data.at(i) == ' ')
+ ++i;
+ if (data.at(i) == '=')
+ data.prepend("text/plain;");
+ }
- if (!data.isEmpty())
- mimeType = QLatin1String(data.trimmed());
+ if (!data.isEmpty())
+ mimeType = QLatin1String(data.trimmed());
- }
}
- return QPair<QString,QByteArray>(mimeType,payload);
+ return true;
}
QT_END_NAMESPACE
diff --git a/src/corelib/io/qdataurl_p.h b/src/corelib/io/qdataurl_p.h
index d666d9e52a..b92f363e1d 100644
--- a/src/corelib/io/qdataurl_p.h
+++ b/src/corelib/io/qdataurl_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
@@ -60,7 +60,7 @@
QT_BEGIN_NAMESPACE
-Q_CORE_EXPORT QPair<QString, QByteArray> qDecodeDataUrl(const QUrl &url);
+Q_CORE_EXPORT bool qDecodeDataUrl(const QUrl &url, QString &mimeType, QByteArray &payload);
QT_END_NAMESPACE
diff --git a/src/corelib/io/qdebug.cpp b/src/corelib/io/qdebug.cpp
index a27716b8dc..8ca15b19ca 100644
--- a/src/corelib/io/qdebug.cpp
+++ b/src/corelib/io/qdebug.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
diff --git a/src/corelib/io/qdebug.h b/src/corelib/io/qdebug.h
index 67221c7ce2..54663d5d65 100644
--- a/src/corelib/io/qdebug.h
+++ b/src/corelib/io/qdebug.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
@@ -129,10 +129,8 @@ public:
inline QNoDebug(){}
inline QNoDebug(const QDebug &){}
inline ~QNoDebug(){}
-#if !defined( QT_NO_TEXTSTREAM )
inline QNoDebug &operator<<(QTextStreamFunction) { return *this; }
inline QNoDebug &operator<<(QTextStreamManipulator) { return *this; }
-#endif
inline QNoDebug &space() { return *this; }
inline QNoDebug &nospace() { return *this; }
inline QNoDebug &maybeSpace() { return *this; }
@@ -141,8 +139,6 @@ public:
inline QNoDebug &operator<<(const T &) { return *this; }
};
-Q_CORE_EXPORT_INLINE QDebug qCritical() { return QDebug(QtCriticalMsg); }
-
inline QDebug &QDebug::operator=(const QDebug &other)
{
if (this != &other) {
@@ -161,7 +157,7 @@ inline QDebug operator<<(QDebug debug, const QList<T> &list)
#endif
{
debug.nospace() << '(';
- for (Q_TYPENAME QList<T>::size_type i = 0; i < list.count(); ++i) {
+ for (typename QList<T>::size_type i = 0; i < list.count(); ++i) {
if (i)
debug << ", ";
debug << list.at(i);
@@ -275,17 +271,15 @@ inline QDebug operator<<(QDebug debug, const QFlags<T> &flags)
return debug.space();
}
-#if !defined(QT_NO_DEBUG_STREAM)
+#if !defined(QT_NO_DEBUG_OUTPUT) && !defined(QT_NO_DEBUG_STREAM)
Q_CORE_EXPORT_INLINE QDebug qDebug() { return QDebug(QtDebugMsg); }
-
-#else // QT_NO_DEBUG_STREAM
+#else
#undef qDebug
inline QNoDebug qDebug() { return QNoDebug(); }
#define qDebug QT_NO_QDEBUG_MACRO
-
#endif
-#if !defined(QT_NO_WARNING_OUTPUT)
+#if !defined(QT_NO_WARNING_OUTPUT) && !defined(QT_NO_DEBUG_STREAM)
Q_CORE_EXPORT_INLINE QDebug qWarning() { return QDebug(QtWarningMsg); }
#else
#undef qWarning
@@ -293,6 +287,11 @@ inline QNoDebug qWarning() { return QNoDebug(); }
#define qWarning QT_NO_QWARNING_MACRO
#endif
+#if !defined(QT_NO_DEBUG_STREAM)
+Q_CORE_EXPORT_INLINE QDebug qCritical() { return QDebug(QtCriticalMsg); }
+#endif
+
+
QT_END_NAMESPACE
QT_END_HEADER
diff --git a/src/corelib/io/qdir.cpp b/src/corelib/io/qdir.cpp
index 44992fcd14..d6979bad57 100644
--- a/src/corelib/io/qdir.cpp
+++ b/src/corelib/io/qdir.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
@@ -1502,7 +1502,7 @@ bool QDir::removeRecursively()
di.next();
const QFileInfo& fi = di.fileInfo();
bool ok;
- if (fi.isDir())
+ if (fi.isDir() && !fi.isSymLink())
ok = QDir(di.filePath()).removeRecursively(); // recursive
else
ok = QFile::remove(di.filePath());
diff --git a/src/corelib/io/qdir.h b/src/corelib/io/qdir.h
index e246f2f1aa..5b058272e7 100644
--- a/src/corelib/io/qdir.h
+++ b/src/corelib/io/qdir.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
diff --git a/src/corelib/io/qdir_p.h b/src/corelib/io/qdir_p.h
index a34427a716..7865c1d5a3 100644
--- a/src/corelib/io/qdir_p.h
+++ b/src/corelib/io/qdir_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
diff --git a/src/corelib/io/qdiriterator.cpp b/src/corelib/io/qdiriterator.cpp
index 0b02adb4b6..28aa4a0f59 100644
--- a/src/corelib/io/qdiriterator.cpp
+++ b/src/corelib/io/qdiriterator.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
diff --git a/src/corelib/io/qdiriterator.h b/src/corelib/io/qdiriterator.h
index 5ad8acb496..be03415372 100644
--- a/src/corelib/io/qdiriterator.h
+++ b/src/corelib/io/qdiriterator.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
diff --git a/src/corelib/io/qfile.cpp b/src/corelib/io/qfile.cpp
index d5118525cf..95d842da42 100644
--- a/src/corelib/io/qfile.cpp
+++ b/src/corelib/io/qfile.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
diff --git a/src/corelib/io/qfile.h b/src/corelib/io/qfile.h
index 554b2954e1..903ba13963 100644
--- a/src/corelib/io/qfile.h
+++ b/src/corelib/io/qfile.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
diff --git a/src/corelib/io/qfile_p.h b/src/corelib/io/qfile_p.h
index 3072f5bc9e..24013c3c3d 100644
--- a/src/corelib/io/qfile_p.h
+++ b/src/corelib/io/qfile_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
diff --git a/src/corelib/io/qfileinfo.cpp b/src/corelib/io/qfileinfo.cpp
index 1ea6c8d50a..226b5d3560 100644
--- a/src/corelib/io/qfileinfo.cpp
+++ b/src/corelib/io/qfileinfo.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
diff --git a/src/corelib/io/qfileinfo.h b/src/corelib/io/qfileinfo.h
index ef4573132c..6d6da3527a 100644
--- a/src/corelib/io/qfileinfo.h
+++ b/src/corelib/io/qfileinfo.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
diff --git a/src/corelib/io/qfileinfo_p.h b/src/corelib/io/qfileinfo_p.h
index 23ea0225f5..64e644f29f 100644
--- a/src/corelib/io/qfileinfo_p.h
+++ b/src/corelib/io/qfileinfo_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
diff --git a/src/corelib/io/qfilesystemengine.cpp b/src/corelib/io/qfilesystemengine.cpp
index 72900ec033..ab10f30585 100644
--- a/src/corelib/io/qfilesystemengine.cpp
+++ b/src/corelib/io/qfilesystemengine.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
diff --git a/src/corelib/io/qfilesystemengine_mac.cpp b/src/corelib/io/qfilesystemengine_mac.cpp
index 0d1556522a..f5e61ff29f 100644
--- a/src/corelib/io/qfilesystemengine_mac.cpp
+++ b/src/corelib/io/qfilesystemengine_mac.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
diff --git a/src/corelib/io/qfilesystemengine_p.h b/src/corelib/io/qfilesystemengine_p.h
index bbd4c4c020..af32a1c575 100644
--- a/src/corelib/io/qfilesystemengine_p.h
+++ b/src/corelib/io/qfilesystemengine_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
diff --git a/src/corelib/io/qfilesystemengine_symbian.cpp b/src/corelib/io/qfilesystemengine_symbian.cpp
deleted file mode 100644
index c8c1dfdc84..0000000000
--- a/src/corelib/io/qfilesystemengine_symbian.cpp
+++ /dev/null
@@ -1,406 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 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$
-** GNU Lesser General Public License Usage
-** 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.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU General
-** Public License version 3.0 as published by the Free Software Foundation
-** and appearing in the file LICENSE.GPL included in the packaging of this
-** file. Please review the following information to ensure the GNU General
-** Public License version 3.0 requirements will be met:
-** http://www.gnu.org/copyleft/gpl.html.
-**
-** Other Usage
-** Alternatively, this file may be used in accordance with the terms and
-** conditions contained in a signed written agreement between you and Nokia.
-**
-**
-**
-**
-**
-** $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 = !entry.isClean();
- 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
index 9778b526ac..901aaf8f91 100644
--- a/src/corelib/io/qfilesystemengine_unix.cpp
+++ b/src/corelib/io/qfilesystemengine_unix.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
diff --git a/src/corelib/io/qfilesystemengine_win.cpp b/src/corelib/io/qfilesystemengine_win.cpp
index 10ba95e97f..d724429f6b 100644
--- a/src/corelib/io/qfilesystemengine_win.cpp
+++ b/src/corelib/io/qfilesystemengine_win.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
@@ -160,6 +160,31 @@ typedef DWORD (WINAPI *PtrGetEffectiveRightsFromAclW)(PACL, PTRUSTEE_W, OUT PACC
static PtrGetEffectiveRightsFromAclW ptrGetEffectiveRightsFromAclW = 0;
static TRUSTEE_W currentUserTrusteeW;
static TRUSTEE_W worldTrusteeW;
+static PSID currentUserSID = 0;
+static PSID worldSID = 0;
+
+/*
+ Deletes the allocated SIDs during global static cleanup
+*/
+class SidCleanup
+{
+public:
+ ~SidCleanup();
+};
+
+SidCleanup::~SidCleanup()
+{
+ qFree(currentUserSID);
+ currentUserSID = 0;
+
+ // worldSID was allocated with AllocateAndInitializeSid so it needs to be freed with FreeSid
+ if (worldSID) {
+ ::FreeSid(worldSID);
+ worldSID = 0;
+ }
+}
+
+Q_GLOBAL_STATIC(SidCleanup, initSidCleanup)
typedef BOOL (WINAPI *PtrGetUserProfileDirectoryW)(HANDLE, LPWSTR, LPDWORD);
static PtrGetUserProfileDirectoryW ptrGetUserProfileDirectoryW = 0;
@@ -199,25 +224,35 @@ static void resolveLibs()
// Create TRUSTEE for current user
HANDLE hnd = ::GetCurrentProcess();
HANDLE token = 0;
+ initSidCleanup();
if (::OpenProcessToken(hnd, TOKEN_QUERY, &token)) {
- TOKEN_USER tu;
- DWORD retsize;
- if (::GetTokenInformation(token, TokenUser, &tu, sizeof(tu), &retsize))
- ptrBuildTrusteeWithSidW(&currentUserTrusteeW, tu.User.Sid);
+ DWORD retsize = 0;
+ // GetTokenInformation requires a buffer big enough for the TOKEN_USER struct and
+ // the SID struct. Since the SID struct can have variable number of subauthorities
+ // tacked at the end, its size is variable. Obtain the required size by first
+ // doing a dummy GetTokenInformation call.
+ ::GetTokenInformation(token, TokenUser, 0, 0, &retsize);
+ if (retsize) {
+ void *tokenBuffer = qMalloc(retsize);
+ if (::GetTokenInformation(token, TokenUser, tokenBuffer, retsize, &retsize)) {
+ PSID tokenSid = reinterpret_cast<PTOKEN_USER>(tokenBuffer)->User.Sid;
+ DWORD sidLen = ::GetLengthSid(tokenSid);
+ currentUserSID = reinterpret_cast<PSID>(qMalloc(sidLen));
+ if (::CopySid(sidLen, currentUserSID, tokenSid))
+ ptrBuildTrusteeWithSidW(&currentUserTrusteeW, currentUserSID);
+ }
+ qFree(tokenBuffer);
+ }
::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) {
+ if (ptrAllocateAndInitializeSid) {
// 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);
+ if (ptrAllocateAndInitializeSid(&worldAuth, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &worldSID))
+ ptrBuildTrusteeWithSidW(&worldTrusteeW, worldSID);
}
}
HINSTANCE userenvHnd = QSystemLibrary::load(L"userenv");
@@ -278,7 +313,7 @@ static QString readSymLink(const QFileSystemEntry &link)
0);
if (handle != INVALID_HANDLE_VALUE) {
DWORD bufsize = MAXIMUM_REPARSE_DATA_BUFFER_SIZE;
- REPARSE_DATA_BUFFER *rdb = (REPARSE_DATA_BUFFER*)qMalloc(bufsize);
+ REPARSE_DATA_BUFFER *rdb = (REPARSE_DATA_BUFFER*)malloc(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) {
@@ -296,7 +331,7 @@ static QString readSymLink(const QFileSystemEntry &link)
if (result.size() > 4 && result.at(0) == QLatin1Char('\\') && result.at(2) == QLatin1Char('?') && result.at(3) == QLatin1Char('\\'))
result = result.mid(4);
}
- qFree(rdb);
+ free(rdb);
CloseHandle(handle);
#if !defined(QT_NO_LIBRARY)
diff --git a/src/corelib/io/qfilesystementry.cpp b/src/corelib/io/qfilesystementry.cpp
index 2f37542f66..11b73dd745 100644
--- a/src/corelib/io/qfilesystementry.cpp
+++ b/src/corelib/io/qfilesystementry.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
diff --git a/src/corelib/io/qfilesystementry_p.h b/src/corelib/io/qfilesystementry_p.h
index 8d524c087e..61902f77d0 100644
--- a/src/corelib/io/qfilesystementry_p.h
+++ b/src/corelib/io/qfilesystementry_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
diff --git a/src/corelib/io/qfilesystemiterator_p.h b/src/corelib/io/qfilesystemiterator_p.h
index 6f2d1e1c6e..7df5988459 100644
--- a/src/corelib/io/qfilesystemiterator_p.h
+++ b/src/corelib/io/qfilesystemiterator_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
diff --git a/src/corelib/io/qfilesystemiterator_symbian.cpp b/src/corelib/io/qfilesystemiterator_symbian.cpp
deleted file mode 100644
index 4347f6acba..0000000000
--- a/src/corelib/io/qfilesystemiterator_symbian.cpp
+++ /dev/null
@@ -1,127 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 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$
-** GNU Lesser General Public License Usage
-** 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.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU General
-** Public License version 3.0 as published by the Free Software Foundation
-** and appearing in the file LICENSE.GPL included in the packaging of this
-** file. Please review the following information to ensure the GNU General
-** Public License version 3.0 requirements will be met:
-** http://www.gnu.org/copyleft/gpl.html.
-**
-** Other Usage
-** Alternatively, this file may be used in accordance with the terms and
-** conditions contained in a signed written agreement between you and Nokia.
-**
-**
-**
-**
-**
-** $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;
- }
-
- 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
index 6987660ea3..d0eb04a145 100644
--- a/src/corelib/io/qfilesystemiterator_unix.cpp
+++ b/src/corelib/io/qfilesystemiterator_unix.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
diff --git a/src/corelib/io/qfilesystemiterator_win.cpp b/src/corelib/io/qfilesystemiterator_win.cpp
index 5fff4f82c6..1f5cf356a0 100644
--- a/src/corelib/io/qfilesystemiterator_win.cpp
+++ b/src/corelib/io/qfilesystemiterator_win.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
diff --git a/src/corelib/io/qfilesystemmetadata_p.h b/src/corelib/io/qfilesystemmetadata_p.h
index 64749e3889..6ed5cec954 100644
--- a/src/corelib/io/qfilesystemmetadata_p.h
+++ b/src/corelib/io/qfilesystemmetadata_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
diff --git a/src/corelib/io/qfilesystemwatcher.cpp b/src/corelib/io/qfilesystemwatcher.cpp
index 9739067c06..4abb4f3cc1 100644
--- a/src/corelib/io/qfilesystemwatcher.cpp
+++ b/src/corelib/io/qfilesystemwatcher.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
@@ -48,234 +48,45 @@
#include <qdebug.h>
#include <qdir.h>
#include <qfileinfo.h>
-#include <qmutex.h>
#include <qset.h>
#include <qtimer.h>
+
+#include "qfilesystemwatcher_polling_p.h"
#if defined(Q_OS_WIN)
# include "qfilesystemwatcher_win_p.h"
#elif defined(Q_OS_LINUX)
# include "qfilesystemwatcher_inotify_p.h"
-# include "qfilesystemwatcher_dnotify_p.h"
#elif defined(Q_OS_FREEBSD) || defined(Q_OS_MAC)
-# if (defined Q_OS_MAC) && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5)
-# include "qfilesystemwatcher_fsevents_p.h"
-# endif //MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5)
# include "qfilesystemwatcher_kqueue_p.h"
-#elif defined(Q_OS_SYMBIAN)
-# include "qfilesystemwatcher_symbian_p.h"
#endif
QT_BEGIN_NAMESPACE
-enum { PollingInterval = 1000 };
-
-class QPollingFileSystemWatcherEngine : public QFileSystemWatcherEngine
-{
- Q_OBJECT
-
- class FileInfo
- {
- uint ownerId;
- uint groupId;
- QFile::Permissions permissions;
- QDateTime lastModified;
- QStringList entries;
-
- public:
- FileInfo(const QFileInfo &fileInfo)
- : ownerId(fileInfo.ownerId()),
- groupId(fileInfo.groupId()),
- permissions(fileInfo.permissions()),
- lastModified(fileInfo.lastModified())
- {
- if (fileInfo.isDir()) {
- entries = fileInfo.absoluteDir().entryList(QDir::AllEntries);
- }
- }
- FileInfo &operator=(const QFileInfo &fileInfo)
- {
- *this = FileInfo(fileInfo);
- return *this;
- }
-
- bool operator!=(const QFileInfo &fileInfo) const
- {
- if (fileInfo.isDir() && entries != fileInfo.absoluteDir().entryList(QDir::AllEntries))
- return true;
- return (ownerId != fileInfo.ownerId()
- || groupId != fileInfo.groupId()
- || permissions != fileInfo.permissions()
- || lastModified != fileInfo.lastModified());
- }
- };
-
- mutable QMutex mutex;
- QHash<QString, FileInfo> files, directories;
-
-public:
- QPollingFileSystemWatcherEngine();
-
- void run();
-
- QStringList addPaths(const QStringList &paths, QStringList *files, QStringList *directories);
- QStringList removePaths(const QStringList &paths, QStringList *files, QStringList *directories);
-
- void stop();
-
-private Q_SLOTS:
- void timeout();
-};
-
-QPollingFileSystemWatcherEngine::QPollingFileSystemWatcherEngine()
-{
-#ifndef QT_NO_THREAD
- moveToThread(this);
-#endif
-}
-
-void QPollingFileSystemWatcherEngine::run()
-{
- QTimer timer;
- connect(&timer, SIGNAL(timeout()), SLOT(timeout()));
- timer.start(PollingInterval);
- (void) exec();
-}
-
-QStringList QPollingFileSystemWatcherEngine::addPaths(const QStringList &paths,
- QStringList *files,
- QStringList *directories)
-{
- QMutexLocker locker(&mutex);
- QStringList p = paths;
- QMutableListIterator<QString> it(p);
- while (it.hasNext()) {
- QString path = it.next();
- QFileInfo fi(path);
- if (!fi.exists())
- continue;
- if (fi.isDir()) {
- if (!directories->contains(path))
- directories->append(path);
- if (!path.endsWith(QLatin1Char('/')))
- fi = QFileInfo(path + QLatin1Char('/'));
- this->directories.insert(path, fi);
- } else {
- if (!files->contains(path))
- files->append(path);
- this->files.insert(path, fi);
- }
- it.remove();
- }
- start();
- return p;
-}
-
-QStringList QPollingFileSystemWatcherEngine::removePaths(const QStringList &paths,
- QStringList *files,
- QStringList *directories)
-{
- QMutexLocker locker(&mutex);
- QStringList p = paths;
- QMutableListIterator<QString> it(p);
- while (it.hasNext()) {
- QString path = it.next();
- if (this->directories.remove(path)) {
- directories->removeAll(path);
- it.remove();
- } else if (this->files.remove(path)) {
- files->removeAll(path);
- it.remove();
- }
- }
- if (this->files.isEmpty() && this->directories.isEmpty()) {
- locker.unlock();
- stop();
- wait();
- }
- return p;
-}
-
-void QPollingFileSystemWatcherEngine::stop()
-{
- quit();
-}
-
-void QPollingFileSystemWatcherEngine::timeout()
-{
- QMutexLocker locker(&mutex);
- QMutableHashIterator<QString, FileInfo> fit(files);
- while (fit.hasNext()) {
- QHash<QString, FileInfo>::iterator x = fit.next();
- QString path = x.key();
- QFileInfo fi(path);
- if (!fi.exists()) {
- fit.remove();
- emit fileChanged(path, true);
- } else if (x.value() != fi) {
- x.value() = fi;
- emit fileChanged(path, false);
- }
- }
- QMutableHashIterator<QString, FileInfo> dit(directories);
- while (dit.hasNext()) {
- QHash<QString, FileInfo>::iterator x = dit.next();
- QString path = x.key();
- QFileInfo fi(path);
- if (!path.endsWith(QLatin1Char('/')))
- fi = QFileInfo(path + QLatin1Char('/'));
- if (!fi.exists()) {
- dit.remove();
- emit directoryChanged(path, true);
- } else if (x.value() != fi) {
- fi.refresh();
- if (!fi.exists()) {
- dit.remove();
- emit directoryChanged(path, true);
- } else {
- x.value() = fi;
- emit directoryChanged(path, false);
- }
- }
-
- }
-}
-
-
-
-
-QFileSystemWatcherEngine *QFileSystemWatcherPrivate::createNativeEngine()
+QFileSystemWatcherEngine *QFileSystemWatcherPrivate::createNativeEngine(QObject *parent)
{
#if defined(Q_OS_WIN)
- return new QWindowsFileSystemWatcherEngine;
+ return new QWindowsFileSystemWatcherEngine(parent);
#elif defined(Q_OS_LINUX)
- QFileSystemWatcherEngine *eng = QInotifyFileSystemWatcherEngine::create();
- if(!eng)
- eng = QDnotifyFileSystemWatcherEngine::create();
- return eng;
+ // there is a chance that inotify may fail on Linux pre-2.6.13 (August
+ // 2005), so we can't just new inotify directly.
+ return QInotifyFileSystemWatcherEngine::create(parent);
#elif defined(Q_OS_FREEBSD) || defined(Q_OS_MAC)
-# if 0 && defined(Q_OS_MAC) && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5)
- if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5)
- return QFSEventsFileSystemWatcherEngine::create();
- else
-# endif
- return QKqueueFileSystemWatcherEngine::create();
-#elif defined(Q_OS_SYMBIAN)
- return new QSymbianFileSystemWatcherEngine;
+ return QKqueueFileSystemWatcherEngine::create(parent);
#else
return 0;
#endif
}
QFileSystemWatcherPrivate::QFileSystemWatcherPrivate()
- : native(0), poller(0), forced(0)
+ : native(0), poller(0)
{
}
void QFileSystemWatcherPrivate::init()
{
Q_Q(QFileSystemWatcher);
- native = createNativeEngine();
+ native = createNativeEngine(q);
if (native) {
QObject::connect(native,
SIGNAL(fileChanged(QString,bool)),
@@ -288,42 +99,13 @@ void QFileSystemWatcherPrivate::init()
}
}
-void QFileSystemWatcherPrivate::initForcedEngine(const QString &forceName)
-{
- if(forced)
- return;
-
- Q_Q(QFileSystemWatcher);
-
-#if defined(Q_OS_LINUX)
- if(forceName == QLatin1String("inotify")) {
- forced = QInotifyFileSystemWatcherEngine::create();
- } else if(forceName == QLatin1String("dnotify")) {
- forced = QDnotifyFileSystemWatcherEngine::create();
- }
-#else
- Q_UNUSED(forceName);
-#endif
-
- if(forced) {
- QObject::connect(forced,
- SIGNAL(fileChanged(QString,bool)),
- q,
- SLOT(_q_fileChanged(QString,bool)));
- QObject::connect(forced,
- SIGNAL(directoryChanged(QString,bool)),
- q,
- SLOT(_q_directoryChanged(QString,bool)));
- }
-}
-
void QFileSystemWatcherPrivate::initPollerEngine()
{
if(poller)
return;
Q_Q(QFileSystemWatcher);
- poller = new QPollingFileSystemWatcherEngine; // that was a mouthful
+ poller = new QPollingFileSystemWatcherEngine(q); // that was a mouthful
QObject::connect(poller,
SIGNAL(fileChanged(QString,bool)),
q,
@@ -434,27 +216,7 @@ QFileSystemWatcher::QFileSystemWatcher(const QStringList &paths, QObject *parent
Destroys the file system watcher.
*/
QFileSystemWatcher::~QFileSystemWatcher()
-{
- Q_D(QFileSystemWatcher);
- if (d->native) {
- d->native->stop();
- d->native->wait();
- delete d->native;
- d->native = 0;
- }
- if (d->poller) {
- d->poller->stop();
- d->poller->wait();
- delete d->poller;
- d->poller = 0;
- }
- if (d->forced) {
- d->forced->stop();
- d->forced->wait();
- delete d->forced;
- d->forced = 0;
- }
-}
+{ }
/*!
Adds \a path to the file system watcher if \a path exists. The
@@ -466,20 +228,28 @@ QFileSystemWatcher::~QFileSystemWatcher()
otherwise the fileChanged() signal is emitted when \a path is
modified, renamed or removed.
- \note There is a system dependent limit to the number of files and
- directories that can be monitored simultaneously. If this limit
- has been reached, \a path will not be added to the file system
- watcher, and a warning message will be printed to \e{stderr}.
+ If the watch was successful, true is returned.
+
+ Reasons for a watch failure are generally system-dependent, but
+ may include the resource not existing, access failures, or the
+ total watch count limit, if the platform has one.
+
+ \note There may be a system dependent limit to the number of
+ files and directories that can be monitored simultaneously.
+ If this limit is been reached, \a path will not be monitored,
+ and false is returned.
\sa addPaths(), removePath()
*/
-void QFileSystemWatcher::addPath(const QString &path)
+bool QFileSystemWatcher::addPath(const QString &path)
{
if (path.isEmpty()) {
qWarning("QFileSystemWatcher::addPath: path is empty");
- return;
+ return true;
}
- addPaths(QStringList(path));
+
+ QStringList paths = addPaths(QStringList(path));
+ return paths.isEmpty();
}
/*!
@@ -492,23 +262,37 @@ void QFileSystemWatcher::addPath(const QString &path)
otherwise the fileChanged() signal is emitted when the path is
modified, renamed, or removed.
- \note There is a system dependent limit to the number of files and
- directories that can be monitored simultaneously. If this limit
- has been reached, the excess \a paths will not be added to the
- file system watcher, and a warning message will be printed to
- \e{stderr} for each path that could not be added.
+ The return value is a list of paths that could not be watched.
+
+ Reasons for a watch failure are generally system-dependent, but
+ may include the resource not existing, access failures, or the
+ total watch count limit, if the platform has one.
+
+ \note There may be a system dependent limit to the number of
+ files and directories that can be monitored simultaneously.
+ If this limit has been reached, the excess \a paths will not
+ be monitored, and they will be added to the returned QStringList.
\sa addPath(), removePaths()
*/
-void QFileSystemWatcher::addPaths(const QStringList &paths)
+QStringList QFileSystemWatcher::addPaths(const QStringList &paths)
{
Q_D(QFileSystemWatcher);
- if (paths.isEmpty()) {
+
+ QStringList p = paths;
+ QMutableListIterator<QString> it(p);
+
+ while (it.hasNext()) {
+ const QString &path = it.next();
+ if (path.isEmpty())
+ it.remove();
+ }
+
+ if (p.isEmpty()) {
qWarning("QFileSystemWatcher::addPaths: list is empty");
- return;
+ return QStringList();
}
- QStringList p = paths;
QFileSystemWatcherEngine *engine = 0;
if(!objectName().startsWith(QLatin1String("_qt_autotest_force_engine_"))) {
@@ -530,54 +314,71 @@ void QFileSystemWatcher::addPaths(const QStringList &paths)
} else if(forceName == QLatin1String("native")) {
qDebug() << "QFileSystemWatcher: skipping polling engine, using only native engine";
engine = d->native;
- } else {
- qDebug() << "QFileSystemWatcher: skipping polling and native engine, using only explicit" << forceName << "engine";
- d_func()->initForcedEngine(forceName);
- engine = d->forced;
}
}
if(engine)
p = engine->addPaths(p, &d->files, &d->directories);
- if (!p.isEmpty())
- qWarning("QFileSystemWatcher: failed to add paths: %s",
- qPrintable(p.join(QLatin1String(", "))));
+ return p;
}
/*!
Removes the specified \a path from the file system watcher.
+ If the watch is successfully removed, true is returned.
+
+ Reasons for watch removal failing are generally system-dependent,
+ but may be due to the path having already been deleted, for example.
+
\sa removePaths(), addPath()
*/
-void QFileSystemWatcher::removePath(const QString &path)
+bool QFileSystemWatcher::removePath(const QString &path)
{
if (path.isEmpty()) {
qWarning("QFileSystemWatcher::removePath: path is empty");
- return;
+ return true;
}
- removePaths(QStringList(path));
+
+ QStringList paths = removePaths(QStringList(path));
+ return paths.isEmpty();
}
/*!
Removes the specified \a paths from the file system watcher.
+ The return value is a list of paths which were not able to be
+ unwatched successfully.
+
+ Reasons for watch removal failing are generally system-dependent,
+ but may be due to the path having already been deleted, for example.
+
\sa removePath(), addPaths()
*/
-void QFileSystemWatcher::removePaths(const QStringList &paths)
+QStringList QFileSystemWatcher::removePaths(const QStringList &paths)
{
- if (paths.isEmpty()) {
- qWarning("QFileSystemWatcher::removePaths: list is empty");
- return;
- }
Q_D(QFileSystemWatcher);
+
QStringList p = paths;
+ QMutableListIterator<QString> it(p);
+
+ while (it.hasNext()) {
+ const QString &path = it.next();
+ if (path.isEmpty())
+ it.remove();
+ }
+
+ if (p.isEmpty()) {
+ qWarning("QFileSystemWatcher::removePaths: list is empty");
+ return QStringList();
+ }
+
if (d->native)
p = d->native->removePaths(p, &d->files, &d->directories);
if (d->poller)
p = d->poller->removePaths(p, &d->files, &d->directories);
- if (d->forced)
- p = d->forced->removePaths(p, &d->files, &d->directories);
+
+ return p;
}
/*!
@@ -634,7 +435,5 @@ QT_END_NAMESPACE
#include "moc_qfilesystemwatcher.cpp"
-#include "qfilesystemwatcher.moc"
-
#endif // QT_NO_FILESYSTEMWATCHER
diff --git a/src/corelib/io/qfilesystemwatcher.h b/src/corelib/io/qfilesystemwatcher.h
index 763c8de0d6..7b7dbe98c5 100644
--- a/src/corelib/io/qfilesystemwatcher.h
+++ b/src/corelib/io/qfilesystemwatcher.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
@@ -64,10 +64,10 @@ public:
QFileSystemWatcher(const QStringList &paths, QObject *parent = 0);
~QFileSystemWatcher();
- void addPath(const QString &file);
- void addPaths(const QStringList &files);
- void removePath(const QString &file);
- void removePaths(const QStringList &files);
+ bool addPath(const QString &file);
+ QStringList addPaths(const QStringList &files);
+ bool removePath(const QString &file);
+ QStringList removePaths(const QStringList &files);
QStringList files() const;
QStringList directories() const;
diff --git a/src/corelib/io/qfilesystemwatcher_dnotify.cpp b/src/corelib/io/qfilesystemwatcher_dnotify.cpp
deleted file mode 100644
index 46c3b46467..0000000000
--- a/src/corelib/io/qfilesystemwatcher_dnotify.cpp
+++ /dev/null
@@ -1,461 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 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$
-** GNU Lesser General Public License Usage
-** 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.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU General
-** Public License version 3.0 as published by the Free Software Foundation
-** and appearing in the file LICENSE.GPL included in the packaging of this
-** file. Please review the following information to ensure the GNU General
-** Public License version 3.0 requirements will be met:
-** http://www.gnu.org/copyleft/gpl.html.
-**
-** Other Usage
-** Alternatively, this file may be used in accordance with the terms and
-** conditions contained in a signed written agreement between you and Nokia.
-**
-**
-**
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qplatformdefs.h"
-#include "qfilesystemwatcher.h"
-#include "qfilesystemwatcher_dnotify_p.h"
-
-#ifndef QT_NO_FILESYSTEMWATCHER
-
-#include <qsocketnotifier.h>
-#include <qcoreapplication.h>
-#include <qfileinfo.h>
-#include <qtimer.h>
-#include <qwaitcondition.h>
-#include <qmutex.h>
-#include <dirent.h>
-#include <qdir.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <signal.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <time.h>
-
-#include "private/qcore_unix_p.h"
-
-#ifdef QT_LINUXBASE
-
-/* LSB doesn't standardize these */
-#define F_NOTIFY 1026
-#define DN_ACCESS 0x00000001
-#define DN_MODIFY 0x00000002
-#define DN_CREATE 0x00000004
-#define DN_DELETE 0x00000008
-#define DN_RENAME 0x00000010
-#define DN_ATTRIB 0x00000020
-#define DN_MULTISHOT 0x80000000
-
-#endif
-
-QT_BEGIN_NAMESPACE
-
-static int qfswd_fileChanged_pipe[2];
-static void (*qfswd_old_sigio_handler)(int) = 0;
-static void (*qfswd_old_sigio_action)(int, siginfo_t *, void *) = 0;
-static void qfswd_sigio_monitor(int signum, siginfo_t *i, void *v)
-{
- qt_safe_write(qfswd_fileChanged_pipe[1], reinterpret_cast<char*>(&i->si_fd), sizeof(int));
-
- if (qfswd_old_sigio_handler && qfswd_old_sigio_handler != SIG_IGN)
- qfswd_old_sigio_handler(signum);
- if (qfswd_old_sigio_action)
- qfswd_old_sigio_action(signum, i, v);
-}
-
-class QDnotifySignalThread : public QThread
-{
-Q_OBJECT
-public:
- QDnotifySignalThread();
- virtual ~QDnotifySignalThread();
-
- void startNotify();
-
- virtual void run();
-
-signals:
- void fdChanged(int);
-
-protected:
- virtual bool event(QEvent *);
-
-private slots:
- void readFromDnotify();
-
-private:
- QMutex mutex;
- QWaitCondition wait;
- bool isExecing;
-};
-
-Q_GLOBAL_STATIC(QDnotifySignalThread, dnotifySignal)
-
-QDnotifySignalThread::QDnotifySignalThread()
-: isExecing(false)
-{
- moveToThread(this);
-
- qt_safe_pipe(qfswd_fileChanged_pipe, O_NONBLOCK);
-
- struct sigaction oldAction;
- struct sigaction action;
- memset(&action, 0, sizeof(action));
- action.sa_sigaction = qfswd_sigio_monitor;
- action.sa_flags = SA_SIGINFO;
- ::sigaction(SIGIO, &action, &oldAction);
- if (!(oldAction.sa_flags & SA_SIGINFO))
- qfswd_old_sigio_handler = oldAction.sa_handler;
- else
- qfswd_old_sigio_action = oldAction.sa_sigaction;
-}
-
-QDnotifySignalThread::~QDnotifySignalThread()
-{
- if(isRunning()) {
- quit();
- QThread::wait();
- }
-}
-
-bool QDnotifySignalThread::event(QEvent *e)
-{
- if(e->type() == QEvent::User) {
- QMutexLocker locker(&mutex);
- isExecing = true;
- wait.wakeAll();
- return true;
- } else {
- return QThread::event(e);
- }
-}
-
-void QDnotifySignalThread::startNotify()
-{
- // Note: All this fancy waiting for the thread to enter its event
- // loop is to avoid nasty messages at app shutdown when the
- // QDnotifySignalThread singleton is deleted
- start();
- mutex.lock();
- while(!isExecing)
- wait.wait(&mutex);
- mutex.unlock();
-}
-
-void QDnotifySignalThread::run()
-{
- QSocketNotifier sn(qfswd_fileChanged_pipe[0], QSocketNotifier::Read, this);
- connect(&sn, SIGNAL(activated(int)), SLOT(readFromDnotify()));
-
- QCoreApplication::instance()->postEvent(this, new QEvent(QEvent::User));
- (void) exec();
-}
-
-void QDnotifySignalThread::readFromDnotify()
-{
- int fd;
- int readrv = qt_safe_read(qfswd_fileChanged_pipe[0], reinterpret_cast<char*>(&fd), sizeof(int));
- // Only expect EAGAIN or EINTR. Other errors are assumed to be impossible.
- if(readrv != -1) {
- Q_ASSERT(readrv == sizeof(int));
- Q_UNUSED(readrv);
-
- if(0 == fd)
- quit();
- else
- emit fdChanged(fd);
- }
-}
-
-QDnotifyFileSystemWatcherEngine::QDnotifyFileSystemWatcherEngine()
-{
- QObject::connect(dnotifySignal(), SIGNAL(fdChanged(int)),
- this, SLOT(refresh(int)), Qt::DirectConnection);
-}
-
-QDnotifyFileSystemWatcherEngine::~QDnotifyFileSystemWatcherEngine()
-{
- QMutexLocker locker(&mutex);
-
- for(QHash<int, Directory>::ConstIterator iter = fdToDirectory.constBegin();
- iter != fdToDirectory.constEnd();
- ++iter) {
- qt_safe_close(iter->fd);
- if(iter->parentFd)
- qt_safe_close(iter->parentFd);
- }
-}
-
-QDnotifyFileSystemWatcherEngine *QDnotifyFileSystemWatcherEngine::create()
-{
- return new QDnotifyFileSystemWatcherEngine();
-}
-
-void QDnotifyFileSystemWatcherEngine::run()
-{
- qFatal("QDnotifyFileSystemWatcherEngine thread should not be run");
-}
-
-QStringList QDnotifyFileSystemWatcherEngine::addPaths(const QStringList &paths, QStringList *files, QStringList *directories)
-{
- QMutexLocker locker(&mutex);
-
- QStringList p = paths;
- QMutableListIterator<QString> it(p);
-
- while (it.hasNext()) {
- QString path = it.next();
-
- QFileInfo fi(path);
-
- if(!fi.exists()) {
- continue;
- }
-
- bool isDir = fi.isDir();
-
- if (isDir && directories->contains(path)) {
- continue; // Skip monitored directories
- } else if(!isDir && files->contains(path)) {
- continue; // Skip monitored files
- }
-
- if(!isDir)
- path = fi.canonicalPath();
-
- // Locate the directory entry (creating if needed)
- int fd = pathToFD[path];
-
- if(fd == 0) {
-
- QT_DIR *d = QT_OPENDIR(path.toUtf8().constData());
- if(!d) continue; // Could not open directory
- QT_DIR *parent = 0;
-
- QDir parentDir(path);
- if(!parentDir.isRoot()) {
- parentDir.cdUp();
- parent = QT_OPENDIR(parentDir.path().toUtf8().constData());
- if(!parent) {
- QT_CLOSEDIR(d);
- continue;
- }
- }
-
- fd = qt_safe_dup(::dirfd(d));
- int parentFd = parent ? qt_safe_dup(::dirfd(parent)) : 0;
-
- QT_CLOSEDIR(d);
- if(parent) QT_CLOSEDIR(parent);
-
- Q_ASSERT(fd);
- if(::fcntl(fd, F_SETSIG, SIGIO) ||
- ::fcntl(fd, F_NOTIFY, DN_MODIFY | DN_CREATE | DN_DELETE |
- DN_RENAME | DN_ATTRIB | DN_MULTISHOT) ||
- (parent && ::fcntl(parentFd, F_SETSIG, SIGIO)) ||
- (parent && ::fcntl(parentFd, F_NOTIFY, DN_DELETE | DN_RENAME |
- DN_MULTISHOT))) {
- continue; // Could not set appropriate flags
- }
-
- Directory dir;
- dir.path = path;
- dir.fd = fd;
- dir.parentFd = parentFd;
-
- fdToDirectory.insert(fd, dir);
- pathToFD.insert(path, fd);
- if(parentFd)
- parentToFD.insert(parentFd, fd);
- }
-
- Directory &directory = fdToDirectory[fd];
-
- if(isDir) {
- directory.isMonitored = true;
- } else {
- Directory::File file;
- file.path = fi.filePath();
- file.lastWrite = fi.lastModified();
- directory.files.append(file);
- pathToFD.insert(fi.filePath(), fd);
- }
-
- it.remove();
-
- if(isDir) {
- directories->append(path);
- } else {
- files->append(fi.filePath());
- }
- }
-
- dnotifySignal()->startNotify();
-
- return p;
-}
-
-QStringList QDnotifyFileSystemWatcherEngine::removePaths(const QStringList &paths, QStringList *files, QStringList *directories)
-{
- QMutexLocker locker(&mutex);
-
- QStringList p = paths;
- QMutableListIterator<QString> it(p);
- while (it.hasNext()) {
-
- QString path = it.next();
- int fd = pathToFD.take(path);
-
- if(!fd)
- continue;
-
- Directory &directory = fdToDirectory[fd];
- bool isDir = false;
- if(directory.path == path) {
- isDir = true;
- directory.isMonitored = false;
- } else {
- for(int ii = 0; ii < directory.files.count(); ++ii) {
- if(directory.files.at(ii).path == path) {
- directory.files.removeAt(ii);
- break;
- }
- }
- }
-
- if(!directory.isMonitored && directory.files.isEmpty()) {
- // No longer needed
- qt_safe_close(directory.fd);
- pathToFD.remove(directory.path);
- fdToDirectory.remove(fd);
- }
-
- if(isDir) {
- directories->removeAll(path);
- } else {
- files->removeAll(path);
- }
-
- it.remove();
- }
-
- return p;
-}
-
-void QDnotifyFileSystemWatcherEngine::refresh(int fd)
-{
- QMutexLocker locker(&mutex);
-
- bool wasParent = false;
- QHash<int, Directory>::Iterator iter = fdToDirectory.find(fd);
- if(iter == fdToDirectory.end()) {
- QHash<int, int>::Iterator pIter = parentToFD.find(fd);
- if(pIter == parentToFD.end())
- return;
-
- iter = fdToDirectory.find(*pIter);
- if (iter == fdToDirectory.end())
- return;
- wasParent = true;
- }
-
- Directory &directory = *iter;
-
- if(!wasParent) {
- for(int ii = 0; ii < directory.files.count(); ++ii) {
- Directory::File &file = directory.files[ii];
- if(file.updateInfo()) {
- // Emit signal
- QString filePath = file.path;
- bool removed = !QFileInfo(filePath).exists();
-
- if(removed) {
- directory.files.removeAt(ii);
- --ii;
- }
-
- emit fileChanged(filePath, removed);
- }
- }
- }
-
- if(directory.isMonitored) {
- // Emit signal
- bool removed = !QFileInfo(directory.path).exists();
- QString path = directory.path;
-
- if(removed)
- directory.isMonitored = false;
-
- emit directoryChanged(path, removed);
- }
-
- if(!directory.isMonitored && directory.files.isEmpty()) {
- qt_safe_close(directory.fd);
- if(directory.parentFd) {
- qt_safe_close(directory.parentFd);
- parentToFD.remove(directory.parentFd);
- }
- fdToDirectory.erase(iter);
- }
-}
-
-void QDnotifyFileSystemWatcherEngine::stop()
-{
-}
-
-bool QDnotifyFileSystemWatcherEngine::Directory::File::updateInfo()
-{
- QFileInfo fi(path);
- QDateTime nLastWrite = fi.lastModified();
- uint nOwnerId = fi.ownerId();
- uint nGroupId = fi.groupId();
- QFile::Permissions nPermissions = fi.permissions();
-
- if(nLastWrite != lastWrite ||
- nOwnerId != ownerId ||
- nGroupId != groupId ||
- nPermissions != permissions) {
- ownerId = nOwnerId;
- groupId = nGroupId;
- permissions = nPermissions;
- lastWrite = nLastWrite;
- return true;
- } else {
- return false;
- }
-}
-
-QT_END_NAMESPACE
-
-#include "qfilesystemwatcher_dnotify.moc"
-
-#endif // QT_NO_FILESYSTEMWATCHER
diff --git a/src/corelib/io/qfilesystemwatcher_fsevents.cpp b/src/corelib/io/qfilesystemwatcher_fsevents.cpp
deleted file mode 100644
index 95da897974..0000000000
--- a/src/corelib/io/qfilesystemwatcher_fsevents.cpp
+++ /dev/null
@@ -1,492 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 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$
-** GNU Lesser General Public License Usage
-** 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.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU General
-** Public License version 3.0 as published by the Free Software Foundation
-** and appearing in the file LICENSE.GPL included in the packaging of this
-** file. Please review the following information to ensure the GNU General
-** Public License version 3.0 requirements will be met:
-** http://www.gnu.org/copyleft/gpl.html.
-**
-** Other Usage
-** Alternatively, this file may be used in accordance with the terms and
-** conditions contained in a signed written agreement between you and Nokia.
-**
-**
-**
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#define _DARWIN_USE_64_BIT_INODE
-#include <qplatformdefs.h>
-
-#include "qfilesystemwatcher.h"
-#include "qfilesystemwatcher_fsevents_p.h"
-
-#ifndef QT_NO_FILESYSTEMWATCHER
-
-#include <qdebug.h>
-#include <qfile.h>
-#include <qdatetime.h>
-#include <qfileinfo.h>
-#include <qvarlengtharray.h>
-
-#include <mach/mach.h>
-#include <sys/types.h>
-#include <CoreFoundation/CFRunLoop.h>
-#include <CoreFoundation/CFUUID.h>
-#include <CoreServices/CoreServices.h>
-#include <AvailabilityMacros.h>
-#include <private/qcore_mac_p.h>
-
-QT_BEGIN_NAMESPACE
-
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
-// Static operator overloading so for the sake of some convieniece.
-// They only live in this compilation unit to avoid polluting Qt in general.
-static bool operator==(const struct ::timespec &left, const struct ::timespec &right)
-{
- return left.tv_sec == right.tv_sec
- && left.tv_nsec == right.tv_nsec;
-}
-
-static bool operator==(const struct ::stat &left, const struct ::stat &right)
-{
- return left.st_dev == right.st_dev
- && left.st_mode == right.st_mode
- && left.st_size == right.st_size
- && left.st_ino == right.st_ino
- && left.st_uid == right.st_uid
- && left.st_gid == right.st_gid
- && left.st_mtimespec == right.st_mtimespec
- && left.st_ctimespec == right.st_ctimespec
- && left.st_flags == right.st_flags;
-}
-
-static bool operator!=(const struct ::stat &left, const struct ::stat &right)
-{
- return !(operator==(left, right));
-}
-
-
-static void addPathToHash(PathHash &pathHash, const QString &key, const QFileInfo &fileInfo,
- const QString &path)
-{
- PathInfoList &list = pathHash[key];
- list.push_back(PathInfo(path,
- fileInfo.canonicalFilePath().normalized(QString::NormalizationForm_D).toUtf8()));
- pathHash.insert(key, list);
-}
-
-static void removePathFromHash(PathHash &pathHash, const QString &key, const QString &path)
-{
- PathInfoList &list = pathHash[key];
- // We make the assumption that the list contains unique paths
- PathInfoList::iterator End = list.end();
- PathInfoList::iterator it = list.begin();
- while (it != End) {
- if (it->originalPath == path) {
- list.erase(it);
- break;
- }
- ++it;
- }
- if (list.isEmpty())
- pathHash.remove(key);
-}
-
-static void stopFSStream(FSEventStreamRef stream)
-{
- if (stream) {
- FSEventStreamStop(stream);
- FSEventStreamInvalidate(stream);
- }
-}
-
-static QString createFSStreamPath(const QString &absolutePath)
-{
- // The path returned has a trailing slash, so ensure that here.
- QString string = absolutePath;
- string.reserve(string.size() + 1);
- string.append(QLatin1Char('/'));
- return string;
-}
-
-static void cleanupFSStream(FSEventStreamRef stream)
-{
- if (stream)
- FSEventStreamRelease(stream);
-}
-
-const FSEventStreamCreateFlags QtFSEventFlags = (kFSEventStreamCreateFlagUseCFTypes | kFSEventStreamCreateFlagNoDefer /* | kFSEventStreamCreateFlagWatchRoot*/);
-
-const CFTimeInterval Latency = 0.033; // This will do updates 30 times a second which is probably more than you need.
-#endif
-
-QFSEventsFileSystemWatcherEngine::QFSEventsFileSystemWatcherEngine()
- : fsStream(0), pathsToWatch(0), threadsRunLoop(0)
-{
-}
-
-QFSEventsFileSystemWatcherEngine::~QFSEventsFileSystemWatcherEngine()
-{
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
- // I assume that at this point, QFileSystemWatcher has already called stop
- // on me, so I don't need to invalidate or stop my stream, simply
- // release it.
- cleanupFSStream(fsStream);
- if (pathsToWatch)
- CFRelease(pathsToWatch);
-#endif
-}
-
-QFSEventsFileSystemWatcherEngine *QFSEventsFileSystemWatcherEngine::create()
-{
- return new QFSEventsFileSystemWatcherEngine();
-}
-
-QStringList QFSEventsFileSystemWatcherEngine::addPaths(const QStringList &paths,
- QStringList *files,
- QStringList *directories)
-{
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
- stop();
- wait();
- QMutexLocker locker(&mutex);
- QStringList failedToAdd;
- // if we have a running FSStreamEvent, we have to kill it, we'll re-add the stream soon.
- FSEventStreamEventId idToCheck;
- if (fsStream) {
- idToCheck = FSEventStreamGetLatestEventId(fsStream);
- cleanupFSStream(fsStream);
- } else {
- idToCheck = kFSEventStreamEventIdSinceNow;
- }
-
- // Brain-dead approach, but works. FSEvents actually can already read sub-trees, but since it's
- // work to figure out if we are doing a double register, we just register it twice as FSEvents
- // seems smart enough to only deliver one event. We also duplicate directory entries in here
- // (e.g., if you watch five files in the same directory, you get that directory included in the
- // array 5 times). This stupidity also makes remove work correctly though. I'll freely admit
- // that we could make this a bit smarter. If you do, check the auto-tests, they should catch at
- // least a couple of the issues.
- QCFType<CFMutableArrayRef> tmpArray = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
- for (int i = 0; i < paths.size(); ++i) {
- const QString &path = paths.at(i);
-
- QFileInfo fileInfo(path);
- if (!fileInfo.exists()) {
- failedToAdd.append(path);
- continue;
- }
-
- if (fileInfo.isDir()) {
- if (directories->contains(path)) {
- failedToAdd.append(path);
- continue;
- } else {
- directories->append(path);
- // Full file path for dirs.
- QCFString cfpath(createFSStreamPath(fileInfo.canonicalFilePath()));
- addPathToHash(dirPathInfoHash, cfpath, fileInfo, path);
- CFArrayAppendValue(tmpArray, cfpath);
- }
- } else {
- if (files->contains(path)) {
- failedToAdd.append(path);
- continue;
- } else {
- // Just the absolute path (minus it's filename) for files.
- QCFString cfpath(createFSStreamPath(fileInfo.canonicalPath()));
- files->append(path);
- addPathToHash(filePathInfoHash, cfpath, fileInfo, path);
- CFArrayAppendValue(tmpArray, cfpath);
- }
- }
- }
-
- if (!pathsToWatch && failedToAdd.size() == paths.size()) {
- return failedToAdd;
- }
-
- if (CFArrayGetCount(tmpArray) > 0) {
- if (pathsToWatch) {
- CFArrayAppendArray(tmpArray, pathsToWatch, CFRangeMake(0, CFArrayGetCount(pathsToWatch)));
- CFRelease(pathsToWatch);
- }
- pathsToWatch = CFArrayCreateCopy(kCFAllocatorDefault, tmpArray);
- }
-
- FSEventStreamContext context = { 0, this, 0, 0, 0 };
- fsStream = FSEventStreamCreate(kCFAllocatorDefault,
- QFSEventsFileSystemWatcherEngine::fseventsCallback,
- &context, pathsToWatch,
- idToCheck, Latency, QtFSEventFlags);
- warmUpFSEvents();
-
- return failedToAdd;
-#else
- Q_UNUSED(paths);
- Q_UNUSED(files);
- Q_UNUSED(directories);
- return QStringList();
-#endif
-}
-
-void QFSEventsFileSystemWatcherEngine::warmUpFSEvents()
-{
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
- // This function assumes that the mutex has already been grabbed before calling it.
- // It exits with the mutex still locked (Q_ASSERT(mutex.isLocked()) ;-).
- start();
- waitCondition.wait(&mutex);
-#endif
-}
-
-QStringList QFSEventsFileSystemWatcherEngine::removePaths(const QStringList &paths,
- QStringList *files,
- QStringList *directories)
-{
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
- stop();
- wait();
- QMutexLocker locker(&mutex);
- // short circuit for smarties that call remove before add and we have nothing.
- if (pathsToWatch == 0)
- return paths;
- QStringList failedToRemove;
- // if we have a running FSStreamEvent, we have to stop it, we'll re-add the stream soon.
- FSEventStreamEventId idToCheck;
- if (fsStream) {
- idToCheck = FSEventStreamGetLatestEventId(fsStream);
- cleanupFSStream(fsStream);
- fsStream = 0;
- } else {
- idToCheck = kFSEventStreamEventIdSinceNow;
- }
-
- CFIndex itemCount = CFArrayGetCount(pathsToWatch);
- QCFType<CFMutableArrayRef> tmpArray = CFArrayCreateMutableCopy(kCFAllocatorDefault, itemCount,
- pathsToWatch);
- CFRelease(pathsToWatch);
- pathsToWatch = 0;
- for (int i = 0; i < paths.size(); ++i) {
- // Get the itemCount at the beginning to avoid any overruns during the iteration.
- itemCount = CFArrayGetCount(tmpArray);
- const QString &path = paths.at(i);
- QFileInfo fi(path);
- QCFString cfpath(createFSStreamPath(fi.canonicalPath()));
-
- CFIndex index = CFArrayGetFirstIndexOfValue(tmpArray, CFRangeMake(0, itemCount), cfpath);
- if (index != -1) {
- CFArrayRemoveValueAtIndex(tmpArray, index);
- files->removeAll(path);
- removePathFromHash(filePathInfoHash, cfpath, path);
- } else {
- // Could be a directory we are watching instead.
- QCFString cfdirpath(createFSStreamPath(fi.canonicalFilePath()));
- index = CFArrayGetFirstIndexOfValue(tmpArray, CFRangeMake(0, itemCount), cfdirpath);
- if (index != -1) {
- CFArrayRemoveValueAtIndex(tmpArray, index);
- directories->removeAll(path);
- removePathFromHash(dirPathInfoHash, cfpath, path);
- } else {
- failedToRemove.append(path);
- }
- }
- }
- itemCount = CFArrayGetCount(tmpArray);
- if (itemCount != 0) {
- pathsToWatch = CFArrayCreateCopy(kCFAllocatorDefault, tmpArray);
-
- FSEventStreamContext context = { 0, this, 0, 0, 0 };
- fsStream = FSEventStreamCreate(kCFAllocatorDefault,
- QFSEventsFileSystemWatcherEngine::fseventsCallback,
- &context, pathsToWatch, idToCheck, Latency, QtFSEventFlags);
- warmUpFSEvents();
- }
- return failedToRemove;
-#else
- Q_UNUSED(paths);
- Q_UNUSED(files);
- Q_UNUSED(directories);
- return QStringList();
-#endif
-}
-
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
-void QFSEventsFileSystemWatcherEngine::updateList(PathInfoList &list, bool directory, bool emitSignals)
-{
- PathInfoList::iterator End = list.end();
- PathInfoList::iterator it = list.begin();
- while (it != End) {
- struct ::stat newInfo;
- if (::stat(it->absolutePath, &newInfo) == 0) {
- if (emitSignals) {
- if (newInfo != it->savedInfo) {
- it->savedInfo = newInfo;
- if (directory)
- emit directoryChanged(it->originalPath, false);
- else
- emit fileChanged(it->originalPath, false);
- }
- } else {
- it->savedInfo = newInfo;
- }
- } else {
- if (errno == ENOENT) {
- if (emitSignals) {
- if (directory)
- emit directoryChanged(it->originalPath, true);
- else
- emit fileChanged(it->originalPath, true);
- }
- it = list.erase(it);
- continue;
- } else {
- qWarning("%s:%d:QFSEventsFileSystemWatcherEngine: stat error on %s:%s",
- __FILE__, __LINE__, qPrintable(it->originalPath), strerror(errno));
-
- }
- }
- ++it;
- }
-}
-
-void QFSEventsFileSystemWatcherEngine::updateHash(PathHash &pathHash)
-{
- PathHash::iterator HashEnd = pathHash.end();
- PathHash::iterator it = pathHash.begin();
- const bool IsDirectory = (&pathHash == &dirPathInfoHash);
- while (it != HashEnd) {
- updateList(it.value(), IsDirectory, false);
- if (it.value().isEmpty())
- it = pathHash.erase(it);
- else
- ++it;
- }
-}
-#endif
-
-void QFSEventsFileSystemWatcherEngine::fseventsCallback(ConstFSEventStreamRef ,
- void *clientCallBackInfo, size_t numEvents,
- void *eventPaths,
- const FSEventStreamEventFlags eventFlags[],
- const FSEventStreamEventId [])
-{
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
- QFSEventsFileSystemWatcherEngine *watcher = static_cast<QFSEventsFileSystemWatcherEngine *>(clientCallBackInfo);
- QMutexLocker locker(&watcher->mutex);
- CFArrayRef paths = static_cast<CFArrayRef>(eventPaths);
- for (size_t i = 0; i < numEvents; ++i) {
- const QString path = QCFString::toQString(
- static_cast<CFStringRef>(CFArrayGetValueAtIndex(paths, i)));
- const FSEventStreamEventFlags pathFlags = eventFlags[i];
- // There are several flags that may be passed, but we really don't care about them ATM.
- // Here they are and why we don't care.
- // kFSEventStreamEventFlagHistoryDone--(very unlikely to be gotten, but even then, not much changes).
- // kFSEventStreamEventFlagMustScanSubDirs--Likely means the data is very much out of date, we
- // aren't coalescing our directories, so again not so much of an issue
- // kFSEventStreamEventFlagRootChanged | kFSEventStreamEventFlagMount | kFSEventStreamEventFlagUnmount--
- // These three flags indicate something has changed, but the stat will likely show this, so
- // there's not really much to worry about.
- // (btw, FSEvents is not the correct way of checking for mounts/unmounts,
- // there are real CarbonCore events for that.)
- Q_UNUSED(pathFlags);
- if (watcher->filePathInfoHash.contains(path))
- watcher->updateList(watcher->filePathInfoHash[path], false, true);
-
- if (watcher->dirPathInfoHash.contains(path))
- watcher->updateList(watcher->dirPathInfoHash[path], true, true);
- }
-#else
- Q_UNUSED(clientCallBackInfo);
- Q_UNUSED(numEvents);
- Q_UNUSED(eventPaths);
- Q_UNUSED(eventFlags);
-#endif
-}
-
-void QFSEventsFileSystemWatcherEngine::stop()
-{
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
- QMutexLocker locker(&mutex);
- stopFSStream(fsStream);
- if (threadsRunLoop) {
- CFRunLoopStop(threadsRunLoop);
- waitForStop.wait(&mutex);
- }
-#endif
-}
-
-void QFSEventsFileSystemWatcherEngine::updateFiles()
-{
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
- QMutexLocker locker(&mutex);
- updateHash(filePathInfoHash);
- updateHash(dirPathInfoHash);
- if (filePathInfoHash.isEmpty() && dirPathInfoHash.isEmpty()) {
- // Everything disappeared before we got to start, don't bother.
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
- // Code duplicated from stop(), with the exception that we
- // don't wait on waitForStop here. Doing this will lead to
- // a deadlock since this function is called from the worker
- // thread. (waitForStop.wakeAll() is only called from the
- // end of run()).
- stopFSStream(fsStream);
- if (threadsRunLoop)
- CFRunLoopStop(threadsRunLoop);
-#endif
- cleanupFSStream(fsStream);
- }
- waitCondition.wakeAll();
-#endif
-}
-
-void QFSEventsFileSystemWatcherEngine::run()
-{
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
- threadsRunLoop = CFRunLoopGetCurrent();
- FSEventStreamScheduleWithRunLoop(fsStream, threadsRunLoop, kCFRunLoopDefaultMode);
- bool startedOK = FSEventStreamStart(fsStream);
- // It's recommended by Apple that you only update the files after you've started
- // the stream, because otherwise you might miss an update in between starting it.
- updateFiles();
-#ifdef QT_NO_DEBUG
- Q_UNUSED(startedOK);
-#else
- Q_ASSERT(startedOK);
-#endif
- // If for some reason we called stop up above (and invalidated our stream), this call will return
- // immediately.
- CFRunLoopRun();
- threadsRunLoop = 0;
- QMutexLocker locker(&mutex);
- waitForStop.wakeAll();
-#endif
-}
-
-QT_END_NAMESPACE
-#endif //QT_NO_FILESYSTEMWATCHER
diff --git a/src/corelib/io/qfilesystemwatcher_fsevents_p.h b/src/corelib/io/qfilesystemwatcher_fsevents_p.h
deleted file mode 100644
index 3830002c0a..0000000000
--- a/src/corelib/io/qfilesystemwatcher_fsevents_p.h
+++ /dev/null
@@ -1,132 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 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$
-** GNU Lesser General Public License Usage
-** 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.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU General
-** Public License version 3.0 as published by the Free Software Foundation
-** and appearing in the file LICENSE.GPL included in the packaging of this
-** file. Please review the following information to ensure the GNU General
-** Public License version 3.0 requirements will be met:
-** http://www.gnu.org/copyleft/gpl.html.
-**
-** Other Usage
-** Alternatively, this file may be used in accordance with the terms and
-** conditions contained in a signed written agreement between you and Nokia.
-**
-**
-**
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-
-#ifndef FILEWATCHER_FSEVENTS_P_H
-#define FILEWATCHER_FSEVENTS_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists for the convenience
-// of the QLibrary class. This header file may change from
-// version to version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include "qfilesystemwatcher_p.h"
-
-#ifndef QT_NO_FILESYSTEMWATCHER
-
-#include <QtCore/qmutex.h>
-#include <QtCore/qwaitcondition.h>
-#include <QtCore/qthread.h>
-#include <QtCore/qhash.h>
-#include <QtCore/qlinkedlist.h>
-#include <private/qcore_mac_p.h>
-#include <sys/stat.h>
-
-typedef struct __FSEventStream *FSEventStreamRef;
-typedef const struct __FSEventStream *ConstFSEventStreamRef;
-typedef const struct __CFArray *CFArrayRef;
-typedef UInt32 FSEventStreamEventFlags;
-typedef uint64_t FSEventStreamEventId;
-
-QT_BEGIN_NAMESPACE
-
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
-// Yes, I use a stat element here. QFileInfo requires too much knowledge about implementation
-// details to be used as a long-standing record. Since I'm going to have to store this information, I can
-// do the stat myself too.
-struct PathInfo {
- PathInfo(const QString &path, const QByteArray &absPath)
- : originalPath(path), absolutePath(absPath) {}
- QString originalPath; // The path we need to emit
- QByteArray absolutePath; // The path we need to stat.
- struct ::stat savedInfo; // All the info for the path so we can compare it.
-};
-typedef QLinkedList<PathInfo> PathInfoList;
-typedef QHash<QString, PathInfoList> PathHash;
-#endif
-
-class QFSEventsFileSystemWatcherEngine : public QFileSystemWatcherEngine
-{
- Q_OBJECT
-public:
- ~QFSEventsFileSystemWatcherEngine();
-
- static QFSEventsFileSystemWatcherEngine *create();
-
- QStringList addPaths(const QStringList &paths, QStringList *files, QStringList *directories);
- QStringList removePaths(const QStringList &paths, QStringList *files, QStringList *directories);
-
- void stop();
-
-private:
- QFSEventsFileSystemWatcherEngine();
- void warmUpFSEvents();
- void updateFiles();
-
- static void fseventsCallback(ConstFSEventStreamRef streamRef, void *clientCallBackInfo, size_t numEvents,
- void *eventPaths, const FSEventStreamEventFlags eventFlags[],
- const FSEventStreamEventId eventIds[]);
- void run();
- FSEventStreamRef fsStream;
- CFArrayRef pathsToWatch;
- CFRunLoopRef threadsRunLoop;
- QMutex mutex;
- QWaitCondition waitCondition;
- QWaitCondition waitForStop;
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
- PathHash filePathInfoHash;
- PathHash dirPathInfoHash;
- void updateHash(PathHash &pathHash);
- void updateList(PathInfoList &list, bool directory, bool emitSignals);
-#endif
-};
-
-#endif //QT_NO_FILESYSTEMWATCHER
-
-#endif
-
-QT_END_NAMESPACE
diff --git a/src/corelib/io/qfilesystemwatcher_inotify.cpp b/src/corelib/io/qfilesystemwatcher_inotify.cpp
index ef302243da..ff732bc70e 100644
--- a/src/corelib/io/qfilesystemwatcher_inotify.cpp
+++ b/src/corelib/io/qfilesystemwatcher_inotify.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
@@ -210,7 +210,7 @@ QT_END_NAMESPACE
QT_BEGIN_NAMESPACE
-QInotifyFileSystemWatcherEngine *QInotifyFileSystemWatcherEngine::create()
+QInotifyFileSystemWatcherEngine *QInotifyFileSystemWatcherEngine::create(QObject *parent)
{
register int fd = -1;
#ifdef IN_CLOEXEC
@@ -220,40 +220,32 @@ QInotifyFileSystemWatcherEngine *QInotifyFileSystemWatcherEngine::create()
fd = inotify_init();
if (fd == -1)
return 0;
- ::fcntl(fd, F_SETFD, FD_CLOEXEC);
}
- return new QInotifyFileSystemWatcherEngine(fd);
+ return new QInotifyFileSystemWatcherEngine(fd, parent);
}
-QInotifyFileSystemWatcherEngine::QInotifyFileSystemWatcherEngine(int fd)
- : inotifyFd(fd)
+QInotifyFileSystemWatcherEngine::QInotifyFileSystemWatcherEngine(int fd, QObject *parent)
+ : QFileSystemWatcherEngine(parent),
+ inotifyFd(fd),
+ notifier(fd, QSocketNotifier::Read, this)
{
fcntl(inotifyFd, F_SETFD, FD_CLOEXEC);
-
- moveToThread(this);
+ connect(&notifier, SIGNAL(activated(int)), SLOT(readFromInotify()));
}
QInotifyFileSystemWatcherEngine::~QInotifyFileSystemWatcherEngine()
{
+ notifier.setEnabled(false);
foreach (int id, pathToID)
inotify_rm_watch(inotifyFd, id < 0 ? -id : id);
::close(inotifyFd);
}
-void QInotifyFileSystemWatcherEngine::run()
-{
- QSocketNotifier sn(inotifyFd, QSocketNotifier::Read, this);
- connect(&sn, SIGNAL(activated(int)), SLOT(readFromInotify()));
- (void) exec();
-}
-
QStringList QInotifyFileSystemWatcherEngine::addPaths(const QStringList &paths,
QStringList *files,
QStringList *directories)
{
- QMutexLocker locker(&mutex);
-
QStringList p = paths;
QMutableListIterator<QString> it(p);
while (it.hasNext()) {
@@ -303,8 +295,6 @@ QStringList QInotifyFileSystemWatcherEngine::addPaths(const QStringList &paths,
idToPath.insert(id, path);
}
- start();
-
return p;
}
@@ -312,8 +302,6 @@ QStringList QInotifyFileSystemWatcherEngine::removePaths(const QStringList &path
QStringList *files,
QStringList *directories)
{
- QMutexLocker locker(&mutex);
-
QStringList p = paths;
QMutableListIterator<QString> it(p);
while (it.hasNext()) {
@@ -338,15 +326,8 @@ QStringList QInotifyFileSystemWatcherEngine::removePaths(const QStringList &path
return p;
}
-void QInotifyFileSystemWatcherEngine::stop()
-{
- quit();
-}
-
void QInotifyFileSystemWatcherEngine::readFromInotify()
{
- QMutexLocker locker(&mutex);
-
// qDebug() << "QInotifyFileSystemWatcherEngine::readFromInotify";
int buffSize = 0;
diff --git a/src/corelib/io/qfilesystemwatcher_inotify_p.h b/src/corelib/io/qfilesystemwatcher_inotify_p.h
index 0abd205237..8b3ce62c46 100644
--- a/src/corelib/io/qfilesystemwatcher_inotify_p.h
+++ b/src/corelib/io/qfilesystemwatcher_inotify_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
@@ -57,8 +57,9 @@
#ifndef QT_NO_FILESYSTEMWATCHER
-#include <qhash.h>
-#include <qmutex.h>
+#include <QtCore/qhash.h>
+#include <QtCore/qmutex.h>
+#include <QtCore/qsocketnotifier.h>
QT_BEGIN_NAMESPACE
@@ -69,24 +70,20 @@ class QInotifyFileSystemWatcherEngine : public QFileSystemWatcherEngine
public:
~QInotifyFileSystemWatcherEngine();
- static QInotifyFileSystemWatcherEngine *create();
-
- void run();
+ static QInotifyFileSystemWatcherEngine *create(QObject *parent);
QStringList addPaths(const QStringList &paths, QStringList *files, QStringList *directories);
QStringList removePaths(const QStringList &paths, QStringList *files, QStringList *directories);
- void stop();
-
private Q_SLOTS:
void readFromInotify();
private:
- QInotifyFileSystemWatcherEngine(int fd);
+ QInotifyFileSystemWatcherEngine(int fd, QObject *parent);
int inotifyFd;
- QMutex mutex;
QHash<QString, int> pathToID;
QHash<int, QString> idToPath;
+ QSocketNotifier notifier;
};
diff --git a/src/corelib/io/qfilesystemwatcher_kqueue.cpp b/src/corelib/io/qfilesystemwatcher_kqueue.cpp
index 387a7f7c4b..fd7bfa2b27 100644
--- a/src/corelib/io/qfilesystemwatcher_kqueue.cpp
+++ b/src/corelib/io/qfilesystemwatcher_kqueue.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
@@ -67,49 +67,28 @@ QT_BEGIN_NAMESPACE
# define DEBUG if(false)qDebug
#endif
-QKqueueFileSystemWatcherEngine *QKqueueFileSystemWatcherEngine::create()
+QKqueueFileSystemWatcherEngine *QKqueueFileSystemWatcherEngine::create(QObject *parent)
{
int kqfd = kqueue();
if (kqfd == -1)
return 0;
- return new QKqueueFileSystemWatcherEngine(kqfd);
+ return new QKqueueFileSystemWatcherEngine(kqfd, parent);
}
-QKqueueFileSystemWatcherEngine::QKqueueFileSystemWatcherEngine(int kqfd)
- : kqfd(kqfd)
+QKqueueFileSystemWatcherEngine::QKqueueFileSystemWatcherEngine(int kqfd, QObject *parent)
+ : QFileSystemWatcherEngine(parent),
+ kqfd(kqfd),
+ notifier(kqfd, QSocketNotifier::Read, this)
{
- fcntl(kqfd, F_SETFD, FD_CLOEXEC);
+ connect(&notifier, SIGNAL(activated(int)), SLOT(readFromKqueue()));
- if (pipe(kqpipe) == -1) {
- perror("QKqueueFileSystemWatcherEngine: cannot create pipe");
- kqpipe[0] = kqpipe[1] = -1;
- return;
- }
- fcntl(kqpipe[0], F_SETFD, FD_CLOEXEC);
- fcntl(kqpipe[1], F_SETFD, FD_CLOEXEC);
-
- struct kevent kev;
- EV_SET(&kev,
- kqpipe[0],
- EVFILT_READ,
- EV_ADD | EV_ENABLE,
- 0,
- 0,
- 0);
- if (kevent(kqfd, &kev, 1, 0, 0, 0) == -1) {
- perror("QKqueueFileSystemWatcherEngine: cannot watch pipe, kevent returned");
- return;
- }
+ fcntl(kqfd, F_SETFD, FD_CLOEXEC);
}
QKqueueFileSystemWatcherEngine::~QKqueueFileSystemWatcherEngine()
{
- stop();
- wait();
-
+ notifier.setEnabled(false);
close(kqfd);
- close(kqpipe[0]);
- close(kqpipe[1]);
foreach (int id, pathToID)
::close(id < 0 ? -id : id);
@@ -120,82 +99,73 @@ QStringList QKqueueFileSystemWatcherEngine::addPaths(const QStringList &paths,
QStringList *directories)
{
QStringList p = paths;
- {
- QMutexLocker locker(&mutex);
-
- QMutableListIterator<QString> it(p);
- while (it.hasNext()) {
- QString path = it.next();
- int fd;
+ QMutableListIterator<QString> it(p);
+ while (it.hasNext()) {
+ QString path = it.next();
+ int fd;
#if defined(O_EVTONLY)
- fd = qt_safe_open(QFile::encodeName(path), O_EVTONLY);
+ fd = qt_safe_open(QFile::encodeName(path), O_EVTONLY);
#else
- fd = qt_safe_open(QFile::encodeName(path), O_RDONLY);
+ fd = qt_safe_open(QFile::encodeName(path), O_RDONLY);
#endif
- if (fd == -1) {
- perror("QKqueueFileSystemWatcherEngine::addPaths: open");
- continue;
- }
- if (fd >= (int)FD_SETSIZE / 2 && fd < (int)FD_SETSIZE) {
- int fddup = fcntl(fd, F_DUPFD, FD_SETSIZE);
- if (fddup != -1) {
- ::close(fd);
- fd = fddup;
- }
+ if (fd == -1) {
+ perror("QKqueueFileSystemWatcherEngine::addPaths: open");
+ continue;
+ }
+ if (fd >= (int)FD_SETSIZE / 2 && fd < (int)FD_SETSIZE) {
+ int fddup = fcntl(fd, F_DUPFD, FD_SETSIZE);
+ if (fddup != -1) {
+ ::close(fd);
+ fd = fddup;
}
- fcntl(fd, F_SETFD, FD_CLOEXEC);
+ }
+ fcntl(fd, F_SETFD, FD_CLOEXEC);
- QT_STATBUF st;
- if (QT_FSTAT(fd, &st) == -1) {
- perror("QKqueueFileSystemWatcherEngine::addPaths: fstat");
+ QT_STATBUF st;
+ if (QT_FSTAT(fd, &st) == -1) {
+ perror("QKqueueFileSystemWatcherEngine::addPaths: fstat");
+ ::close(fd);
+ continue;
+ }
+ int id = (S_ISDIR(st.st_mode)) ? -fd : fd;
+ if (id < 0) {
+ if (directories->contains(path)) {
::close(fd);
continue;
}
- int id = (S_ISDIR(st.st_mode)) ? -fd : fd;
- if (id < 0) {
- if (directories->contains(path)) {
- ::close(fd);
- continue;
- }
- } else {
- if (files->contains(path)) {
- ::close(fd);
- continue;
- }
- }
-
- struct kevent kev;
- EV_SET(&kev,
- fd,
- EVFILT_VNODE,
- EV_ADD | EV_ENABLE | EV_CLEAR,
- NOTE_DELETE | NOTE_WRITE | NOTE_EXTEND | NOTE_ATTRIB | NOTE_RENAME | NOTE_REVOKE,
- 0,
- 0);
- if (kevent(kqfd, &kev, 1, 0, 0, 0) == -1) {
- perror("QKqueueFileSystemWatcherEngine::addPaths: kevent");
+ } else {
+ if (files->contains(path)) {
::close(fd);
continue;
}
+ }
- it.remove();
- if (id < 0) {
- DEBUG() << "QKqueueFileSystemWatcherEngine: added directory path" << path;
- directories->append(path);
- } else {
- DEBUG() << "QKqueueFileSystemWatcherEngine: added file path" << path;
- files->append(path);
- }
+ struct kevent kev;
+ EV_SET(&kev,
+ fd,
+ EVFILT_VNODE,
+ EV_ADD | EV_ENABLE | EV_CLEAR,
+ NOTE_DELETE | NOTE_WRITE | NOTE_EXTEND | NOTE_ATTRIB | NOTE_RENAME | NOTE_REVOKE,
+ 0,
+ 0);
+ if (kevent(kqfd, &kev, 1, 0, 0, 0) == -1) {
+ perror("QKqueueFileSystemWatcherEngine::addPaths: kevent");
+ ::close(fd);
+ continue;
+ }
- pathToID.insert(path, id);
- idToPath.insert(id, path);
+ it.remove();
+ if (id < 0) {
+ DEBUG() << "QKqueueFileSystemWatcherEngine: added directory path" << path;
+ directories->append(path);
+ } else {
+ DEBUG() << "QKqueueFileSystemWatcherEngine: added file path" << path;
+ files->append(path);
}
- }
- if (!isRunning())
- start();
- else
- write(kqpipe[1], "@", 1);
+ pathToID.insert(path, id);
+ idToPath.insert(id, path);
+ }
return p;
}
@@ -206,126 +176,86 @@ QStringList QKqueueFileSystemWatcherEngine::removePaths(const QStringList &paths
{
bool isEmpty;
QStringList p = paths;
- {
- QMutexLocker locker(&mutex);
- if (pathToID.isEmpty())
- return p;
-
- QMutableListIterator<QString> it(p);
- while (it.hasNext()) {
- QString path = it.next();
- int id = pathToID.take(path);
- QString x = idToPath.take(id);
- if (x.isEmpty() || x != path)
- continue;
+ if (pathToID.isEmpty())
+ return p;
- ::close(id < 0 ? -id : id);
+ QMutableListIterator<QString> it(p);
+ while (it.hasNext()) {
+ QString path = it.next();
+ int id = pathToID.take(path);
+ QString x = idToPath.take(id);
+ if (x.isEmpty() || x != path)
+ continue;
- it.remove();
- if (id < 0)
- directories->removeAll(path);
- else
- files->removeAll(path);
- }
- isEmpty = pathToID.isEmpty();
- }
+ ::close(id < 0 ? -id : id);
- if (isEmpty) {
- stop();
- wait();
- } else {
- write(kqpipe[1], "@", 1);
+ it.remove();
+ if (id < 0)
+ directories->removeAll(path);
+ else
+ files->removeAll(path);
}
+ isEmpty = pathToID.isEmpty();
return p;
}
-void QKqueueFileSystemWatcherEngine::stop()
-{
- write(kqpipe[1], "q", 1);
-}
-
-void QKqueueFileSystemWatcherEngine::run()
+void QKqueueFileSystemWatcherEngine::readFromKqueue()
{
forever {
+ DEBUG() << "QKqueueFileSystemWatcherEngine: polling for changes";
int r;
struct kevent kev;
- DEBUG() << "QKqueueFileSystemWatcherEngine: waiting for kevents...";
- EINTR_LOOP(r, kevent(kqfd, 0, 0, &kev, 1, 0));
+ struct timespec ts = { 0, 0 }; // 0 ts, because we want to poll
+ EINTR_LOOP(r, kevent(kqfd, 0, 0, &kev, 1, &ts));
if (r < 0) {
perror("QKqueueFileSystemWatcherEngine: error during kevent wait");
return;
+ } else if (r == 0) {
+ // polling returned no events, so stop
+ break;
} else {
int fd = kev.ident;
DEBUG() << "QKqueueFileSystemWatcherEngine: processing kevent" << kev.ident << kev.filter;
- if (fd == kqpipe[0]) {
- // read all pending data from the pipe
- QByteArray ba;
- ba.resize(kev.data);
- if (read(kqpipe[0], ba.data(), ba.size()) != ba.size()) {
- perror("QKqueueFileSystemWatcherEngine: error reading from pipe");
- return;
- }
- // read the command from the buffer (but break and return on 'q')
- char cmd = 0;
- for (int i = 0; i < ba.size(); ++i) {
- cmd = ba.constData()[i];
- if (cmd == 'q')
- break;
- }
- // handle the command
- switch (cmd) {
- case 'q':
- DEBUG() << "QKqueueFileSystemWatcherEngine: thread received 'q', exiting...";
- return;
- case '@':
- DEBUG() << "QKqueueFileSystemWatcherEngine: thread received '@', continuing...";
- break;
- default:
- DEBUG() << "QKqueueFileSystemWatcherEngine: thread received unknow message" << cmd;
- break;
- }
- } else {
- QMutexLocker locker(&mutex);
- int id = fd;
- QString path = idToPath.value(id);
+ int id = fd;
+ QString path = idToPath.value(id);
+ if (path.isEmpty()) {
+ // perhaps a directory?
+ id = -id;
+ path = idToPath.value(id);
if (path.isEmpty()) {
- // perhaps a directory?
- id = -id;
- path = idToPath.value(id);
- if (path.isEmpty()) {
- DEBUG() << "QKqueueFileSystemWatcherEngine: received a kevent for a file we're not watching";
- continue;
- }
- }
- if (kev.filter != EVFILT_VNODE) {
- DEBUG() << "QKqueueFileSystemWatcherEngine: received a kevent with the wrong filter";
+ DEBUG() << "QKqueueFileSystemWatcherEngine: received a kevent for a file we're not watching";
continue;
}
+ }
+ if (kev.filter != EVFILT_VNODE) {
+ DEBUG() << "QKqueueFileSystemWatcherEngine: received a kevent with the wrong filter";
+ continue;
+ }
- if ((kev.fflags & (NOTE_DELETE | NOTE_REVOKE | NOTE_RENAME)) != 0) {
- DEBUG() << path << "removed, removing watch also";
+ if ((kev.fflags & (NOTE_DELETE | NOTE_REVOKE | NOTE_RENAME)) != 0) {
+ DEBUG() << path << "removed, removing watch also";
- pathToID.remove(path);
- idToPath.remove(id);
- ::close(fd);
+ pathToID.remove(path);
+ idToPath.remove(id);
+ ::close(fd);
- if (id < 0)
- emit directoryChanged(path, true);
- else
- emit fileChanged(path, true);
- } else {
- DEBUG() << path << "changed";
+ if (id < 0)
+ emit directoryChanged(path, true);
+ else
+ emit fileChanged(path, true);
+ } else {
+ DEBUG() << path << "changed";
- if (id < 0)
- emit directoryChanged(path, false);
- else
- emit fileChanged(path, false);
- }
+ if (id < 0)
+ emit directoryChanged(path, false);
+ else
+ emit fileChanged(path, false);
}
}
+
}
}
diff --git a/src/corelib/io/qfilesystemwatcher_kqueue_p.h b/src/corelib/io/qfilesystemwatcher_kqueue_p.h
index fd9d820e7d..9bd9378c0c 100644
--- a/src/corelib/io/qfilesystemwatcher_kqueue_p.h
+++ b/src/corelib/io/qfilesystemwatcher_kqueue_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
@@ -59,6 +59,7 @@
#include <QtCore/qmutex.h>
#include <QtCore/qthread.h>
#include <QtCore/qvector.h>
+#include <QtCore/qsocketnotifier.h>
#ifndef QT_NO_FILESYSTEMWATCHER
struct kevent;
@@ -71,24 +72,22 @@ class QKqueueFileSystemWatcherEngine : public QFileSystemWatcherEngine
public:
~QKqueueFileSystemWatcherEngine();
- static QKqueueFileSystemWatcherEngine *create();
+ static QKqueueFileSystemWatcherEngine *create(QObject *parent);
QStringList addPaths(const QStringList &paths, QStringList *files, QStringList *directories);
QStringList removePaths(const QStringList &paths, QStringList *files, QStringList *directories);
- void stop();
+private Q_SLOTS:
+ void readFromKqueue();
private:
- QKqueueFileSystemWatcherEngine(int kqfd);
-
- void run();
+ QKqueueFileSystemWatcherEngine(int kqfd, QObject *parent);
int kqfd;
- int kqpipe[2];
- QMutex mutex;
QHash<QString, int> pathToID;
QHash<int, QString> idToPath;
+ QSocketNotifier notifier;
};
QT_END_NAMESPACE
diff --git a/src/corelib/io/qfilesystemwatcher_p.h b/src/corelib/io/qfilesystemwatcher_p.h
index e136273b36..9f403b308f 100644
--- a/src/corelib/io/qfilesystemwatcher_p.h
+++ b/src/corelib/io/qfilesystemwatcher_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
@@ -60,19 +60,17 @@
#include <private/qobject_p.h>
#include <QtCore/qstringlist.h>
-#include <QtCore/qthread.h>
QT_BEGIN_NAMESPACE
-class QFileSystemWatcherEngine : public QThread
+class QFileSystemWatcherEngine : public QObject
{
Q_OBJECT
protected:
- inline QFileSystemWatcherEngine(bool move = true)
+ inline QFileSystemWatcherEngine(QObject *parent)
+ : QObject(parent)
{
- if (move)
- moveToThread(this);
}
public:
@@ -88,8 +86,6 @@ public:
QStringList *files,
QStringList *directories) = 0;
- virtual void stop() = 0;
-
Q_SIGNALS:
void fileChanged(const QString &path, bool removed);
void directoryChanged(const QString &path, bool removed);
@@ -99,15 +95,14 @@ class QFileSystemWatcherPrivate : public QObjectPrivate
{
Q_DECLARE_PUBLIC(QFileSystemWatcher)
- static QFileSystemWatcherEngine *createNativeEngine();
+ static QFileSystemWatcherEngine *createNativeEngine(QObject *parent);
public:
QFileSystemWatcherPrivate();
void init();
void initPollerEngine();
- void initForcedEngine(const QString &);
- QFileSystemWatcherEngine *native, *poller, *forced;
+ QFileSystemWatcherEngine *native, *poller;
QStringList files, directories;
// private slots
diff --git a/src/corelib/io/qfilesystemwatcher_polling.cpp b/src/corelib/io/qfilesystemwatcher_polling.cpp
new file mode 100644
index 0000000000..23dca140d6
--- /dev/null
+++ b/src/corelib/io/qfilesystemwatcher_polling.cpp
@@ -0,0 +1,151 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 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$
+** GNU Lesser General Public License Usage
+** 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.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qfilesystemwatcher_polling_p.h"
+#include <QtCore/qtimer.h>
+
+QT_BEGIN_NAMESPACE
+
+QPollingFileSystemWatcherEngine::QPollingFileSystemWatcherEngine(QObject *parent)
+ : QFileSystemWatcherEngine(parent),
+ timer(this)
+{
+ connect(&timer, SIGNAL(timeout()), SLOT(timeout()));
+}
+
+QStringList QPollingFileSystemWatcherEngine::addPaths(const QStringList &paths,
+ QStringList *files,
+ QStringList *directories)
+{
+ QStringList p = paths;
+ QMutableListIterator<QString> it(p);
+ while (it.hasNext()) {
+ QString path = it.next();
+ QFileInfo fi(path);
+ if (!fi.exists())
+ continue;
+ if (fi.isDir()) {
+ if (!directories->contains(path))
+ directories->append(path);
+ if (!path.endsWith(QLatin1Char('/')))
+ fi = QFileInfo(path + QLatin1Char('/'));
+ this->directories.insert(path, fi);
+ } else {
+ if (!files->contains(path))
+ files->append(path);
+ this->files.insert(path, fi);
+ }
+ it.remove();
+ }
+
+ if ((!this->files.isEmpty() ||
+ !this->directories.isEmpty()) &&
+ !timer.isActive()) {
+ timer.start(PollingInterval);
+ }
+
+ return p;
+}
+
+QStringList QPollingFileSystemWatcherEngine::removePaths(const QStringList &paths,
+ QStringList *files,
+ QStringList *directories)
+{
+ QStringList p = paths;
+ QMutableListIterator<QString> it(p);
+ while (it.hasNext()) {
+ QString path = it.next();
+ if (this->directories.remove(path)) {
+ directories->removeAll(path);
+ it.remove();
+ } else if (this->files.remove(path)) {
+ files->removeAll(path);
+ it.remove();
+ }
+ }
+
+ if (this->files.isEmpty() &&
+ this->directories.isEmpty()) {
+ timer.stop();
+ }
+
+ return p;
+}
+
+void QPollingFileSystemWatcherEngine::timeout()
+{
+ QMutableHashIterator<QString, FileInfo> fit(files);
+ while (fit.hasNext()) {
+ QHash<QString, FileInfo>::iterator x = fit.next();
+ QString path = x.key();
+ QFileInfo fi(path);
+ if (!fi.exists()) {
+ fit.remove();
+ emit fileChanged(path, true);
+ } else if (x.value() != fi) {
+ x.value() = fi;
+ emit fileChanged(path, false);
+ }
+ }
+ QMutableHashIterator<QString, FileInfo> dit(directories);
+ while (dit.hasNext()) {
+ QHash<QString, FileInfo>::iterator x = dit.next();
+ QString path = x.key();
+ QFileInfo fi(path);
+ if (!path.endsWith(QLatin1Char('/')))
+ fi = QFileInfo(path + QLatin1Char('/'));
+ if (!fi.exists()) {
+ dit.remove();
+ emit directoryChanged(path, true);
+ } else if (x.value() != fi) {
+ fi.refresh();
+ if (!fi.exists()) {
+ dit.remove();
+ emit directoryChanged(path, true);
+ } else {
+ x.value() = fi;
+ emit directoryChanged(path, false);
+ }
+ }
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/io/qfilesystemwatcher_dnotify_p.h b/src/corelib/io/qfilesystemwatcher_polling_p.h
index f759e87d89..3b3272a890 100644
--- a/src/corelib/io/qfilesystemwatcher_dnotify_p.h
+++ b/src/corelib/io/qfilesystemwatcher_polling_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
@@ -39,8 +39,8 @@
**
****************************************************************************/
-#ifndef QFILESYSTEMWATCHER_DNOTIFY_P_H
-#define QFILESYSTEMWATCHER_DNOTIFY_P_H
+#ifndef QFILESYSTEMWATCHER_POLLING_P_H
+#define QFILESYSTEMWATCHER_POLLING_P_H
//
// W A R N I N G
@@ -53,79 +53,74 @@
// We mean it.
//
-#include "qfilesystemwatcher_p.h"
-
-#ifndef QT_NO_FILESYSTEMWATCHER
+#include <QtCore/qfileinfo.h>
+#include <QtCore/qmutex.h>
+#include <QtCore/qdatetime.h>
+#include <QtCore/qdir.h>
+#include <QtCore/qtimer.h>
-#include <qmutex.h>
-#include <qhash.h>
-#include <qdatetime.h>
-#include <qfile.h>
+#include "qfilesystemwatcher_p.h"
QT_BEGIN_NAMESPACE
-class QDnotifyFileSystemWatcherEngine : public QFileSystemWatcherEngine
+enum { PollingInterval = 1000 };
+
+class QPollingFileSystemWatcherEngine : public QFileSystemWatcherEngine
{
Q_OBJECT
-public:
- virtual ~QDnotifyFileSystemWatcherEngine();
+ class FileInfo
+ {
+ uint ownerId;
+ uint groupId;
+ QFile::Permissions permissions;
+ QDateTime lastModified;
+ QStringList entries;
+
+ public:
+ FileInfo(const QFileInfo &fileInfo)
+ : ownerId(fileInfo.ownerId()),
+ groupId(fileInfo.groupId()),
+ permissions(fileInfo.permissions()),
+ lastModified(fileInfo.lastModified())
+ {
+ if (fileInfo.isDir()) {
+ entries = fileInfo.absoluteDir().entryList(QDir::AllEntries);
+ }
+ }
+ FileInfo &operator=(const QFileInfo &fileInfo)
+ {
+ *this = FileInfo(fileInfo);
+ return *this;
+ }
+
+ bool operator!=(const QFileInfo &fileInfo) const
+ {
+ if (fileInfo.isDir() && entries != fileInfo.absoluteDir().entryList(QDir::AllEntries))
+ return true;
+ return (ownerId != fileInfo.ownerId()
+ || groupId != fileInfo.groupId()
+ || permissions != fileInfo.permissions()
+ || lastModified != fileInfo.lastModified());
+ }
+ };
- static QDnotifyFileSystemWatcherEngine *create();
+ QHash<QString, FileInfo> files, directories;
- void run();
+public:
+ QPollingFileSystemWatcherEngine(QObject *parent);
QStringList addPaths(const QStringList &paths, QStringList *files, QStringList *directories);
QStringList removePaths(const QStringList &paths, QStringList *files, QStringList *directories);
- void stop();
-
private Q_SLOTS:
- void refresh(int);
+ void timeout();
private:
- struct Directory {
- Directory() : fd(0), parentFd(0), isMonitored(false) {}
- Directory(const Directory &o) : path(o.path),
- fd(o.fd),
- parentFd(o.parentFd),
- isMonitored(o.isMonitored),
- files(o.files) {}
- QString path;
- int fd;
- int parentFd;
- bool isMonitored;
-
- struct File {
- File() : ownerId(0u), groupId(0u), permissions(0u) { }
- File(const File &o) : path(o.path),
- ownerId(o.ownerId),
- groupId(o.groupId),
- permissions(o.permissions),
- lastWrite(o.lastWrite) {}
- QString path;
-
- bool updateInfo();
-
- uint ownerId;
- uint groupId;
- QFile::Permissions permissions;
- QDateTime lastWrite;
- };
-
- QList<File> files;
- };
-
- QDnotifyFileSystemWatcherEngine();
-
- QMutex mutex;
- QHash<QString, int> pathToFD;
- QHash<int, Directory> fdToDirectory;
- QHash<int, int> parentToFD;
+ QTimer timer;
};
+QT_END_NAMESPACE
+#endif // QFILESYSTEMWATCHER_POLLING_P_H
-QT_END_NAMESPACE
-#endif // QT_NO_FILESYSTEMWATCHER
-#endif // QFILESYSTEMWATCHER_DNOTIFY_P_H
diff --git a/src/corelib/io/qfilesystemwatcher_symbian.cpp b/src/corelib/io/qfilesystemwatcher_symbian.cpp
deleted file mode 100644
index 6e5e91114c..0000000000
--- a/src/corelib/io/qfilesystemwatcher_symbian.cpp
+++ /dev/null
@@ -1,273 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 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$
-** GNU Lesser General Public License Usage
-** 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.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU General
-** Public License version 3.0 as published by the Free Software Foundation
-** and appearing in the file LICENSE.GPL included in the packaging of this
-** file. Please review the following information to ensure the GNU General
-** Public License version 3.0 requirements will be met:
-** http://www.gnu.org/copyleft/gpl.html.
-**
-** Other Usage
-** Alternatively, this file may be used in accordance with the terms and
-** conditions contained in a signed written agreement between you and Nokia.
-**
-**
-**
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qfilesystemwatcher.h"
-#include "qfilesystemwatcher_symbian_p.h"
-#include "qfileinfo.h"
-#include "qdebug.h"
-#include "private/qcore_symbian_p.h"
-#include <QDir>
-
-#ifndef QT_NO_FILESYSTEMWATCHER
-
-
-QT_BEGIN_NAMESPACE
-
-QNotifyChangeEvent::QNotifyChangeEvent(RFs &fs, const TDesC &file,
- QSymbianFileSystemWatcherEngine *e, bool aIsDir,
- TInt aPriority) :
- CActive(aPriority),
- isDir(aIsDir),
- fsSession(fs),
- watchedPath(file),
- engine(e),
- failureCount(0)
-{
- if (isDir) {
- fsSession.NotifyChange(ENotifyEntry, iStatus, file);
- } else {
- fsSession.NotifyChange(ENotifyAll, iStatus, file);
- }
- CActiveScheduler::Add(this);
- SetActive();
-}
-
-QNotifyChangeEvent::~QNotifyChangeEvent()
-{
- Cancel();
-}
-
-void QNotifyChangeEvent::RunL()
-{
- if(iStatus.Int() == KErrNone) {
- failureCount = 0;
- } else {
- qWarning("QNotifyChangeEvent::RunL() - Failed to order change notifications: %d", iStatus.Int());
- failureCount++;
- }
-
- // Re-request failed notification once, but if it won't start working,
- // we can't do much besides just not request any more notifications.
- if (failureCount < 2) {
- if (isDir) {
- fsSession.NotifyChange(ENotifyEntry, iStatus, watchedPath);
- } else {
- fsSession.NotifyChange(ENotifyAll, iStatus, watchedPath);
- }
- SetActive();
-
- if (!failureCount) {
- int err;
- QT_TRYCATCH_ERROR(err, engine->emitPathChanged(this));
- if (err != KErrNone)
- qWarning("QNotifyChangeEvent::RunL() - emitPathChanged threw exception (Converted error code: %d)", err);
- }
- }
-}
-
-void QNotifyChangeEvent::DoCancel()
-{
- fsSession.NotifyChangeCancel(iStatus);
-}
-
-QSymbianFileSystemWatcherEngine::QSymbianFileSystemWatcherEngine() :
- watcherStarted(false)
-{
- moveToThread(this);
-}
-
-QSymbianFileSystemWatcherEngine::~QSymbianFileSystemWatcherEngine()
-{
- stop();
-}
-
-QStringList QSymbianFileSystemWatcherEngine::addPaths(const QStringList &paths, QStringList *files,
- QStringList *directories)
-{
- QMutexLocker locker(&mutex);
- QStringList p = paths;
-
- startWatcher();
-
- QMutableListIterator<QString> it(p);
- while (it.hasNext()) {
- QString path = it.next();
- QFileInfo fi(path);
- if (!fi.exists())
- continue;
-
- bool isDir = fi.isDir();
- if (isDir) {
- if (directories->contains(path))
- continue;
- } else {
- if (files->contains(path))
- continue;
- }
-
- // Use absolute filepath as relative paths seem to have some issues.
- QString filePath = fi.absoluteFilePath();
- if (isDir && filePath.at(filePath.size() - 1) != QChar(L'/')) {
- filePath += QChar(L'/');
- }
-
- currentAddEvent = NULL;
- QMetaObject::invokeMethod(this,
- "addNativeListener",
- Qt::QueuedConnection,
- Q_ARG(QString, filePath));
-
- syncCondition.wait(&mutex);
- if (currentAddEvent) {
- currentAddEvent->isDir = isDir;
-
- activeObjectToPath.insert(currentAddEvent, path);
- it.remove();
-
- if (isDir)
- directories->append(path);
- else
- files->append(path);
- }
- }
-
- return p;
-}
-
-QStringList QSymbianFileSystemWatcherEngine::removePaths(const QStringList &paths,
- QStringList *files,
- QStringList *directories)
-{
- QMutexLocker locker(&mutex);
-
- QStringList p = paths;
- QMutableListIterator<QString> it(p);
- while (it.hasNext()) {
- QString path = it.next();
-
- currentRemoveEvent = activeObjectToPath.key(path);
- if (!currentRemoveEvent)
- continue;
- activeObjectToPath.remove(currentRemoveEvent);
-
- QMetaObject::invokeMethod(this,
- "removeNativeListener",
- Qt::QueuedConnection);
-
- syncCondition.wait(&mutex);
-
- it.remove();
-
- files->removeAll(path);
- directories->removeAll(path);
- }
-
- return p;
-}
-
-void QSymbianFileSystemWatcherEngine::emitPathChanged(QNotifyChangeEvent *e)
-{
- QMutexLocker locker(&mutex);
-
- QString path = activeObjectToPath.value(e);
- QFileInfo fi(path);
-
- if (e->isDir)
- emit directoryChanged(path, !fi.exists());
- else
- emit fileChanged(path, !fi.exists());
-}
-
-void QSymbianFileSystemWatcherEngine::stop()
-{
- quit();
- wait();
-}
-
-// This method must be called inside mutex
-void QSymbianFileSystemWatcherEngine::startWatcher()
-{
- if (!watcherStarted) {
- setStackSize(0x5000);
- start();
- syncCondition.wait(&mutex);
- watcherStarted = true;
- }
-}
-
-
-void QSymbianFileSystemWatcherEngine::run()
-{
- mutex.lock();
- syncCondition.wakeOne();
- mutex.unlock();
-
- exec();
-
- foreach(QNotifyChangeEvent *e, activeObjectToPath.keys()) {
- e->Cancel();
- delete e;
- }
-
- activeObjectToPath.clear();
-}
-
-void QSymbianFileSystemWatcherEngine::addNativeListener(const QString &directoryPath)
-{
- QMutexLocker locker(&mutex);
- QString nativeDir(QDir::toNativeSeparators(directoryPath));
- TPtrC ptr(qt_QString2TPtrC(nativeDir));
- currentAddEvent = new QNotifyChangeEvent(qt_s60GetRFs(), ptr, this, directoryPath.endsWith(QChar(L'/'), Qt::CaseSensitive));
- syncCondition.wakeOne();
-}
-
-void QSymbianFileSystemWatcherEngine::removeNativeListener()
-{
- QMutexLocker locker(&mutex);
- currentRemoveEvent->Cancel();
- delete currentRemoveEvent;
- currentRemoveEvent = NULL;
- syncCondition.wakeOne();
-}
-
-
-QT_END_NAMESPACE
-#endif // QT_NO_FILESYSTEMWATCHER
diff --git a/src/corelib/io/qfilesystemwatcher_win.cpp b/src/corelib/io/qfilesystemwatcher_win.cpp
index 4e94623844..e82a9a5b56 100644
--- a/src/corelib/io/qfilesystemwatcher_win.cpp
+++ b/src/corelib/io/qfilesystemwatcher_win.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
@@ -50,25 +50,12 @@
#include <qset.h>
#include <qdatetime.h>
#include <qdir.h>
+#include <qtextstream.h>
QT_BEGIN_NAMESPACE
-void QWindowsFileSystemWatcherEngine::stop()
-{
- foreach(QWindowsFileSystemWatcherEngineThread *thread, threads)
- thread->stop();
-}
-
-QWindowsFileSystemWatcherEngine::QWindowsFileSystemWatcherEngine()
- : QFileSystemWatcherEngine(false)
-{
-}
-
QWindowsFileSystemWatcherEngine::~QWindowsFileSystemWatcherEngine()
{
- if (threads.isEmpty())
- return;
-
foreach(QWindowsFileSystemWatcherEngineThread *thread, threads) {
thread->stop();
thread->wait();
@@ -310,7 +297,6 @@ QWindowsFileSystemWatcherEngineThread::QWindowsFileSystemWatcherEngineThread()
handles.reserve(MAXIMUM_WAIT_OBJECTS);
handles.append(h);
}
- moveToThread(this);
}
@@ -326,6 +312,17 @@ QWindowsFileSystemWatcherEngineThread::~QWindowsFileSystemWatcherEngineThread()
}
}
+static inline QString msgFindNextFailed(const QHash<QString, QWindowsFileSystemWatcherEngine::PathInfo> &pathInfos)
+{
+ QString result;
+ QTextStream str(&result);
+ str << "QFileSystemWatcher: FindNextChangeNotification failed for";
+ foreach (const QWindowsFileSystemWatcherEngine::PathInfo &pathInfo, pathInfos)
+ str << " \"" << QDir::toNativeSeparators(pathInfo.absolutePath) << '"';
+ str << ' ';
+ return result;
+}
+
void QWindowsFileSystemWatcherEngineThread::run()
{
QMutexLocker locker(&mutex);
@@ -356,11 +353,11 @@ void QWindowsFileSystemWatcherEngineThread::run()
// for some reason, so we must check if the handle exist in the handles vector
if (handles.contains(handle)) {
// qDebug()<<"thread"<<this<<"Acknowledged handle:"<<at<<handle;
+ QHash<QString, QWindowsFileSystemWatcherEngine::PathInfo> &h = pathInfoForHandle[handle];
if (!FindNextChangeNotification(handle)) {
- qErrnoWarning("QFileSystemWatcher: FindNextChangeNotification failed!!");
+ const DWORD error = GetLastError();
+ qErrnoWarning(error, "%s", qPrintable(msgFindNextFailed(h)));
}
-
- QHash<QString, QWindowsFileSystemWatcherEngine::PathInfo> &h = pathInfoForHandle[handle];
QMutableHashIterator<QString, QWindowsFileSystemWatcherEngine::PathInfo> it(h);
while (it.hasNext()) {
QHash<QString, QWindowsFileSystemWatcherEngine::PathInfo>::iterator x = it.next();
diff --git a/src/corelib/io/qfilesystemwatcher_win_p.h b/src/corelib/io/qfilesystemwatcher_win_p.h
index 3e9938a490..8e6b779b93 100644
--- a/src/corelib/io/qfilesystemwatcher_win_p.h
+++ b/src/corelib/io/qfilesystemwatcher_win_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
@@ -60,6 +60,7 @@
#include <qt_windows.h>
#include <QtCore/qdatetime.h>
+#include <QtCore/qthread.h>
#include <QtCore/qfile.h>
#include <QtCore/qfileinfo.h>
#include <QtCore/qhash.h>
@@ -78,15 +79,14 @@ class QWindowsFileSystemWatcherEngine : public QFileSystemWatcherEngine
{
Q_OBJECT
public:
- QWindowsFileSystemWatcherEngine();
+ inline QWindowsFileSystemWatcherEngine(QObject *parent)
+ : QFileSystemWatcherEngine(parent)
+ { }
~QWindowsFileSystemWatcherEngine();
QStringList addPaths(const QStringList &paths, QStringList *files, QStringList *directories);
QStringList removePaths(const QStringList &paths, QStringList *files, QStringList *directories);
- void stop();
-
-
class Handle
{
public:
diff --git a/src/corelib/io/qfsfileengine.cpp b/src/corelib/io/qfsfileengine.cpp
index 0d23a27909..a49ea84603 100644
--- a/src/corelib/io/qfsfileengine.cpp
+++ b/src/corelib/io/qfsfileengine.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
diff --git a/src/corelib/io/qfsfileengine.h b/src/corelib/io/qfsfileengine.h
index 2e0b1eb923..0ed883a4a7 100644
--- a/src/corelib/io/qfsfileengine.h
+++ b/src/corelib/io/qfsfileengine.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
diff --git a/src/corelib/io/qfsfileengine_iterator.cpp b/src/corelib/io/qfsfileengine_iterator.cpp
index 323ab58335..2d162f6a7d 100644
--- a/src/corelib/io/qfsfileengine_iterator.cpp
+++ b/src/corelib/io/qfsfileengine_iterator.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
diff --git a/src/corelib/io/qfsfileengine_iterator_p.h b/src/corelib/io/qfsfileengine_iterator_p.h
index deccb01bfb..782930a52c 100644
--- a/src/corelib/io/qfsfileengine_iterator_p.h
+++ b/src/corelib/io/qfsfileengine_iterator_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
diff --git a/src/corelib/io/qfsfileengine_p.h b/src/corelib/io/qfsfileengine_p.h
index 89c08aeca7..158c6f3a23 100644
--- a/src/corelib/io/qfsfileengine_p.h
+++ b/src/corelib/io/qfsfileengine_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
diff --git a/src/corelib/io/qfsfileengine_unix.cpp b/src/corelib/io/qfsfileengine_unix.cpp
index 681e55dff7..b09518865e 100644
--- a/src/corelib/io/qfsfileengine_unix.cpp
+++ b/src/corelib/io/qfsfileengine_unix.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
diff --git a/src/corelib/io/qfsfileengine_win.cpp b/src/corelib/io/qfsfileengine_win.cpp
index f2b3e5f534..5dc96ea8a2 100644
--- a/src/corelib/io/qfsfileengine_win.cpp
+++ b/src/corelib/io/qfsfileengine_win.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
@@ -550,7 +550,7 @@ QString QFSFileEngine::currentPath(const QString &fileName)
return ret;
#else
Q_UNUSED(fileName);
- return QFileSystemEngine::currentPath();
+ return QFileSystemEngine::currentPath().filePath();
#endif
}
@@ -661,6 +661,7 @@ bool QFSFileEngine::link(const QString &newName)
#endif // QT_NO_LIBRARY
#else
QString linkName = newName;
+ linkName.replace(QLatin1Char('/'), QLatin1Char('\\'));
if (!linkName.endsWith(QLatin1String(".lnk")))
linkName += QLatin1String(".lnk");
QString orgName = fileName(AbsoluteName).replace(QLatin1Char('/'), QLatin1Char('\\'));
diff --git a/src/corelib/io/qiodevice.cpp b/src/corelib/io/qiodevice.cpp
index 8e1b2d5d0c..ef530f379f 100644
--- a/src/corelib/io/qiodevice.cpp
+++ b/src/corelib/io/qiodevice.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
diff --git a/src/corelib/io/qiodevice.h b/src/corelib/io/qiodevice.h
index 7d4afca850..4b34ad4f69 100644
--- a/src/corelib/io/qiodevice.h
+++ b/src/corelib/io/qiodevice.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
diff --git a/src/corelib/io/qiodevice_p.h b/src/corelib/io/qiodevice_p.h
index 3ccad6254a..2515fe5705 100644
--- a/src/corelib/io/qiodevice_p.h
+++ b/src/corelib/io/qiodevice_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
diff --git a/src/corelib/io/qnoncontiguousbytedevice.cpp b/src/corelib/io/qnoncontiguousbytedevice.cpp
index 113ba4b4bb..ba711493c6 100644
--- a/src/corelib/io/qnoncontiguousbytedevice.cpp
+++ b/src/corelib/io/qnoncontiguousbytedevice.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
diff --git a/src/corelib/io/qnoncontiguousbytedevice_p.h b/src/corelib/io/qnoncontiguousbytedevice_p.h
index c7c94243b9..ded605681e 100644
--- a/src/corelib/io/qnoncontiguousbytedevice_p.h
+++ b/src/corelib/io/qnoncontiguousbytedevice_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
diff --git a/src/corelib/io/qprocess.cpp b/src/corelib/io/qprocess.cpp
index d2aee16c45..8f76e0e4b9 100644
--- a/src/corelib/io/qprocess.cpp
+++ b/src/corelib/io/qprocess.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
@@ -471,7 +471,7 @@ void QProcessPrivate::Channel::clear()
read the standard output by calling read(), readLine(), and
getChar(). Because it inherits QIODevice, QProcess can also be
used as an input source for QXmlReader, or for generating data to
- be uploaded using QFtp.
+ be uploaded using QNetworkAccessManager.
\note On Windows CE and Symbian, reading and writing to a process
is not supported.
@@ -617,6 +617,14 @@ void QProcessPrivate::Channel::clear()
writes to its standard output and standard error will be written
to the standard output and standard error of the main process.
+ \note Windows intentionally suppresses output from GUI-only
+ applications to inherited consoles.
+ This does \e not apply to output redirected to files or pipes.
+ To forward the output of GUI-only applications on the console
+ nonetheless, you must use SeparateChannels and do the forwarding
+ yourself by reading the output and writing it to the appropriate
+ output channels.
+
\sa setProcessChannelMode()
*/
@@ -2271,7 +2279,7 @@ QT_END_INCLUDE_NAMESPACE
However, note that repeated calls to this function will recreate the
list of environment variables, which is a non-trivial operation.
- \note For new code, it is recommended to use QProcessEvironment::systemEnvironment()
+ \note For new code, it is recommended to use QProcessEnvironment::systemEnvironment()
\sa QProcessEnvironment::systemEnvironment(), environment(), setEnvironment()
*/
diff --git a/src/corelib/io/qprocess.h b/src/corelib/io/qprocess.h
index b2a5a4cbff..96a1edefd8 100644
--- a/src/corelib/io/qprocess.h
+++ b/src/corelib/io/qprocess.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
diff --git a/src/corelib/io/qprocess_p.h b/src/corelib/io/qprocess_p.h
index 5bebff089e..7e0fecc320 100644
--- a/src/corelib/io/qprocess_p.h
+++ b/src/corelib/io/qprocess_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
diff --git a/src/corelib/io/qprocess_symbian.cpp b/src/corelib/io/qprocess_symbian.cpp
deleted file mode 100644
index 9fd0c3aa65..0000000000
--- a/src/corelib/io/qprocess_symbian.cpp
+++ /dev/null
@@ -1,1072 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 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$
-** GNU Lesser General Public License Usage
-** 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.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU General
-** Public License version 3.0 as published by the Free Software Foundation
-** and appearing in the file LICENSE.GPL included in the packaging of this
-** file. Please review the following information to ensure the GNU General
-** Public License version 3.0 requirements will be met:
-** http://www.gnu.org/copyleft/gpl.html.
-**
-** Other Usage
-** Alternatively, this file may be used in accordance with the terms and
-** conditions contained in a signed written agreement between you and Nokia.
-**
-**
-**
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-//#define QPROCESS_DEBUG
-
-#ifdef QPROCESS_DEBUG
-#include "qdebug.h"
-#define QPROCESS_DEBUG_PRINT(args...) qDebug(args);
-#else
-#define QPROCESS_DEBUG_PRINT(args...)
-#endif
-
-#ifndef QT_NO_PROCESS
-
-#define QPROCESS_ASSERT(check, panicReason, args...) \
- if (!(check)) { \
- qWarning(args); \
- User::Panic(KQProcessPanic, panicReason); \
- }
-
-#include <exception>
-#include <e32base.h>
-#include <e32std.h>
-#include <stdio.h>
-#include "qplatformdefs.h"
-
-#include "qdir.h"
-#include "qstring.h"
-#include "qprocess.h"
-#include "qprocess_p.h"
-#include "private/qeventdispatcher_symbian_p.h"
-
-#include <private/qthread_p.h>
-#include <qmutex.h>
-#include <qmap.h>
-#include <qsocketnotifier.h>
-
-#include <errno.h>
-
-
-QT_BEGIN_NAMESPACE
-
-_LIT(KQProcessManagerThreadName, "QProcManThread");
-_LIT(KQProcessPanic, "QPROCESS");
-enum TQProcessPanic {
- EProcessManagerMediatorRunError = 1,
- EProcessManagerMediatorInactive = 2,
- EProcessManagerMediatorNotPending = 3,
- EProcessManagerMediatorInvalidCmd = 4,
- EProcessManagerMediatorCreationFailed = 5,
- EProcessManagerMediatorThreadOpenFailed = 6,
- EProcessManagerMediatorNullObserver = 7,
- EProcessActiveRunError = 10,
- EProcessActiveNullParameter = 11,
- EProcessManagerMutexCreationFail = 20,
- EProcessManagerThreadCreationFail = 21,
- EProcessManagerSchedulerCreationFail = 22,
- EProcessManagerNullParam = 23
-};
-
-// Forward declarations
-class QProcessManager;
-
-
-// Active object to listen for child process death
-class QProcessActive : public CActive
-{
-public:
- static QProcessActive *construct(QProcess *process,
- RProcess **proc,
- int serial,
- int deathPipe);
-
- virtual ~QProcessActive();
-
- void start();
- void stop();
-
- bool error();
-
-protected:
-
- // Inherited from CActive
- void RunL();
- TInt RunError(TInt aError);
- void DoCancel();
-
- QProcessActive();
-
-private:
-
- QProcess *process;
- RProcess **pproc;
- int serial;
- int deathPipe;
- bool errorValue;
-};
-
-// Active object to communicate synchronously with process manager thread
-class QProcessManagerMediator : public CActive
-{
-public:
- static QProcessManagerMediator *construct();
-
- virtual ~QProcessManagerMediator();
-
- bool add(QProcessActive *processObserver);
- void remove(QProcessActive *processObserver);
- void terminate();
-
-protected:
-
- enum Commands {
- ENoCommand,
- EAdd,
- ERemove,
- ETerminate
- };
-
- // Inherited from CActive
- void RunL();
- TInt RunError(TInt aError);
- void DoCancel();
-
- QProcessManagerMediator();
-
- bool notify(QProcessActive *processObserver, Commands command);
-
-private:
- QProcessActive *currentObserver;
- Commands currentCommand;
-
- RThread processManagerThread;
-};
-
-// Process manager manages child process death listeners.
-//
-// Note: Because QProcess can be used outside event loop, we cannot be guaranteed
-// an active scheduler exists for us to add our process death listener objects.
-// We can't just install active scheduler on the calling thread, as that would block it
-// if we want to actually use it, so a separate manager thread is required.
-class QProcessManager
-{
-public:
- QProcessManager();
- ~QProcessManager();
-
- void startThread();
-
- TInt run(void *param);
- bool add(QProcess *process);
- void remove(QProcess *process);
-
- inline void setMediator(QProcessManagerMediator *newMediator) {
- mediator = newMediator;
- };
-
-private:
- inline void lock() {
- managerMutex.Wait();
- };
- inline void unlock() {
- managerMutex.Signal();
- };
-
- QMap<int, QProcessActive *> children;
- QProcessManagerMediator *mediator;
- RMutex managerMutex;
- bool threadStarted;
- RThread managerThread;
-};
-
-static bool qt_rprocess_running(RProcess *proc)
-{
- if (proc && proc->Handle()) {
- TExitType et = proc->ExitType();
- if (et == EExitPending)
- return true;
- }
-
- return false;
-}
-
-static void qt_create_symbian_commandline(
- const QStringList &arguments, const QString &nativeArguments, QString &commandLine)
-{
- for (int i = 0; i < arguments.size(); ++i) {
- QString tmp = arguments.at(i);
- // in the case of \" already being in the string the \ must also be escaped
- tmp.replace(QLatin1String("\\\""), QLatin1String("\\\\\""));
- // escape a single " because the arguments will be parsed
- tmp.replace(QLatin1String("\""), QLatin1String("\\\""));
- if (tmp.isEmpty() || tmp.contains(QLatin1Char(' ')) || tmp.contains(QLatin1Char('\t'))) {
- // The argument must not end with a \ since this would be interpreted
- // as escaping the quote -- rather put the \ behind the quote: e.g.
- // rather use "foo"\ than "foo\"
- QString endQuote(QLatin1String("\""));
- int i = tmp.length();
- while (i > 0 && tmp.at(i - 1) == QLatin1Char('\\')) {
- --i;
- endQuote += QLatin1String("\\");
- }
- commandLine += QLatin1String("\"") + tmp.left(i) + endQuote + QLatin1Char(' ');
- } else {
- commandLine += tmp + QLatin1Char(' ');
- }
- }
-
- if (!nativeArguments.isEmpty())
- commandLine += nativeArguments;
- else if (!commandLine.isEmpty()) // Chop the extra trailing space if any arguments were appended
- commandLine.chop(1);
-}
-
-static TInt qt_create_symbian_process(RProcess **proc,
- const QString &programName, const QStringList &arguments, const QString &nativeArguments)
-{
- RProcess *newProc = NULL;
- newProc = new RProcess();
-
- if (!newProc)
- return KErrNoMemory;
-
- QString commandLine;
- qt_create_symbian_commandline(arguments, nativeArguments, commandLine);
-
- TPtrC program_ptr(reinterpret_cast<const TText*>(programName.constData()));
- TPtrC cmdline_ptr(reinterpret_cast<const TText*>(commandLine.constData()));
-
- TInt err = newProc->Create(program_ptr, cmdline_ptr);
-
- if (err == KErrNotFound) {
- // Strip path from program name and try again (i.e. try from default location "\sys\bin")
- int index = programName.lastIndexOf(QDir::separator());
- int index2 = programName.lastIndexOf(QChar(QLatin1Char('/')));
- index = qMax(index, index2);
-
- if (index != -1 && programName.length() >= index) {
- QString strippedName;
- strippedName = programName.mid(index + 1);
- QPROCESS_DEBUG_PRINT("qt_create_symbian_process() Executable '%s' not found, trying stripped version '%s'",
- qPrintable(programName), qPrintable(strippedName));
-
- TPtrC stripped_ptr(reinterpret_cast<const TText*>(strippedName.constData()));
- err = newProc->Create(stripped_ptr, cmdline_ptr);
-
- if (err != KErrNone) {
- QPROCESS_DEBUG_PRINT("qt_create_symbian_process() Unable to create process '%s': %d",
- qPrintable(strippedName), err);
- }
- }
- }
-
- if (err == KErrNone)
- *proc = newProc;
- else
- delete newProc;
-
- return err;
-}
-
-static qint64 qt_native_read(int fd, char *data, qint64 maxlen)
-{
- qint64 ret = 0;
- do {
- ret = ::read(fd, data, maxlen);
- } while (ret == -1 && errno == EINTR);
-
- QPROCESS_DEBUG_PRINT("qt_native_read(): fd: %d, result: %d, errno = %d", fd, (int)ret, errno);
-
- return ret;
-}
-
-static qint64 qt_native_write(int fd, const char *data, qint64 len)
-{
- qint64 ret = 0;
- do {
- ret = ::write(fd, data, len);
- } while (ret == -1 && errno == EINTR);
-
- QPROCESS_DEBUG_PRINT("qt_native_write(): fd: %d, result: %d, errno = %d", fd, (int)ret, errno);
-
- return ret;
-}
-
-static void qt_native_close(int fd)
-{
- int ret;
- do {
- ret = ::close(fd);
- } while (ret == -1 && errno == EINTR);
-}
-
-static void qt_create_pipe(int *pipe)
-{
- if (pipe[0] != -1)
- qt_native_close(pipe[0]);
- if (pipe[1] != -1)
- qt_native_close(pipe[1]);
- if (::pipe(pipe) != 0) {
- qWarning("QProcessPrivate::createPipe: Cannot create pipe %p: %s",
- pipe, qPrintable(qt_error_string(errno)));
- } else {
- QPROCESS_DEBUG_PRINT("qt_create_pipe(): Created pipe %d - %d", pipe[0], pipe[1]);
- }
-}
-
-// Called from ProcessManagerThread
-QProcessActive *QProcessActive::construct(QProcess *process,
- RProcess **proc,
- int serial,
- int deathPipe)
-{
- QPROCESS_ASSERT((process || proc || *proc),
- EProcessActiveNullParameter,
- "QProcessActive::construct(): process (0x%x), proc (0x%x) or *proc == NULL, not creating an instance", process, proc)
-
- QProcessActive *newInstance = new QProcessActive();
-
- if (!newInstance) {
- QPROCESS_DEBUG_PRINT("QProcessActive::construct(): Failed to create new instance");
- } else {
- newInstance->process = process;
- newInstance->pproc = proc;
- newInstance->serial = serial;
- newInstance->deathPipe = deathPipe;
- newInstance->errorValue = false;
- }
-
- return newInstance;
-}
-
-// Called from ProcessManagerThread
-QProcessActive::QProcessActive()
- : CActive(CActive::EPriorityStandard)
-{
- // Nothing to do
-}
-
-// Called from main thread
-QProcessActive::~QProcessActive()
-{
- process = NULL;
- pproc = NULL;
-}
-
-// Called from ProcessManagerThread
-void QProcessActive::start()
-{
- if (qt_rprocess_running(*pproc)) {
- CActiveScheduler::Add(this);
- (*pproc)->Logon(iStatus);
- SetActive();
- QPROCESS_DEBUG_PRINT("QProcessActive::start(): Started monitoring for process exit.");
- } else {
- QPROCESS_DEBUG_PRINT("QProcessActive::start(): Process doesn't exist or is already dead");
- // Assume process has already died
- qt_native_write(deathPipe, "", 1);
- errorValue = true;
- }
-}
-
-// Called from ProcessManagerThread
-void QProcessActive::stop()
-{
- QPROCESS_DEBUG_PRINT("QProcessActive::stop()");
-
- // Remove this from scheduler (also cancels the request)
- Deque();
-}
-
-bool QProcessActive::error()
-{
- return errorValue;
-}
-
-// Called from ProcessManagerThread
-void QProcessActive::RunL()
-{
- // If this method gets executed, the monitored process has died
-
- // Notify main thread
- qt_native_write(deathPipe, "", 1);
- QPROCESS_DEBUG_PRINT("QProcessActive::RunL() sending death notice to %d", deathPipe);
-}
-
-// Called from ProcessManagerThread
-TInt QProcessActive::RunError(TInt aError)
-{
- Q_UNUSED(aError);
- // Handle RunL leave (should never happen)
- QPROCESS_ASSERT(0, EProcessActiveRunError, "QProcessActive::RunError(): Should never get here!")
- return 0;
-}
-
-// Called from ProcessManagerThread
-void QProcessActive::DoCancel()
-{
- QPROCESS_DEBUG_PRINT("QProcessActive::DoCancel()");
-
- if (qt_rprocess_running(*pproc)) {
- (*pproc)->LogonCancel(iStatus);
- QPROCESS_DEBUG_PRINT("QProcessActive::DoCancel(): Stopped monitoring for process exit.");
- } else {
- QPROCESS_DEBUG_PRINT("QProcessActive::DoCancel(): Process doesn't exist");
- }
-}
-
-
-// Called from ProcessManagerThread
-QProcessManagerMediator *QProcessManagerMediator::construct()
-{
- QProcessManagerMediator *newInstance = new QProcessManagerMediator;
- TInt err(KErrNone);
-
- newInstance->currentCommand = ENoCommand;
- newInstance->currentObserver = NULL;
-
- if (newInstance) {
- err = newInstance->processManagerThread.Open(newInstance->processManagerThread.Id());
- QPROCESS_ASSERT((err == KErrNone),
- EProcessManagerMediatorThreadOpenFailed,
- "QProcessManagerMediator::construct(): Failed to open processManagerThread (err:%d)", err)
- } else {
- QPROCESS_ASSERT(0,
- EProcessManagerMediatorCreationFailed,
- "QProcessManagerMediator::construct(): Failed to open construct mediator")
- }
-
- // Activate mediator
- CActiveScheduler::Add(newInstance);
- newInstance->iStatus = KRequestPending;
- newInstance->SetActive();
- QPROCESS_DEBUG_PRINT("QProcessManagerMediator::construct(): new instance successfully created and activated");
-
- return newInstance;
-}
-
-// Called from ProcessManagerThread
-QProcessManagerMediator::QProcessManagerMediator()
- : CActive(CActive::EPriorityStandard)
-{
- // Nothing to do
-}
-
-// Called from main thread
-QProcessManagerMediator::~QProcessManagerMediator()
-{
- processManagerThread.Close();
- currentCommand = ENoCommand;
- currentObserver = NULL;
-}
-
-// Called from main thread
-bool QProcessManagerMediator::add(QProcessActive *processObserver)
-{
- QPROCESS_DEBUG_PRINT("QProcessManagerMediator::add()");
- return notify(processObserver, EAdd);
-}
-
-// Called from main thread
-void QProcessManagerMediator::remove(QProcessActive *processObserver)
-{
- QPROCESS_DEBUG_PRINT("QProcessManagerMediator::remove()");
- notify(processObserver, ERemove);
-}
-
-// Called from main thread
-void QProcessManagerMediator::terminate()
-{
- QPROCESS_DEBUG_PRINT("QProcessManagerMediator::terminate()");
- notify(NULL, ETerminate);
-}
-
-// Called from main thread
-bool QProcessManagerMediator::notify(QProcessActive *processObserver, Commands command)
-{
- bool success(true);
-
- QPROCESS_DEBUG_PRINT("QProcessManagerMediator::Notify(): Command: %d, processObserver: 0x%x", command, processObserver);
-
- QPROCESS_ASSERT((command == ETerminate || processObserver),
- EProcessManagerMediatorNullObserver,
- "QProcessManagerMediator::Notify(): NULL processObserver not allowed for command: %d", command)
-
- QPROCESS_ASSERT(IsActive(),
- EProcessManagerMediatorInactive,
- "QProcessManagerMediator::Notify(): Mediator is not active!")
-
- QPROCESS_ASSERT(iStatus == KRequestPending,
- EProcessManagerMediatorNotPending,
- "QProcessManagerMediator::Notify(): Mediator request not pending!")
-
- currentObserver = processObserver;
- currentCommand = command;
-
- // Sync with process manager thread
- TRequestStatus pmStatus;
- processManagerThread.Rendezvous(pmStatus);
-
- // Complete request -> RunL will run in the process manager thread
- TRequestStatus *status = &iStatus;
- processManagerThread.RequestComplete(status, command);
-
- QPROCESS_DEBUG_PRINT("QProcessManagerMediator::Notify(): Waiting process manager to complete...");
- User::WaitForRequest(pmStatus);
- QPROCESS_DEBUG_PRINT("QProcessManagerMediator::Notify(): Wait over");
-
- if (currentObserver) {
- success = !(currentObserver->error());
- QPROCESS_DEBUG_PRINT("QProcessManagerMediator::Notify(): success = %d", success);
- }
-
- currentObserver = NULL;
- currentCommand = ENoCommand;
-
- return success;
-}
-
-// Called from ProcessManagerThread
-void QProcessManagerMediator::RunL()
-{
- QPROCESS_DEBUG_PRINT("QProcessManagerMediator::RunL(): currentCommand: %d, iStatus: %d", currentCommand, iStatus.Int());
- switch (currentCommand) {
- case EAdd:
- currentObserver->start();
- break;
- case ERemove:
- currentObserver->stop();
- break;
- case ETerminate:
- Deque();
- CActiveScheduler::Stop();
- return;
- default:
- QPROCESS_ASSERT(0,
- EProcessManagerMediatorInvalidCmd,
- "QProcessManagerMediator::RunL(): Invalid command!")
- break;
- }
-
- iStatus = KRequestPending;
- SetActive();
-
- // Notify main thread that we are done
- RThread::Rendezvous(KErrNone);
-}
-
-// Called from ProcessManagerThread
-TInt QProcessManagerMediator::RunError(TInt aError)
-{
- Q_UNUSED(aError);
- // Handle RunL leave (should never happen)
- QPROCESS_ASSERT(0,
- EProcessManagerMediatorRunError,
- "QProcessManagerMediator::RunError(): Should never get here!")
- return 0;
-}
-
-// Called from ProcessManagerThread
-void QProcessManagerMediator::DoCancel()
-{
- QPROCESS_DEBUG_PRINT("QProcessManagerMediator::DoCancel()");
- TRequestStatus *status = &iStatus;
- processManagerThread.RequestComplete(status, KErrCancel);
-}
-
-Q_GLOBAL_STATIC(QProcessManager, processManager)
-
-TInt processManagerThreadFunction(TAny *param)
-{
- QPROCESS_ASSERT(param,
- EProcessManagerNullParam,
- "processManagerThreadFunction(): NULL param")
-
- QProcessManager *manager = reinterpret_cast<QProcessManager*>(param);
-
- CActiveScheduler *scheduler = new CQtActiveScheduler();
-
- QPROCESS_ASSERT(scheduler,
- EProcessManagerSchedulerCreationFail,
- "processManagerThreadFunction(): Scheduler creation failed")
-
- CActiveScheduler::Install(scheduler);
-
- //Creating mediator also adds it to scheduler and activates it. Failure will panic.
- manager->setMediator(QProcessManagerMediator::construct());
- RThread::Rendezvous(KErrNone);
-
- CActiveScheduler::Start();
-
- CActiveScheduler::Install(NULL);
- delete scheduler;
-
- return KErrNone;
-}
-
-QProcessManager::QProcessManager()
- : mediator(NULL), threadStarted(false)
-{
- TInt err = managerMutex.CreateLocal();
-
- QPROCESS_ASSERT(err == KErrNone,
- EProcessManagerMutexCreationFail,
- "QProcessManager::QProcessManager(): Failed to create new managerMutex (err: %d)", err)
-}
-
-QProcessManager::~QProcessManager()
-{
- QPROCESS_DEBUG_PRINT("QProcessManager::~QProcessManager()");
-
- // Check if manager thread is still alive. If this destructor is ran as part of global
- // static cleanup, manager thread will most likely be terminated by kernel at this point,
- // so trying to delete QProcessActives and QProcessMediators will panic as they
- // will still be active. They can also no longer be canceled as the thread is already gone.
- // In case manager thread has already died, we simply do nothing and let the deletion of
- // the main heap at process exit take care of stray objects.
-
- if (managerThread.Handle() && managerThread.ExitType() == EExitPending) {
- // Cancel death listening for all child processes
- if (mediator) {
- QMap<int, QProcessActive *>::Iterator it = children.begin();
- while (it != children.end()) {
- // Remove all monitors
- QProcessActive *active = it.value();
- mediator->remove(active);
-
- QPROCESS_DEBUG_PRINT("QProcessManager::~QProcessManager() removed listening for a process");
- ++it;
- }
-
- // Terminate process manager thread.
- mediator->terminate();
- delete mediator;
- }
-
- qDeleteAll(children.values());
- children.clear();
- }
-
- managerThread.Close();
- managerMutex.Close();
-}
-
-void QProcessManager::startThread()
-{
- lock();
-
- if (!threadStarted) {
- TInt err = managerThread.Create(KQProcessManagerThreadName,
- processManagerThreadFunction,
- 0x5000,
- (RAllocator*)NULL,
- (TAny*)this,
- EOwnerProcess);
-
- QPROCESS_ASSERT(err == KErrNone,
- EProcessManagerThreadCreationFail,
- "QProcessManager::startThread(): Failed to create new managerThread (err:%d)", err)
-
- threadStarted = true;
-
- // Manager thread must start running before we continue, so sync with rendezvous
- TRequestStatus status;
- managerThread.Rendezvous(status);
- managerThread.Resume();
- User::WaitForRequest(status);
- }
-
- unlock();
-}
-
-static QBasicAtomicInt idCounter = Q_BASIC_ATOMIC_INITIALIZER(1);
-
-bool QProcessManager::add(QProcess *process)
-{
- QPROCESS_ASSERT(process,
- EProcessManagerNullParam,
- "QProcessManager::add(): Failed to add QProcessActive to ProcessManager - NULL process")
-
- lock();
-
- int serial = idCounter.fetchAndAddRelaxed(1);
- process->d_func()->serial = serial;
-
- QPROCESS_DEBUG_PRINT("QProcessManager::add(): serial: %d, deathPipe: %d - %d, symbianProcess: 0x%x", serial, process->d_func()->deathPipe[0], process->d_func()->deathPipe[1], process->d_func()->symbianProcess);
-
- QProcessActive *newActive =
- QProcessActive::construct(process,
- &(process->d_func()->symbianProcess),
- serial,
- process->d_func()->deathPipe[1]);
-
- if (newActive) {
- if (mediator->add(newActive)) {
- children.insert(serial, newActive);
- unlock();
- return true;
- } else {
- QPROCESS_DEBUG_PRINT("QProcessManager::add(): Failed to add QProcessActive to ProcessManager");
- delete newActive;
- }
- }
-
- unlock();
-
- return false;
-}
-
-void QProcessManager::remove(QProcess *process)
-{
- QPROCESS_ASSERT(process,
- EProcessManagerNullParam,
- "QProcessManager::remove(): Failed to remove QProcessActive from ProcessManager - NULL process")
-
- lock();
-
- int serial = process->d_func()->serial;
- QProcessActive *active = children.value(serial);
- if (!active) {
- unlock();
- return;
- }
-
- mediator->remove(active);
-
- children.remove(serial);
- delete active;
-
- unlock();
-}
-
-void QProcessPrivate::destroyPipe(int *pipe)
-{
- if (pipe[1] != -1) {
- qt_native_close(pipe[1]);
- pipe[1] = -1;
- }
- if (pipe[0] != -1) {
- qt_native_close(pipe[0]);
- pipe[0] = -1;
- }
-}
-
-bool QProcessPrivate::createChannel(Channel &channel)
-{
- Q_UNUSED(channel);
- // No channels used
- return false;
-}
-
-void QProcessPrivate::startProcess()
-{
- Q_Q(QProcess);
-
- QPROCESS_DEBUG_PRINT("QProcessPrivate::startProcess()");
-
- // Start the process (platform dependent)
- q->setProcessState(QProcess::Starting);
-
- processManager()->startThread();
-
- qt_create_pipe(deathPipe);
- if (threadData->eventDispatcher) {
- deathNotifier = new QSocketNotifier(deathPipe[0],
- QSocketNotifier::Read, q);
- QObject::connect(deathNotifier, SIGNAL(activated(int)),
- q, SLOT(_q_processDied()));
- }
-
- TInt err = qt_create_symbian_process(&symbianProcess, program, arguments, nativeArguments);
-
- if (err == KErrNone) {
- pid = symbianProcess->Id().Id();
-
- ::fcntl(deathPipe[0], F_SETFL, ::fcntl(deathPipe[0], F_GETFL) | O_NONBLOCK);
-
- if (!processManager()->add(q)) {
- qWarning("QProcessPrivate::startProcess(): Failed to start monitoring for process death.");
- err = KErrNoMemory;
- }
- }
-
- if (err != KErrNone) {
- // Cleanup, report error and return
- QPROCESS_DEBUG_PRINT("QProcessPrivate::startProcess() Process open failed, err: %d, '%s'", err, qPrintable(program));
- q->setProcessState(QProcess::NotRunning);
- processError = QProcess::FailedToStart;
- q->setErrorString(QLatin1String(QT_TRANSLATE_NOOP(QProcess, "Resource error (qt_create_symbian_process failure)")));
- emit q->error(processError);
- cleanup();
- return;
- }
-
- processLaunched = true;
-
- symbianProcess->Resume();
-
- QPROCESS_DEBUG_PRINT("QProcessPrivate::startProcess(): this: 0x%x, pid: %ld", this, pid);
-
- // Notify child start
- _q_startupNotification();
-
-}
-
-bool QProcessPrivate::processStarted()
-{
- QPROCESS_DEBUG_PRINT("QProcessPrivate::processStarted() == %s", processLaunched ? "true" : "false");
-
- // Since we cannot get information whether process has actually been launched
- // or not in Symbian, we need to fake it. Assume process is started if launch was
- // successful.
-
- return processLaunched;
-}
-
-qint64 QProcessPrivate::bytesAvailableFromStdout() const
-{
- // In Symbian, stdout is not supported
- return 0;
-}
-
-qint64 QProcessPrivate::bytesAvailableFromStderr() const
-{
- // In Symbian, stderr is not supported
- return 0;
-}
-
-qint64 QProcessPrivate::readFromStdout(char *data, qint64 maxlen)
-{
- Q_UNUSED(data);
- Q_UNUSED(maxlen);
- // In Symbian, stdout is not supported
- return 0;
-}
-
-qint64 QProcessPrivate::readFromStderr(char *data, qint64 maxlen)
-{
- Q_UNUSED(data);
- Q_UNUSED(maxlen);
- // In Symbian, stderr is not supported
- return 0;
-}
-
-qint64 QProcessPrivate::writeToStdin(const char *data, qint64 maxlen)
-{
- Q_UNUSED(data);
- Q_UNUSED(maxlen);
- // In Symbian, stdin is not supported
- return 0;
-}
-
-void QProcessPrivate::terminateProcess()
-{
- // Needs PowerMgmt capability if process has been started; will panic kern-exec 46 otherwise.
- // Always works if process is not yet started.
- if (qt_rprocess_running(symbianProcess)) {
- symbianProcess->Terminate(0);
- } else {
- QPROCESS_DEBUG_PRINT("QProcessPrivate::terminateProcess(), Process not running");
- }
-}
-
-void QProcessPrivate::killProcess()
-{
- // Needs PowerMgmt capability if process has been started; will panic kern-exec 46 otherwise.
- // Always works if process is not yet started.
- if (qt_rprocess_running(symbianProcess)) {
- symbianProcess->Kill(0);
- } else {
- QPROCESS_DEBUG_PRINT("QProcessPrivate::killProcess(), Process not running");
- }
-}
-
-bool QProcessPrivate::waitForStarted(int msecs)
-{
- Q_UNUSED(msecs);
- // Since we can get no actual feedback from process beyond its death,
- // assume that started has already been emitted if process has been launched
- return processLaunched;
-}
-
-bool QProcessPrivate::waitForReadyRead(int msecs)
-{
- // Functionality not supported in Symbian
- Q_UNUSED(msecs);
- return false;
-}
-
-bool QProcessPrivate::waitForBytesWritten(int msecs)
-{
- // Functionality not supported in Symbian
- Q_UNUSED(msecs);
- return false;
-}
-
-bool QProcessPrivate::waitForFinished(int msecs)
-{
- Q_Q(QProcess);
- QPROCESS_DEBUG_PRINT("QProcessPrivate::waitForFinished(%d)", msecs);
-
- TRequestStatus timerStatus = KErrNone;
- TRequestStatus logonStatus = KErrNone;
- bool timeoutOccurred = false;
-
- // Logon to process to observe its death
- if (qt_rprocess_running(symbianProcess)) {
- symbianProcess->Logon(logonStatus);
-
- if (msecs < 0) {
- // If timeout is negative, there is no timeout
- QPROCESS_DEBUG_PRINT("QProcessPrivate::waitForFinished() - Waiting (just logon)...");
- User::WaitForRequest(logonStatus);
- QPROCESS_DEBUG_PRINT("QProcessPrivate::waitForFinished() - Wait completed");
- } else {
- // Create timer
- RTimer timer;
- timer.CreateLocal();
- TTimeIntervalMicroSeconds32 interval(msecs*1000);
- timer.After(timerStatus, interval);
-
- QPROCESS_DEBUG_PRINT("QProcessPrivate::waitForFinished() - Waiting (logon + timer)...");
- User::WaitForRequest(logonStatus, timerStatus);
- QPROCESS_DEBUG_PRINT("QProcessPrivate::waitForFinished() - Wait completed");
-
- if (logonStatus != KRequestPending) {
- timer.Cancel();
- User::WaitForRequest(timerStatus);
- } else {
- timeoutOccurred = true;
- symbianProcess->LogonCancel(logonStatus);
- User::WaitForRequest(logonStatus);
- }
- timer.Close();
- }
- } else {
- QPROCESS_DEBUG_PRINT("QProcessPrivate::waitForFinished(), qt_rprocess_running returned false");
- }
-
- if (timeoutOccurred) {
- processError = QProcess::Timedout;
- q->setErrorString(QLatin1String(QT_TRANSLATE_NOOP(QProcess, "Process operation timed out")));
- return false;
- }
-
- _q_processDied();
-
- return true;
-}
-
-bool QProcessPrivate::waitForWrite(int msecs)
-{
- // Functionality not supported in Symbian
- Q_UNUSED(msecs);
- return false;
-}
-
-// Deceptively named function. Exit code is actually got in waitForDeadChild().
-void QProcessPrivate::findExitCode()
-{
- Q_Q(QProcess);
- processManager()->remove(q);
-}
-
-bool QProcessPrivate::waitForDeadChild()
-{
- Q_Q(QProcess);
-
- // read a byte from the death pipe
- char c;
- qt_native_read(deathPipe[0], &c, 1);
-
- if (symbianProcess && symbianProcess->Handle()) {
- TExitType et = symbianProcess->ExitType();
- QPROCESS_DEBUG_PRINT("QProcessPrivate::waitForDeadChild() symbianProcess->ExitType: %d", et);
- if (et != EExitPending) {
- processManager()->remove(q);
- exitCode = symbianProcess->ExitReason();
- crashed = (et == EExitPanic);
-#if defined QPROCESS_DEBUG
- TExitCategoryName catName = symbianProcess->ExitCategory();
- qDebug() << "QProcessPrivate::waitForDeadChild() dead with exitCode"
- << exitCode << ", crashed:" << crashed
- << ", category:" << QString((const QChar *)catName.Ptr());
-#endif
- } else {
- QPROCESS_DEBUG_PRINT("QProcessPrivate::waitForDeadChild() not dead!");
- }
- }
-
- return true;
-}
-
-void QProcessPrivate::_q_notified()
-{
- // Nothing to do in Symbian
-}
-
-bool QProcessPrivate::startDetached(const QString &program, const QStringList &arguments, const QString &workingDirectory, qint64 *pid)
-{
- QPROCESS_DEBUG_PRINT("QProcessPrivate::startDetached()");
- Q_UNUSED(workingDirectory);
-
- RProcess *newProc = NULL;
-
- TInt err = qt_create_symbian_process(&newProc, program, arguments, QString());
-
- if (err == KErrNone) {
- if (pid)
- *pid = newProc->Id().Id();
-
- newProc->Resume();
- newProc->Close();
- delete newProc;
- return true;
- }
-
- return false;
-}
-
-
-void QProcessPrivate::initializeProcessManager()
-{
- (void) processManager();
-}
-
-QProcessEnvironment QProcessEnvironment::systemEnvironment()
-{
- return QProcessEnvironment();
-}
-
-QT_END_NAMESPACE
-
-#endif // QT_NO_PROCESS
diff --git a/src/corelib/io/qprocess_unix.cpp b/src/corelib/io/qprocess_unix.cpp
index 5fc69ed2cd..f01df3c078 100644
--- a/src/corelib/io/qprocess_unix.cpp
+++ b/src/corelib/io/qprocess_unix.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
diff --git a/src/corelib/io/qprocess_win.cpp b/src/corelib/io/qprocess_win.cpp
index d47e55dee4..8c6444d173 100644
--- a/src/corelib/io/qprocess_win.cpp
+++ b/src/corelib/io/qprocess_win.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
@@ -72,7 +72,6 @@ static void qt_create_pipe(Q_PIPE *pipe, bool in)
// read handles to avoid non-closable handles (this is done by the
// DuplicateHandle() call).
-#if !defined(Q_OS_WINCE)
SECURITY_ATTRIBUTES secAtt = { sizeof( SECURITY_ATTRIBUTES ), NULL, TRUE };
HANDLE tmpHandle;
@@ -91,10 +90,15 @@ static void qt_create_pipe(Q_PIPE *pipe, bool in)
}
CloseHandle(tmpHandle);
-#else
- Q_UNUSED(pipe);
- Q_UNUSED(in);
-#endif
+}
+
+static void duplicateStdWriteChannel(Q_PIPE *pipe, DWORD nStdHandle)
+{
+ pipe[0] = INVALID_Q_PIPE;
+ HANDLE hStdWriteChannel = GetStdHandle(nStdHandle);
+ HANDLE hCurrentProcess = GetCurrentProcess();
+ DuplicateHandle(hCurrentProcess, hStdWriteChannel, hCurrentProcess,
+ &pipe[1], 0, TRUE, DUPLICATE_SAME_ACCESS);
}
/*
@@ -113,8 +117,11 @@ bool QProcessPrivate::createChannel(Channel &channel)
if (channel.type == Channel::Normal) {
// we're piping this channel to our own process
- qt_create_pipe(channel.pipe, &channel == &stdinChannel);
-
+ const bool isStdInChannel = (&channel == &stdinChannel);
+ if (isStdInChannel || processChannelMode != QProcess::ForwardedChannels)
+ qt_create_pipe(channel.pipe, isStdInChannel);
+ else
+ duplicateStdWriteChannel(channel.pipe, (&channel == &stdoutChannel) ? STD_OUTPUT_HANDLE : STD_ERROR_HANDLE);
return true;
} else if (channel.type == Channel::Redirect) {
// we're redirecting the channel to/from a file
@@ -277,7 +284,6 @@ static QString qt_create_commandline(const QString &program, const QStringList &
QProcessEnvironment QProcessEnvironment::systemEnvironment()
{
QProcessEnvironment env;
-#if !defined(Q_OS_WINCE)
// Calls to setenv() affect the low-level environment as well.
// This is not the case the other way round.
if (wchar_t *envStrings = GetEnvironmentStringsW()) {
@@ -293,11 +299,9 @@ QProcessEnvironment QProcessEnvironment::systemEnvironment()
}
FreeEnvironmentStringsW(envStrings);
}
-#endif
return env;
}
-#if !defined(Q_OS_WINCE)
static QByteArray qt_create_environment(const QProcessEnvironmentPrivate::Hash &environment)
{
QByteArray envlist;
@@ -357,7 +361,6 @@ static QByteArray qt_create_environment(const QProcessEnvironmentPrivate::Hash &
}
return envlist;
}
-#endif
void QProcessPrivate::startProcess()
{
@@ -381,14 +384,10 @@ void QProcessPrivate::startProcess()
!createChannel(stderrChannel))
return;
-#if defined(Q_OS_WINCE)
- QString args = qt_create_commandline(QString(), arguments);
-#else
QString args = qt_create_commandline(program, arguments);
QByteArray envlist;
if (environment.d.constData())
envlist = qt_create_environment(environment.d.constData()->hash);
-#endif
if (!nativeArguments.isEmpty()) {
if (!args.isEmpty())
args += QLatin1Char(' ');
@@ -402,15 +401,6 @@ void QProcessPrivate::startProcess()
qDebug(" pass environment : %s", environment.isEmpty() ? "no" : "yes");
#endif
-#if defined(Q_OS_WINCE)
- QString fullPathProgram = program;
- if (!QDir::isAbsolutePath(fullPathProgram))
- fullPathProgram = QFileInfo(fullPathProgram).absoluteFilePath();
- fullPathProgram.replace(QLatin1Char('/'), QLatin1Char('\\'));
- success = CreateProcess((wchar_t*)fullPathProgram.utf16(),
- (wchar_t*)args.utf16(),
- 0, 0, false, 0, 0, 0, 0, pid);
-#else
DWORD dwCreationFlags = CREATE_NO_WINDOW;
dwCreationFlags |= CREATE_UNICODE_ENVIRONMENT;
STARTUPINFOW startupInfo = { sizeof( STARTUPINFO ), 0, 0, 0,
@@ -443,7 +433,6 @@ void QProcessPrivate::startProcess()
CloseHandle(stderrChannel.pipe[1]);
stderrChannel.pipe[1] = INVALID_Q_PIPE;
}
-#endif // Q_OS_WINCE
if (!success) {
cleanup();
@@ -484,24 +473,10 @@ qint64 QProcessPrivate::bytesAvailableFromStdout() const
return 0;
DWORD bytesAvail = 0;
-#if !defined(Q_OS_WINCE)
PeekNamedPipe(stdoutChannel.pipe[0], 0, 0, 0, &bytesAvail, 0);
#if defined QPROCESS_DEBUG
qDebug("QProcessPrivate::bytesAvailableFromStdout() == %d", bytesAvail);
#endif
- if (processChannelMode == QProcess::ForwardedChannels && bytesAvail > 0) {
- QByteArray buf(bytesAvail, 0);
- DWORD bytesRead = 0;
- if (ReadFile(stdoutChannel.pipe[0], buf.data(), buf.size(), &bytesRead, 0) && bytesRead > 0) {
- HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
- if (hStdout) {
- DWORD bytesWritten = 0;
- WriteFile(hStdout, buf.data(), bytesRead, &bytesWritten, 0);
- }
- }
- bytesAvail = 0;
- }
-#endif
return bytesAvail;
}
@@ -511,24 +486,10 @@ qint64 QProcessPrivate::bytesAvailableFromStderr() const
return 0;
DWORD bytesAvail = 0;
-#if !defined(Q_OS_WINCE)
PeekNamedPipe(stderrChannel.pipe[0], 0, 0, 0, &bytesAvail, 0);
#if defined QPROCESS_DEBUG
qDebug("QProcessPrivate::bytesAvailableFromStderr() == %d", bytesAvail);
#endif
- if (processChannelMode == QProcess::ForwardedChannels && bytesAvail > 0) {
- QByteArray buf(bytesAvail, 0);
- DWORD bytesRead = 0;
- if (ReadFile(stderrChannel.pipe[0], buf.data(), buf.size(), &bytesRead, 0) && bytesRead > 0) {
- HANDLE hStderr = GetStdHandle(STD_ERROR_HANDLE);
- if (hStderr) {
- DWORD bytesWritten = 0;
- WriteFile(hStderr, buf.data(), bytesRead, &bytesWritten, 0);
- }
- }
- bytesAvail = 0;
- }
-#endif
return bytesAvail;
}
@@ -596,13 +557,6 @@ bool QProcessPrivate::waitForReadyRead(int msecs)
{
Q_Q(QProcess);
-#if defined(Q_OS_WINCE)
- processError = QProcess::ReadError;
- q->setErrorString(QProcess::tr("Error reading from process"));
- emit q->error(processError);
- return false;
-#endif
-
QIncrementalSleepTimer timer(msecs);
forever {
@@ -646,13 +600,6 @@ bool QProcessPrivate::waitForBytesWritten(int msecs)
{
Q_Q(QProcess);
-#if defined(Q_OS_WINCE)
- processError = QProcess::ReadError;
- q->setErrorString(QProcess::tr("Error reading from process"));
- emit q->error(processError);
- return false;
-#endif
-
QIncrementalSleepTimer timer(msecs);
forever {
@@ -786,13 +733,6 @@ qint64 QProcessPrivate::writeToStdin(const char *data, qint64 maxlen)
{
Q_Q(QProcess);
-#if defined(Q_OS_WINCE)
- processError = QProcess::WriteError;
- q->setErrorString(QProcess::tr("Error writing to process"));
- emit q->error(processError);
- return -1;
-#endif
-
if (!pipeWriter) {
pipeWriter = new QWindowsPipeWriter(stdinChannel.pipe[1], q);
pipeWriter->start();
@@ -832,36 +772,19 @@ void QProcessPrivate::_q_notified()
bool QProcessPrivate::startDetached(const QString &program, const QStringList &arguments, const QString &workingDir, qint64 *pid)
{
-#if defined(Q_OS_WINCE)
- Q_UNUSED(workingDir);
- QString args = qt_create_commandline(QString(), arguments);
-#else
QString args = qt_create_commandline(program, arguments);
-#endif
-
bool success = false;
-
PROCESS_INFORMATION pinfo;
-#if defined(Q_OS_WINCE)
- QString fullPathProgram = program;
- if (!QDir::isAbsolutePath(fullPathProgram))
- fullPathProgram.prepend(QDir::currentPath().append(QLatin1Char('/')));
- fullPathProgram.replace(QLatin1Char('/'), QLatin1Char('\\'));
- success = CreateProcess((wchar_t*)fullPathProgram.utf16(),
- (wchar_t*)args.utf16(),
- 0, 0, false, CREATE_NEW_CONSOLE, 0, 0, 0, &pinfo);
-#else
- STARTUPINFOW startupInfo = { sizeof( STARTUPINFO ), 0, 0, 0,
- (ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT,
- (ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
- };
- success = CreateProcess(0, (wchar_t*)args.utf16(),
- 0, 0, FALSE, CREATE_UNICODE_ENVIRONMENT | CREATE_NEW_CONSOLE, 0,
- workingDir.isEmpty() ? 0 : (wchar_t*)workingDir.utf16(),
- &startupInfo, &pinfo);
-#endif // Q_OS_WINCE
+ STARTUPINFOW startupInfo = { sizeof( STARTUPINFO ), 0, 0, 0,
+ (ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT,
+ (ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ };
+ success = CreateProcess(0, (wchar_t*)args.utf16(),
+ 0, 0, FALSE, CREATE_UNICODE_ENVIRONMENT | CREATE_NEW_CONSOLE, 0,
+ workingDir.isEmpty() ? 0 : (wchar_t*)workingDir.utf16(),
+ &startupInfo, &pinfo);
if (success) {
CloseHandle(pinfo.hThread);
diff --git a/src/corelib/io/qprocess_wince.cpp b/src/corelib/io/qprocess_wince.cpp
new file mode 100644
index 0000000000..16a34469e7
--- /dev/null
+++ b/src/corelib/io/qprocess_wince.cpp
@@ -0,0 +1,330 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 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$
+** GNU Lesser General Public License Usage
+** 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.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qprocess.h"
+#include "qprocess_p.h"
+
+#include <qdir.h>
+#include <qfileinfo.h>
+#include <qregexp.h>
+#include <qtimer.h>
+#include <qwineventnotifier.h>
+#include <qdebug.h>
+
+#ifndef QT_NO_PROCESS
+
+QT_BEGIN_NAMESPACE
+
+//#define QPROCESS_DEBUG
+
+void QProcessPrivate::destroyPipe(Q_PIPE pipe[2])
+{
+ Q_UNUSED(pipe);
+}
+
+static QString qt_create_commandline(const QString &program, const QStringList &arguments)
+{
+ QString args;
+ if (!program.isEmpty()) {
+ QString programName = program;
+ if (!programName.startsWith(QLatin1Char('\"')) && !programName.endsWith(QLatin1Char('\"')) && programName.contains(QLatin1Char(' ')))
+ programName = QLatin1Char('\"') + programName + QLatin1Char('\"');
+ programName.replace(QLatin1Char('/'), QLatin1Char('\\'));
+
+ // add the prgram as the first arg ... it works better
+ args = programName + QLatin1Char(' ');
+ }
+
+ for (int i=0; i<arguments.size(); ++i) {
+ QString tmp = arguments.at(i);
+ // Quotes are escaped and their preceding backslashes are doubled.
+ tmp.replace(QRegExp(QLatin1String("(\\\\*)\"")), QLatin1String("\\1\\1\\\""));
+ if (tmp.isEmpty() || tmp.contains(QLatin1Char(' ')) || tmp.contains(QLatin1Char('\t'))) {
+ // The argument must not end with a \ since this would be interpreted
+ // as escaping the quote -- rather put the \ behind the quote: e.g.
+ // rather use "foo"\ than "foo\"
+ int i = tmp.length();
+ while (i > 0 && tmp.at(i - 1) == QLatin1Char('\\'))
+ --i;
+ tmp.insert(i, QLatin1Char('"'));
+ tmp.prepend(QLatin1Char('"'));
+ }
+ args += QLatin1Char(' ') + tmp;
+ }
+ return args;
+}
+
+QProcessEnvironment QProcessEnvironment::systemEnvironment()
+{
+ QProcessEnvironment env;
+ return env;
+}
+
+void QProcessPrivate::startProcess()
+{
+ Q_Q(QProcess);
+
+ bool success = false;
+
+ if (pid) {
+ CloseHandle(pid->hThread);
+ CloseHandle(pid->hProcess);
+ delete pid;
+ pid = 0;
+ }
+ pid = new PROCESS_INFORMATION;
+ memset(pid, 0, sizeof(PROCESS_INFORMATION));
+
+ q->setProcessState(QProcess::Starting);
+
+ QString args = qt_create_commandline(QString(), arguments);
+ if (!nativeArguments.isEmpty()) {
+ if (!args.isEmpty())
+ args += QLatin1Char(' ');
+ args += nativeArguments;
+ }
+
+#if defined QPROCESS_DEBUG
+ qDebug("Creating process");
+ qDebug(" program : [%s]", program.toLatin1().constData());
+ qDebug(" args : %s", args.toLatin1().constData());
+ qDebug(" pass environment : %s", environment.isEmpty() ? "no" : "yes");
+#endif
+
+ QString fullPathProgram = program;
+ if (!QDir::isAbsolutePath(fullPathProgram))
+ fullPathProgram = QFileInfo(fullPathProgram).absoluteFilePath();
+ fullPathProgram.replace(QLatin1Char('/'), QLatin1Char('\\'));
+ success = CreateProcess((wchar_t*)fullPathProgram.utf16(),
+ (wchar_t*)args.utf16(),
+ 0, 0, false, 0, 0, 0, 0, pid);
+
+ if (!success) {
+ cleanup();
+ processError = QProcess::FailedToStart;
+ emit q->error(processError);
+ q->setProcessState(QProcess::NotRunning);
+ return;
+ }
+
+ q->setProcessState(QProcess::Running);
+ // User can call kill()/terminate() from the stateChanged() slot
+ // so check before proceeding
+ if (!pid)
+ return;
+
+ if (threadData->eventDispatcher) {
+ processFinishedNotifier = new QWinEventNotifier(pid->hProcess, q);
+ QObject::connect(processFinishedNotifier, SIGNAL(activated(HANDLE)), q, SLOT(_q_processDied()));
+ processFinishedNotifier->setEnabled(true);
+ }
+
+ // give the process a chance to start ...
+ Sleep(SLEEPMIN * 2);
+ _q_startupNotification();
+}
+
+bool QProcessPrivate::processStarted()
+{
+ return processState == QProcess::Running;
+}
+
+qint64 QProcessPrivate::bytesAvailableFromStdout() const
+{
+ return 0;
+}
+
+qint64 QProcessPrivate::bytesAvailableFromStderr() const
+{
+ return 0;
+}
+
+qint64 QProcessPrivate::readFromStdout(char *data, qint64 maxlen)
+{
+ return -1;
+}
+
+qint64 QProcessPrivate::readFromStderr(char *data, qint64 maxlen)
+{
+ return -1;
+}
+
+static BOOL QT_WIN_CALLBACK qt_terminateApp(HWND hwnd, LPARAM procId)
+{
+ DWORD currentProcId = 0;
+ GetWindowThreadProcessId(hwnd, &currentProcId);
+ if (currentProcId == (DWORD)procId)
+ PostMessage(hwnd, WM_CLOSE, 0, 0);
+
+ return TRUE;
+}
+
+void QProcessPrivate::terminateProcess()
+{
+ if (pid) {
+ EnumWindows(qt_terminateApp, (LPARAM)pid->dwProcessId);
+ PostThreadMessage(pid->dwThreadId, WM_CLOSE, 0, 0);
+ }
+}
+
+void QProcessPrivate::killProcess()
+{
+ if (pid)
+ TerminateProcess(pid->hProcess, 0xf291);
+}
+
+bool QProcessPrivate::waitForStarted(int)
+{
+ Q_Q(QProcess);
+
+ if (processStarted())
+ return true;
+
+ if (processError == QProcess::FailedToStart)
+ return false;
+
+ processError = QProcess::Timedout;
+ q->setErrorString(QProcess::tr("Process operation timed out"));
+ return false;
+}
+
+bool QProcessPrivate::waitForReadyRead(int msecs)
+{
+ return false;
+}
+
+bool QProcessPrivate::waitForBytesWritten(int msecs)
+{
+ return false;
+}
+
+bool QProcessPrivate::waitForFinished(int msecs)
+{
+ Q_Q(QProcess);
+#if defined QPROCESS_DEBUG
+ qDebug("QProcessPrivate::waitForFinished(%d)", msecs);
+#endif
+
+ QIncrementalSleepTimer timer(msecs);
+
+ forever {
+ if (!pid)
+ return true;
+
+ if (WaitForSingleObject(pid->hProcess, timer.nextSleepTime()) == WAIT_OBJECT_0) {
+ _q_processDied();
+ return true;
+ }
+
+ if (timer.hasTimedOut())
+ break;
+ }
+ processError = QProcess::Timedout;
+ q->setErrorString(QProcess::tr("Process operation timed out"));
+ return false;
+}
+
+void QProcessPrivate::findExitCode()
+{
+ DWORD theExitCode;
+ if (GetExitCodeProcess(pid->hProcess, &theExitCode)) {
+ exitCode = theExitCode;
+ //### for now we assume a crash if exit code is less than -1 or the magic number
+ crashed = (exitCode == 0xf291 || (int)exitCode < 0);
+ }
+}
+
+void QProcessPrivate::flushPipeWriter()
+{
+}
+
+qint64 QProcessPrivate::pipeWriterBytesToWrite() const
+{
+ return 0;
+}
+
+qint64 QProcessPrivate::writeToStdin(const char *data, qint64 maxlen)
+{
+ Q_UNUSED(data);
+ Q_UNUSED(maxlen);
+ return -1;
+}
+
+bool QProcessPrivate::waitForWrite(int msecs)
+{
+ Q_UNUSED(msecs);
+ return false;
+}
+
+void QProcessPrivate::_q_notified()
+{
+}
+
+bool QProcessPrivate::startDetached(const QString &program, const QStringList &arguments, const QString &workingDir, qint64 *pid)
+{
+ Q_UNUSED(workingDir);
+ QString args = qt_create_commandline(QString(), arguments);
+
+ bool success = false;
+
+ PROCESS_INFORMATION pinfo;
+
+ QString fullPathProgram = program;
+ if (!QDir::isAbsolutePath(fullPathProgram))
+ fullPathProgram.prepend(QDir::currentPath().append(QLatin1Char('/')));
+ fullPathProgram.replace(QLatin1Char('/'), QLatin1Char('\\'));
+ success = CreateProcess((wchar_t*)fullPathProgram.utf16(),
+ (wchar_t*)args.utf16(),
+ 0, 0, false, CREATE_NEW_CONSOLE, 0, 0, 0, &pinfo);
+
+ if (success) {
+ CloseHandle(pinfo.hThread);
+ CloseHandle(pinfo.hProcess);
+ if (pid)
+ *pid = pinfo.dwProcessId;
+ }
+
+ return success;
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_PROCESS
diff --git a/src/corelib/io/qresource.cpp b/src/corelib/io/qresource.cpp
index 6ad15788b0..0ae3f9e647 100644
--- a/src/corelib/io/qresource.cpp
+++ b/src/corelib/io/qresource.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
@@ -1491,6 +1491,4 @@ bool QResourceFileEnginePrivate::unmap(uchar *ptr)
return true;
}
-Q_CORE_EXPORT void qInitResourceIO() { } // ### Qt 5: remove
-
QT_END_NAMESPACE
diff --git a/src/corelib/io/qresource.h b/src/corelib/io/qresource.h
index 1edc7a4f13..452e141e41 100644
--- a/src/corelib/io/qresource.h
+++ b/src/corelib/io/qresource.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
diff --git a/src/corelib/io/qresource_iterator.cpp b/src/corelib/io/qresource_iterator.cpp
index e19bad1e03..3317ef5fff 100644
--- a/src/corelib/io/qresource_iterator.cpp
+++ b/src/corelib/io/qresource_iterator.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
diff --git a/src/corelib/io/qresource_iterator_p.h b/src/corelib/io/qresource_iterator_p.h
index 519f46199c..3603c64819 100644
--- a/src/corelib/io/qresource_iterator_p.h
+++ b/src/corelib/io/qresource_iterator_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
diff --git a/src/corelib/io/qresource_p.h b/src/corelib/io/qresource_p.h
index 4beda142ed..f558319dc2 100644
--- a/src/corelib/io/qresource_p.h
+++ b/src/corelib/io/qresource_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
diff --git a/src/corelib/io/qsettings.cpp b/src/corelib/io/qsettings.cpp
index 37bd8c460d..81dc5bb078 100644
--- a/src/corelib/io/qsettings.cpp
+++ b/src/corelib/io/qsettings.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
diff --git a/src/corelib/io/qsettings.h b/src/corelib/io/qsettings.h
index b144a9af4c..65aeb89523 100644
--- a/src/corelib/io/qsettings.h
+++ b/src/corelib/io/qsettings.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
diff --git a/src/corelib/io/qsettings_mac.cpp b/src/corelib/io/qsettings_mac.cpp
index 11e0c3c103..6bb815c561 100644
--- a/src/corelib/io/qsettings_mac.cpp
+++ b/src/corelib/io/qsettings_mac.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
diff --git a/src/corelib/io/qsettings_p.h b/src/corelib/io/qsettings_p.h
index 5d62c839a6..cf348122dc 100644
--- a/src/corelib/io/qsettings_p.h
+++ b/src/corelib/io/qsettings_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
diff --git a/src/corelib/io/qsettings_win.cpp b/src/corelib/io/qsettings_win.cpp
index bbc7dd1677..2cac379ec6 100644
--- a/src/corelib/io/qsettings_win.cpp
+++ b/src/corelib/io/qsettings_win.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
diff --git a/src/corelib/io/qstandardpaths.cpp b/src/corelib/io/qstandardpaths.cpp
index 43ae5c07ab..5accb61cc5 100644
--- a/src/corelib/io/qstandardpaths.cpp
+++ b/src/corelib/io/qstandardpaths.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
@@ -83,6 +83,8 @@ QT_BEGIN_NAMESPACE
returned for GenericDataLocation.
\value CacheLocation Returns a directory location where user-specific
non-essential (cached) data should be written.
+ \value GenericCacheLocation Returns a directory location where user-specific
+ non-essential (cached) data, shared across applications, should be written.
\value GenericDataLocation Returns a directory location where persistent
data shared across applications can be stored.
\value RuntimeLocation Returns a directory location where runtime communication
diff --git a/src/corelib/io/qstandardpaths.h b/src/corelib/io/qstandardpaths.h
index d91da9de2f..bae7b3f7b5 100644
--- a/src/corelib/io/qstandardpaths.h
+++ b/src/corelib/io/qstandardpaths.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
@@ -73,7 +73,8 @@ public:
GenericDataLocation,
RuntimeLocation,
ConfigLocation,
- DownloadLocation
+ DownloadLocation,
+ GenericCacheLocation
};
static QString writableLocation(StandardLocation type);
diff --git a/src/corelib/io/qstandardpaths_mac.cpp b/src/corelib/io/qstandardpaths_mac.cpp
index 84fc81494c..f37c21ed39 100644
--- a/src/corelib/io/qstandardpaths_mac.cpp
+++ b/src/corelib/io/qstandardpaths_mac.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
@@ -82,6 +82,7 @@ OSType translateLocation(QStandardPaths::StandardLocation type)
case QStandardPaths::RuntimeLocation:
case QStandardPaths::DataLocation:
return kApplicationSupportFolderType;
+ case QStandardPaths::GenericCacheLocation:
case QStandardPaths::CacheLocation:
return kCachedDataFolderType;
default:
@@ -128,6 +129,7 @@ QString QStandardPaths::writableLocation(StandardLocation type)
return QDir::tempPath();
case GenericDataLocation:
case DataLocation:
+ case GenericCacheLocation:
case CacheLocation:
case RuntimeLocation:
return macLocation(type, kUserDomain);
@@ -140,7 +142,7 @@ QStringList QStandardPaths::standardLocations(StandardLocation type)
{
QStringList dirs;
- if (type == GenericDataLocation || type == DataLocation || type == CacheLocation) {
+ if (type == GenericDataLocation || type == DataLocation || type == GenericCacheLocation || type == CacheLocation) {
const QString path = macLocation(type, kOnAppropriateDisk);
if (!path.isEmpty())
dirs.append(path);
diff --git a/src/corelib/io/qstandardpaths_unix.cpp b/src/corelib/io/qstandardpaths_unix.cpp
index b1c5869f71..5aef52eaba 100644
--- a/src/corelib/io/qstandardpaths_unix.cpp
+++ b/src/corelib/io/qstandardpaths_unix.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
@@ -62,15 +62,18 @@ QString QStandardPaths::writableLocation(StandardLocation type)
case TempLocation:
return QDir::tempPath();
case CacheLocation:
+ case GenericCacheLocation:
{
// http://standards.freedesktop.org/basedir-spec/basedir-spec-0.6.html
QString xdgCacheHome = QFile::decodeName(qgetenv("XDG_CACHE_HOME"));
if (xdgCacheHome.isEmpty())
xdgCacheHome = QDir::homePath() + QLatin1String("/.cache");
- if (!QCoreApplication::organizationName().isEmpty())
- xdgCacheHome += QLatin1Char('/') + QCoreApplication::organizationName();
- if (!QCoreApplication::applicationName().isEmpty())
- xdgCacheHome += QLatin1Char('/') + QCoreApplication::applicationName();
+ if (type == QStandardPaths::CacheLocation) {
+ if (!QCoreApplication::organizationName().isEmpty())
+ xdgCacheHome += QLatin1Char('/') + QCoreApplication::organizationName();
+ if (!QCoreApplication::applicationName().isEmpty())
+ xdgCacheHome += QLatin1Char('/') + QCoreApplication::applicationName();
+ }
return xdgCacheHome;
}
case DataLocation:
diff --git a/src/corelib/io/qstandardpaths_win.cpp b/src/corelib/io/qstandardpaths_win.cpp
index e9093649f3..e3f86b7134 100644
--- a/src/corelib/io/qstandardpaths_win.cpp
+++ b/src/corelib/io/qstandardpaths_win.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
@@ -160,6 +160,9 @@ QString QStandardPaths::writableLocation(StandardLocation type)
// cache directory located in their AppData directory
return writableLocation(DataLocation) + QLatin1String("\\cache");
+ case GenericCacheLocation:
+ return writableLocation(GenericDataLocation) + QLatin1String("\\cache");
+
case RuntimeLocation:
case HomeLocation:
result = QDir::homePath();
diff --git a/src/corelib/io/qtemporarydir.cpp b/src/corelib/io/qtemporarydir.cpp
index 78ec1774eb..15d3258a9a 100644
--- a/src/corelib/io/qtemporarydir.cpp
+++ b/src/corelib/io/qtemporarydir.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
diff --git a/src/corelib/io/qtemporarydir.h b/src/corelib/io/qtemporarydir.h
index da0d1214c4..22c0a271e4 100644
--- a/src/corelib/io/qtemporarydir.h
+++ b/src/corelib/io/qtemporarydir.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
diff --git a/src/corelib/io/qtemporaryfile.cpp b/src/corelib/io/qtemporaryfile.cpp
index 677be45f65..eb645fabe8 100644
--- a/src/corelib/io/qtemporaryfile.cpp
+++ b/src/corelib/io/qtemporaryfile.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
diff --git a/src/corelib/io/qtemporaryfile.h b/src/corelib/io/qtemporaryfile.h
index 282b897813..20956d2cf0 100644
--- a/src/corelib/io/qtemporaryfile.h
+++ b/src/corelib/io/qtemporaryfile.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
diff --git a/src/corelib/io/qtextstream.cpp b/src/corelib/io/qtextstream.cpp
index 177f73def3..8c7f57fddf 100644
--- a/src/corelib/io/qtextstream.cpp
+++ b/src/corelib/io/qtextstream.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
diff --git a/src/corelib/io/qtextstream.h b/src/corelib/io/qtextstream.h
index db038855a8..0531d4017d 100644
--- a/src/corelib/io/qtextstream.h
+++ b/src/corelib/io/qtextstream.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
diff --git a/src/corelib/io/qtldurl.cpp b/src/corelib/io/qtldurl.cpp
index 7d06ca4b17..2c725f17fd 100644
--- a/src/corelib/io/qtldurl.cpp
+++ b/src/corelib/io/qtldurl.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
diff --git a/src/corelib/io/qtldurl_p.h b/src/corelib/io/qtldurl_p.h
index 77c0a15823..0a94f3015b 100644
--- a/src/corelib/io/qtldurl_p.h
+++ b/src/corelib/io/qtldurl_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
diff --git a/src/corelib/io/qurl.cpp b/src/corelib/io/qurl.cpp
index c921a89b30..53b4df4729 100644
--- a/src/corelib/io/qurl.cpp
+++ b/src/corelib/io/qurl.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
diff --git a/src/corelib/io/qurl.h b/src/corelib/io/qurl.h
index e62cd0a85b..75a88e8048 100644
--- a/src/corelib/io/qurl.h
+++ b/src/corelib/io/qurl.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
diff --git a/src/corelib/io/qwindowspipereader.cpp b/src/corelib/io/qwindowspipereader.cpp
new file mode 100644
index 0000000000..8da786ebd9
--- /dev/null
+++ b/src/corelib/io/qwindowspipereader.cpp
@@ -0,0 +1,315 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 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$
+** GNU Lesser General Public License Usage
+** 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.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwindowspipereader_p.h"
+#include <qdebug.h>
+#include <qelapsedtimer.h>
+#include <qeventloop.h>
+#include <qtimer.h>
+#include <qwineventnotifier.h>
+
+QT_BEGIN_NAMESPACE
+
+QWindowsPipeReader::QWindowsPipeReader(QObject *parent)
+ : QObject(parent),
+ handle(INVALID_HANDLE_VALUE),
+ readBufferMaxSize(0),
+ actualReadBufferSize(0),
+ emitReadyReadTimer(new QTimer(this)),
+ pipeBroken(false)
+{
+ emitReadyReadTimer->setSingleShot(true);
+ connect(emitReadyReadTimer, SIGNAL(timeout()), SIGNAL(readyRead()));
+
+ ZeroMemory(&overlapped, sizeof(overlapped));
+ overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+ dataReadNotifier = new QWinEventNotifier(overlapped.hEvent, this);
+ connect(dataReadNotifier, SIGNAL(activated(HANDLE)), SLOT(readEventSignalled()));
+}
+
+QWindowsPipeReader::~QWindowsPipeReader()
+{
+ CloseHandle(overlapped.hEvent);
+}
+
+/*!
+ Sets the handle to read from. The handle must be valid.
+ */
+void QWindowsPipeReader::setHandle(HANDLE hPipeReadEnd)
+{
+ readBuffer.clear();
+ actualReadBufferSize = 0;
+ handle = hPipeReadEnd;
+ pipeBroken = false;
+ dataReadNotifier->setEnabled(true);
+}
+
+/*!
+ Stops the asynchronous read sequence.
+ This function assumes that the file already has been closed.
+ It does not cancel any I/O operation.
+ */
+void QWindowsPipeReader::stop()
+{
+ dataReadNotifier->setEnabled(false);
+ readSequenceStarted = false;
+ handle = INVALID_HANDLE_VALUE;
+ ResetEvent(overlapped.hEvent);
+}
+
+/*!
+ Returns the number of bytes we've read so far.
+ */
+qint64 QWindowsPipeReader::bytesAvailable() const
+{
+ return actualReadBufferSize;
+}
+
+/*!
+ Stops the asynchronous read sequence.
+ */
+qint64 QWindowsPipeReader::read(char *data, qint64 maxlen)
+{
+ if (pipeBroken && actualReadBufferSize == 0)
+ return -1; // signal EOF
+
+ qint64 readSoFar;
+ // If startAsyncRead() has read data, copy it to its destination.
+ if (maxlen == 1 && actualReadBufferSize > 0) {
+ *data = readBuffer.getChar();
+ actualReadBufferSize--;
+ readSoFar = 1;
+ } else {
+ qint64 bytesToRead = qMin(qint64(actualReadBufferSize), maxlen);
+ readSoFar = 0;
+ while (readSoFar < bytesToRead) {
+ const char *ptr = readBuffer.readPointer();
+ int bytesToReadFromThisBlock = qMin(bytesToRead - readSoFar,
+ qint64(readBuffer.nextDataBlockSize()));
+ memcpy(data + readSoFar, ptr, bytesToReadFromThisBlock);
+ readSoFar += bytesToReadFromThisBlock;
+ readBuffer.free(bytesToReadFromThisBlock);
+ actualReadBufferSize -= bytesToReadFromThisBlock;
+ }
+ }
+
+ if (!pipeBroken) {
+ if (!actualReadBufferSize)
+ emitReadyReadTimer->stop();
+ if (!readSequenceStarted)
+ startAsyncRead();
+ }
+
+ return readSoFar;
+}
+
+bool QWindowsPipeReader::canReadLine() const
+{
+ return readBuffer.indexOf('\n', actualReadBufferSize) >= 0;
+}
+
+/*!
+ \internal
+ Will be called whenever the read operation completes.
+ Returns true, if readyRead() has been emitted.
+ */
+bool QWindowsPipeReader::readEventSignalled()
+{
+ if (!completeAsyncRead()) {
+ pipeBroken = true;
+ emit pipeClosed();
+ return false;
+ }
+ startAsyncRead();
+ emitReadyReadTimer->stop();
+ emit readyRead();
+ return true;
+}
+
+/*!
+ \internal
+ Reads data from the socket into the readbuffer
+ */
+void QWindowsPipeReader::startAsyncRead()
+{
+ do {
+ DWORD bytesToRead = checkPipeState();
+ if (pipeBroken)
+ return;
+
+ if (bytesToRead == 0) {
+ // There are no bytes in the pipe but we need to
+ // start the overlapped read with some buffer size.
+ bytesToRead = initialReadBufferSize;
+ }
+
+ if (readBufferMaxSize && bytesToRead > (readBufferMaxSize - readBuffer.size())) {
+ bytesToRead = readBufferMaxSize - readBuffer.size();
+ if (bytesToRead == 0) {
+ // Buffer is full. User must read data from the buffer
+ // before we can read more from the pipe.
+ return;
+ }
+ }
+
+ char *ptr = readBuffer.reserve(bytesToRead);
+
+ readSequenceStarted = true;
+ if (ReadFile(handle, ptr, bytesToRead, NULL, &overlapped)) {
+ completeAsyncRead();
+ } else {
+ switch (GetLastError()) {
+ case ERROR_IO_PENDING:
+ // This is not an error. We're getting notified, when data arrives.
+ return;
+ case ERROR_MORE_DATA:
+ // This is not an error. The synchronous read succeeded.
+ // We're connected to a message mode pipe and the message
+ // didn't fit into the pipe's system buffer.
+ completeAsyncRead();
+ break;
+ case ERROR_PIPE_NOT_CONNECTED:
+ {
+ // It may happen, that the other side closes the connection directly
+ // after writing data. Then we must set the appropriate socket state.
+ pipeBroken = true;
+ emit pipeClosed();
+ return;
+ }
+ default:
+ emit winError(GetLastError(), QLatin1String("QWindowsPipeReader::startAsyncRead"));
+ return;
+ }
+ }
+ } while (!readSequenceStarted);
+}
+
+/*!
+ \internal
+ Sets the correct size of the read buffer after a read operation.
+ Returns false, if an error occurred or the connection dropped.
+ */
+bool QWindowsPipeReader::completeAsyncRead()
+{
+ ResetEvent(overlapped.hEvent);
+ readSequenceStarted = false;
+
+ DWORD bytesRead;
+ if (!GetOverlappedResult(handle, &overlapped, &bytesRead, TRUE)) {
+ switch (GetLastError()) {
+ case ERROR_MORE_DATA:
+ // This is not an error. We're connected to a message mode
+ // pipe and the message didn't fit into the pipe's system
+ // buffer. We will read the remaining data in the next call.
+ break;
+ case ERROR_BROKEN_PIPE:
+ case ERROR_PIPE_NOT_CONNECTED:
+ return false;
+ default:
+ emit winError(GetLastError(), QLatin1String("QWindowsPipeReader::completeAsyncRead"));
+ return false;
+ }
+ }
+
+ actualReadBufferSize += bytesRead;
+ readBuffer.truncate(actualReadBufferSize);
+ if (!emitReadyReadTimer->isActive())
+ emitReadyReadTimer->start();
+ return true;
+}
+
+/*!
+ \internal
+ Returns the number of available bytes in the pipe.
+ Sets QWindowsPipeReader::pipeBroken to true if the connection is broken.
+ */
+DWORD QWindowsPipeReader::checkPipeState()
+{
+ DWORD bytes;
+ if (PeekNamedPipe(handle, NULL, 0, NULL, &bytes, NULL)) {
+ return bytes;
+ } else {
+ if (!pipeBroken) {
+ pipeBroken = true;
+ emit pipeClosed();
+ }
+ }
+ return 0;
+}
+
+/*!
+ Waits for the completion of the asynchronous read operation.
+ Returns true, if we've emitted the readyRead signal.
+ */
+bool QWindowsPipeReader::waitForReadyRead(int msecs)
+{
+ Q_ASSERT(readSequenceStarted);
+ DWORD result = WaitForSingleObject(overlapped.hEvent, msecs == -1 ? INFINITE : msecs);
+ switch (result) {
+ case WAIT_OBJECT_0:
+ return readEventSignalled();
+ case WAIT_TIMEOUT:
+ return false;
+ }
+
+ qWarning("QWindowsPipeReader::waitForReadyRead WaitForSingleObject failed with error code %d.", int(GetLastError()));
+ return false;
+}
+
+/*!
+ Waits until the pipe is closed.
+ */
+bool QWindowsPipeReader::waitForPipeClosed(int msecs)
+{
+ const int sleepTime = 10;
+ QElapsedTimer stopWatch;
+ stopWatch.start();
+ forever {
+ checkPipeState();
+ if (pipeBroken)
+ return true;
+ if (stopWatch.hasExpired(msecs - sleepTime))
+ return false;
+ Sleep(sleepTime);
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/io/qfilesystemwatcher_symbian_p.h b/src/corelib/io/qwindowspipereader_p.h
index 0b317a062f..e78d6b29ad 100644
--- a/src/corelib/io/qfilesystemwatcher_symbian_p.h
+++ b/src/corelib/io/qwindowspipereader_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
@@ -39,8 +39,8 @@
**
****************************************************************************/
-#ifndef QFILESYSTEMWATCHER_SYMBIAN_P_H
-#define QFILESYSTEMWATCHER_SYMBIAN_P_H
+#ifndef QWINDOWSPIPEREADER_P_H
+#define QWINDOWSPIPEREADER_P_H
//
// W A R N I N G
@@ -53,78 +53,70 @@
// We mean it.
//
-#include "qfilesystemwatcher_p.h"
+#include <qbytearray.h>
+#include <qobject.h>
+#include <qtimer.h>
+#include <qt_windows.h>
-#ifndef QT_NO_FILESYSTEMWATCHER
+#include <private/qringbuffer_p.h>
-#include "qhash.h"
-#include "qmutex.h"
-#include "qwaitcondition.h"
-
-#include <e32base.h>
-#include <f32file.h>
+QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
-class QSymbianFileSystemWatcherEngine;
-
-class QNotifyChangeEvent : public CActive
-{
-public:
- QNotifyChangeEvent(RFs &fsSession, const TDesC &file, QSymbianFileSystemWatcherEngine *engine,
- bool aIsDir, TInt aPriority = EPriorityStandard);
- ~QNotifyChangeEvent();
-
- bool isDir;
+QT_MODULE(Core)
-private:
- void RunL();
- void DoCancel();
-
- RFs &fsSession;
- TPath watchedPath;
- QSymbianFileSystemWatcherEngine *engine;
-
- int failureCount;
-};
+class QWinEventNotifier;
-class QSymbianFileSystemWatcherEngine : public QFileSystemWatcherEngine
+class Q_CORE_EXPORT QWindowsPipeReader : public QObject
{
Q_OBJECT
-
public:
- QSymbianFileSystemWatcherEngine();
- ~QSymbianFileSystemWatcherEngine();
-
- QStringList addPaths(const QStringList &paths, QStringList *files, QStringList *directories);
- QStringList removePaths(const QStringList &paths, QStringList *files,
- QStringList *directories);
+ explicit QWindowsPipeReader(QObject *parent = 0);
+ ~QWindowsPipeReader();
+ void setHandle(HANDLE hPipeReadEnd);
void stop();
-protected:
- void run();
+ void setMaxReadBufferSize(qint64 size) { readBufferMaxSize = size; }
+ qint64 maxReadBufferSize() const { return readBufferMaxSize; }
-public Q_SLOTS:
- void addNativeListener(const QString &directoryPath);
- void removeNativeListener();
+ bool isPipeClosed() const { return pipeBroken; }
+ qint64 bytesAvailable() const;
+ qint64 read(char *data, qint64 maxlen);
+ bool canReadLine() const;
+ bool waitForReadyRead(int msecs);
+ bool waitForPipeClosed(int msecs);
-private:
- friend class QNotifyChangeEvent;
- void emitPathChanged(QNotifyChangeEvent *e);
+ void startAsyncRead();
+ bool completeAsyncRead();
- void startWatcher();
+Q_SIGNALS:
+ void winError(ulong, const QString &);
+ void readyRead();
+ void pipeClosed();
- QHash<QNotifyChangeEvent*, QString> activeObjectToPath;
- QMutex mutex;
- QWaitCondition syncCondition;
- bool watcherStarted;
- QNotifyChangeEvent *currentAddEvent;
- QNotifyChangeEvent *currentRemoveEvent;
-};
+private Q_SLOTS:
+ bool readEventSignalled();
-#endif // QT_NO_FILESYSTEMWATCHER
+private:
+ DWORD checkPipeState();
+
+private:
+ HANDLE handle;
+ OVERLAPPED overlapped;
+ QWinEventNotifier *dataReadNotifier;
+ qint64 readBufferMaxSize;
+ QRingBuffer readBuffer;
+ int actualReadBufferSize;
+ bool readSequenceStarted;
+ QTimer *emitReadyReadTimer;
+ bool pipeBroken;
+ static const qint64 initialReadBufferSize = 4096;
+};
QT_END_NAMESPACE
-#endif // QFILESYSTEMWATCHER_WIN_P_H
+QT_END_HEADER
+
+#endif // QWINDOWSPIPEREADER_P_H
diff --git a/src/corelib/io/qwindowspipewriter.cpp b/src/corelib/io/qwindowspipewriter.cpp
index cb802f1d91..a1765b4178 100644
--- a/src/corelib/io/qwindowspipewriter.cpp
+++ b/src/corelib/io/qwindowspipewriter.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
diff --git a/src/corelib/io/qwindowspipewriter_p.h b/src/corelib/io/qwindowspipewriter_p.h
index dfcb77e17c..44a1d04b4e 100644
--- a/src/corelib/io/qwindowspipewriter_p.h
+++ b/src/corelib/io/qwindowspipewriter_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**