summaryrefslogtreecommitdiffstats
path: root/src/corelib/io
diff options
context:
space:
mode:
authormread <qt-info@nokia.com>2009-08-07 13:34:12 (GMT)
committermread <qt-info@nokia.com>2009-08-07 13:34:12 (GMT)
commit5a72890b7ce12815f9567316da867006cff73f39 (patch)
tree46c8c793f19274f9ed19678d1732d2123adbdf34 /src/corelib/io
parent0f6f1f841cea61cbb6905de92c2ca63bd369d55d (diff)
parentcc0a411e5e874aa224c26298a109973cb15ea291 (diff)
downloadQt-5a72890b7ce12815f9567316da867006cff73f39.zip
Qt-5a72890b7ce12815f9567316da867006cff73f39.tar.gz
Qt-5a72890b7ce12815f9567316da867006cff73f39.tar.bz2
Merge branch 'master' of git@scm.dev.nokia.troll.no:qt/qt-s60-public
Conflicts fixed: src/corelib/io/qdiriterator.cpp
Diffstat (limited to 'src/corelib/io')
-rw-r--r--src/corelib/io/io.pri5
-rw-r--r--src/corelib/io/qabstractfileengine.cpp22
-rw-r--r--src/corelib/io/qabstractfileengine.h2
-rw-r--r--src/corelib/io/qbuffer.h2
-rw-r--r--src/corelib/io/qdatastream.cpp10
-rw-r--r--src/corelib/io/qdir.h2
-rw-r--r--src/corelib/io/qdiriterator.cpp231
-rw-r--r--src/corelib/io/qfile.h2
-rw-r--r--src/corelib/io/qfileinfo.cpp6
-rw-r--r--src/corelib/io/qfileinfo.h2
-rw-r--r--src/corelib/io/qfilesystemwatcher.cpp18
-rw-r--r--src/corelib/io/qfilesystemwatcher.h2
-rw-r--r--src/corelib/io/qfilesystemwatcher_dnotify.cpp20
-rw-r--r--src/corelib/io/qfilesystemwatcher_fsevents.cpp472
-rw-r--r--src/corelib/io/qfilesystemwatcher_fsevents_p.h128
-rw-r--r--src/corelib/io/qfilesystemwatcher_inotify.cpp40
-rw-r--r--src/corelib/io/qfilesystemwatcher_kqueue.cpp5
-rw-r--r--src/corelib/io/qfilesystemwatcher_p.h7
-rw-r--r--src/corelib/io/qfilesystemwatcher_symbian.cpp8
-rw-r--r--src/corelib/io/qfilesystemwatcher_symbian_p.h8
-rw-r--r--src/corelib/io/qfilesystemwatcher_win.cpp435
-rw-r--r--src/corelib/io/qfilesystemwatcher_win_p.h53
-rw-r--r--src/corelib/io/qfsfileengine.cpp6
-rw-r--r--src/corelib/io/qfsfileengine.h2
-rw-r--r--src/corelib/io/qfsfileengine_iterator_win.cpp32
-rw-r--r--src/corelib/io/qfsfileengine_p.h4
-rw-r--r--src/corelib/io/qfsfileengine_unix.cpp24
-rw-r--r--src/corelib/io/qfsfileengine_win.cpp935
-rw-r--r--src/corelib/io/qiodevice.h2
-rw-r--r--src/corelib/io/qprocess.cpp6
-rw-r--r--src/corelib/io/qprocess.h2
-rw-r--r--src/corelib/io/qprocess_symbian.cpp8
-rw-r--r--src/corelib/io/qprocess_unix.cpp285
-rw-r--r--src/corelib/io/qprocess_win.cpp231
-rw-r--r--src/corelib/io/qresource.cpp15
-rw-r--r--src/corelib/io/qresource.h2
-rw-r--r--src/corelib/io/qresource_iterator.cpp8
-rw-r--r--src/corelib/io/qresource_iterator_p.h4
-rw-r--r--src/corelib/io/qresource_p.h2
-rw-r--r--src/corelib/io/qsettings.cpp43
-rw-r--r--src/corelib/io/qsettings.h2
-rw-r--r--src/corelib/io/qsettings_win.cpp209
-rw-r--r--src/corelib/io/qtemporaryfile.cpp26
-rw-r--r--src/corelib/io/qtemporaryfile.h2
-rw-r--r--src/corelib/io/qtextstream.h2
-rw-r--r--src/corelib/io/qurl.cpp318
46 files changed, 1974 insertions, 1676 deletions
diff --git a/src/corelib/io/io.pri b/src/corelib/io/io.pri
index edbab9c..b49554e 100644
--- a/src/corelib/io/io.pri
+++ b/src/corelib/io/io.pri
@@ -66,7 +66,10 @@ win32 {
SOURCES += io/qfsfileengine_iterator_unix.cpp
symbian:SOURCES += io/qprocess_symbian.cpp
else:SOURCES += io/qprocess_unix.cpp
- mac:SOURCES += io/qsettings_mac.cpp
+ macx-*: {
+ HEADERS += io/qfilesystemwatcher_fsevents_p.h
+ SOURCES += io/qsettings_mac.cpp io/qfilesystemwatcher_fsevents.cpp
+ }
linux-*:{
SOURCES += \
diff --git a/src/corelib/io/qabstractfileengine.cpp b/src/corelib/io/qabstractfileengine.cpp
index d2fb768..fbd838a 100644
--- a/src/corelib/io/qabstractfileengine.cpp
+++ b/src/corelib/io/qabstractfileengine.cpp
@@ -42,7 +42,7 @@
#include "qabstractfileengine.h"
#include "private/qabstractfileengine_p.h"
#include "qdatetime.h"
-#include "qmutex.h"
+#include "qreadwritelock.h"
#include "qvariant.h"
// built-in handlers
#include "qfsfileengine.h"
@@ -98,14 +98,14 @@ QT_BEGIN_NAMESPACE
All application-wide handlers are stored in this list. The mutex must be
acquired to ensure thread safety.
*/
-Q_GLOBAL_STATIC_WITH_ARGS(QMutex, fileEngineHandlerMutex, (QMutex::Recursive))
+Q_GLOBAL_STATIC_WITH_ARGS(QReadWriteLock, fileEngineHandlerMutex, (QReadWriteLock::Recursive))
static bool qt_abstractfileenginehandlerlist_shutDown = false;
class QAbstractFileEngineHandlerList : public QList<QAbstractFileEngineHandler *>
{
public:
~QAbstractFileEngineHandlerList()
{
- QMutexLocker locker(fileEngineHandlerMutex());
+ QWriteLocker locker(fileEngineHandlerMutex());
qt_abstractfileenginehandlerlist_shutDown = true;
}
};
@@ -122,7 +122,7 @@ Q_GLOBAL_STATIC(QAbstractFileEngineHandlerList, fileEngineHandlers)
*/
QAbstractFileEngineHandler::QAbstractFileEngineHandler()
{
- QMutexLocker locker(fileEngineHandlerMutex());
+ QWriteLocker locker(fileEngineHandlerMutex());
fileEngineHandlers()->prepend(this);
}
@@ -132,7 +132,7 @@ QAbstractFileEngineHandler::QAbstractFileEngineHandler()
*/
QAbstractFileEngineHandler::~QAbstractFileEngineHandler()
{
- QMutexLocker locker(fileEngineHandlerMutex());
+ QWriteLocker locker(fileEngineHandlerMutex());
// Remove this handler from the handler list only if the list is valid.
if (!qt_abstractfileenginehandlerlist_shutDown)
fileEngineHandlers()->removeAll(this);
@@ -166,12 +166,14 @@ QAbstractFileEngineHandler::~QAbstractFileEngineHandler()
*/
QAbstractFileEngine *QAbstractFileEngine::create(const QString &fileName)
{
- QMutexLocker locker(fileEngineHandlerMutex());
+ {
+ QReadLocker locker(fileEngineHandlerMutex());
- // check for registered handlers that can load the file
- for (int i = 0; i < fileEngineHandlers()->size(); i++) {
- if (QAbstractFileEngine *ret = fileEngineHandlers()->at(i)->create(fileName))
- return ret;
+ // check for registered handlers that can load the file
+ for (int i = 0; i < fileEngineHandlers()->size(); i++) {
+ if (QAbstractFileEngine *ret = fileEngineHandlers()->at(i)->create(fileName))
+ return ret;
+ }
}
#ifdef QT_BUILD_CORE_LIB
diff --git a/src/corelib/io/qabstractfileengine.h b/src/corelib/io/qabstractfileengine.h
index 07c92d2..54eb6de 100644
--- a/src/corelib/io/qabstractfileengine.h
+++ b/src/corelib/io/qabstractfileengine.h
@@ -196,7 +196,7 @@ protected:
QScopedPointer<QAbstractFileEnginePrivate> d_ptr;
private:
- Q_DECLARE_SCOPED_PRIVATE(QAbstractFileEngine)
+ Q_DECLARE_PRIVATE(QAbstractFileEngine)
Q_DISABLE_COPY(QAbstractFileEngine)
};
diff --git a/src/corelib/io/qbuffer.h b/src/corelib/io/qbuffer.h
index ce5f605..e078d05 100644
--- a/src/corelib/io/qbuffer.h
+++ b/src/corelib/io/qbuffer.h
@@ -96,7 +96,7 @@ protected:
qint64 writeData(const char *data, qint64 len);
private:
- Q_DECLARE_SCOPED_PRIVATE(QBuffer)
+ Q_DECLARE_PRIVATE(QBuffer)
Q_DISABLE_COPY(QBuffer)
Q_PRIVATE_SLOT(d_func(), void _q_emitSignals())
diff --git a/src/corelib/io/qdatastream.cpp b/src/corelib/io/qdatastream.cpp
index 244299c..1023868 100644
--- a/src/corelib/io/qdatastream.cpp
+++ b/src/corelib/io/qdatastream.cpp
@@ -362,17 +362,19 @@ QDataStream::~QDataStream()
/*!
\fn QIODevice *QDataStream::device() const
- Returns the I/O device currently set.
+ Returns the I/O device currently set, or 0 if no
+ device is currently set.
- \sa setDevice(), unsetDevice()
+ \sa setDevice()
*/
/*!
void QDataStream::setDevice(QIODevice *d)
- Sets the I/O device to \a d.
+ Sets the I/O device to \a d, which can be 0
+ to unset to current I/O device.
- \sa device(), unsetDevice()
+ \sa device()
*/
void QDataStream::setDevice(QIODevice *d)
diff --git a/src/corelib/io/qdir.h b/src/corelib/io/qdir.h
index 5ef4356..f54fbdc 100644
--- a/src/corelib/io/qdir.h
+++ b/src/corelib/io/qdir.h
@@ -60,7 +60,7 @@ class Q_CORE_EXPORT QDir
protected:
QScopedPointer<QDirPrivate> d_ptr;
private:
- Q_DECLARE_SCOPED_PRIVATE(QDir)
+ Q_DECLARE_PRIVATE(QDir)
public:
enum Filter { Dirs = 0x001,
Files = 0x002,
diff --git a/src/corelib/io/qdiriterator.cpp b/src/corelib/io/qdiriterator.cpp
index 12fe258..a91c112 100644
--- a/src/corelib/io/qdiriterator.cpp
+++ b/src/corelib/io/qdiriterator.cpp
@@ -118,26 +118,28 @@ public:
QDir::Filters filters, QDirIterator::IteratorFlags flags);
~QDirIteratorPrivate();
- void pushSubDirectory(const QString &path, const QStringList &nameFilters,
- QDir::Filters filters);
void advance();
- bool shouldFollowDirectory(const QFileInfo &);
+
+ void pushDirectory(const QFileInfo &fileInfo);
+ void checkAndPushDirectory(const QFileInfo &);
bool matchesFilters(const QString &fileName, const QFileInfo &fi) const;
- QSet<QString> visitedLinks;
+ const QString path;
+ const QStringList nameFilters;
+ const QDir::Filters filters;
+ const QDirIterator::IteratorFlags iteratorFlags;
+
+#ifndef QT_NO_REGEXP
+ QVector<QRegExp> nameRegExps;
+#endif
+
QScopedPointer<QAbstractFileEngine> engine;
QDirIteratorPrivateIteratorStack fileEngineIterators;
- QString path;
- QFileInfo nextFileInfo;
- //This fileinfo is the current that we will return from the public API
QFileInfo currentFileInfo;
- QString currentFilePath;
- QDirIterator::IteratorFlags iteratorFlags;
- QDir::Filters filters;
- QStringList nameFilters;
- bool followNextDir;
- bool first;
- bool done;
+ QFileInfo nextFileInfo;
+
+ // Loop protection
+ QSet<QString> visitedLinks;
QDirIterator *q;
};
@@ -147,15 +149,24 @@ public:
*/
QDirIteratorPrivate::QDirIteratorPrivate(const QString &path, const QStringList &nameFilters,
QDir::Filters filters, QDirIterator::IteratorFlags flags)
- : path(path), nextFileInfo(path), iteratorFlags(flags), followNextDir(false), first(true), done(false)
+ : engine(QAbstractFileEngine::create(path))
+ , path(path)
+ , nameFilters(nameFilters.contains(QLatin1String("*")) ? QStringList() : nameFilters)
+ , filters(QDir::NoFilter == filters ? QDir::AllEntries : filters)
+ , iteratorFlags(flags)
{
- if (filters == QDir::NoFilter)
- filters = QDir::AllEntries;
- this->filters = filters;
- this->nameFilters = nameFilters;
+#ifndef QT_NO_REGEXP
+ nameRegExps.reserve(nameFilters.size());
+ for (int i = 0; i < nameFilters.size(); ++i)
+ nameRegExps.append(
+ QRegExp(nameFilters.at(i),
+ (filters & QDir::CaseSensitive) ? Qt::CaseSensitive : Qt::CaseInsensitive,
+ QRegExp::Wildcard));
+#endif
- pushSubDirectory(nextFileInfo.isSymLink() ? nextFileInfo.canonicalFilePath() : path,
- nameFilters, filters);
+ // Populate fields for hasNext() and next()
+ pushDirectory(QFileInfo(path));
+ advance();
}
/*!
@@ -168,24 +179,19 @@ QDirIteratorPrivate::~QDirIteratorPrivate()
/*!
\internal
*/
-void QDirIteratorPrivate::pushSubDirectory(const QString &path, const QStringList &nameFilters,
- QDir::Filters filters)
+void QDirIteratorPrivate::pushDirectory(const QFileInfo &fileInfo)
{
- if (iteratorFlags & QDirIterator::FollowSymlinks) {
- if (nextFileInfo.filePath() != path)
- nextFileInfo.setFile(path);
- if (nextFileInfo.isSymLink()) {
- visitedLinks << nextFileInfo.canonicalFilePath();
- } else {
- visitedLinks << nextFileInfo.absoluteFilePath();
- }
- }
-
- if (engine.isNull()) {
- engine.reset(QAbstractFileEngine::create(this->path));
- }
-
- if (!engine.isNull()) {
+ QString path = fileInfo.filePath();
+
+#ifdef Q_OS_WIN
+ if (fileInfo.isSymLink())
+ path = fileInfo.canonicalFilePath();
+#endif
+
+ if (iteratorFlags & QDirIterator::FollowSymlinks)
+ visitedLinks << fileInfo.canonicalFilePath();
+
+ if (engine) {
engine->setFileName(path);
QAbstractFileEngineIterator *it = engine->beginEntryList(filters, nameFilters);
if (it) {
@@ -202,95 +208,64 @@ void QDirIteratorPrivate::pushSubDirectory(const QString &path, const QStringLis
*/
void QDirIteratorPrivate::advance()
{
- // Store the current entry
- if (!fileEngineIterators.isEmpty())
- currentFilePath = fileEngineIterators.top()->currentFilePath();
-
- // Advance to the next entry
- if (followNextDir) {
- // Start by navigating into the current directory.
- followNextDir = false;
-
- QAbstractFileEngineIterator *it = fileEngineIterators.top();
-
- QString subDir = it->currentFilePath();
-#ifdef Q_OS_WIN
- if (nextFileInfo.isSymLink())
- subDir = nextFileInfo.canonicalFilePath();
-#endif
- pushSubDirectory(subDir, it->nameFilters(), it->filters());
- }
-
while (!fileEngineIterators.isEmpty()) {
- QAbstractFileEngineIterator *it = fileEngineIterators.top();
// Find the next valid iterator that matches the filters.
- bool foundDirectory = false;
- while (it->hasNext()) {
+ while (fileEngineIterators.top()->hasNext()) {
+ QAbstractFileEngineIterator *it = fileEngineIterators.top();
it->next();
+
const QFileInfo info = it->currentFileInfo();
+ checkAndPushDirectory(it->currentFileInfo());
+
if (matchesFilters(it->currentFileName(), info)) {
currentFileInfo = nextFileInfo;
nextFileInfo = info;
- // Signal that we want to follow this entry.
- followNextDir = shouldFollowDirectory(nextFileInfo);
+
//We found a matching entry.
return;
-
- } else if (iteratorFlags & QDirIterator::Subdirectories) {
-
- if (!shouldFollowDirectory(info))
- continue;
- QString subDir = it->currentFilePath();
-#ifdef Q_OS_WIN
- if (info.isSymLink())
- subDir = info.canonicalFilePath();
-#endif
- pushSubDirectory(subDir, it->nameFilters(), it->filters());
-
- foundDirectory = true;
- break;
}
}
- if (!foundDirectory)
- delete fileEngineIterators.pop();
+
+ delete fileEngineIterators.pop();
}
+
currentFileInfo = nextFileInfo;
- done = true;
+ nextFileInfo = QFileInfo();
}
/*!
\internal
*/
-bool QDirIteratorPrivate::shouldFollowDirectory(const QFileInfo &fileInfo)
+void QDirIteratorPrivate::checkAndPushDirectory(const QFileInfo &fileInfo)
{
// If we're doing flat iteration, we're done.
if (!(iteratorFlags & QDirIterator::Subdirectories))
- return false;
-
+ return;
+
// Never follow non-directory entries
if (!fileInfo.isDir())
- return false;
+ return;
+ // Follow symlinks only when asked
+ if (!(iteratorFlags & QDirIterator::FollowSymlinks) && fileInfo.isSymLink())
+ return;
// Never follow . and ..
- if (fileInfo.fileName() == QLatin1String(".") || fileInfo.fileName() == QLatin1String(".."))
- return false;
+ QString fileName = fileInfo.fileName();
+ if (QLatin1String(".") == fileName || QLatin1String("..") == fileName)
+ return;
-
- // Check symlinks
- if (fileInfo.isSymLink() && !(iteratorFlags & QDirIterator::FollowSymlinks)) {
- // Follow symlinks only if FollowSymlinks was passed
- return false;
- }
+ // No hidden directories unless requested
+ if (!(filters & QDir::AllDirs) && !(filters & QDir::Hidden) && fileInfo.isHidden())
+ return;
// Stop link loops
if (visitedLinks.contains(fileInfo.canonicalFilePath()))
- return false;
-
- return true;
+ return;
+
+ pushDirectory(fileInfo);
}
-
/*!
\internal
@@ -304,10 +279,7 @@ bool QDirIteratorPrivate::shouldFollowDirectory(const QFileInfo &fileInfo)
*/
bool QDirIteratorPrivate::matchesFilters(const QString &fileName, const QFileInfo &fi) const
{
- if (fileName.isEmpty()) {
- // invalid entry
- return false;
- }
+ Q_ASSERT(!fileName.isEmpty());
// filter . and ..?
const int fileNameSize = fileName.size();
@@ -318,16 +290,15 @@ bool QDirIteratorPrivate::matchesFilters(const QString &fileName, const QFileInf
return false;
// name filter
-#ifndef QT_NO_REGEXP
- const bool hasNameFilters = !nameFilters.isEmpty() && !(nameFilters.contains(QLatin1String("*")));
+#ifndef QT_NO_REGEXP
// Pass all entries through name filters, except dirs if the AllDirs
- if (hasNameFilters && !((filters & QDir::AllDirs) && fi.isDir())) {
+ if (!nameFilters.isEmpty() && !((filters & QDir::AllDirs) && fi.isDir())) {
bool matched = false;
- for (int i = 0; i < nameFilters.size(); ++i) {
- QRegExp regexp(nameFilters.at(i),
- (filters & QDir::CaseSensitive) ? Qt::CaseSensitive : Qt::CaseInsensitive,
- QRegExp::Wildcard);
- if (regexp.exactMatch(fileName)) {
+ for (QVector<QRegExp>::const_iterator iter = nameRegExps.constBegin(),
+ end = nameRegExps.constEnd();
+ iter != end; ++iter) {
+
+ if (iter->exactMatch(fileName)) {
matched = true;
break;
}
@@ -348,17 +319,11 @@ bool QDirIteratorPrivate::matchesFilters(const QString &fileName, const QFileInf
|| (!fi.exists() && fi.isSymLink())))
return false;
-
- if (!includeSystem && !dotOrDotDot && ((fi.exists() && !fi.isFile() && !fi.isDir() && !fi.isSymLink())
- || (!fi.exists() && fi.isSymLink()))) {
- return false;
- }
-
// skip directories
const bool skipDirs = !(filters & (QDir::Dirs | QDir::AllDirs));
if (skipDirs && fi.isDir()) {
- if (!(includeHidden && !dotOrDotDot && fi.isHidden())
- || (includeSystem && !fi.exists() && fi.isSymLink()))
+ if (!((includeHidden && !dotOrDotDot && fi.isHidden())
+ || (includeSystem && !fi.exists() && fi.isSymLink())))
return false;
}
@@ -383,7 +348,7 @@ bool QDirIteratorPrivate::matchesFilters(const QString &fileName, const QFileInf
|| (doExecutable && !fi.isExecutable()))) {
return false;
}
-
+
return true;
}
@@ -425,7 +390,7 @@ QDirIterator::QDirIterator(const QDir &dir, IteratorFlags flags)
\sa hasNext(), next(), IteratorFlags
*/
QDirIterator::QDirIterator(const QString &path, QDir::Filters filters, IteratorFlags flags)
- : d(new QDirIteratorPrivate(path, QStringList(QLatin1String("*")), filters, flags))
+ : d(new QDirIteratorPrivate(path, QStringList(), filters, flags))
{
d->q = this;
}
@@ -443,7 +408,7 @@ QDirIterator::QDirIterator(const QString &path, QDir::Filters filters, IteratorF
\sa hasNext(), next(), IteratorFlags
*/
QDirIterator::QDirIterator(const QString &path, IteratorFlags flags)
- : d(new QDirIteratorPrivate(path, QStringList(QLatin1String("*")), QDir::NoFilter, flags))
+ : d(new QDirIteratorPrivate(path, QStringList(), QDir::NoFilter, flags))
{
d->q = this;
}
@@ -460,7 +425,7 @@ QDirIterator::QDirIterator(const QString &path, IteratorFlags flags)
passed to the flags.
\warning This constructor expects \c flags to be left at its default value. Use the
- constructors that do not take the \a filters argument instead.
+ constructors that do not take the \a filters argument instead.
\sa hasNext(), next(), IteratorFlags
*/
@@ -490,8 +455,6 @@ QDirIterator::~QDirIterator()
*/
QString QDirIterator::next()
{
- if (!hasNext())
- return QString();
d->advance();
return filePath();
}
@@ -504,22 +467,17 @@ QString QDirIterator::next()
*/
bool QDirIterator::hasNext() const
{
- if (d->first) {
- d->first = false;
- d->advance();
- }
- return !d->done;
+ return !d->fileEngineIterators.isEmpty();
}
/*!
Returns the file name for the current directory entry, without the path
- prepended. If the current entry is invalid (i.e., isValid() returns
- false), a null QString is returned.
+ prepended.
+
+ This function is convenient when iterating a single directory. When using
+ the QDirIterator::Subdirectories flag, you can use filePath() to get the
+ full path.
- This function is provided for the convenience when iterating single
- directories. For recursive iteration, you should call filePath() or
- fileInfo() instead.
-
\sa filePath(), fileInfo()
*/
QString QDirIterator::fileName() const
@@ -528,20 +486,17 @@ QString QDirIterator::fileName() const
}
/*!
- Returns the full file path for the current directory entry. If the current
- entry is invalid (i.e., isValid() returns false), a null QString is
- returned.
+ Returns the full file path for the current directory entry.
\sa fileInfo(), fileName()
*/
QString QDirIterator::filePath() const
{
- return d->currentFilePath;
+ return d->currentFileInfo.filePath();
}
/*!
- Returns a QFileInfo for the current directory entry. If the current entry
- is invalid (i.e., isValid() returns false), a null QFileInfo is returned.
+ Returns a QFileInfo for the current directory entry.
\sa filePath(), fileName()
*/
diff --git a/src/corelib/io/qfile.h b/src/corelib/io/qfile.h
index 24ce617..f448609 100644
--- a/src/corelib/io/qfile.h
+++ b/src/corelib/io/qfile.h
@@ -64,7 +64,7 @@ class Q_CORE_EXPORT QFile : public QIODevice
#ifndef QT_NO_QOBJECT
Q_OBJECT
#endif
- Q_DECLARE_SCOPED_PRIVATE(QFile)
+ Q_DECLARE_PRIVATE(QFile)
public:
diff --git a/src/corelib/io/qfileinfo.cpp b/src/corelib/io/qfileinfo.cpp
index afc7c31..c568369 100644
--- a/src/corelib/io/qfileinfo.cpp
+++ b/src/corelib/io/qfileinfo.cpp
@@ -117,11 +117,7 @@ bool QFileInfoPrivate::hasAccess(Access access) const
if (access == ExecuteAccess)
return getFileFlags(QAbstractFileEngine::ExeUserPerm);
- QT_WA( {
- return ::_waccess((TCHAR *)QFSFileEnginePrivate::longFileName(data->fileName).utf16(), mode) == 0;
- } , {
- return QT_ACCESS(QFSFileEnginePrivate::win95Name(data->fileName), mode) == 0;
- } );
+ return ::_waccess((wchar_t*)QFSFileEnginePrivate::longFileName(data->fileName).utf16(), mode) == 0;
#endif
return false;
}
diff --git a/src/corelib/io/qfileinfo.h b/src/corelib/io/qfileinfo.h
index c73823a..5295b16 100644
--- a/src/corelib/io/qfileinfo.h
+++ b/src/corelib/io/qfileinfo.h
@@ -168,7 +168,7 @@ public:
protected:
QScopedPointer<QFileInfoPrivate> d_ptr;
private:
- Q_DECLARE_SCOPED_PRIVATE(QFileInfo)
+ Q_DECLARE_PRIVATE(QFileInfo)
};
Q_DECLARE_TYPEINFO(QFileInfo, Q_MOVABLE_TYPE);
diff --git a/src/corelib/io/qfilesystemwatcher.cpp b/src/corelib/io/qfilesystemwatcher.cpp
index 8f18df8..883a77a 100644
--- a/src/corelib/io/qfilesystemwatcher.cpp
+++ b/src/corelib/io/qfilesystemwatcher.cpp
@@ -58,6 +58,9 @@
# include "qfilesystemwatcher_inotify_p.h"
# include "qfilesystemwatcher_dnotify_p.h"
#elif defined(Q_OS_FREEBSD) || defined(Q_OS_MAC)
+# if (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"
@@ -245,7 +248,12 @@ QFileSystemWatcherEngine *QFileSystemWatcherPrivate::createNativeEngine()
eng = QDnotifyFileSystemWatcherEngine::create();
return eng;
#elif defined(Q_OS_FREEBSD) || defined(Q_OS_MAC)
- return QKqueueFileSystemWatcherEngine::create();
+# if (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;
#else
@@ -380,15 +388,17 @@ void QFileSystemWatcherPrivate::_q_directoryChanged(const QString &path, bool re
\note The act of monitoring files and directories for
modifications consumes system resources. This implies there is a
limit to the number of files and directories your process can
- monitor simultaneously. On Mac OS and all BSD variants, for
+ monitor simultaneously. On Mac OS X 10.4 and all BSD variants, for
example, an open file descriptor is required for each monitored
- file. The system limits the number of open file descriptors to 256
+ file. Some system limits the number of open file descriptors to 256
by default. This means that addPath() and addPaths() will fail if
your process tries to add more than 256 files or directories to
the file system monitor. Also note that your process may have
other file descriptors open in addition to the ones for files
being monitored, and these other open descriptors also count in
- the total.
+ the total. Mac OS X 10.5 and up use a different backend and do not
+ suffer from this issue.
+
\sa QFile, QDir
*/
diff --git a/src/corelib/io/qfilesystemwatcher.h b/src/corelib/io/qfilesystemwatcher.h
index 76a6c60..60458e5 100644
--- a/src/corelib/io/qfilesystemwatcher.h
+++ b/src/corelib/io/qfilesystemwatcher.h
@@ -57,7 +57,7 @@ class QFileSystemWatcherPrivate;
class Q_CORE_EXPORT QFileSystemWatcher : public QObject
{
Q_OBJECT
- Q_DECLARE_SCOPED_PRIVATE(QFileSystemWatcher)
+ Q_DECLARE_PRIVATE(QFileSystemWatcher)
public:
QFileSystemWatcher(QObject *parent = 0);
diff --git a/src/corelib/io/qfilesystemwatcher_dnotify.cpp b/src/corelib/io/qfilesystemwatcher_dnotify.cpp
index c68af85..6df3746 100644
--- a/src/corelib/io/qfilesystemwatcher_dnotify.cpp
+++ b/src/corelib/io/qfilesystemwatcher_dnotify.cpp
@@ -59,6 +59,8 @@
#include <fcntl.h>
#include <time.h>
+#include "private/qcore_unix_p.h"
+
#ifdef QT_LINUXBASE
/* LSB doesn't standardize these */
@@ -80,7 +82,7 @@ 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)
{
- ::write(qfswd_fileChanged_pipe[1], &i->si_fd, sizeof(int));
+ 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);
@@ -121,9 +123,7 @@ QDnotifySignalThread::QDnotifySignalThread()
{
moveToThread(this);
- ::pipe(qfswd_fileChanged_pipe);
- ::fcntl(qfswd_fileChanged_pipe[0], F_SETFL,
- ::fcntl(qfswd_fileChanged_pipe[0], F_GETFL) | O_NONBLOCK);
+ qt_safe_pipe(qfswd_fileChanged_pipe, O_NONBLOCK);
struct sigaction oldAction;
struct sigaction action;
@@ -181,7 +181,7 @@ void QDnotifySignalThread::run()
void QDnotifySignalThread::readFromDnotify()
{
int fd;
- int readrv = ::read(qfswd_fileChanged_pipe[0], &fd,sizeof(int));
+ 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));
@@ -207,9 +207,9 @@ QDnotifyFileSystemWatcherEngine::~QDnotifyFileSystemWatcherEngine()
for(QHash<int, Directory>::ConstIterator iter = fdToDirectory.constBegin();
iter != fdToDirectory.constEnd();
++iter) {
- ::close(iter->fd);
+ qt_safe_close(iter->fd);
if(iter->parentFd)
- ::close(iter->parentFd);
+ qt_safe_close(iter->parentFd);
}
}
@@ -353,7 +353,7 @@ QStringList QDnotifyFileSystemWatcherEngine::removePaths(const QStringList &path
if(!directory.isMonitored && directory.files.isEmpty()) {
// No longer needed
- ::close(directory.fd);
+ qt_safe_close(directory.fd);
pathToFD.remove(directory.path);
fdToDirectory.remove(fd);
}
@@ -419,9 +419,9 @@ void QDnotifyFileSystemWatcherEngine::refresh(int fd)
}
if(!directory.isMonitored && directory.files.isEmpty()) {
- ::close(directory.fd);
+ qt_safe_close(directory.fd);
if(directory.parentFd) {
- ::close(directory.parentFd);
+ qt_safe_close(directory.parentFd);
parentToFD.remove(directory.parentFd);
}
fdToDirectory.erase(iter);
diff --git a/src/corelib/io/qfilesystemwatcher_fsevents.cpp b/src/corelib/io/qfilesystemwatcher_fsevents.cpp
new file mode 100644
index 0000000..cb276b7
--- /dev/null
+++ b/src/corelib/io/qfilesystemwatcher_fsevents.cpp
@@ -0,0 +1,472 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://www.qtsoftware.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <qplatformdefs.h>
+
+#include "qfilesystemwatcher.h"
+#include "qfilesystemwatcher_fsevents_p.h"
+
+#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 ::stat64 &left, const struct ::stat64 &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 ::stat64 &left, const struct ::stat64 &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.absoluteFilePath().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();
+ 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.absoluteFilePath()));
+ 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.absolutePath()));
+ files->append(path);
+ addPathToHash(filePathInfoHash, cfpath, fileInfo, path);
+ CFArrayAppendValue(tmpArray, cfpath);
+ }
+ }
+ }
+ 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();
+ 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.absolutePath()));
+
+ 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.absoluteFilePath()));
+ 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 ::stat64 newInfo;
+ if (::stat64(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.
+ stop();
+ 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
diff --git a/src/corelib/io/qfilesystemwatcher_fsevents_p.h b/src/corelib/io/qfilesystemwatcher_fsevents_p.h
new file mode 100644
index 0000000..ffc0c68
--- /dev/null
+++ b/src/corelib/io/qfilesystemwatcher_fsevents_p.h
@@ -0,0 +1,128 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://www.qtsoftware.com/contact.
+** $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"
+
+#include <QtCore/qmutex.h>
+#include <QtCore/qwaitcondition.h>
+#include <QtCore/qthread.h>
+#include <QtCore/QHash>
+#include <QtCore/QLinkedList>
+#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 stat64 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 ::stat64 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_END_NAMESPACE
diff --git a/src/corelib/io/qfilesystemwatcher_inotify.cpp b/src/corelib/io/qfilesystemwatcher_inotify.cpp
index 401e545..9d08228 100644
--- a/src/corelib/io/qfilesystemwatcher_inotify.cpp
+++ b/src/corelib/io/qfilesystemwatcher_inotify.cpp
@@ -44,6 +44,8 @@
#ifndef QT_NO_FILESYSTEMWATCHER
+#include "private/qcore_unix_p.h"
+
#include <qdebug.h>
#include <qfile.h>
#include <qfileinfo.h>
@@ -62,62 +64,80 @@
# define __NR_inotify_init 291
# define __NR_inotify_add_watch 292
# define __NR_inotify_rm_watch 293
+# define __NR_inotify_init1 332
#elif defined(__x86_64__)
# define __NR_inotify_init 253
# define __NR_inotify_add_watch 254
# define __NR_inotify_rm_watch 255
+# define __NR_inotify_init1 294
#elif defined(__powerpc__) || defined(__powerpc64__)
# define __NR_inotify_init 275
# define __NR_inotify_add_watch 276
# define __NR_inotify_rm_watch 277
+# define __NR_inotify_init1 318
#elif defined (__ia64__)
# define __NR_inotify_init 1277
# define __NR_inotify_add_watch 1278
# define __NR_inotify_rm_watch 1279
+# define __NR_inotify_init1 1318
#elif defined (__s390__) || defined (__s390x__)
# define __NR_inotify_init 284
# define __NR_inotify_add_watch 285
# define __NR_inotify_rm_watch 286
+# define __NR_inotify_init1 324
#elif defined (__alpha__)
# define __NR_inotify_init 444
# define __NR_inotify_add_watch 445
# define __NR_inotify_rm_watch 446
+// no inotify_init1 for the Alpha
#elif defined (__sparc__) || defined (__sparc64__)
# define __NR_inotify_init 151
# define __NR_inotify_add_watch 152
# define __NR_inotify_rm_watch 156
+# define __NR_inotify_init1 322
#elif defined (__arm__)
# define __NR_inotify_init 316
# define __NR_inotify_add_watch 317
# define __NR_inotify_rm_watch 318
+# define __NR_inotify_init1 360
#elif defined (__sh__)
# define __NR_inotify_init 290
# define __NR_inotify_add_watch 291
# define __NR_inotify_rm_watch 292
+# define __NR_inotify_init1 332
#elif defined (__sh64__)
# define __NR_inotify_init 318
# define __NR_inotify_add_watch 319
# define __NR_inotify_rm_watch 320
+# define __NR_inotify_init1 360
#elif defined (__mips__)
# define __NR_inotify_init 284
# define __NR_inotify_add_watch 285
# define __NR_inotify_rm_watch 286
+# define __NR_inotify_init1 329
#elif defined (__hppa__)
# define __NR_inotify_init 269
# define __NR_inotify_add_watch 270
# define __NR_inotify_rm_watch 271
+# define __NR_inotify_init1 314
#elif defined (__avr32__)
# define __NR_inotify_init 240
# define __NR_inotify_add_watch 241
# define __NR_inotify_rm_watch 242
+// no inotify_init1 for AVR32
#elif defined (__mc68000__)
# define __NR_inotify_init 284
# define __NR_inotify_add_watch 285
# define __NR_inotify_rm_watch 286
+# define __NR_inotify_init1 328
#else
# error "This architecture is not supported. Please talk to qt-bugs@trolltech.com"
#endif
+#if !defined(IN_CLOEXEC) && defined(O_CLOEXEC) && defined(__NR_inotify_init1)
+# define IN_CLOEXEC O_CLOEXEC
+#endif
+
QT_BEGIN_NAMESPACE
#ifdef QT_LINUXBASE
@@ -140,6 +160,13 @@ static inline int inotify_rm_watch(int fd, __u32 wd)
return syscall(__NR_inotify_rm_watch, fd, wd);
}
+#ifdef IN_CLOEXEC
+static inline int inotify_init1(int flags)
+{
+ return syscall(__NR_inotify_init1, flags);
+}
+#endif
+
// the following struct and values are documented in linux/inotify.h
extern "C" {
@@ -185,9 +212,16 @@ QT_BEGIN_NAMESPACE
QInotifyFileSystemWatcherEngine *QInotifyFileSystemWatcherEngine::create()
{
- int fd = inotify_init();
- if (fd <= 0)
- return 0;
+ register int fd = -1;
+#ifdef IN_CLOEXEC
+ fd = inotify_init1(IN_CLOEXEC);
+#endif
+ if (fd == -1) {
+ fd = inotify_init();
+ if (fd == -1)
+ return 0;
+ ::fcntl(fd, F_SETFD, FD_CLOEXEC);
+ }
return new QInotifyFileSystemWatcherEngine(fd);
}
diff --git a/src/corelib/io/qfilesystemwatcher_kqueue.cpp b/src/corelib/io/qfilesystemwatcher_kqueue.cpp
index ed42c34..dfed6a4 100644
--- a/src/corelib/io/qfilesystemwatcher_kqueue.cpp
+++ b/src/corelib/io/qfilesystemwatcher_kqueue.cpp
@@ -43,6 +43,7 @@
#include "qfilesystemwatcher.h"
#include "qfilesystemwatcher_kqueue_p.h"
+#include "private/qcore_unix_p.h"
#include <qdebug.h>
#include <qfile.h>
@@ -124,9 +125,9 @@ QStringList QKqueueFileSystemWatcherEngine::addPaths(const QStringList &paths,
QString path = it.next();
int fd;
#if defined(O_EVTONLY)
- fd = ::open(QFile::encodeName(path), O_EVTONLY);
+ fd = qt_safe_open(QFile::encodeName(path), O_EVTONLY);
#else
- fd = ::open(QFile::encodeName(path), O_RDONLY);
+ fd = qt_safe_open(QFile::encodeName(path), O_RDONLY);
#endif
if (fd == -1) {
perror("QKqueueFileSystemWatcherEngine::addPaths: open");
diff --git a/src/corelib/io/qfilesystemwatcher_p.h b/src/corelib/io/qfilesystemwatcher_p.h
index 850e150..83be197 100644
--- a/src/corelib/io/qfilesystemwatcher_p.h
+++ b/src/corelib/io/qfilesystemwatcher_p.h
@@ -69,13 +69,14 @@ class QFileSystemWatcherEngine : public QThread
Q_OBJECT
protected:
- inline QFileSystemWatcherEngine()
+ inline QFileSystemWatcherEngine(bool move = true)
{
- moveToThread(this);
+ if (move)
+ moveToThread(this);
}
public:
- // fills \a files and \a directires with the \a paths it could
+ // fills \a files and \a directories with the \a paths it could
// watch, and returns a list of paths this engine could not watch
virtual QStringList addPaths(const QStringList &paths,
QStringList *files,
diff --git a/src/corelib/io/qfilesystemwatcher_symbian.cpp b/src/corelib/io/qfilesystemwatcher_symbian.cpp
index c8c1d82..49a5f34 100644
--- a/src/corelib/io/qfilesystemwatcher_symbian.cpp
+++ b/src/corelib/io/qfilesystemwatcher_symbian.cpp
@@ -1,9 +1,9 @@
/****************************************************************************
**
-** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
-** Contact: Qt Software Information (qt-info@nokia.com)
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
**
-** This file is part of the $MODULE$ of the Qt Toolkit.
+** This file is part of the QtCore of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
@@ -34,7 +34,7 @@
** met: http://www.gnu.org/copyleft/gpl.html.
**
** If you are unsure which license is appropriate for your use, please
-** contact the sales department at qt-sales@nokia.com.
+** contact the sales department at http://www.qtsoftware.com/contact.
** $QT_END_LICENSE$
**
****************************************************************************/
diff --git a/src/corelib/io/qfilesystemwatcher_symbian_p.h b/src/corelib/io/qfilesystemwatcher_symbian_p.h
index 9919114..53b2b13 100644
--- a/src/corelib/io/qfilesystemwatcher_symbian_p.h
+++ b/src/corelib/io/qfilesystemwatcher_symbian_p.h
@@ -1,9 +1,9 @@
/****************************************************************************
**
-** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
-** Contact: Qt Software Information (qt-info@nokia.com)
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
**
-** This file is part of the $MODULE$ of the Qt Toolkit.
+** This file is part of the QtCore of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
@@ -34,7 +34,7 @@
** met: http://www.gnu.org/copyleft/gpl.html.
**
** If you are unsure which license is appropriate for your use, please
-** contact the sales department at qt-sales@nokia.com.
+** contact the sales department at http://www.qtsoftware.com/contact.
** $QT_END_LICENSE$
**
****************************************************************************/
diff --git a/src/corelib/io/qfilesystemwatcher_win.cpp b/src/corelib/io/qfilesystemwatcher_win.cpp
index 9a3aeae..9eeef02 100644
--- a/src/corelib/io/qfilesystemwatcher_win.cpp
+++ b/src/corelib/io/qfilesystemwatcher_win.cpp
@@ -53,25 +53,268 @@
QT_BEGIN_NAMESPACE
+void QWindowsFileSystemWatcherEngine::stop()
+{
+ foreach(QWindowsFileSystemWatcherEngineThread *thread, threads)
+ thread->stop();
+}
+
QWindowsFileSystemWatcherEngine::QWindowsFileSystemWatcherEngine()
- : msg(0)
+ : QFileSystemWatcherEngine(false)
{
- HANDLE h = QT_WA_INLINE(CreateEventW(0, false, false, 0),
- CreateEventA(0, false, false, 0));
- if (h != INVALID_HANDLE_VALUE) {
- handles.reserve(MAXIMUM_WAIT_OBJECTS);
- handles.append(h);
- }
}
QWindowsFileSystemWatcherEngine::~QWindowsFileSystemWatcherEngine()
{
- if (handles.isEmpty())
+ if (threads.isEmpty())
return;
- stop();
- wait();
+ foreach(QWindowsFileSystemWatcherEngineThread *thread, threads) {
+ thread->stop();
+ thread->wait();
+ delete thread;
+ }
+}
+
+QStringList QWindowsFileSystemWatcherEngine::addPaths(const QStringList &paths,
+ QStringList *files,
+ QStringList *directories)
+{
+ // qDebug()<<"Adding"<<paths.count()<<"to existing"<<(files->count() + directories->count())<<"watchers";
+ QStringList p = paths;
+ QMutableListIterator<QString> it(p);
+ while (it.hasNext()) {
+ QString path = it.next();
+ QString normalPath = path;
+ if ((normalPath.endsWith(QLatin1Char('/')) || normalPath.endsWith(QLatin1Char('\\')))
+#ifdef Q_OS_WINCE
+ && normalPath.size() > 1)
+#else
+ )
+#endif
+ normalPath.chop(1);
+ QFileInfo fileInfo(normalPath.toLower());
+ if (!fileInfo.exists())
+ continue;
+
+ bool isDir = fileInfo.isDir();
+ if (isDir) {
+ if (directories->contains(path))
+ continue;
+ } else {
+ if (files->contains(path))
+ continue;
+ }
+
+ // qDebug()<<"Looking for a thread/handle for"<<normalPath;
+
+ const QString absolutePath = isDir ? fileInfo.absoluteFilePath() : fileInfo.absolutePath();
+ const uint flags = isDir
+ ? (FILE_NOTIFY_CHANGE_DIR_NAME
+ | FILE_NOTIFY_CHANGE_FILE_NAME)
+ : (FILE_NOTIFY_CHANGE_DIR_NAME
+ | FILE_NOTIFY_CHANGE_FILE_NAME
+ | FILE_NOTIFY_CHANGE_ATTRIBUTES
+ | FILE_NOTIFY_CHANGE_SIZE
+ | FILE_NOTIFY_CHANGE_LAST_WRITE
+ | FILE_NOTIFY_CHANGE_SECURITY);
+
+ QWindowsFileSystemWatcherEngine::PathInfo pathInfo;
+ pathInfo.absolutePath = absolutePath;
+ pathInfo.isDir = isDir;
+ pathInfo.path = path;
+ pathInfo = fileInfo;
+
+ // Look for a thread
+ QWindowsFileSystemWatcherEngineThread *thread = 0;
+ QWindowsFileSystemWatcherEngine::Handle handle;
+ QList<QWindowsFileSystemWatcherEngineThread *>::const_iterator jt, end;
+ end = threads.constEnd();
+ for(jt = threads.constBegin(); jt != end; ++jt) {
+ thread = *jt;
+ QMutexLocker locker(&(thread->mutex));
+
+ handle = thread->handleForDir.value(absolutePath);
+ if (handle.handle != INVALID_HANDLE_VALUE && handle.flags == flags) {
+ // found a thread now insert...
+ // qDebug()<<" Found a thread"<<thread;
+
+ QHash<QString, QWindowsFileSystemWatcherEngine::PathInfo> &h
+ = thread->pathInfoForHandle[handle.handle];
+ if (!h.contains(fileInfo.absoluteFilePath())) {
+ thread->pathInfoForHandle[handle.handle].insert(fileInfo.absoluteFilePath(), pathInfo);
+ if (isDir)
+ directories->append(path);
+ else
+ files->append(path);
+ }
+ it.remove();
+ thread->wakeup();
+ break;
+ }
+ }
+
+ // no thread found, first create a handle
+ if (handle.handle == INVALID_HANDLE_VALUE || handle.flags != flags) {
+ // qDebug()<<" No thread found";
+ // Volume and folder paths need a trailing slash for proper notification
+ // (e.g. "c:" -> "c:/").
+ const QString effectiveAbsolutePath =
+ isDir ? (absolutePath + QLatin1Char('/')) : absolutePath;
+
+ handle.handle = FindFirstChangeNotification((wchar_t*) QDir::toNativeSeparators(effectiveAbsolutePath).utf16(), false, flags);
+ handle.flags = flags;
+ if (handle.handle == INVALID_HANDLE_VALUE)
+ continue;
+
+ // now look for a thread to insert
+ bool found = false;
+ foreach(QWindowsFileSystemWatcherEngineThread *thread, threads) {
+ QMutexLocker(&(thread->mutex));
+ if (thread->handles.count() < MAXIMUM_WAIT_OBJECTS) {
+ // qDebug() << " Added handle" << handle.handle << "for" << absolutePath << "to watch" << fileInfo.absoluteFilePath();
+ // qDebug()<< " to existing thread"<<thread;
+ thread->handles.append(handle.handle);
+ thread->handleForDir.insert(absolutePath, handle);
+
+ thread->pathInfoForHandle[handle.handle].insert(fileInfo.absoluteFilePath(), pathInfo);
+ if (isDir)
+ directories->append(path);
+ else
+ files->append(path);
+
+ it.remove();
+ found = true;
+ thread->wakeup();
+ break;
+ }
+ }
+ if (!found) {
+ QWindowsFileSystemWatcherEngineThread *thread = new QWindowsFileSystemWatcherEngineThread();
+ //qDebug()<<" ###Creating new thread"<<thread<<"("<<(threads.count()+1)<<"threads)";
+ thread->handles.append(handle.handle);
+ thread->handleForDir.insert(absolutePath, handle);
+
+ thread->pathInfoForHandle[handle.handle].insert(fileInfo.absoluteFilePath(), pathInfo);
+ if (isDir)
+ directories->append(path);
+ else
+ files->append(path);
+
+ connect(thread, SIGNAL(fileChanged(const QString &, bool)),
+ this, SIGNAL(fileChanged(const QString &, bool)));
+ connect(thread, SIGNAL(directoryChanged(const QString &, bool)),
+ this, SIGNAL(directoryChanged(const QString &, bool)));
+
+ thread->msg = '@';
+ thread->start();
+ threads.append(thread);
+ it.remove();
+ }
+ }
+ }
+ return p;
+}
+
+QStringList QWindowsFileSystemWatcherEngine::removePaths(const QStringList &paths,
+ QStringList *files,
+ QStringList *directories)
+{
+ // qDebug()<<"removePaths"<<paths;
+ QStringList p = paths;
+ QMutableListIterator<QString> it(p);
+ while (it.hasNext()) {
+ QString path = it.next();
+ QString normalPath = path;
+ if (normalPath.endsWith(QLatin1Char('/')) || normalPath.endsWith(QLatin1Char('\\')))
+ normalPath.chop(1);
+ QFileInfo fileInfo(normalPath.toLower());
+ // qDebug()<<"removing"<<normalPath;
+ QString absolutePath = fileInfo.absoluteFilePath();
+ QList<QWindowsFileSystemWatcherEngineThread *>::iterator jt, end;
+ end = threads.end();
+ for(jt = threads.begin(); jt!= end; ++jt) {
+ QWindowsFileSystemWatcherEngineThread *thread = *jt;
+ if (*jt == 0)
+ continue;
+
+ QMutexLocker locker(&(thread->mutex));
+
+ QWindowsFileSystemWatcherEngine::Handle handle = thread->handleForDir.value(absolutePath);
+ if (handle.handle == INVALID_HANDLE_VALUE) {
+ // perhaps path is a file?
+ absolutePath = fileInfo.absolutePath();
+ handle = thread->handleForDir.value(absolutePath);
+ }
+ if (handle.handle != INVALID_HANDLE_VALUE) {
+ QHash<QString, QWindowsFileSystemWatcherEngine::PathInfo> &h =
+ thread->pathInfoForHandle[handle.handle];
+ if (h.remove(fileInfo.absoluteFilePath())) {
+ // ###
+ files->removeAll(path);
+ directories->removeAll(path);
+
+ if (h.isEmpty()) {
+ // qDebug() << "Closing handle" << handle.handle;
+ FindCloseChangeNotification(handle.handle); // This one might generate a notification
+
+ int indexOfHandle = thread->handles.indexOf(handle.handle);
+ Q_ASSERT(indexOfHandle != -1);
+ thread->handles.remove(indexOfHandle);
+
+ thread->handleForDir.remove(absolutePath);
+ // h is now invalid
+
+ it.remove();
+
+ if (thread->handleForDir.isEmpty()) {
+ // qDebug()<<"Stopping thread "<<thread;
+ locker.unlock();
+ thread->stop();
+ thread->wait();
+ locker.relock();
+ // We can't delete the thread until the mutex locker is
+ // out of scope
+ }
+ }
+ }
+ // Found the file, go to next one
+ break;
+ }
+ }
+ }
+
+ // Remove all threads that we stopped
+ QList<QWindowsFileSystemWatcherEngineThread *>::iterator jt, end;
+ end = threads.end();
+ for(jt = threads.begin(); jt != end; ++jt) {
+ if (!(*jt)->isRunning()) {
+ delete *jt;
+ *jt = 0;
+ }
+ }
+
+ threads.removeAll(0);
+ return p;
+}
+
+///////////
+// QWindowsFileSystemWatcherEngineThread
+///////////
+QWindowsFileSystemWatcherEngineThread::QWindowsFileSystemWatcherEngineThread()
+ : msg(0)
+{
+ if (HANDLE h = CreateEvent(0, false, false, 0)) {
+ handles.reserve(MAXIMUM_WAIT_OBJECTS);
+ handles.append(h);
+ }
+ moveToThread(this);
+}
+
+
+QWindowsFileSystemWatcherEngineThread::~QWindowsFileSystemWatcherEngineThread()
+{
CloseHandle(handles.at(0));
handles[0] = INVALID_HANDLE_VALUE;
@@ -82,13 +325,13 @@ QWindowsFileSystemWatcherEngine::~QWindowsFileSystemWatcherEngine()
}
}
-void QWindowsFileSystemWatcherEngine::run()
+void QWindowsFileSystemWatcherEngineThread::run()
{
QMutexLocker locker(&mutex);
forever {
QVector<HANDLE> handlesCopy = handles;
locker.unlock();
- // qDebug() << "QWindowsFileSystemWatcherEngine: waiting on" << handlesCopy.count() << "handles";
+ // qDebug() << "QWindowsFileSystemWatcherThread"<<this<<"waiting on" << handlesCopy.count() << "handles";
DWORD r = WaitForMultipleObjects(handlesCopy.count(), handlesCopy.constData(), false, INFINITE);
locker.relock();
do {
@@ -96,7 +339,7 @@ void QWindowsFileSystemWatcherEngine::run()
int m = msg;
msg = 0;
if (m == 'q') {
- // qDebug() << "thread told to quit";
+ // qDebug() << "thread"<<this<<"told to quit";
return;
}
if (m != '@') {
@@ -111,15 +354,15 @@ void QWindowsFileSystemWatcherEngine::run()
// When removing a path, FindCloseChangeNotification might actually fire a notification
// for some reason, so we must check if the handle exist in the handles vector
if (handles.contains(handle)) {
- // qDebug("Acknowledged handle: %d, %p", at, handle);
+ // qDebug()<<"thread"<<this<<"Acknowledged handle:"<<at<<handle;
if (!FindNextChangeNotification(handle)) {
- qErrnoWarning("QFileSystemWatcher: FindNextChangeNotification failed");
+ qErrnoWarning("QFileSystemWatcher: FindNextChangeNotification failed!!");
}
- QHash<QString, PathInfo> &h = pathInfoForHandle[handle];
- QMutableHashIterator<QString, PathInfo> it(h);
+ QHash<QString, QWindowsFileSystemWatcherEngine::PathInfo> &h = pathInfoForHandle[handle];
+ QMutableHashIterator<QString, QWindowsFileSystemWatcherEngine::PathInfo> it(h);
while (it.hasNext()) {
- QHash<QString, PathInfo>::iterator x = it.next();
+ QHash<QString, QWindowsFileSystemWatcherEngine::PathInfo>::iterator x = it.next();
QString absolutePath = x.value().absolutePath;
QFileInfo fileInfo(x.value().path);
// qDebug() << "checking" << x.key();
@@ -164,166 +407,14 @@ void QWindowsFileSystemWatcherEngine::run()
}
}
-QStringList QWindowsFileSystemWatcherEngine::addPaths(const QStringList &paths,
- QStringList *files,
- QStringList *directories)
-{
- if (handles.isEmpty() || handles.count() == MAXIMUM_WAIT_OBJECTS)
- return paths;
-
- QMutexLocker locker(&mutex);
-
- QStringList p = paths;
- QMutableListIterator<QString> it(p);
- while (it.hasNext()) {
- QString path = it.next();
- QString normalPath = path;
- if ((normalPath.endsWith(QLatin1Char('/')) || normalPath.endsWith(QLatin1Char('\\')))
-#ifdef Q_OS_WINCE
- && normalPath.size() > 1)
-#else
- )
-#endif
- normalPath.chop(1);
- QFileInfo fileInfo(normalPath.toLower());
- if (!fileInfo.exists())
- continue;
-
- bool isDir = fileInfo.isDir();
- if (isDir) {
- if (directories->contains(path))
- continue;
- } else {
- if (files->contains(path))
- continue;
- }
-
- const QString absolutePath = isDir ? fileInfo.absoluteFilePath() : fileInfo.absolutePath();
- const uint flags = isDir
- ? (FILE_NOTIFY_CHANGE_DIR_NAME
- | FILE_NOTIFY_CHANGE_FILE_NAME)
- : (FILE_NOTIFY_CHANGE_DIR_NAME
- | FILE_NOTIFY_CHANGE_FILE_NAME
- | FILE_NOTIFY_CHANGE_ATTRIBUTES
- | FILE_NOTIFY_CHANGE_SIZE
- | FILE_NOTIFY_CHANGE_LAST_WRITE
- | FILE_NOTIFY_CHANGE_SECURITY);
-
- Handle handle = handleForDir.value(absolutePath);
- if (handle.handle == INVALID_HANDLE_VALUE || handle.flags != flags) {
- // Volume and folder paths need a trailing slash for proper notification
- // (e.g. "c:" -> "c:/").
- const QString effectiveAbsolutePath =
- isDir ? (absolutePath + QLatin1Char('/')) : absolutePath;
-
- QT_WA({
- handle.handle = FindFirstChangeNotificationW((TCHAR *) QDir::toNativeSeparators(effectiveAbsolutePath).utf16(),
- false, flags);
- },{
- handle.handle = FindFirstChangeNotificationA(QDir::toNativeSeparators(effectiveAbsolutePath).toLocal8Bit(),
- false, flags);
- })
- handle.flags = flags;
- if (handle.handle == INVALID_HANDLE_VALUE)
- continue;
- // qDebug() << "Added handle" << handle << "for" << absolutePath << "to watch" << fileInfo.absoluteFilePath();
- handles.append(handle.handle);
- handleForDir.insert(absolutePath, handle);
- }
-
- PathInfo pathInfo;
- pathInfo.absolutePath = absolutePath;
- pathInfo.isDir = isDir;
- pathInfo.path = path;
- pathInfo = fileInfo;
- QHash<QString, PathInfo> &h = pathInfoForHandle[handle.handle];
- if (!h.contains(fileInfo.absoluteFilePath())) {
- pathInfoForHandle[handle.handle].insert(fileInfo.absoluteFilePath(), pathInfo);
- if (isDir)
- directories->append(path);
- else
- files->append(path);
- }
-
- it.remove();
- }
-
- if (!isRunning()) {
- msg = '@';
- start();
- } else {
- wakeup();
- }
-
- return p;
-}
-
-QStringList QWindowsFileSystemWatcherEngine::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();
- QString normalPath = path;
- if (normalPath.endsWith(QLatin1Char('/')) || normalPath.endsWith(QLatin1Char('\\')))
- normalPath.chop(1);
- QFileInfo fileInfo(normalPath.toLower());
-
- QString absolutePath = fileInfo.absoluteFilePath();
- Handle handle = handleForDir.value(absolutePath);
- if (handle.handle == INVALID_HANDLE_VALUE) {
- // perhaps path is a file?
- absolutePath = fileInfo.absolutePath();
- handle = handleForDir.value(absolutePath);
- if (handle.handle == INVALID_HANDLE_VALUE)
- continue;
- }
-
- QHash<QString, PathInfo> &h = pathInfoForHandle[handle.handle];
- if (h.remove(fileInfo.absoluteFilePath())) {
- // ###
- files->removeAll(path);
- directories->removeAll(path);
-
- if (h.isEmpty()) {
- // qDebug() << "Closing handle" << handle;
- FindCloseChangeNotification(handle.handle); // This one might generate a notification
-
- int indexOfHandle = handles.indexOf(handle.handle);
- Q_ASSERT(indexOfHandle != -1);
- handles.remove(indexOfHandle);
-
- handleForDir.remove(absolutePath);
- // h is now invalid
-
- it.remove();
- }
- }
- }
-
- if (handleForDir.isEmpty()) {
- stop();
- locker.unlock();
- wait();
- locker.relock();
- } else {
- wakeup();
- }
-
- return p;
-}
-void QWindowsFileSystemWatcherEngine::stop()
+void QWindowsFileSystemWatcherEngineThread::stop()
{
msg = 'q';
SetEvent(handles.at(0));
}
-void QWindowsFileSystemWatcherEngine::wakeup()
+void QWindowsFileSystemWatcherEngineThread::wakeup()
{
msg = '@';
SetEvent(handles.at(0));
diff --git a/src/corelib/io/qfilesystemwatcher_win_p.h b/src/corelib/io/qfilesystemwatcher_win_p.h
index d0eecfc..405d255 100644
--- a/src/corelib/io/qfilesystemwatcher_win_p.h
+++ b/src/corelib/io/qfilesystemwatcher_win_p.h
@@ -57,7 +57,7 @@
#ifndef QT_NO_FILESYSTEMWATCHER
-#include <windows.h>
+#include <qt_windows.h>
#include <QtCore/qdatetime.h>
#include <QtCore/qfile.h>
@@ -68,27 +68,24 @@
QT_BEGIN_NAMESPACE
+class QWindowsFileSystemWatcherEngineThread;
+
+// Even though QWindowsFileSystemWatcherEngine is derived of QThread
+// via QFileSystemWatcher, it does not start a thread.
+// Instead QWindowsFileSystemWatcher creates QWindowsFileSystemWatcherEngineThreads
+// to do the actually watching.
class QWindowsFileSystemWatcherEngine : public QFileSystemWatcherEngine
{
Q_OBJECT
-
public:
QWindowsFileSystemWatcherEngine();
~QWindowsFileSystemWatcherEngine();
- void run();
-
QStringList addPaths(const QStringList &paths, QStringList *files, QStringList *directories);
QStringList removePaths(const QStringList &paths, QStringList *files, QStringList *directories);
void stop();
-private:
- void wakeup();
-
- QMutex mutex;
- QVector<HANDLE> handles;
- int msg;
class Handle
{
@@ -97,13 +94,12 @@ private:
uint flags;
Handle()
- : handle(INVALID_HANDLE_VALUE), flags(0u)
+ : handle(INVALID_HANDLE_VALUE), flags(0u)
{ }
Handle(const Handle &other)
- : handle(other.handle), flags(other.flags)
+ : handle(other.handle), flags(other.flags)
{ }
};
- QHash<QString, Handle> handleForDir;
class PathInfo {
public:
@@ -118,7 +114,7 @@ private:
QDateTime lastModified;
PathInfo &operator=(const QFileInfo &fileInfo)
- {
+ {
ownerId = fileInfo.ownerId();
groupId = fileInfo.groupId();
permissions = fileInfo.permissions();
@@ -134,8 +130,35 @@ private:
|| lastModified != fileInfo.lastModified());
}
};
- QHash<HANDLE, QHash<QString, PathInfo> > pathInfoForHandle;
+private:
+ QList<QWindowsFileSystemWatcherEngineThread *> threads;
+
+};
+
+class QWindowsFileSystemWatcherEngineThread : public QThread
+{
+ Q_OBJECT
+
+public:
+ QWindowsFileSystemWatcherEngineThread();
+ ~QWindowsFileSystemWatcherEngineThread();
+ void run();
+ void stop();
+ void wakeup();
+
+ QMutex mutex;
+ QVector<HANDLE> handles;
+ int msg;
+
+ QHash<QString, QWindowsFileSystemWatcherEngine::Handle> handleForDir;
+
+ QHash<HANDLE, QHash<QString, QWindowsFileSystemWatcherEngine::PathInfo> > pathInfoForHandle;
+
+Q_SIGNALS:
+ void fileChanged(const QString &path, bool removed);
+ void directoryChanged(const QString &path, bool removed);
};
+
#endif // QT_NO_FILESYSTEMWATCHER
QT_END_NAMESPACE
diff --git a/src/corelib/io/qfsfileengine.cpp b/src/corelib/io/qfsfileengine.cpp
index e32b818..3a43ec7 100644
--- a/src/corelib/io/qfsfileengine.cpp
+++ b/src/corelib/io/qfsfileengine.cpp
@@ -44,12 +44,16 @@
#include "qdatetime.h"
#include "qdiriterator.h"
#include "qset.h"
+#include <QtCore/qdebug.h>
#ifndef QT_NO_FSFILEENGINE
#if !defined(Q_OS_WINCE)
#include <errno.h>
#endif
+#if defined(Q_OS_UNIX)
+#include "private/qcore_unix_p.h"
+#endif
#include <stdio.h>
QT_BEGIN_NAMESPACE
@@ -568,7 +572,7 @@ bool QFSFileEnginePrivate::seekFdFh(qint64 pos)
} else {
// Unbuffered stdio mode.
if (QT_LSEEK(fd, pos, SEEK_SET) == -1) {
- qWarning("QFile::at: Cannot set file position %lld", pos);
+ qWarning() << "QFile::at: Cannot set file position" << pos;
q->setError(QFile::PositionError, qt_error_string(errno));
return false;
}
diff --git a/src/corelib/io/qfsfileengine.h b/src/corelib/io/qfsfileengine.h
index 0fd87a4..feca09b 100644
--- a/src/corelib/io/qfsfileengine.h
+++ b/src/corelib/io/qfsfileengine.h
@@ -56,7 +56,7 @@ class QFSFileEnginePrivate;
class Q_CORE_EXPORT QFSFileEngine : public QAbstractFileEngine
{
- Q_DECLARE_SCOPED_PRIVATE(QFSFileEngine)
+ Q_DECLARE_PRIVATE(QFSFileEngine)
public:
QFSFileEngine();
explicit QFSFileEngine(const QString &file);
diff --git a/src/corelib/io/qfsfileengine_iterator_win.cpp b/src/corelib/io/qfsfileengine_iterator_win.cpp
index 2336542..dd4ddf3 100644
--- a/src/corelib/io/qfsfileengine_iterator_win.cpp
+++ b/src/corelib/io/qfsfileengine_iterator_win.cpp
@@ -79,11 +79,7 @@ void QFSFileEngineIteratorPlatformSpecificData::saveCurrentFileName()
it->currentEntry = uncShares.at(uncShareIndex - 1);
} else {
// Local directory
- QT_WA({
- it->currentEntry = QString::fromUtf16((unsigned short *)findData.cFileName);
- } , {
- it->currentEntry = QString::fromLocal8Bit((const char *)findData.cFileName);
- });
+ it->currentEntry = QString::fromWCharArray(findData.cFileName);
}
}
@@ -97,17 +93,10 @@ void QFSFileEngineIterator::advance()
if (platform->uncFallback) {
++platform->uncShareIndex;
} else if (platform->findFileHandle != INVALID_HANDLE_VALUE) {
- QT_WA({
- if (!FindNextFile(platform->findFileHandle, &platform->findData)) {
- platform->done = true;
- FindClose(platform->findFileHandle);
- }
- } , {
- if (!FindNextFileA(platform->findFileHandle, (WIN32_FIND_DATAA *)&platform->findData)) {
- platform->done = true;
- FindClose(platform->findFileHandle);
- }
- });
+ if (!FindNextFile(platform->findFileHandle, &platform->findData)) {
+ platform->done = true;
+ FindClose(platform->findFileHandle);
+ }
}
}
@@ -141,15 +130,8 @@ bool QFSFileEngineIterator::hasNext() const
path.append(QLatin1Char('/'));
path.append(QLatin1String("*.*"));
- QT_WA({
- QString fileName = QFSFileEnginePrivate::longFileName(path);
- platform->findFileHandle = FindFirstFileW((TCHAR *)fileName.utf16(),
- &platform->findData);
- }, {
- // Cast is safe, since char is at end of WIN32_FIND_DATA
- platform->findFileHandle = FindFirstFileA(QFSFileEnginePrivate::win95Name(path),
- (WIN32_FIND_DATAA*)&platform->findData);
- });
+ QString fileName = QFSFileEnginePrivate::longFileName(path);
+ platform->findFileHandle = FindFirstFile((const wchar_t *)fileName.utf16(), &platform->findData);
if (platform->findFileHandle == INVALID_HANDLE_VALUE) {
if (path.startsWith(QLatin1String("//"))) {
diff --git a/src/corelib/io/qfsfileengine_p.h b/src/corelib/io/qfsfileengine_p.h
index 5aef229..864599f 100644
--- a/src/corelib/io/qfsfileengine_p.h
+++ b/src/corelib/io/qfsfileengine_p.h
@@ -72,7 +72,6 @@ class QFSFileEnginePrivate : public QAbstractFileEnginePrivate
public:
#ifdef Q_WS_WIN
- static QByteArray win95Name(const QString &path);
static QString longFileName(const QString &path);
#endif
static QString canonicalized(const QString &path);
@@ -151,8 +150,7 @@ public:
#if defined(Q_OS_WIN32) || defined(Q_OS_WINCE)
static void resolveLibs();
- static bool resolveUNCLibs_NT();
- static bool resolveUNCLibs_9x();
+ static bool resolveUNCLibs();
static bool uncListSharesOnServer(const QString &server, QStringList *list);
#endif
diff --git a/src/corelib/io/qfsfileengine_unix.cpp b/src/corelib/io/qfsfileengine_unix.cpp
index 2421282..fa2aaf7 100644
--- a/src/corelib/io/qfsfileengine_unix.cpp
+++ b/src/corelib/io/qfsfileengine_unix.cpp
@@ -42,6 +42,7 @@
#include "qplatformdefs.h"
#include "qabstractfileengine.h"
#include "private/qfsfileengine_p.h"
+#include "private/qcore_unix_p.h"
#ifndef QT_NO_FSFILEENGINE
@@ -110,6 +111,12 @@ static QByteArray openModeToFopenMode(QIODevice::OpenMode flags, const QString &
if (flags & QIODevice::ReadOnly)
mode += '+';
}
+
+#if defined(__GLIBC__) && (__GLIBC__ * 0x100 + __GLIBC_MINOR__) >= 0x0207
+ // must be glibc >= 2.7
+ mode += 'e';
+#endif
+
return mode;
}
@@ -138,12 +145,6 @@ static int openModeToOpenFlags(QIODevice::OpenMode mode)
oflags |= QT_OPEN_TRUNC;
}
-#ifdef O_CLOEXEC
- // supported on Linux >= 2.6.23; avoids one extra system call
- // and avoids a race condition: if another thread forks, we could
- // end up leaking a file descriptor...
- oflags |= O_CLOEXEC;
-#endif
return oflags;
}
@@ -197,11 +198,6 @@ bool QFSFileEnginePrivate::nativeOpen(QIODevice::OpenMode openMode)
}
}
-#ifndef O_CLOEXEC
- // not needed on Linux >= 2.6.23
- setCloseOnExec(fd); // ignore failure
-#endif
-
// Seek to the end when in Append mode.
if (flags & QFile::Append) {
int ret;
@@ -468,7 +464,7 @@ bool QFSFileEngine::mkdir(const QString &name, bool createParentDirectories) con
if (QT_STAT(chunk, &st) != -1) {
if ((st.st_mode & S_IFMT) != S_IFDIR)
return false;
- } else if (::mkdir(chunk, 0777) != 0) {
+ } else if (QT_MKDIR(chunk, 0777) != 0) {
return false;
}
}
@@ -479,7 +475,7 @@ bool QFSFileEngine::mkdir(const QString &name, bool createParentDirectories) con
if (dirName[dirName.length() - 1] == QLatin1Char('/'))
dirName = dirName.left(dirName.length() - 1);
#endif
- return (::mkdir(QFile::encodeName(dirName), 0777) == 0);
+ return (QT_MKDIR(QFile::encodeName(dirName), 0777) == 0);
}
bool QFSFileEngine::rmdir(const QString &name, bool recurseParentDirectories) const
@@ -521,7 +517,7 @@ bool QFSFileEngine::caseSensitive() const
bool QFSFileEngine::setCurrentPath(const QString &path)
{
int r;
- r = ::chdir(QFile::encodeName(path));
+ r = QT_CHDIR(QFile::encodeName(path));
return r >= 0;
}
diff --git a/src/corelib/io/qfsfileengine_win.cpp b/src/corelib/io/qfsfileengine_win.cpp
index 3b2bc60..68eef5f 100644
--- a/src/corelib/io/qfsfileengine_win.cpp
+++ b/src/corelib/io/qfsfileengine_win.cpp
@@ -109,9 +109,9 @@ static QString qfsPrivateCurrentDir = QLatin1String("");
QT_BEGIN_INCLUDE_NAMESPACE
typedef DWORD (WINAPI *PtrGetNamedSecurityInfoW)(LPWSTR, SE_OBJECT_TYPE, SECURITY_INFORMATION, PSID*, PSID*, PACL*, PACL*, PSECURITY_DESCRIPTOR*);
static PtrGetNamedSecurityInfoW ptrGetNamedSecurityInfoW = 0;
-typedef DECLSPEC_IMPORT BOOL (WINAPI *PtrLookupAccountSidW)(LPCWSTR, PSID, LPWSTR, LPDWORD, LPWSTR, LPDWORD, PSID_NAME_USE);
+typedef BOOL (WINAPI *PtrLookupAccountSidW)(LPCWSTR, PSID, LPWSTR, LPDWORD, LPWSTR, LPDWORD, PSID_NAME_USE);
static PtrLookupAccountSidW ptrLookupAccountSidW = 0;
-typedef DECLSPEC_IMPORT BOOL (WINAPI *PtrAllocateAndInitializeSid)(PSID_IDENTIFIER_AUTHORITY, BYTE, DWORD, DWORD, DWORD, DWORD, DWORD, DWORD, DWORD, DWORD, PSID*);
+typedef BOOL (WINAPI *PtrAllocateAndInitializeSid)(PSID_IDENTIFIER_AUTHORITY, BYTE, DWORD, DWORD, DWORD, DWORD, DWORD, DWORD, DWORD, DWORD, PSID*);
static PtrAllocateAndInitializeSid ptrAllocateAndInitializeSid = 0;
typedef VOID (WINAPI *PtrBuildTrusteeWithSidW)(PTRUSTEE_W, PSID);
static PtrBuildTrusteeWithSidW ptrBuildTrusteeWithSidW = 0;
@@ -119,7 +119,7 @@ typedef VOID (WINAPI *PtrBuildTrusteeWithNameW)(PTRUSTEE_W, unsigned short*);
static PtrBuildTrusteeWithNameW ptrBuildTrusteeWithNameW = 0;
typedef DWORD (WINAPI *PtrGetEffectiveRightsFromAclW)(PACL, PTRUSTEE_W, OUT PACCESS_MASK);
static PtrGetEffectiveRightsFromAclW ptrGetEffectiveRightsFromAclW = 0;
-typedef DECLSPEC_IMPORT PVOID (WINAPI *PtrFreeSid)(PSID);
+typedef PVOID (WINAPI *PtrFreeSid)(PSID);
static PtrFreeSid ptrFreeSid = 0;
static TRUSTEE_W currentUserTrusteeW;
@@ -152,66 +152,64 @@ void QFSFileEnginePrivate::resolveLibs()
triedResolve = true;
#if !defined(Q_OS_WINCE)
- if(QSysInfo::WindowsVersion & QSysInfo::WV_NT_based) {
- HINSTANCE advapiHnd = LoadLibraryW(L"advapi32");
- if (advapiHnd) {
- ptrGetNamedSecurityInfoW = (PtrGetNamedSecurityInfoW)GetProcAddress(advapiHnd, "GetNamedSecurityInfoW");
- ptrLookupAccountSidW = (PtrLookupAccountSidW)GetProcAddress(advapiHnd, "LookupAccountSidW");
- ptrAllocateAndInitializeSid = (PtrAllocateAndInitializeSid)GetProcAddress(advapiHnd, "AllocateAndInitializeSid");
- ptrBuildTrusteeWithSidW = (PtrBuildTrusteeWithSidW)GetProcAddress(advapiHnd, "BuildTrusteeWithSidW");
- ptrBuildTrusteeWithNameW = (PtrBuildTrusteeWithNameW)GetProcAddress(advapiHnd, "BuildTrusteeWithNameW");
- ptrGetEffectiveRightsFromAclW = (PtrGetEffectiveRightsFromAclW)GetProcAddress(advapiHnd, "GetEffectiveRightsFromAclW");
- ptrFreeSid = (PtrFreeSid)GetProcAddress(advapiHnd, "FreeSid");
- }
- if (ptrBuildTrusteeWithNameW) {
- HINSTANCE versionHnd = LoadLibraryW(L"version");
- if (versionHnd) {
- typedef DWORD (WINAPI *PtrGetFileVersionInfoSizeW)(LPWSTR lptstrFilename,LPDWORD lpdwHandle);
- PtrGetFileVersionInfoSizeW ptrGetFileVersionInfoSizeW = (PtrGetFileVersionInfoSizeW)GetProcAddress(versionHnd, "GetFileVersionInfoSizeW");
- typedef BOOL (WINAPI *PtrGetFileVersionInfoW)(LPWSTR lptstrFilename,DWORD dwHandle,DWORD dwLen,LPVOID lpData);
- PtrGetFileVersionInfoW ptrGetFileVersionInfoW = (PtrGetFileVersionInfoW)GetProcAddress(versionHnd, "GetFileVersionInfoW");
- typedef BOOL (WINAPI *PtrVerQueryValueW)(const LPVOID pBlock,LPWSTR lpSubBlock,LPVOID *lplpBuffer,PUINT puLen);
- PtrVerQueryValueW ptrVerQueryValueW = (PtrVerQueryValueW)GetProcAddress(versionHnd, "VerQueryValueW");
- if(ptrGetFileVersionInfoSizeW && ptrGetFileVersionInfoW && ptrVerQueryValueW) {
- DWORD fakeHandle;
- DWORD versionSize = ptrGetFileVersionInfoSizeW(L"secur32.dll", &fakeHandle);
- if(versionSize) {
- LPVOID versionData;
- versionData = malloc(versionSize);
- if(ptrGetFileVersionInfoW(L"secur32.dll", 0, versionSize, versionData)) {
- UINT puLen;
- VS_FIXEDFILEINFO *pLocalInfo;
- if(ptrVerQueryValueW(versionData, L"\\", (void**)&pLocalInfo, &puLen)) {
- WORD wVer1, wVer2, wVer3, wVer4;
- wVer1 = HIWORD(pLocalInfo->dwFileVersionMS);
- wVer2 = LOWORD(pLocalInfo->dwFileVersionMS);
- wVer3 = HIWORD(pLocalInfo->dwFileVersionLS);
- wVer4 = LOWORD(pLocalInfo->dwFileVersionLS);
- // It will not work with secur32.dll version 5.0.2195.2862
- if(!(wVer1 == 5 && wVer2 == 0 && wVer3 == 2195 && (wVer4 == 2862 || wVer4 == 4587))) {
- HINSTANCE userHnd = LoadLibraryW(L"secur32");
- if (userHnd) {
- typedef BOOL (WINAPI *PtrGetUserNameExW)(EXTENDED_NAME_FORMAT nameFormat, ushort* lpBuffer, LPDWORD nSize);
- PtrGetUserNameExW ptrGetUserNameExW = (PtrGetUserNameExW)GetProcAddress(userHnd, "GetUserNameExW");
- if(ptrGetUserNameExW) {
- static TCHAR buffer[258];
- DWORD bufferSize = 257;
- ptrGetUserNameExW(NameSamCompatible, (ushort*)buffer, &bufferSize);
- ptrBuildTrusteeWithNameW(&currentUserTrusteeW, (ushort*)buffer);
- }
- FreeLibrary(userHnd);
+ HINSTANCE advapiHnd = LoadLibraryW(L"advapi32");
+ if (advapiHnd) {
+ ptrGetNamedSecurityInfoW = (PtrGetNamedSecurityInfoW)GetProcAddress(advapiHnd, "GetNamedSecurityInfoW");
+ ptrLookupAccountSidW = (PtrLookupAccountSidW)GetProcAddress(advapiHnd, "LookupAccountSidW");
+ ptrAllocateAndInitializeSid = (PtrAllocateAndInitializeSid)GetProcAddress(advapiHnd, "AllocateAndInitializeSid");
+ ptrBuildTrusteeWithSidW = (PtrBuildTrusteeWithSidW)GetProcAddress(advapiHnd, "BuildTrusteeWithSidW");
+ ptrBuildTrusteeWithNameW = (PtrBuildTrusteeWithNameW)GetProcAddress(advapiHnd, "BuildTrusteeWithNameW");
+ ptrGetEffectiveRightsFromAclW = (PtrGetEffectiveRightsFromAclW)GetProcAddress(advapiHnd, "GetEffectiveRightsFromAclW");
+ ptrFreeSid = (PtrFreeSid)GetProcAddress(advapiHnd, "FreeSid");
+ }
+ if (ptrBuildTrusteeWithNameW) {
+ HINSTANCE versionHnd = LoadLibraryW(L"version");
+ if (versionHnd) {
+ typedef DWORD (WINAPI *PtrGetFileVersionInfoSizeW)(LPCWSTR lptstrFilename,LPDWORD lpdwHandle);
+ PtrGetFileVersionInfoSizeW ptrGetFileVersionInfoSizeW = (PtrGetFileVersionInfoSizeW)GetProcAddress(versionHnd, "GetFileVersionInfoSizeW");
+ typedef BOOL (WINAPI *PtrGetFileVersionInfoW)(LPCWSTR lptstrFilename,DWORD dwHandle,DWORD dwLen,LPVOID lpData);
+ PtrGetFileVersionInfoW ptrGetFileVersionInfoW = (PtrGetFileVersionInfoW)GetProcAddress(versionHnd, "GetFileVersionInfoW");
+ typedef BOOL (WINAPI *PtrVerQueryValueW)(const LPVOID pBlock,LPCWSTR lpSubBlock,LPVOID *lplpBuffer,PUINT puLen);
+ PtrVerQueryValueW ptrVerQueryValueW = (PtrVerQueryValueW)GetProcAddress(versionHnd, "VerQueryValueW");
+ if(ptrGetFileVersionInfoSizeW && ptrGetFileVersionInfoW && ptrVerQueryValueW) {
+ DWORD fakeHandle;
+ DWORD versionSize = ptrGetFileVersionInfoSizeW(L"secur32.dll", &fakeHandle);
+ if(versionSize) {
+ LPVOID versionData;
+ versionData = malloc(versionSize);
+ if(ptrGetFileVersionInfoW(L"secur32.dll", 0, versionSize, versionData)) {
+ UINT puLen;
+ VS_FIXEDFILEINFO *pLocalInfo;
+ if(ptrVerQueryValueW(versionData, L"\\", (void**)&pLocalInfo, &puLen)) {
+ WORD wVer1, wVer2, wVer3, wVer4;
+ wVer1 = HIWORD(pLocalInfo->dwFileVersionMS);
+ wVer2 = LOWORD(pLocalInfo->dwFileVersionMS);
+ wVer3 = HIWORD(pLocalInfo->dwFileVersionLS);
+ wVer4 = LOWORD(pLocalInfo->dwFileVersionLS);
+ // It will not work with secur32.dll version 5.0.2195.2862
+ if(!(wVer1 == 5 && wVer2 == 0 && wVer3 == 2195 && (wVer4 == 2862 || wVer4 == 4587))) {
+ HINSTANCE userHnd = LoadLibraryW(L"secur32");
+ if (userHnd) {
+ typedef BOOL (WINAPI *PtrGetUserNameExW)(EXTENDED_NAME_FORMAT nameFormat, ushort* lpBuffer, LPDWORD nSize);
+ PtrGetUserNameExW ptrGetUserNameExW = (PtrGetUserNameExW)GetProcAddress(userHnd, "GetUserNameExW");
+ if(ptrGetUserNameExW) {
+ static wchar_t buffer[258];
+ DWORD bufferSize = 257;
+ ptrGetUserNameExW(NameSamCompatible, (ushort*)buffer, &bufferSize);
+ ptrBuildTrusteeWithNameW(&currentUserTrusteeW, (ushort*)buffer);
}
+ FreeLibrary(userHnd);
}
}
}
- free(versionData);
}
+ free(versionData);
}
- FreeLibrary(versionHnd);
}
+ FreeLibrary(versionHnd);
}
ptrOpenProcessToken = (PtrOpenProcessToken)GetProcAddress(advapiHnd, "OpenProcessToken");
- HINSTANCE userenvHnd = LoadLibraryW(L"userenv");
+ HINSTANCE userenvHnd = LoadLibraryW(L"userenv");
if (userenvHnd) {
ptrGetUserProfileDirectoryW = (PtrGetUserProfileDirectoryW)GetProcAddress(userenvHnd, "GetUserProfileDirectoryW");
}
@@ -225,120 +223,60 @@ void QFSFileEnginePrivate::resolveLibs()
#endif // QT_NO_LIBRARY
// UNC functions NT
-typedef DWORD (WINAPI *PtrNetShareEnum_NT)(LPWSTR, DWORD, LPBYTE*, DWORD, LPDWORD, LPDWORD, LPDWORD);
-static PtrNetShareEnum_NT ptrNetShareEnum_NT = 0;
-typedef DWORD (WINAPI *PtrNetApiBufferFree_NT)(LPVOID);
-static PtrNetApiBufferFree_NT ptrNetApiBufferFree_NT = 0;
-typedef struct _SHARE_INFO_1_NT {
+typedef DWORD (WINAPI *PtrNetShareEnum)(LPWSTR, DWORD, LPBYTE*, DWORD, LPDWORD, LPDWORD, LPDWORD);
+static PtrNetShareEnum ptrNetShareEnum = 0;
+typedef DWORD (WINAPI *PtrNetApiBufferFree)(LPVOID);
+static PtrNetApiBufferFree ptrNetApiBufferFree = 0;
+typedef struct _SHARE_INFO_1 {
LPWSTR shi1_netname;
DWORD shi1_type;
LPWSTR shi1_remark;
-} SHARE_INFO_1_NT;
+} SHARE_INFO_1;
-bool QFSFileEnginePrivate::resolveUNCLibs_NT()
+bool QFSFileEnginePrivate::resolveUNCLibs()
{
static bool triedResolve = false;
if (!triedResolve) {
#ifndef QT_NO_THREAD
QMutexLocker locker(QMutexPool::globalInstanceGet(&triedResolve));
if (triedResolve) {
- return ptrNetShareEnum_NT && ptrNetApiBufferFree_NT;
+ return ptrNetShareEnum && ptrNetApiBufferFree;
}
#endif
triedResolve = true;
#if !defined(Q_OS_WINCE)
HINSTANCE hLib = LoadLibraryW(L"Netapi32");
if (hLib) {
- ptrNetShareEnum_NT = (PtrNetShareEnum_NT)GetProcAddress(hLib, "NetShareEnum");
- if (ptrNetShareEnum_NT)
- ptrNetApiBufferFree_NT = (PtrNetApiBufferFree_NT)GetProcAddress(hLib, "NetApiBufferFree");
- }
-#endif
- }
- return ptrNetShareEnum_NT && ptrNetApiBufferFree_NT;
-}
-
-// UNC functions 9x
-typedef DWORD (WINAPI *PtrNetShareEnum_9x)(const char FAR *, short, char FAR *, unsigned short, unsigned short FAR *, unsigned short FAR *);
-static PtrNetShareEnum_9x ptrNetShareEnum_9x = 0;
-#ifdef LM20_NNLEN
-# define LM20_NNLEN_9x LM20_NNLEN
-#else
-# define LM20_NNLEN_9x 12
-#endif
-typedef struct _SHARE_INFO_1_9x {
- char shi1_netname[LM20_NNLEN_9x+1];
- char shi1_pad1;
- unsigned short shi1_type;
- char FAR* shi1_remark;
-} SHARE_INFO_1_9x;
-
-bool QFSFileEnginePrivate::resolveUNCLibs_9x()
-{
- static bool triedResolve = false;
- if (!triedResolve) {
-#ifndef QT_NO_THREAD
- QMutexLocker locker(QMutexPool::globalInstanceGet(&triedResolve));
- if (triedResolve) {
- return ptrNetShareEnum_9x;
+ ptrNetShareEnum = (PtrNetShareEnum)GetProcAddress(hLib, "NetShareEnum");
+ if (ptrNetShareEnum)
+ ptrNetApiBufferFree = (PtrNetApiBufferFree)GetProcAddress(hLib, "NetApiBufferFree");
}
#endif
- triedResolve = true;
-#if !defined(Q_OS_WINCE)
- HINSTANCE hLib = LoadLibraryA("Svrapi");
- if (hLib)
- ptrNetShareEnum_9x = (PtrNetShareEnum_9x)GetProcAddress(hLib, "NetShareEnum");
-#endif
}
- return ptrNetShareEnum_9x;
+ return ptrNetShareEnum && ptrNetApiBufferFree;
}
bool QFSFileEnginePrivate::uncListSharesOnServer(const QString &server, QStringList *list)
{
- if (resolveUNCLibs_NT()) {
- SHARE_INFO_1_NT *BufPtr, *p;
+ if (resolveUNCLibs()) {
+ SHARE_INFO_1 *BufPtr, *p;
DWORD res;
DWORD er=0,tr=0,resume=0, i;
do {
- res = ptrNetShareEnum_NT((wchar_t*)server.utf16(), 1, (LPBYTE *)&BufPtr, DWORD(-1), &er, &tr, &resume);
+ res = ptrNetShareEnum((wchar_t*)server.utf16(), 1, (LPBYTE *)&BufPtr, DWORD(-1), &er, &tr, &resume);
if (res == ERROR_SUCCESS || res == ERROR_MORE_DATA) {
p=BufPtr;
for (i = 1; i <= er; ++i) {
if (list && p->shi1_type == 0)
- list->append(QString::fromUtf16((unsigned short *)p->shi1_netname));
+ list->append(QString::fromWCharArray(p->shi1_netname));
p++;
}
}
- ptrNetApiBufferFree_NT(BufPtr);
+ ptrNetApiBufferFree(BufPtr);
} while (res==ERROR_MORE_DATA);
return res == ERROR_SUCCESS;
- } else if (resolveUNCLibs_9x()) {
- SHARE_INFO_1_9x *pBuf = 0;
- short cbBuffer;
- unsigned short nEntriesRead = 0;
- unsigned short nTotalEntries = 0;
- short numBuffs = 20;
- DWORD nStatus = 0;
- do {
- cbBuffer = numBuffs * sizeof(SHARE_INFO_1_9x);
- pBuf = (SHARE_INFO_1_9x *)malloc(cbBuffer);
- if (pBuf) {
- nStatus = ptrNetShareEnum_9x(server.toLocal8Bit().constData(), 1, (char FAR *)pBuf, cbBuffer, &nEntriesRead, &nTotalEntries);
- if ((nStatus == ERROR_SUCCESS)) {
- for (int i = 0; i < nEntriesRead; ++i) {
- if (list && pBuf[i].shi1_type == 0)
- list->append(QString::fromLocal8Bit(pBuf[i].shi1_netname));
- }
- free(pBuf);
- break;
- }
- free(pBuf);
- numBuffs *=2;
- }
- } while (nStatus == ERROR_MORE_DATA);
- return nStatus == ERROR_SUCCESS;
}
return false;
}
@@ -399,39 +337,19 @@ static bool uncShareExists(const QString &server)
return false;
}
-#if !defined(Q_OS_WINCE)
-// If you change this function, remember to also change the UNICODE version
-static QString nativeAbsoluteFilePathA(const QString &path)
-{
- QString ret;
- QVarLengthArray<char, MAX_PATH> buf(MAX_PATH);
- char *fileName = 0;
- QByteArray ba = path.toLocal8Bit();
- DWORD retLen = GetFullPathNameA(ba.constData(), buf.size(), buf.data(), &fileName);
- if (retLen > (DWORD)buf.size()) {
- buf.resize(retLen);
- retLen = GetFullPathNameA(ba.constData(), buf.size(), buf.data(), &fileName);
- }
- if (retLen != 0)
- ret = QString::fromLocal8Bit(buf.data(), retLen);
- return ret;
-}
-#endif
-
-// If you change this function, remember to also change the NON-UNICODE version
-static QString nativeAbsoluteFilePathW(const QString &path)
+static QString nativeAbsoluteFilePathCore(const QString &path)
{
QString ret;
#if !defined(Q_OS_WINCE)
QVarLengthArray<wchar_t, MAX_PATH> buf(MAX_PATH);
wchar_t *fileName = 0;
- DWORD retLen = GetFullPathNameW((wchar_t*)path.utf16(), buf.size(), buf.data(), &fileName);
+ DWORD retLen = GetFullPathName((wchar_t*)path.utf16(), buf.size(), buf.data(), &fileName);
if (retLen > (DWORD)buf.size()) {
buf.resize(retLen);
- retLen = GetFullPathNameW((wchar_t*)path.utf16(), buf.size(), buf.data(), &fileName);
+ retLen = GetFullPathName((wchar_t*)path.utf16(), buf.size(), buf.data(), &fileName);
}
if (retLen != 0)
- ret = QString::fromUtf16((unsigned short *)buf.data(), retLen);
+ ret = QString::fromWCharArray(buf.data(), retLen);
#else
if (path.startsWith(QLatin1Char('/')) || path.startsWith(QLatin1Char('\\')))
ret = QDir::toNativeSeparators(path);
@@ -443,7 +361,7 @@ static QString nativeAbsoluteFilePathW(const QString &path)
static QString nativeAbsoluteFilePath(const QString &path)
{
- QString absPath = QT_WA_INLINE(nativeAbsoluteFilePathW(path), nativeAbsoluteFilePathA(path));
+ QString absPath = nativeAbsoluteFilePathCore(path);
// This is really ugly, but GetFullPathName strips off whitespace at the end.
// If you for instance write ". " in the lineedit of QFileDialog,
// (which is an invalid filename) this function will strip the space off and viola,
@@ -461,26 +379,6 @@ static QString nativeAbsoluteFilePath(const QString &path)
return absPath;
}
-QByteArray QFSFileEnginePrivate::win95Name(const QString &path)
-{
- QString ret(path);
- if(path.length() > 1 && path[0] == QLatin1Char('/') && path[1] == QLatin1Char('/')) {
- // Win95 cannot handle slash-slash needs slosh-slosh.
- ret[0] = QLatin1Char('\\');
- ret[1] = QLatin1Char('\\');
- int n = ret.indexOf(QLatin1Char('/'));
- if(n >= 0)
- ret[n] = QLatin1Char('\\');
- } else if(path.length() > 3 && path[2] == QLatin1Char('/') && path[3] == QLatin1Char('/')) {
- ret[2] = QLatin1Char('\\');
- ret.remove(3, 1);
- int n = ret.indexOf(QLatin1Char('/'));
- if(n >= 0)
- ret[n] = QLatin1Char('\\');
- }
- return ret.toLocal8Bit();
-}
-
/*!
\internal
*/
@@ -507,13 +405,8 @@ QString QFSFileEnginePrivate::longFileName(const QString &path)
*/
void QFSFileEnginePrivate::nativeInitFileName()
{
- QT_WA({
- QString path = longFileName(QDir::toNativeSeparators(fixIfRelativeUncPath(filePath)));
- nativeFilePath = QByteArray((const char *)path.utf16(), path.size() * 2 + 1);
- }, {
- QString path = fixIfRelativeUncPath(filePath);
- nativeFilePath = win95Name(path).replace('/', '\\');
- });
+ QString path = longFileName(QDir::toNativeSeparators(fixIfRelativeUncPath(filePath)));
+ nativeFilePath = QByteArray((const char *)path.utf16(), path.size() * 2 + 1);
}
/*
@@ -539,23 +432,13 @@ bool QFSFileEnginePrivate::nativeOpen(QIODevice::OpenMode openMode)
? OPEN_ALWAYS : OPEN_EXISTING;
// Create the file handle.
- QT_WA({
- fileHandle = CreateFileW((TCHAR *)nativeFilePath.constData(),
- accessRights,
- shareMode,
- &securityAtts,
- creationDisp,
- FILE_ATTRIBUTE_NORMAL,
- NULL);
- }, {
- fileHandle = CreateFileA(nativeFilePath.constData(),
- accessRights,
- shareMode,
- &securityAtts,
- creationDisp,
- FILE_ATTRIBUTE_NORMAL,
- NULL);
- });
+ fileHandle = CreateFile((const wchar_t*)nativeFilePath.constData(),
+ accessRights,
+ shareMode,
+ &securityAtts,
+ creationDisp,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
// Bail out on error.
if (fileHandle == INVALID_HANDLE_VALUE) {
@@ -641,15 +524,31 @@ qint64 QFSFileEnginePrivate::nativeSize() const
// Not-open mode, where the file name is known: We'll check the
// file system directly.
if (openMode == QIODevice::NotOpen && !nativeFilePath.isEmpty()) {
- bool ok = false;
WIN32_FILE_ATTRIBUTE_DATA attribData;
- QT_WA({
- ok = ::GetFileAttributesExW((TCHAR *)nativeFilePath.constData(),
+ bool ok = ::GetFileAttributesEx((const wchar_t*)nativeFilePath.constData(),
GetFileExInfoStandard, &attribData);
- } , {
- ok = ::GetFileAttributesExA(nativeFilePath.constData(),
- GetFileExInfoStandard, &attribData);
- });
+ if (!ok) {
+ int errorCode = GetLastError();
+ if (errorCode == ERROR_ACCESS_DENIED || errorCode == ERROR_SHARING_VIOLATION) {
+ QByteArray path = nativeFilePath;
+ // path for the FindFirstFile should not end with a trailing slash
+ while (path.endsWith('\\'))
+ path.chop(1);
+
+ // FindFirstFile can not handle drives
+ if (!path.endsWith(':')) {
+ WIN32_FIND_DATA findData;
+ HANDLE hFind = ::FindFirstFile((const wchar_t*)path.constData(),
+ &findData);
+ if (hFind != INVALID_HANDLE_VALUE) {
+ ::FindClose(hFind);
+ ok = true;
+ attribData.nFileSizeHigh = findData.nFileSizeHigh;
+ attribData.nFileSizeLow = findData.nFileSizeLow;
+ }
+ }
+ }
+ }
if (ok) {
qint64 size = attribData.nFileSizeHigh;
size <<= 32;
@@ -711,28 +610,28 @@ qint64 QFSFileEnginePrivate::nativePos() const
if (fileHandle == INVALID_HANDLE_VALUE)
return 0;
-#if !defined(QT_NO_LIBRARY)
+#if !defined(QT_NO_LIBRARY) && !defined(Q_OS_WINCE)
QFSFileEnginePrivate::resolveLibs();
if (!ptrSetFilePointerEx) {
#endif
- DWORD newFilePointer = SetFilePointer(fileHandle, 0, NULL, FILE_CURRENT);
- if (newFilePointer == 0xFFFFFFFF) {
+ LARGE_INTEGER filepos;
+ filepos.HighPart = 0;
+ DWORD newFilePointer = SetFilePointer(fileHandle, 0, &filepos.HighPart, FILE_CURRENT);
+ if (newFilePointer == 0xFFFFFFFF && GetLastError() != NO_ERROR) {
thatQ->setError(QFile::UnspecifiedError, qt_error_string());
return 0;
}
- // Note: returns <4GB; does not work with large files. This is the
- // case for MOC, UIC, qmake and other bootstrapped tools, and for
- // Win9x/ME.
- return qint64(newFilePointer);
-#if !defined(QT_NO_LIBRARY)
+ // Note: This is the case for MOC, UIC, qmake and other
+ // bootstrapped tools, and for Windows CE.
+ filepos.LowPart = newFilePointer;
+ return filepos.QuadPart;
+#if !defined(QT_NO_LIBRARY) && !defined(Q_OS_WINCE)
}
- // This approach supports large files.
LARGE_INTEGER currentFilePos;
LARGE_INTEGER offset;
- offset.LowPart = 0;
- offset.HighPart = 0;
+ offset.QuadPart = 0;
if (!ptrSetFilePointerEx(fileHandle, offset, &currentFilePos, FILE_CURRENT)) {
thatQ->setError(QFile::UnspecifiedError, qt_error_string());
return 0;
@@ -755,28 +654,27 @@ bool QFSFileEnginePrivate::nativeSeek(qint64 pos)
return seekFdFh(pos);
}
-#if !defined(QT_NO_LIBRARY)
+#if !defined(QT_NO_LIBRARY) && !defined(Q_OS_WINCE)
QFSFileEnginePrivate::resolveLibs();
if (!ptrSetFilePointerEx) {
#endif
- LONG seekToPos = LONG(pos); // <- lossy
- DWORD newFilePointer = SetFilePointer(fileHandle, seekToPos, NULL, FILE_BEGIN);
- if (newFilePointer == 0xFFFFFFFF) {
- thatQ->setError(QFile::UnspecifiedError, qt_error_string());
+ DWORD newFilePointer;
+ LARGE_INTEGER *li = reinterpret_cast<LARGE_INTEGER*>(&pos);
+ newFilePointer = SetFilePointer(fileHandle, li->LowPart, &li->HighPart, FILE_BEGIN);
+ if (newFilePointer == 0xFFFFFFFF && GetLastError() != NO_ERROR) {
+ thatQ->setError(QFile::PositionError, qt_error_string());
return false;
}
- // Note: does not work with large files. This is the case for MOC,
- // UIC, qmake and other bootstrapped tools, and for Win9x/ME.
+ // Note: This is the case for MOC, UIC, qmake and other
+ // bootstrapped tools, and for Windows CE.
return true;
-#if !defined(QT_NO_LIBRARY)
+#if !defined(QT_NO_LIBRARY) && !defined(Q_OS_WINCE)
}
- // This approach supports large files.
LARGE_INTEGER currentFilePos;
LARGE_INTEGER offset;
- offset.LowPart = (unsigned int)(quint64(pos) & Q_UINT64_C(0xffffffff));
- offset.HighPart = (unsigned int)((quint64(pos) >> 32) & Q_UINT64_C(0xffffffff));
+ offset.QuadPart = pos;
if (ptrSetFilePointerEx(fileHandle, offset, &currentFilePos, FILE_BEGIN) == 0) {
thatQ->setError(QFile::UnspecifiedError, qt_error_string());
return false;
@@ -949,35 +847,21 @@ bool QFSFileEnginePrivate::nativeIsSequential() const
bool QFSFileEngine::remove()
{
Q_D(QFSFileEngine);
- QT_WA({
- return ::DeleteFileW((TCHAR*)QFSFileEnginePrivate::longFileName(d->filePath).utf16()) != 0;
- } , {
- return ::DeleteFileA(QFSFileEnginePrivate::win95Name(d->filePath)) != 0;
- });
+ return ::DeleteFile((wchar_t*)QFSFileEnginePrivate::longFileName(d->filePath).utf16()) != 0;
}
bool QFSFileEngine::copy(const QString &copyName)
{
Q_D(QFSFileEngine);
- QT_WA({
- return ::CopyFileW((TCHAR*)QFSFileEnginePrivate::longFileName(d->filePath).utf16(),
- (TCHAR*)QFSFileEnginePrivate::longFileName(copyName).utf16(), true) != 0;
- } , {
- return ::CopyFileA(QFSFileEnginePrivate::win95Name(d->filePath),
- QFSFileEnginePrivate::win95Name(copyName), true) != 0;
- });
+ return ::CopyFile((wchar_t*)QFSFileEnginePrivate::longFileName(d->filePath).utf16(),
+ (wchar_t*)QFSFileEnginePrivate::longFileName(copyName).utf16(), true) != 0;
}
bool QFSFileEngine::rename(const QString &newName)
{
Q_D(QFSFileEngine);
- QT_WA({
- return ::MoveFileW((TCHAR*)QFSFileEnginePrivate::longFileName(d->filePath).utf16(),
- (TCHAR*)QFSFileEnginePrivate::longFileName(newName).utf16()) != 0;
- } , {
- return ::MoveFileA(QFSFileEnginePrivate::win95Name(d->filePath),
- QFSFileEnginePrivate::win95Name(newName)) != 0;
- });
+ return ::MoveFile((wchar_t*)QFSFileEnginePrivate::longFileName(d->filePath).utf16(),
+ (wchar_t*)QFSFileEnginePrivate::longFileName(newName).utf16()) != 0;
}
static inline bool mkDir(const QString &path)
@@ -1001,20 +885,12 @@ static inline bool mkDir(const QString &path)
if (platformId == 1 && QFSFileEnginePrivate::longFileName(path).size() > 256)
return false;
#endif
- QT_WA({
- return ::CreateDirectoryW((TCHAR*)QFSFileEnginePrivate::longFileName(path).utf16(), 0);
- } , {
- return ::CreateDirectoryA(QFSFileEnginePrivate::win95Name(QFileInfo(path).absoluteFilePath()), 0);
- });
+ return ::CreateDirectory((wchar_t*)QFSFileEnginePrivate::longFileName(path).utf16(), 0);
}
static inline bool rmDir(const QString &path)
{
- QT_WA({
- return ::RemoveDirectoryW((TCHAR*)QFSFileEnginePrivate::longFileName(path).utf16());
- } , {
- return ::RemoveDirectoryA(QFSFileEnginePrivate::win95Name(QFileInfo(path).absoluteFilePath()));
- });
+ return ::RemoveDirectory((wchar_t*)QFSFileEnginePrivate::longFileName(path).utf16());
}
static inline bool isDirPath(const QString &dirPath, bool *existed)
@@ -1023,12 +899,26 @@ static inline bool isDirPath(const QString &dirPath, bool *existed)
if (path.length() == 2 &&path.at(1) == QLatin1Char(':'))
path += QLatin1Char('\\');
- DWORD fileAttrib = INVALID_FILE_ATTRIBUTES;
- QT_WA({
- fileAttrib = ::GetFileAttributesW((TCHAR*)QFSFileEnginePrivate::longFileName(path).utf16());
- } , {
- fileAttrib = ::GetFileAttributesA(QFSFileEnginePrivate::win95Name(QFileInfo(path).absoluteFilePath()));
- });
+ DWORD fileAttrib = ::GetFileAttributes((wchar_t*)QFSFileEnginePrivate::longFileName(path).utf16());
+ if (fileAttrib == INVALID_FILE_ATTRIBUTES) {
+ int errorCode = GetLastError();
+ if (errorCode == ERROR_ACCESS_DENIED || errorCode == ERROR_SHARING_VIOLATION) {
+ // path for the FindFirstFile should not end with a trailing slash
+ while (path.endsWith(QLatin1Char('\\')))
+ path.chop(1);
+
+ // FindFirstFile can not handle drives
+ if (!path.endsWith(QLatin1Char(':'))) {
+ WIN32_FIND_DATA findData;
+ HANDLE hFind = ::FindFirstFile((wchar_t*)QFSFileEnginePrivate::longFileName(path).utf16(),
+ &findData);
+ if (hFind != INVALID_HANDLE_VALUE) {
+ ::FindClose(hFind);
+ fileAttrib = findData.dwFileAttributes;
+ }
+ }
+ }
+ }
if (existed)
*existed = fileAttrib != INVALID_FILE_ATTRIBUTES;
@@ -1110,16 +1000,10 @@ bool QFSFileEngine::setCurrentPath(const QString &path)
return false;
#if !defined(Q_OS_WINCE)
- int r;
- QT_WA({
- r = ::SetCurrentDirectoryW((WCHAR*)path.utf16());
- } , {
- r = ::SetCurrentDirectoryA(QFSFileEnginePrivate::win95Name(path));
- });
- return r != 0;
+ return ::SetCurrentDirectory((wchar_t*)path.utf16()) != 0;
#else
- qfsPrivateCurrentDir = QFSFileEnginePrivate::longFileName(path);
- return true;
+ qfsPrivateCurrentDir = QFSFileEnginePrivate::longFileName(path);
+ return true;
#endif
}
@@ -1132,48 +1016,34 @@ QString QFSFileEngine::currentPath(const QString &fileName)
fileName.at(0).isLetter() && fileName.at(1) == QLatin1Char(':')) {
int drv = fileName.toUpper().at(0).toLatin1() - 'A' + 1;
if (_getdrive() != drv) {
- QT_WA({
- TCHAR buf[PATH_MAX];
- ::_wgetdcwd(drv, buf, PATH_MAX);
- ret.setUtf16((ushort*)buf, uint(::wcslen(buf)));
- }, {
- char buf[PATH_MAX];
- ::_getdcwd(drv, buf, PATH_MAX);
- ret = QString::fromLatin1(buf);
- });
+ wchar_t buf[PATH_MAX];
+ ::_wgetdcwd(drv, buf, PATH_MAX);
+ ret = QString::fromWCharArray(buf);
}
}
if (ret.isEmpty()) {
//just the pwd
- QT_WA({
- DWORD size = 0;
- WCHAR currentName[PATH_MAX];
- size = ::GetCurrentDirectoryW(PATH_MAX, currentName);
- if (size !=0) {
- if (size > PATH_MAX) {
- WCHAR * newCurrentName = new WCHAR[size];
- if (::GetCurrentDirectoryW(PATH_MAX, newCurrentName) != 0)
- ret = QString::fromUtf16((ushort*)newCurrentName);
- delete [] newCurrentName;
- } else {
- ret = QString::fromUtf16((ushort*)currentName);
- }
+ DWORD size = 0;
+ wchar_t currentName[PATH_MAX];
+ size = ::GetCurrentDirectory(PATH_MAX, currentName);
+ if (size != 0) {
+ if (size > PATH_MAX) {
+ wchar_t *newCurrentName = new wchar_t[size];
+ if (::GetCurrentDirectory(PATH_MAX, newCurrentName) != 0)
+ ret = QString::fromWCharArray(newCurrentName);
+ delete [] newCurrentName;
+ } else {
+ ret = QString::fromWCharArray(currentName);
}
- } , {
- DWORD size = 0;
- char currentName[PATH_MAX];
- size = ::GetCurrentDirectoryA(PATH_MAX, currentName);
- if (size !=0)
- ret = QString::fromLocal8Bit(currentName);
- });
+ }
}
if (ret.length() >= 2 && ret[1] == QLatin1Char(':'))
ret[0] = ret.at(0).toUpper(); // Force uppercase drive letters.
return QDir::fromNativeSeparators(ret);
#else
- Q_UNUSED(fileName);
- if (qfsPrivateCurrentDir.isEmpty())
- qfsPrivateCurrentDir = QCoreApplication::applicationDirPath();
+ Q_UNUSED(fileName);
+ if (qfsPrivateCurrentDir.isEmpty())
+ qfsPrivateCurrentDir = QCoreApplication::applicationDirPath();
return QDir::fromNativeSeparators(qfsPrivateCurrentDir);
#endif
@@ -1183,35 +1053,27 @@ QString QFSFileEngine::homePath()
{
QString ret;
#if !defined(QT_NO_LIBRARY)
- QT_WA (
- {
- QFSFileEnginePrivate::resolveLibs();
- if (ptrOpenProcessToken && ptrGetUserProfileDirectoryW) {
- HANDLE hnd = ::GetCurrentProcess();
- HANDLE token = 0;
- BOOL ok = ::ptrOpenProcessToken(hnd, TOKEN_QUERY, &token);
- if (ok) {
- DWORD dwBufferSize = 0;
- // First call, to determine size of the strings (with '\0').
- ok = ::ptrGetUserProfileDirectoryW(token, NULL, &dwBufferSize);
- if (!ok && dwBufferSize != 0) { // We got the required buffer size
- wchar_t *userDirectory = new wchar_t[dwBufferSize];
- // Second call, now we can fill the allocated buffer.
- ok = ::ptrGetUserProfileDirectoryW(token, userDirectory, &dwBufferSize);
- if (ok)
- ret = QString::fromUtf16((ushort*)userDirectory);
-
- delete [] userDirectory;
- }
- ::CloseHandle(token);
- }
- }
- }
- ,
- {
- // GetUserProfileDirectory is only available from NT 4.0,
- // so fall through for Win98 and friends version.
- })
+ QFSFileEnginePrivate::resolveLibs();
+ if (ptrOpenProcessToken && ptrGetUserProfileDirectoryW) {
+ HANDLE hnd = ::GetCurrentProcess();
+ HANDLE token = 0;
+ BOOL ok = ::ptrOpenProcessToken(hnd, TOKEN_QUERY, &token);
+ if (ok) {
+ DWORD dwBufferSize = 0;
+ // First call, to determine size of the strings (with '\0').
+ ok = ::ptrGetUserProfileDirectoryW(token, NULL, &dwBufferSize);
+ if (!ok && dwBufferSize != 0) { // We got the required buffer size
+ wchar_t *userDirectory = new wchar_t[dwBufferSize];
+ // Second call, now we can fill the allocated buffer.
+ ok = ::ptrGetUserProfileDirectoryW(token, userDirectory, &dwBufferSize);
+ if (ok)
+ ret = QString::fromWCharArray(userDirectory);
+
+ delete [] userDirectory;
+ }
+ ::CloseHandle(token);
+ }
+ }
#endif
if(ret.isEmpty() || !QFile::exists(ret)) {
ret = QString::fromLocal8Bit(qgetenv("USERPROFILE").constData());
@@ -1251,17 +1113,10 @@ QString QFSFileEngine::rootPath()
QString QFSFileEngine::tempPath()
{
- QString ret;
- int success;
- QT_WA({
- wchar_t tempPath[MAX_PATH];
- success = GetTempPathW(MAX_PATH, tempPath);
- ret = QString::fromUtf16((ushort*)tempPath);
- } , {
- char tempPath[MAX_PATH];
- success = GetTempPathA(MAX_PATH, tempPath);
- ret = QString::fromLocal8Bit(tempPath);
- });
+ wchar_t tempPath[MAX_PATH];
+ int success = GetTempPath(MAX_PATH, tempPath);
+ QString ret = QString::fromWCharArray(tempPath);
+
if (ret.isEmpty() || !success) {
#if !defined(Q_OS_WINCE)
ret = QString::fromLatin1("c:/tmp");
@@ -1285,7 +1140,7 @@ QFileInfoList QFSFileEngine::drives()
#elif defined(Q_OS_OS2EMX)
quint32 driveBits, cur;
if(DosQueryCurrentDisk(&cur,&driveBits) != NO_ERROR)
- exit(1);
+ exit(1);
driveBits &= 0x3ffffff;
#endif
char driveName[] = "A:/";
@@ -1327,18 +1182,34 @@ bool QFSFileEnginePrivate::doStat() const
}
}
#else
- DWORD tmpAttributes = GetFileAttributesW((TCHAR*)QFSFileEnginePrivate::longFileName(fname).utf16());
+ DWORD tmpAttributes = GetFileAttributes((wchar_t*)QFSFileEnginePrivate::longFileName(fname).utf16());
if (tmpAttributes != -1) {
fileAttrib = tmpAttributes;
could_stat = true;
}
#endif
} else {
- QT_WA({
- fileAttrib = GetFileAttributesW((TCHAR*)QFSFileEnginePrivate::longFileName(fname).utf16());
- } , {
- fileAttrib = GetFileAttributesA(QFSFileEnginePrivate::win95Name(QFileInfo(fname).absoluteFilePath()));
- });
+ fileAttrib = GetFileAttributes((wchar_t*)QFSFileEnginePrivate::longFileName(fname).utf16());
+ if (fileAttrib == INVALID_FILE_ATTRIBUTES) {
+ int errorCode = GetLastError();
+ if (errorCode == ERROR_ACCESS_DENIED || errorCode == ERROR_SHARING_VIOLATION) {
+ QString path = QDir::toNativeSeparators(fname);
+ // path for the FindFirstFile should not end with a trailing slash
+ while (path.endsWith(QLatin1Char('\\')))
+ path.chop(1);
+
+ // FindFirstFile can not handle drives
+ if (!path.endsWith(QLatin1Char(':'))) {
+ WIN32_FIND_DATA findData;
+ HANDLE hFind = ::FindFirstFile((wchar_t*)QFSFileEnginePrivate::longFileName(path).utf16(),
+ &findData);
+ if (hFind != INVALID_HANDLE_VALUE) {
+ ::FindClose(hFind);
+ fileAttrib = findData.dwFileAttributes;
+ }
+ }
+ }
+ }
could_stat = fileAttrib != INVALID_FILE_ATTRIBUTES;
if (!could_stat) {
#if !defined(Q_OS_WINCE)
@@ -1398,74 +1269,39 @@ static QString readLink(const QString &link)
#if !defined(Q_OS_WINCE)
#if !defined(QT_NO_LIBRARY) && !defined(Q_CC_MWERKS)
QString ret;
- QT_WA({
- bool neededCoInit = false;
- IShellLink *psl; // pointer to IShellLink i/f
- HRESULT hres;
- WIN32_FIND_DATA wfd;
- TCHAR szGotPath[MAX_PATH];
- // Get pointer to the IShellLink interface.
- hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
- IID_IShellLink, (LPVOID *)&psl);
- if(hres == CO_E_NOTINITIALIZED) { // COM was not initialized
- neededCoInit = true;
- CoInitialize(NULL);
- hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
- IID_IShellLink, (LPVOID *)&psl);
- }
- if(SUCCEEDED(hres)) { // Get pointer to the IPersistFile interface.
- IPersistFile *ppf;
- hres = psl->QueryInterface(IID_IPersistFile, (LPVOID *)&ppf);
- if(SUCCEEDED(hres)) {
- hres = ppf->Load((LPOLESTR)link.utf16(), STGM_READ);
- //The original path of the link is retrieved. If the file/folder
- //was moved, the return value still have the old path.
- if(SUCCEEDED(hres)) {
- if (psl->GetPath(szGotPath, MAX_PATH, &wfd, SLGP_UNCPRIORITY) == NOERROR)
- ret = QString::fromUtf16((ushort*)szGotPath);
- }
- ppf->Release();
- }
- psl->Release();
- }
- if(neededCoInit)
- CoUninitialize();
- } , {
- bool neededCoInit = false;
- IShellLinkA *psl; // pointer to IShellLink i/f
- HRESULT hres;
- WIN32_FIND_DATAA wfd;
- char szGotPath[MAX_PATH];
- // Get pointer to the IShellLink interface.
+ bool neededCoInit = false;
+ IShellLink *psl; // pointer to IShellLink i/f
+ WIN32_FIND_DATA wfd;
+ wchar_t szGotPath[MAX_PATH];
- hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
- IID_IShellLinkA, (LPVOID *)&psl);
+ // Get pointer to the IShellLink interface.
+ HRESULT hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID *)&psl);
- if(hres == CO_E_NOTINITIALIZED) { // COM was not initialized
- neededCoInit = true;
- CoInitialize(NULL);
- hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
- IID_IShellLinkA, (LPVOID *)&psl);
- }
- if(SUCCEEDED(hres)) { // Get pointer to the IPersistFile interface.
- IPersistFile *ppf;
- hres = psl->QueryInterface(IID_IPersistFile, (LPVOID *)&ppf);
- if(SUCCEEDED(hres)) {
- hres = ppf->Load((LPOLESTR)QFileInfo(link).absoluteFilePath().utf16(), STGM_READ);
- //The original path of the link is retrieved. If the file/folder
- //was moved, the return value still have the old path.
- if(SUCCEEDED(hres)) {
- if (psl->GetPath((char*)szGotPath, MAX_PATH, &wfd, SLGP_UNCPRIORITY) == NOERROR)
- ret = QString::fromLocal8Bit(szGotPath);
- }
- ppf->Release();
+ if (hres == CO_E_NOTINITIALIZED) { // COM was not initialized
+ neededCoInit = true;
+ CoInitialize(NULL);
+ hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
+ IID_IShellLink, (LPVOID *)&psl);
+ }
+ if (SUCCEEDED(hres)) { // Get pointer to the IPersistFile interface.
+ IPersistFile *ppf;
+ hres = psl->QueryInterface(IID_IPersistFile, (LPVOID *)&ppf);
+ if(SUCCEEDED(hres)) {
+ hres = ppf->Load((LPOLESTR)link.utf16(), STGM_READ);
+ //The original path of the link is retrieved. If the file/folder
+ //was moved, the return value still have the old path.
+ if(SUCCEEDED(hres)) {
+ if (psl->GetPath(szGotPath, MAX_PATH, &wfd, SLGP_UNCPRIORITY) == NOERROR)
+ ret = QString::fromWCharArray(szGotPath);
}
- psl->Release();
+ ppf->Release();
}
- if(neededCoInit)
- CoUninitialize();
- });
+ psl->Release();
+ }
+ if (neededCoInit)
+ CoUninitialize();
+
return ret;
#else
Q_UNUSED(link);
@@ -1475,7 +1311,7 @@ static QString readLink(const QString &link)
wchar_t target[MAX_PATH];
QString result;
if (SHGetShortcutTarget((wchar_t*)QFileInfo(link).absoluteFilePath().replace(QLatin1Char('/'),QLatin1Char('\\')).utf16(), target, MAX_PATH)) {
- result = QString::fromUtf16(reinterpret_cast<const ushort *> (target));
+ result = QString::fromWCharArray(target);
if (result.startsWith(QLatin1Char('"')))
result.remove(0,1);
if (result.endsWith(QLatin1Char('"')))
@@ -1502,76 +1338,37 @@ bool QFSFileEngine::link(const QString &newName)
QString linkName = newName;
//### assume that they add .lnk
- QT_WA({
- HRESULT hres;
- IShellLink *psl;
- bool neededCoInit = false;
+ IShellLink *psl;
+ bool neededCoInit = false;
- hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void **)&psl);
- if(hres == CO_E_NOTINITIALIZED) { // COM was not initialized
- neededCoInit = true;
- CoInitialize(NULL);
- hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void **)&psl);
- }
- if (SUCCEEDED(hres)) {
- hres = psl->SetPath((wchar_t *)fileName(AbsoluteName).replace(QLatin1Char('/'), QLatin1Char('\\')).utf16());
- if (SUCCEEDED(hres)) {
- hres = psl->SetWorkingDirectory((wchar_t *)fileName(AbsolutePathName).replace(QLatin1Char('/'), QLatin1Char('\\')).utf16());
- if (SUCCEEDED(hres)) {
- IPersistFile *ppf;
- hres = psl->QueryInterface(IID_IPersistFile, (void **)&ppf);
- if (SUCCEEDED(hres)) {
- hres = ppf->Save((TCHAR*)linkName.utf16(), TRUE);
- if (SUCCEEDED(hres))
- ret = true;
- ppf->Release();
- }
- }
- }
- psl->Release();
- }
- if(neededCoInit)
- CoUninitialize();
- } , {
- // the SetPath() call _sometimes_ changes the current path and when it does it sometimes
- // does not let us change it back unless we call currentPath() many times.
- QString cwd = currentPath();
- HRESULT hres;
- IShellLinkA *psl;
- bool neededCoInit = false;
+ HRESULT hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void **)&psl);
+ if (hres == CO_E_NOTINITIALIZED) { // COM was not initialized
+ neededCoInit = true;
+ CoInitialize(NULL);
hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void **)&psl);
- if(hres == CO_E_NOTINITIALIZED) { // COM was not initialized
- neededCoInit = true;
- CoInitialize(NULL);
- hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void **)&psl);
- }
+ }
+
+ if (SUCCEEDED(hres)) {
+ hres = psl->SetPath((wchar_t *)fileName(AbsoluteName).replace(QLatin1Char('/'), QLatin1Char('\\')).utf16());
if (SUCCEEDED(hres)) {
- currentPath();
- hres = psl->SetPath((char *)QString::fromLocal8Bit(QFSFileEnginePrivate::win95Name(fileName(AbsoluteName))).utf16());
- currentPath();
+ hres = psl->SetWorkingDirectory((wchar_t *)fileName(AbsolutePathName).replace(QLatin1Char('/'), QLatin1Char('\\')).utf16());
if (SUCCEEDED(hres)) {
- hres = psl->SetWorkingDirectory((char *)QString::fromLocal8Bit(QFSFileEnginePrivate::win95Name(fileName(AbsolutePathName))).utf16());
- currentPath();
+ IPersistFile *ppf;
+ hres = psl->QueryInterface(IID_IPersistFile, (void **)&ppf);
if (SUCCEEDED(hres)) {
- IPersistFile *ppf;
- hres = psl->QueryInterface(IID_IPersistFile, (void **)&ppf);
- if (SUCCEEDED(hres)) {
- currentPath();
- hres = ppf->Save((LPCOLESTR)linkName.utf16(), TRUE);
- currentPath();
- if (SUCCEEDED(hres))
- ret = true;
- ppf->Release();
- }
+ hres = ppf->Save((wchar_t*)linkName.utf16(), TRUE);
+ if (SUCCEEDED(hres))
+ ret = true;
+ ppf->Release();
}
- psl->Release();
}
}
- if(neededCoInit)
+ psl->Release();
+ }
+ if(neededCoInit)
CoUninitialize();
- setCurrentPath(cwd);
- });
+
return ret;
#else
Q_UNUSED(newName);
@@ -1598,9 +1395,9 @@ QAbstractFileEngine::FileFlags QFSFileEnginePrivate::getPermissions() const
#if !defined(QT_NO_LIBRARY)
if((qt_ntfs_permission_lookup > 0) && ((QSysInfo::WindowsVersion&QSysInfo::WV_NT_based) > QSysInfo::WV_NT)) {
- PSID pOwner = 0;
- PSID pGroup = 0;
- PACL pDacl;
+ PSID pOwner = 0;
+ PSID pGroup = 0;
+ PACL pDacl;
PSECURITY_DESCRIPTOR pSD;
ACCESS_MASK access_mask;
@@ -1610,42 +1407,42 @@ QAbstractFileEngine::FileFlags QFSFileEnginePrivate::getPermissions() const
QString fname = filePath.endsWith(QLatin1String(".lnk")) ? readLink(filePath) : filePath;
DWORD res = ptrGetNamedSecurityInfoW((wchar_t*)fname.utf16(), SE_FILE_OBJECT,
- OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
- &pOwner, &pGroup, &pDacl, 0, &pSD);
+ OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
+ &pOwner, &pGroup, &pDacl, 0, &pSD);
if(res == ERROR_SUCCESS) {
TRUSTEE_W trustee;
{ //user
if(ptrGetEffectiveRightsFromAclW(pDacl, &currentUserTrusteeW, &access_mask) != ERROR_SUCCESS)
access_mask = (ACCESS_MASK)-1;
- if(access_mask & ReadMask)
- ret |= QAbstractFileEngine::ReadUserPerm;
- if(access_mask & WriteMask)
- ret |= QAbstractFileEngine::WriteUserPerm;
- if(access_mask & ExecMask)
- ret |= QAbstractFileEngine::ExeUserPerm;
+ if(access_mask & ReadMask)
+ ret |= QAbstractFileEngine::ReadUserPerm;
+ if(access_mask & WriteMask)
+ ret |= QAbstractFileEngine::WriteUserPerm;
+ if(access_mask & ExecMask)
+ ret |= QAbstractFileEngine::ExeUserPerm;
}
{ //owner
ptrBuildTrusteeWithSidW(&trustee, pOwner);
if(ptrGetEffectiveRightsFromAclW(pDacl, &trustee, &access_mask) != ERROR_SUCCESS)
access_mask = (ACCESS_MASK)-1;
- if(access_mask & ReadMask)
- ret |= QAbstractFileEngine::ReadOwnerPerm;
- if(access_mask & WriteMask)
- ret |= QAbstractFileEngine::WriteOwnerPerm;
- if(access_mask & ExecMask)
- ret |= QAbstractFileEngine::ExeOwnerPerm;
+ if(access_mask & ReadMask)
+ ret |= QAbstractFileEngine::ReadOwnerPerm;
+ if(access_mask & WriteMask)
+ ret |= QAbstractFileEngine::WriteOwnerPerm;
+ if(access_mask & ExecMask)
+ ret |= QAbstractFileEngine::ExeOwnerPerm;
}
{ //group
ptrBuildTrusteeWithSidW(&trustee, pGroup);
if(ptrGetEffectiveRightsFromAclW(pDacl, &trustee, &access_mask) != ERROR_SUCCESS)
access_mask = (ACCESS_MASK)-1;
- if(access_mask & ReadMask)
- ret |= QAbstractFileEngine::ReadGroupPerm;
- if(access_mask & WriteMask)
- ret |= QAbstractFileEngine::WriteGroupPerm;
- if(access_mask & ExecMask)
- ret |= QAbstractFileEngine::ExeGroupPerm;
+ if(access_mask & ReadMask)
+ ret |= QAbstractFileEngine::ReadGroupPerm;
+ if(access_mask & WriteMask)
+ ret |= QAbstractFileEngine::WriteGroupPerm;
+ if(access_mask & ExecMask)
+ ret |= QAbstractFileEngine::ExeGroupPerm;
}
{ //other (world)
// Create SID for Everyone (World)
@@ -1655,12 +1452,12 @@ QAbstractFileEngine::FileFlags QFSFileEnginePrivate::getPermissions() const
ptrBuildTrusteeWithSidW(&trustee, pWorld);
if(ptrGetEffectiveRightsFromAclW(pDacl, &trustee, &access_mask) != ERROR_SUCCESS)
access_mask = (ACCESS_MASK)-1; // ###
- if(access_mask & ReadMask)
- ret |= QAbstractFileEngine::ReadOtherPerm;
- if(access_mask & WriteMask)
- ret |= QAbstractFileEngine::WriteOtherPerm;
- if(access_mask & ExecMask)
- ret |= QAbstractFileEngine::ExeOtherPerm;
+ if(access_mask & ReadMask)
+ ret |= QAbstractFileEngine::ReadOtherPerm;
+ if(access_mask & WriteMask)
+ ret |= QAbstractFileEngine::WriteOtherPerm;
+ if(access_mask & ExecMask)
+ ret |= QAbstractFileEngine::ExeOtherPerm;
}
ptrFreeSid(pWorld);
}
@@ -1670,13 +1467,13 @@ QAbstractFileEngine::FileFlags QFSFileEnginePrivate::getPermissions() const
} else
#endif
{
- //### what to do with permissions if we don't use ntfs or are not on a NT system
- // for now just add all permissions and what about exe missions ??
- // also qt_ntfs_permission_lookup is now not set by defualt ... should it ?
- ret |= QAbstractFileEngine::ReadOtherPerm | QAbstractFileEngine::ReadGroupPerm
- | QAbstractFileEngine::ReadOwnerPerm | QAbstractFileEngine::ReadUserPerm
- | QAbstractFileEngine::WriteUserPerm | QAbstractFileEngine::WriteOwnerPerm
- | QAbstractFileEngine::WriteGroupPerm | QAbstractFileEngine::WriteOtherPerm;
+ //### what to do with permissions if we don't use NTFS
+ // for now just add all permissions and what about exe missions ??
+ // also qt_ntfs_permission_lookup is now not set by defualt ... should it ?
+ ret |= QAbstractFileEngine::ReadOtherPerm | QAbstractFileEngine::ReadGroupPerm
+ | QAbstractFileEngine::ReadOwnerPerm | QAbstractFileEngine::ReadUserPerm
+ | QAbstractFileEngine::WriteUserPerm | QAbstractFileEngine::WriteOwnerPerm
+ | QAbstractFileEngine::WriteGroupPerm | QAbstractFileEngine::WriteOtherPerm;
}
if (doStat()) {
@@ -1783,8 +1580,8 @@ QString QFSFileEngine::fileName(FileName file) const
if (!isRelativePath()) {
#if !defined(Q_OS_WINCE)
- if (d->filePath.size() > 2 && d->filePath.at(1) == QLatin1Char(':')
- && d->filePath.at(2) != QLatin1Char('/') || // It's a drive-relative path, so Z:a.txt -> Z:\currentpath\a.txt
+ if ((d->filePath.size() > 2 && d->filePath.at(1) == QLatin1Char(':')
+ && d->filePath.at(2) != QLatin1Char('/')) || // It's a drive-relative path, so Z:a.txt -> Z:\currentpath\a.txt
d->filePath.startsWith(QLatin1Char('/')) // It's a absolute path to the current drive, so \a.txt -> Z:\a.txt
) {
ret = QDir::fromNativeSeparators(nativeAbsoluteFilePath(d->filePath));
@@ -1911,13 +1708,9 @@ bool QFSFileEngine::setPermissions(uint perms)
return false;
#if !defined(Q_OS_WINCE)
- QT_WA({
- ret = ::_wchmod((TCHAR*)d->filePath.utf16(), mode) == 0;
- } , {
- ret = ::_chmod(d->filePath.toLocal8Bit(), mode) == 0;
- });
+ ret = ::_wchmod((wchar_t*)d->filePath.utf16(), mode) == 0;
#else
- ret = ::_wchmod((TCHAR*)d->longFileName(d->filePath).utf16(), mode);
+ ret = ::_wchmod((wchar_t*)d->longFileName(d->filePath).utf16(), mode);
#endif
return ret;
}
@@ -1960,34 +1753,33 @@ bool QFSFileEngine::setSize(qint64 size)
static inline QDateTime fileTimeToQDateTime(const FILETIME *time)
{
QDateTime ret;
- if (QSysInfo::WindowsVersion & QSysInfo::WV_DOS_based || QSysInfo::WindowsVersion & QSysInfo::WV_CE_based) {
- // SystemTimeToTzSpecificLocalTime is not available on Win98/ME so we have to pull it off ourselves.
- SYSTEMTIME systime;
- FILETIME ftime;
- systime.wYear = 1970;
- systime.wMonth = 1;
- systime.wDay = 1;
- systime.wHour = 0;
- systime.wMinute = 0;
- systime.wSecond = 0;
- systime.wMilliseconds = 0;
- systime.wDayOfWeek = 4;
- SystemTimeToFileTime(&systime, &ftime);
- unsigned __int64 acttime = (unsigned __int64)time->dwHighDateTime << 32 | time->dwLowDateTime;
- FileTimeToSystemTime(time, &systime);
- unsigned __int64 time1970 = (unsigned __int64)ftime.dwHighDateTime << 32 | ftime.dwLowDateTime;
- unsigned __int64 difftime = acttime - time1970;
- difftime /= 10000000;
- ret.setTime_t((unsigned int)difftime);
- } else {
-#ifndef Q_OS_WINCE
- SYSTEMTIME sTime, lTime;
- FileTimeToSystemTime(time, &sTime);
- SystemTimeToTzSpecificLocalTime(0, &sTime, &lTime);
- ret.setDate(QDate(lTime.wYear, lTime.wMonth, lTime.wDay));
- ret.setTime(QTime(lTime.wHour, lTime.wMinute, lTime.wSecond, lTime.wMilliseconds));
+
+#if defined(Q_OS_WINCE)
+ SYSTEMTIME systime;
+ FILETIME ftime;
+ systime.wYear = 1970;
+ systime.wMonth = 1;
+ systime.wDay = 1;
+ systime.wHour = 0;
+ systime.wMinute = 0;
+ systime.wSecond = 0;
+ systime.wMilliseconds = 0;
+ systime.wDayOfWeek = 4;
+ SystemTimeToFileTime(&systime, &ftime);
+ unsigned __int64 acttime = (unsigned __int64)time->dwHighDateTime << 32 | time->dwLowDateTime;
+ FileTimeToSystemTime(time, &systime);
+ unsigned __int64 time1970 = (unsigned __int64)ftime.dwHighDateTime << 32 | ftime.dwLowDateTime;
+ unsigned __int64 difftime = acttime - time1970;
+ difftime /= 10000000;
+ ret.setTime_t((unsigned int)difftime);
+#else
+ SYSTEMTIME sTime, lTime;
+ FileTimeToSystemTime(time, &sTime);
+ SystemTimeToTzSpecificLocalTime(0, &sTime, &lTime);
+ ret.setDate(QDate(lTime.wYear, lTime.wMonth, lTime.wDay));
+ ret.setTime(QTime(lTime.wHour, lTime.wMinute, lTime.wSecond, lTime.wMilliseconds));
#endif
- }
+
return ret;
}
@@ -2011,13 +1803,31 @@ QDateTime QFSFileEngine::fileTime(FileTime time) const
}
#endif
} else {
- bool ok = false;
WIN32_FILE_ATTRIBUTE_DATA attribData;
- QT_WA({
- ok = ::GetFileAttributesExW((TCHAR*)QFSFileEnginePrivate::longFileName(d->filePath).utf16(), GetFileExInfoStandard, &attribData);
- } , {
- ok = ::GetFileAttributesExA(QFSFileEnginePrivate::win95Name(QFileInfo(d->filePath).absoluteFilePath()), GetFileExInfoStandard, &attribData);
- });
+ bool ok = ::GetFileAttributesEx((wchar_t*)QFSFileEnginePrivate::longFileName(d->filePath).utf16(), GetFileExInfoStandard, &attribData);
+ if (!ok) {
+ int errorCode = GetLastError();
+ if (errorCode == ERROR_ACCESS_DENIED || errorCode == ERROR_SHARING_VIOLATION) {
+ QString path = QDir::toNativeSeparators(d->filePath);
+ // path for the FindFirstFile should not end with a trailing slash
+ while (path.endsWith(QLatin1Char('\\')))
+ path.chop(1);
+
+ // FindFirstFile can not handle drives
+ if (!path.endsWith(QLatin1Char(':'))) {
+ WIN32_FIND_DATA findData;
+ HANDLE hFind = ::FindFirstFile((wchar_t*)QFSFileEnginePrivate::longFileName(path).utf16(),
+ &findData);
+ if (hFind != INVALID_HANDLE_VALUE) {
+ ::FindClose(hFind);
+ ok = true;
+ attribData.ftCreationTime = findData.ftCreationTime;
+ attribData.ftLastWriteTime = findData.ftLastWriteTime;
+ attribData.ftLastAccessTime = findData.ftLastAccessTime;
+ }
+ }
+ }
+ }
if (ok) {
if(time == CreationTime)
ret = fileTimeToQDateTime(&attribData.ftCreationTime);
@@ -2037,11 +1847,11 @@ uchar *QFSFileEnginePrivate::map(qint64 offset, qint64 size,
Q_UNUSED(flags);
if (openMode == QFile::NotOpen) {
q->setError(QFile::PermissionsError, qt_error_string());
- return 0;
+ return 0;
}
if (offset == 0 && size == 0) {
q->setError(QFile::UnspecifiedError, qt_error_string());
- return 0;
+ return 0;
}
@@ -2054,7 +1864,7 @@ uchar *QFSFileEnginePrivate::map(qint64 offset, qint64 size,
#ifdef Q_USE_DEPRECATED_MAP_API
nativeClose();
if (fileMapHandle == INVALID_HANDLE_VALUE) {
- fileMapHandle = CreateFileForMappingW((TCHAR *)nativeFilePath.constData(),
+ fileMapHandle = CreateFileForMapping((const wchar_t*)nativeFilePath.constData(),
GENERIC_READ | (openMode & QIODevice::WriteOnly ? GENERIC_WRITE : 0),
0,
NULL,
@@ -2069,21 +1879,14 @@ uchar *QFSFileEnginePrivate::map(qint64 offset, qint64 size,
#endif
// first create the file mapping handle
- HANDLE mapHandle = 0;
DWORD protection = (openMode & QIODevice::WriteOnly) ? PAGE_READWRITE : PAGE_READONLY;
- QT_WA({
- mapHandle = ::CreateFileMappingW(handle, 0, protection,
- 0, 0, 0);
- },{
- mapHandle = ::CreateFileMappingA(handle, 0, protection,
- 0, 0, 0);
- });
+ HANDLE mapHandle = ::CreateFileMapping(handle, 0, protection, 0, 0, 0);
if (mapHandle == NULL) {
q->setError(QFile::PermissionsError, qt_error_string());
#ifdef Q_USE_DEPRECATED_MAP_API
mapHandleClose();
#endif
- return 0;
+ return 0;
}
// setup args to map
@@ -2112,7 +1915,7 @@ uchar *QFSFileEnginePrivate::map(qint64 offset, qint64 size,
switch(GetLastError()) {
case ERROR_ACCESS_DENIED:
q->setError(QFile::PermissionsError, qt_error_string());
- break;
+ break;
case ERROR_INVALID_PARAMETER:
// size are out of bounds
default:
diff --git a/src/corelib/io/qiodevice.h b/src/corelib/io/qiodevice.h
index d8237a7..866fa72 100644
--- a/src/corelib/io/qiodevice.h
+++ b/src/corelib/io/qiodevice.h
@@ -165,7 +165,7 @@ protected:
#endif
private:
- Q_DECLARE_SCOPED_PRIVATE(QIODevice)
+ Q_DECLARE_PRIVATE(QIODevice)
Q_DISABLE_COPY(QIODevice)
#ifdef QT3_SUPPORT
diff --git a/src/corelib/io/qprocess.cpp b/src/corelib/io/qprocess.cpp
index 03ae1fe..871ea63 100644
--- a/src/corelib/io/qprocess.cpp
+++ b/src/corelib/io/qprocess.cpp
@@ -310,7 +310,7 @@ 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.
- \sa setReadChannelMode()
+ \sa setProcessChannelMode()
*/
/*!
@@ -878,7 +878,7 @@ void QProcess::setReadChannelMode(ProcessChannelMode mode)
Returns the channel mode of the QProcess standard output and
standard error channels.
- \sa setReadChannelMode(), ProcessChannelMode, setReadChannel()
+ \sa setProcessChannelMode(), ProcessChannelMode, setReadChannel()
*/
QProcess::ProcessChannelMode QProcess::processChannelMode() const
{
@@ -895,7 +895,7 @@ QProcess::ProcessChannelMode QProcess::processChannelMode() const
\snippet doc/src/snippets/code/src_corelib_io_qprocess.cpp 0
- \sa readChannelMode(), ProcessChannelMode, setReadChannel()
+ \sa processChannelMode(), ProcessChannelMode, setReadChannel()
*/
void QProcess::setProcessChannelMode(ProcessChannelMode mode)
{
diff --git a/src/corelib/io/qprocess.h b/src/corelib/io/qprocess.h
index a4025a1..bff5f7e 100644
--- a/src/corelib/io/qprocess.h
+++ b/src/corelib/io/qprocess.h
@@ -191,7 +191,7 @@ protected:
qint64 writeData(const char *data, qint64 len);
private:
- Q_DECLARE_SCOPED_PRIVATE(QProcess)
+ Q_DECLARE_PRIVATE(QProcess)
Q_DISABLE_COPY(QProcess)
Q_PRIVATE_SLOT(d_func(), bool _q_canReadStandardOutput())
diff --git a/src/corelib/io/qprocess_symbian.cpp b/src/corelib/io/qprocess_symbian.cpp
index 7da6a1d..64519f6 100644
--- a/src/corelib/io/qprocess_symbian.cpp
+++ b/src/corelib/io/qprocess_symbian.cpp
@@ -1,9 +1,9 @@
/****************************************************************************
**
-** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
-** Contact: Qt Software Information (qt-info@nokia.com)
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
**
-** This file is part of the $MODULE$ of the Qt Toolkit.
+** This file is part of the QtCore of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
@@ -34,7 +34,7 @@
** met: http://www.gnu.org/copyleft/gpl.html.
**
** If you are unsure which license is appropriate for your use, please
-** contact the sales department at qt-sales@nokia.com.
+** contact the sales department at http://www.qtsoftware.com/contact.
** $QT_END_LICENSE$
**
****************************************************************************/
diff --git a/src/corelib/io/qprocess_unix.cpp b/src/corelib/io/qprocess_unix.cpp
index 49869a4..607b734 100644
--- a/src/corelib/io/qprocess_unix.cpp
+++ b/src/corelib/io/qprocess_unix.cpp
@@ -84,6 +84,7 @@ QT_END_NAMESPACE
#include "qprocess.h"
#include "qprocess_p.h"
+#include "private/qcore_unix_p.h"
#ifdef Q_OS_MAC
#include <private/qcore_mac_p.h>
@@ -114,78 +115,11 @@ static inline char *strdup(const char *data)
}
#endif
-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);
- 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);
- return ret;
-}
-
-static void qt_native_close(int fd)
-{
- int ret;
- do {
- ret = ::close(fd);
- } while (ret == -1 && errno == EINTR);
-}
-
-static void qt_native_dup2(int oldfd, int newfd)
-{
- int ret;
- do {
- ret = ::dup2(oldfd, newfd);
- } while (ret == -1 && errno == EINTR);
-}
-
-static void qt_native_chdir(const char *path)
-{
- int ret;
- do {
- ret = ::chdir(path);
- } while (ret == -1 && errno == EINTR);
-}
-
-static void qt_native_execve(const char *filename, char *const argv[],
- char *const envp[])
-{
- int ret;
- do {
- ret = ::execve(filename, argv, envp);
- } while (ret == -1 && errno == EINTR);
-}
-
-static void qt_native_execv(const char *path, char *const argv[])
-{
- int ret;
- do {
- ret = ::execv(path, argv);
- } while (ret == -1 && errno == EINTR);
-}
-
-static void qt_native_execvp(const char *file, char *const argv[])
-{
- int ret;
- do {
- ret = ::execvp(file, argv);
- } while (ret == -1 && errno == EINTR);
-}
-
static int qt_qprocess_deadChild_pipe[2];
static void (*qt_sa_old_sigchld_handler)(int) = 0;
static void qt_sa_sigchld_handler(int signum)
{
- qt_native_write(qt_qprocess_deadChild_pipe[1], "", 1);
+ qt_safe_write(qt_qprocess_deadChild_pipe[1], "", 1);
#if defined (QPROCESS_DEBUG)
fprintf(stderr, "*** SIGCHLD\n");
#endif
@@ -194,6 +128,13 @@ static void qt_sa_sigchld_handler(int signum)
qt_sa_old_sigchld_handler(signum);
}
+static inline void add_fd(int &nfds, int fd, fd_set *fdset)
+{
+ FD_SET(fd, fdset);
+ if ((fd) > nfds)
+ nfds = fd;
+}
+
struct QProcessInfo {
QProcess *process;
int deathPipe;
@@ -231,13 +172,7 @@ QProcessManager::QProcessManager()
// initialize the dead child pipe and make it non-blocking. in the
// extremely unlikely event that the pipe fills up, we do not under any
// circumstances want to block.
- ::pipe(qt_qprocess_deadChild_pipe);
- ::fcntl(qt_qprocess_deadChild_pipe[0], F_SETFD, FD_CLOEXEC);
- ::fcntl(qt_qprocess_deadChild_pipe[1], F_SETFD, FD_CLOEXEC);
- ::fcntl(qt_qprocess_deadChild_pipe[0], F_SETFL,
- ::fcntl(qt_qprocess_deadChild_pipe[0], F_GETFL) | O_NONBLOCK);
- ::fcntl(qt_qprocess_deadChild_pipe[1], F_SETFL,
- ::fcntl(qt_qprocess_deadChild_pipe[1], F_GETFL) | O_NONBLOCK);
+ qt_safe_pipe(qt_qprocess_deadChild_pipe, O_NONBLOCK);
// set up the SIGCHLD handler, which writes a single byte to the dead
// child pipe every time a child dies.
@@ -254,13 +189,13 @@ QProcessManager::QProcessManager()
QProcessManager::~QProcessManager()
{
// notify the thread that we're shutting down.
- qt_native_write(qt_qprocess_deadChild_pipe[1], "@", 1);
- qt_native_close(qt_qprocess_deadChild_pipe[1]);
+ qt_safe_write(qt_qprocess_deadChild_pipe[1], "@", 1);
+ qt_safe_close(qt_qprocess_deadChild_pipe[1]);
wait();
// on certain unixes, closing the reading end of the pipe will cause
// select in run() to block forever, rather than return with EBADF.
- qt_native_close(qt_qprocess_deadChild_pipe[0]);
+ qt_safe_close(qt_qprocess_deadChild_pipe[0]);
qt_qprocess_deadChild_pipe[0] = -1;
qt_qprocess_deadChild_pipe[1] = -1;
@@ -304,7 +239,7 @@ void QProcessManager::run()
// signals may have been delivered in the meantime, to avoid race
// conditions.
char c;
- if (qt_native_read(qt_qprocess_deadChild_pipe[0], &c, 1) < 0 || c == '@')
+ if (qt_safe_read(qt_qprocess_deadChild_pipe[0], &c, 1) < 0 || c == '@')
break;
// catch any and all children that we can.
@@ -323,7 +258,7 @@ void QProcessManager::catchDeadChildren()
// notify all children that they may have died. they need to run
// waitpid() in their own thread.
QProcessInfo *info = it.value();
- qt_native_write(info->deathPipe, "", 1);
+ qt_safe_write(info->deathPipe, "", 1);
#if defined (QPROCESS_DEBUG)
qDebug() << "QProcessManager::run() sending death notice to" << info->process;
@@ -382,25 +317,23 @@ void QProcessManager::unlock()
static void qt_create_pipe(int *pipe)
{
if (pipe[0] != -1)
- qt_native_close(pipe[0]);
+ qt_safe_close(pipe[0]);
if (pipe[1] != -1)
- qt_native_close(pipe[1]);
- if (::pipe(pipe) != 0) {
+ qt_safe_close(pipe[1]);
+ if (qt_safe_pipe(pipe) != 0) {
qWarning("QProcessPrivate::createPipe: Cannot create pipe %p: %s",
pipe, qPrintable(qt_error_string(errno)));
}
- ::fcntl(pipe[0], F_SETFD, FD_CLOEXEC);
- ::fcntl(pipe[1], F_SETFD, FD_CLOEXEC);
}
void QProcessPrivate::destroyPipe(int *pipe)
{
if (pipe[1] != -1) {
- qt_native_close(pipe[1]);
+ qt_safe_close(pipe[1]);
pipe[1] = -1;
}
if (pipe[0] != -1) {
- qt_native_close(pipe[0]);
+ qt_safe_close(pipe[0]);
pipe[0] = -1;
}
}
@@ -453,7 +386,7 @@ bool QProcessPrivate::createChannel(Channel &channel)
if (&channel == &stdinChannel) {
// try to open in read-only mode
channel.pipe[1] = -1;
- if ( (channel.pipe[0] = QT_OPEN(fname, O_RDONLY)) != -1)
+ if ( (channel.pipe[0] = qt_safe_open(fname, O_RDONLY)) != -1)
return true; // success
q->setErrorString(QProcess::tr("Could not open input redirection for reading"));
@@ -465,7 +398,7 @@ bool QProcessPrivate::createChannel(Channel &channel)
mode |= O_TRUNC;
channel.pipe[0] = -1;
- if ( (channel.pipe[1] = QT_OPEN(fname, mode, 0666)) != -1)
+ if ( (channel.pipe[1] = qt_safe_open(fname, mode, 0666)) != -1)
return true; // success
q->setErrorString(QProcess::tr("Could not open output redirection for writing"));
@@ -586,8 +519,6 @@ void QProcessPrivate::startProcess()
return;
qt_create_pipe(childStartedPipe);
qt_create_pipe(deathPipe);
- ::fcntl(deathPipe[0], F_SETFD, FD_CLOEXEC);
- ::fcntl(deathPipe[1], F_SETFD, FD_CLOEXEC);
if (threadData->eventDispatcher) {
startupSocketNotifier = new QSocketNotifier(childStartedPipe[0],
@@ -728,11 +659,11 @@ void QProcessPrivate::startProcess()
// parent
// close the ends we don't use and make all pipes non-blocking
::fcntl(deathPipe[0], F_SETFL, ::fcntl(deathPipe[0], F_GETFL) | O_NONBLOCK);
- qt_native_close(childStartedPipe[1]);
+ qt_safe_close(childStartedPipe[1]);
childStartedPipe[1] = -1;
if (stdinChannel.pipe[0] != -1) {
- qt_native_close(stdinChannel.pipe[0]);
+ qt_safe_close(stdinChannel.pipe[0]);
stdinChannel.pipe[0] = -1;
}
@@ -740,7 +671,7 @@ void QProcessPrivate::startProcess()
::fcntl(stdinChannel.pipe[1], F_SETFL, ::fcntl(stdinChannel.pipe[1], F_GETFL) | O_NONBLOCK);
if (stdoutChannel.pipe[1] != -1) {
- qt_native_close(stdoutChannel.pipe[1]);
+ qt_safe_close(stdoutChannel.pipe[1]);
stdoutChannel.pipe[1] = -1;
}
@@ -748,7 +679,7 @@ void QProcessPrivate::startProcess()
::fcntl(stdoutChannel.pipe[0], F_SETFL, ::fcntl(stdoutChannel.pipe[0], F_GETFL) | O_NONBLOCK);
if (stderrChannel.pipe[1] != -1) {
- qt_native_close(stderrChannel.pipe[1]);
+ qt_safe_close(stderrChannel.pipe[1]);
stderrChannel.pipe[1] = -1;
}
if (stderrChannel.pipe[0] != -1)
@@ -761,35 +692,34 @@ void QProcessPrivate::execChild(const char *workingDir, char **path, char **argv
Q_Q(QProcess);
- // copy the stdin socket
- qt_native_dup2(stdinChannel.pipe[0], fileno(stdin));
+ // copy the stdin socket (without closing on exec)
+ qt_safe_dup2(stdinChannel.pipe[0], fileno(stdin), 0);
// copy the stdout and stderr if asked to
if (processChannelMode != QProcess::ForwardedChannels) {
- qt_native_dup2(stdoutChannel.pipe[1], fileno(stdout));
+ qt_safe_dup2(stdoutChannel.pipe[1], fileno(stdout), 0);
// merge stdout and stderr if asked to
if (processChannelMode == QProcess::MergedChannels) {
- qt_native_dup2(fileno(stdout), fileno(stderr));
+ qt_safe_dup2(fileno(stdout), fileno(stderr), 0);
} else {
- qt_native_dup2(stderrChannel.pipe[1], fileno(stderr));
+ qt_safe_dup2(stderrChannel.pipe[1], fileno(stderr), 0);
}
}
// make sure this fd is closed if execvp() succeeds
- qt_native_close(childStartedPipe[0]);
- ::fcntl(childStartedPipe[1], F_SETFD, FD_CLOEXEC);
+ qt_safe_close(childStartedPipe[0]);
// enter the working directory
if (workingDir)
- qt_native_chdir(workingDir);
+ QT_CHDIR(workingDir);
// this is a virtual call, and it base behavior is to do nothing.
q->setupChildProcess();
// execute the process
if (!envp) {
- qt_native_execvp(argv[0], argv);
+ qt_safe_execvp(argv[0], argv);
} else {
if (path) {
char **arg = path;
@@ -798,14 +728,14 @@ void QProcessPrivate::execChild(const char *workingDir, char **path, char **argv
#if defined (QPROCESS_DEBUG)
fprintf(stderr, "QProcessPrivate::execChild() searching / starting %s\n", argv[0]);
#endif
- qt_native_execve(argv[0], argv, envp);
+ qt_safe_execve(argv[0], argv, envp);
++arg;
}
} else {
#if defined (QPROCESS_DEBUG)
fprintf(stderr, "QProcessPrivate::execChild() starting %s\n", argv[0]);
#endif
- qt_native_execve(argv[0], argv, envp);
+ qt_safe_execve(argv[0], argv, envp);
}
}
@@ -813,21 +743,21 @@ void QProcessPrivate::execChild(const char *workingDir, char **path, char **argv
#if defined (QPROCESS_DEBUG)
fprintf(stderr, "QProcessPrivate::execChild() failed, notifying parent process\n");
#endif
- qt_native_write(childStartedPipe[1], "", 1);
- qt_native_close(childStartedPipe[1]);
+ qt_safe_write(childStartedPipe[1], "", 1);
+ qt_safe_close(childStartedPipe[1]);
childStartedPipe[1] = -1;
}
bool QProcessPrivate::processStarted()
{
char c;
- int i = qt_native_read(childStartedPipe[0], &c, 1);
+ int i = qt_safe_read(childStartedPipe[0], &c, 1);
if (startupSocketNotifier) {
startupSocketNotifier->setEnabled(false);
startupSocketNotifier->deleteLater();
startupSocketNotifier = 0;
}
- qt_native_close(childStartedPipe[0]);
+ qt_safe_close(childStartedPipe[0]);
childStartedPipe[0] = -1;
#if defined (QPROCESS_DEBUG)
@@ -862,7 +792,7 @@ qint64 QProcessPrivate::bytesAvailableFromStderr() const
qint64 QProcessPrivate::readFromStdout(char *data, qint64 maxlen)
{
- qint64 bytesRead = qt_native_read(stdoutChannel.pipe[0], data, maxlen);
+ qint64 bytesRead = qt_safe_read(stdoutChannel.pipe[0], data, maxlen);
#if defined QPROCESS_DEBUG
qDebug("QProcessPrivate::readFromStdout(%p \"%s\", %lld) == %lld",
data, qt_prettyDebug(data, bytesRead, 16).constData(), maxlen, bytesRead);
@@ -872,7 +802,7 @@ qint64 QProcessPrivate::readFromStdout(char *data, qint64 maxlen)
qint64 QProcessPrivate::readFromStderr(char *data, qint64 maxlen)
{
- qint64 bytesRead = qt_native_read(stderrChannel.pipe[0], data, maxlen);
+ qint64 bytesRead = qt_safe_read(stderrChannel.pipe[0], data, maxlen);
#if defined QPROCESS_DEBUG
qDebug("QProcessPrivate::readFromStderr(%p \"%s\", %lld) == %lld",
data, qt_prettyDebug(data, bytesRead, 16).constData(), maxlen, bytesRead);
@@ -896,7 +826,7 @@ qint64 QProcessPrivate::writeToStdin(const char *data, qint64 maxlen)
{
qt_ignore_sigpipe();
- qint64 written = qt_native_write(stdinChannel.pipe[1], data, maxlen);
+ qint64 written = qt_safe_write(stdinChannel.pipe[1], data, maxlen);
#if defined QPROCESS_DEBUG
qDebug("QProcessPrivate::writeToStdin(%p \"%s\", %lld) == %lld",
data, qt_prettyDebug(data, maxlen, 16).constData(), maxlen, written);
@@ -922,17 +852,15 @@ void QProcessPrivate::killProcess()
::kill(pid_t(pid), SIGKILL);
}
-static int qt_native_select(fd_set *fdread, fd_set *fdwrite, int timeout)
+static int select_msecs(int nfds, fd_set *fdread, fd_set *fdwrite, int timeout)
{
+ if (timeout < 0)
+ return qt_safe_select(nfds, fdread, fdwrite, 0, 0);
+
struct timeval tv;
tv.tv_sec = timeout / 1000;
tv.tv_usec = (timeout % 1000) * 1000;
-
- int ret;
- do {
- ret = select(FD_SETSIZE, fdread, fdwrite, 0, timeout < 0 ? 0 : &tv);
- } while (ret < 0 && (errno == EINTR));
- return ret;
+ return qt_safe_select(nfds, fdread, fdwrite, 0, &tv);
}
/*
@@ -960,11 +888,7 @@ bool QProcessPrivate::waitForStarted(int msecs)
fd_set fds;
FD_ZERO(&fds);
FD_SET(childStartedPipe[0], &fds);
- int ret;
- do {
- ret = qt_native_select(&fds, 0, msecs);
- } while (ret < 0 && errno == EINTR);
- if (ret == 0) {
+ if (select_msecs(childStartedPipe[0] + 1, &fds, 0, msecs) == 0) {
processError = QProcess::Timedout;
q->setErrorString(QProcess::tr("Process operation timed out"));
#if defined (QPROCESS_DEBUG)
@@ -997,24 +921,23 @@ bool QProcessPrivate::waitForReadyRead(int msecs)
FD_ZERO(&fdread);
FD_ZERO(&fdwrite);
+ int nfds = deathPipe[0];
+ FD_SET(deathPipe[0], &fdread);
+
if (processState == QProcess::Starting)
- FD_SET(childStartedPipe[0], &fdread);
+ add_fd(nfds, childStartedPipe[0], &fdread);
if (stdoutChannel.pipe[0] != -1)
- FD_SET(stdoutChannel.pipe[0], &fdread);
+ add_fd(nfds, stdoutChannel.pipe[0], &fdread);
if (stderrChannel.pipe[0] != -1)
- FD_SET(stderrChannel.pipe[0], &fdread);
-
- FD_SET(deathPipe[0], &fdread);
+ add_fd(nfds, stderrChannel.pipe[0], &fdread);
if (!writeBuffer.isEmpty() && stdinChannel.pipe[1] != -1)
- FD_SET(stdinChannel.pipe[1], &fdwrite);
+ add_fd(nfds, stdinChannel.pipe[1], &fdwrite);
int timeout = qt_timeout_value(msecs, stopWatch.elapsed());
- int ret = qt_native_select(&fdread, &fdwrite, timeout);
+ int ret = select_msecs(nfds + 1, &fdread, &fdwrite, timeout);
if (ret < 0) {
- if (errno == EINTR)
- continue;
break;
}
if (ret == 0) {
@@ -1070,24 +993,24 @@ bool QProcessPrivate::waitForBytesWritten(int msecs)
FD_ZERO(&fdread);
FD_ZERO(&fdwrite);
+ int nfds = deathPipe[0];
+ FD_SET(deathPipe[0], &fdread);
+
if (processState == QProcess::Starting)
- FD_SET(childStartedPipe[0], &fdread);
+ add_fd(nfds, childStartedPipe[0], &fdread);
if (stdoutChannel.pipe[0] != -1)
- FD_SET(stdoutChannel.pipe[0], &fdread);
+ add_fd(nfds, stdoutChannel.pipe[0], &fdread);
if (stderrChannel.pipe[0] != -1)
- FD_SET(stderrChannel.pipe[0], &fdread);
+ add_fd(nfds, stderrChannel.pipe[0], &fdread);
- FD_SET(deathPipe[0], &fdread);
if (!writeBuffer.isEmpty() && stdinChannel.pipe[1] != -1)
- FD_SET(stdinChannel.pipe[1], &fdwrite);
+ add_fd(nfds, stdinChannel.pipe[1], &fdwrite);
int timeout = qt_timeout_value(msecs, stopWatch.elapsed());
- int ret = qt_native_select(&fdread, &fdwrite, timeout);
+ int ret = select_msecs(nfds + 1, &fdread, &fdwrite, timeout);
if (ret < 0) {
- if (errno == EINTR)
- continue;
break;
}
@@ -1133,29 +1056,28 @@ bool QProcessPrivate::waitForFinished(int msecs)
forever {
fd_set fdread;
fd_set fdwrite;
+ int nfds = -1;
FD_ZERO(&fdread);
FD_ZERO(&fdwrite);
if (processState == QProcess::Starting)
- FD_SET(childStartedPipe[0], &fdread);
+ add_fd(nfds, childStartedPipe[0], &fdread);
if (stdoutChannel.pipe[0] != -1)
- FD_SET(stdoutChannel.pipe[0], &fdread);
+ add_fd(nfds, stdoutChannel.pipe[0], &fdread);
if (stderrChannel.pipe[0] != -1)
- FD_SET(stderrChannel.pipe[0], &fdread);
+ add_fd(nfds, stderrChannel.pipe[0], &fdread);
if (processState == QProcess::Running)
- FD_SET(deathPipe[0], &fdread);
+ add_fd(nfds, deathPipe[0], &fdread);
if (!writeBuffer.isEmpty() && stdinChannel.pipe[1] != -1)
- FD_SET(stdinChannel.pipe[1], &fdwrite);
+ add_fd(nfds, stdinChannel.pipe[1], &fdwrite);
int timeout = qt_timeout_value(msecs, stopWatch.elapsed());
- int ret = qt_native_select(&fdread, &fdwrite, timeout);
+ int ret = select_msecs(nfds + 1, &fdread, &fdwrite, timeout);
if (ret < 0) {
- if (errno == EINTR)
- continue;
break;
}
if (ret == 0) {
@@ -1190,12 +1112,7 @@ bool QProcessPrivate::waitForWrite(int msecs)
fd_set fdwrite;
FD_ZERO(&fdwrite);
FD_SET(stdinChannel.pipe[1], &fdwrite);
-
- int ret;
- do {
- ret = qt_native_select(0, &fdwrite, msecs < 0 ? 0 : msecs) == 1;
- } while (ret < 0 && errno == EINTR);
- return ret == 1;
+ return select_msecs(stdinChannel.pipe[1] + 1, 0, &fdwrite, msecs < 0 ? 0 : msecs) == 1;
}
void QProcessPrivate::findExitCode()
@@ -1210,15 +1127,11 @@ bool QProcessPrivate::waitForDeadChild()
// read a byte from the death pipe
char c;
- qt_native_read(deathPipe[0], &c, 1);
+ qt_safe_read(deathPipe[0], &c, 1);
// check if our process is dead
int exitStatus;
- pid_t waitResult = 0;
- do {
- waitResult = waitpid(pid_t(pid), &exitStatus, WNOHANG);
- } while ((waitResult == -1 && errno == EINTR));
- if (waitResult > 0) {
+ if (qt_safe_waitpid(pid_t(pid), &exitStatus, WNOHANG) > 0) {
processManager()->remove(q);
crashed = !WIFEXITED(exitStatus);
exitCode = WEXITSTATUS(exitStatus);
@@ -1248,10 +1161,10 @@ bool QProcessPrivate::startDetached(const QString &program, const QStringList &a
// To catch the startup of the child
int startedPipe[2];
- ::pipe(startedPipe);
+ qt_safe_pipe(startedPipe);
// To communicate the pid of the child
int pidPipe[2];
- ::pipe(pidPipe);
+ qt_safe_pipe(pidPipe);
pid_t childPid = qt_fork();
if (childPid == 0) {
@@ -1262,16 +1175,15 @@ bool QProcessPrivate::startDetached(const QString &program, const QStringList &a
::setsid();
- qt_native_close(startedPipe[0]);
- qt_native_close(pidPipe[0]);
+ qt_safe_close(startedPipe[0]);
+ qt_safe_close(pidPipe[0]);
pid_t doubleForkPid = qt_fork();
if (doubleForkPid == 0) {
- ::fcntl(startedPipe[1], F_SETFD, FD_CLOEXEC);
- qt_native_close(pidPipe[1]);
+ qt_safe_close(pidPipe[1]);
if (!encodedWorkingDirectory.isEmpty())
- qt_native_chdir(encodedWorkingDirectory.constData());
+ QT_CHDIR(encodedWorkingDirectory.constData());
char **argv = new char *[arguments.size() + 2];
for (int i = 0; i < arguments.size(); ++i) {
@@ -1292,13 +1204,13 @@ bool QProcessPrivate::startDetached(const QString &program, const QStringList &a
if (!tmp.endsWith('/')) tmp += '/';
tmp += QFile::encodeName(program);
argv[0] = tmp.data();
- qt_native_execv(argv[0], argv);
+ qt_safe_execv(argv[0], argv);
}
}
} else {
QByteArray tmp = QFile::encodeName(program);
argv[0] = tmp.data();
- qt_native_execv(argv[0], argv);
+ qt_safe_execv(argv[0], argv);
}
struct sigaction noaction;
@@ -1308,8 +1220,8 @@ bool QProcessPrivate::startDetached(const QString &program, const QStringList &a
// '\1' means execv failed
char c = '\1';
- qt_native_write(startedPipe[1], &c, 1);
- qt_native_close(startedPipe[1]);
+ qt_safe_write(startedPipe[1], &c, 1);
+ qt_safe_close(startedPipe[1]);
::_exit(1);
} else if (doubleForkPid == -1) {
struct sigaction noaction;
@@ -1319,40 +1231,39 @@ bool QProcessPrivate::startDetached(const QString &program, const QStringList &a
// '\2' means internal error
char c = '\2';
- qt_native_write(startedPipe[1], &c, 1);
+ qt_safe_write(startedPipe[1], &c, 1);
}
- qt_native_close(startedPipe[1]);
- qt_native_write(pidPipe[1], (const char *)&doubleForkPid, sizeof(pid_t));
- qt_native_chdir("/");
+ qt_safe_close(startedPipe[1]);
+ qt_safe_write(pidPipe[1], (const char *)&doubleForkPid, sizeof(pid_t));
+ QT_CHDIR("/");
::_exit(1);
}
- qt_native_close(startedPipe[1]);
- qt_native_close(pidPipe[1]);
+ qt_safe_close(startedPipe[1]);
+ qt_safe_close(pidPipe[1]);
if (childPid == -1) {
- qt_native_close(startedPipe[0]);
- qt_native_close(pidPipe[0]);
+ qt_safe_close(startedPipe[0]);
+ qt_safe_close(pidPipe[0]);
return false;
}
char reply = '\0';
- int startResult = qt_native_read(startedPipe[0], &reply, 1);
+ int startResult = qt_safe_read(startedPipe[0], &reply, 1);
int result;
- qt_native_close(startedPipe[0]);
- while (::waitpid(childPid, &result, 0) == -1 && errno == EINTR)
- { }
+ qt_safe_close(startedPipe[0]);
+ qt_safe_waitpid(childPid, &result, 0);
bool success = (startResult != -1 && reply == '\0');
if (success && pid) {
pid_t actualPid = 0;
- if (qt_native_read(pidPipe[0], (char *)&actualPid, sizeof(pid_t)) == sizeof(pid_t)) {
+ if (qt_safe_read(pidPipe[0], (char *)&actualPid, sizeof(pid_t)) == sizeof(pid_t)) {
*pid = actualPid;
} else {
*pid = 0;
}
}
- qt_native_close(pidPipe[0]);
+ qt_safe_close(pidPipe[0]);
return success;
}
diff --git a/src/corelib/io/qprocess_win.cpp b/src/corelib/io/qprocess_win.cpp
index d028df1..eae17b4 100644
--- a/src/corelib/io/qprocess_win.cpp
+++ b/src/corelib/io/qprocess_win.cpp
@@ -54,7 +54,7 @@
#include <private/qthread_p.h>
#include <qdebug.h>
-#include "private/qfsfileengine_p.h" // for longFileName and win95FileName
+#include "private/qfsfileengine_p.h" // for longFileName
#ifndef QT_NO_PROCESS
@@ -122,25 +122,15 @@ bool QProcessPrivate::createChannel(Channel &channel)
if (&channel == &stdinChannel) {
// try to open in read-only mode
channel.pipe[1] = INVALID_Q_PIPE;
- QT_WA({
- channel.pipe[0] =
- CreateFileW((TCHAR*)QFSFileEnginePrivate::longFileName(channel.file).utf16(),
- GENERIC_READ,
- FILE_SHARE_READ | FILE_SHARE_WRITE,
- &secAtt,
- OPEN_EXISTING,
- FILE_ATTRIBUTE_NORMAL,
- NULL);
- }, {
- channel.pipe[0] =
- CreateFileA(QFSFileEnginePrivate::win95Name(channel.file),
- GENERIC_READ,
- FILE_SHARE_READ | FILE_SHARE_WRITE,
- &secAtt,
- OPEN_EXISTING,
- FILE_ATTRIBUTE_NORMAL,
- NULL);
- });
+ channel.pipe[0] =
+ CreateFile((const wchar_t*)QFSFileEnginePrivate::longFileName(channel.file).utf16(),
+ GENERIC_READ,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ &secAtt,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
if (channel.pipe[0] != INVALID_Q_PIPE)
return true;
@@ -148,31 +138,15 @@ bool QProcessPrivate::createChannel(Channel &channel)
} else {
// open in write mode
channel.pipe[0] = INVALID_Q_PIPE;
- DWORD creation;
- if (channel.append)
- creation = OPEN_ALWAYS;
- else
- creation = CREATE_ALWAYS;
-
- QT_WA({
- channel.pipe[1] =
- CreateFileW((TCHAR*)QFSFileEnginePrivate::longFileName(channel.file).utf16(),
- GENERIC_WRITE,
- FILE_SHARE_READ | FILE_SHARE_WRITE,
- &secAtt,
- creation,
- FILE_ATTRIBUTE_NORMAL,
- NULL);
- }, {
- channel.pipe[1] =
- CreateFileA(QFSFileEnginePrivate::win95Name(channel.file),
- GENERIC_WRITE,
- FILE_SHARE_READ | FILE_SHARE_WRITE,
- &secAtt,
- creation,
- FILE_ATTRIBUTE_NORMAL,
- NULL);
- });
+ channel.pipe[1] =
+ CreateFile((const wchar_t *)QFSFileEnginePrivate::longFileName(channel.file).utf16(),
+ GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ &secAtt,
+ channel.append ? OPEN_ALWAYS : CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
if (channel.pipe[1] != INVALID_Q_PIPE) {
if (channel.append) {
SetFilePointer(channel.pipe[1], 0, NULL, FILE_END);
@@ -327,56 +301,37 @@ static QByteArray qt_create_environment(const QHash<QString, QString> *environme
int pos = 0;
QHash<QString, QString>::ConstIterator it = copy.constBegin(),
end = copy.constEnd();
-#ifdef UNICODE
- if (!(QSysInfo::WindowsVersion & QSysInfo::WV_DOS_based)) {
- static const TCHAR equal = L'=';
- static const TCHAR nul = L'\0';
-
- for ( ; it != end; ++it) {
- uint tmpSize = sizeof(TCHAR) * (it.key().length() + it.value().length() + 2);
- // ignore empty strings
- if (tmpSize == sizeof(TCHAR)*2)
- continue;
- envlist.resize(envlist.size() + tmpSize);
-
- tmpSize = it.key().length() * sizeof(TCHAR);
- memcpy(envlist.data()+pos, it.key().utf16(), tmpSize);
- pos += tmpSize;
-
- memcpy(envlist.data()+pos, &equal, sizeof(TCHAR));
- pos += sizeof(TCHAR);
-
- tmpSize = it.value().length() * sizeof(TCHAR);
- memcpy(envlist.data()+pos, it.value().utf16(), tmpSize);
- pos += tmpSize;
-
- memcpy(envlist.data()+pos, &nul, sizeof(TCHAR));
- pos += sizeof(TCHAR);
- }
- // add the 2 terminating 0 (actually 4, just to be on the safe side)
- envlist.resize( envlist.size()+4 );
- envlist[pos++] = 0;
- envlist[pos++] = 0;
- envlist[pos++] = 0;
- envlist[pos++] = 0;
- } else
-#endif // UNICODE
- {
- for ( ; it != end; it++) {
- QByteArray tmp = it.key().toLocal8Bit();
- tmp.append('=');
- tmp.append(it.value().toLocal8Bit());
-
- uint tmpSize = tmp.length() + 1;
- envlist.resize(envlist.size() + tmpSize);
- memcpy(envlist.data()+pos, tmp.data(), tmpSize);
- pos += tmpSize;
- }
- // add the terminating 0 (actually 2, just to be on the safe side)
- envlist.resize(envlist.size()+2);
- envlist[pos++] = 0;
- envlist[pos++] = 0;
+
+ static const wchar_t equal = L'=';
+ static const wchar_t nul = L'\0';
+
+ for ( ; it != end; ++it) {
+ uint tmpSize = sizeof(wchar_t) * (it.key().length() + it.value().length() + 2);
+ // ignore empty strings
+ if (tmpSize == sizeof(wchar_t) * 2)
+ continue;
+ envlist.resize(envlist.size() + tmpSize);
+
+ tmpSize = it.key().length() * sizeof(wchar_t);
+ memcpy(envlist.data()+pos, it.key().utf16(), tmpSize);
+ pos += tmpSize;
+
+ memcpy(envlist.data()+pos, &equal, sizeof(wchar_t));
+ pos += sizeof(wchar_t);
+
+ tmpSize = it.value().length() * sizeof(wchar_t);
+ memcpy(envlist.data()+pos, it.value().utf16(), tmpSize);
+ pos += tmpSize;
+
+ memcpy(envlist.data()+pos, &nul, sizeof(wchar_t));
+ pos += sizeof(wchar_t);
}
+ // add the 2 terminating 0 (actually 4, just to be on the safe side)
+ envlist.resize( envlist.size()+4 );
+ envlist[pos++] = 0;
+ envlist[pos++] = 0;
+ envlist[pos++] = 0;
+ envlist[pos++] = 0;
}
return envlist;
}
@@ -417,58 +372,33 @@ void QProcessPrivate::startProcess()
qDebug(" pass environment : %s", environment.isEmpty() ? "no" : "yes");
#endif
- DWORD dwCreationFlags = 0;
- if (!(QSysInfo::WindowsVersion & QSysInfo::WV_DOS_based))
- dwCreationFlags |= CREATE_NO_WINDOW;
+ DWORD dwCreationFlags = CREATE_NO_WINDOW;
-#ifdef UNICODE
- if (!(QSysInfo::WindowsVersion & QSysInfo::WV_DOS_based)) {
#if defined(Q_OS_WINCE)
QString fullPathProgram = program;
if (!QDir::isAbsolutePath(fullPathProgram))
fullPathProgram = QFileInfo(fullPathProgram).absoluteFilePath();
fullPathProgram.replace(QLatin1Char('/'), QLatin1Char('\\'));
- success = CreateProcessW((WCHAR*)fullPathProgram.utf16(),
- (WCHAR*)args.utf16(),
- 0, 0, false, 0, 0, 0, 0, pid);
+ success = CreateProcess((wchar_t*)fullPathProgram.utf16(),
+ (wchar_t*)args.utf16(),
+ 0, 0, false, 0, 0, 0, 0, pid);
#else
dwCreationFlags |= CREATE_UNICODE_ENVIRONMENT;
STARTUPINFOW startupInfo = { sizeof( STARTUPINFO ), 0, 0, 0,
(ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT,
- (ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT,
- 0, 0, 0,
- STARTF_USESTDHANDLES,
- 0, 0, 0,
- stdinChannel.pipe[0], stdoutChannel.pipe[1], stderrChannel.pipe[1]
+ (ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT,
+ 0, 0, 0,
+ STARTF_USESTDHANDLES,
+ 0, 0, 0,
+ stdinChannel.pipe[0], stdoutChannel.pipe[1], stderrChannel.pipe[1]
};
- success = CreateProcessW(0, (WCHAR*)args.utf16(),
- 0, 0, TRUE, dwCreationFlags,
- environment ? envlist.data() : 0,
- workingDirectory.isEmpty() ? 0
- : (WCHAR*)QDir::toNativeSeparators(workingDirectory).utf16(),
- &startupInfo, pid);
-#endif
- } else
-#endif // UNICODE
- {
-#ifndef Q_OS_WINCE
- STARTUPINFOA startupInfo = { sizeof( STARTUPINFOA ), 0, 0, 0,
- (ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT,
- (ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT,
- 0, 0, 0,
- STARTF_USESTDHANDLES,
- 0, 0, 0,
- stdinChannel.pipe[0], stdoutChannel.pipe[1], stderrChannel.pipe[1]
- };
-
- success = CreateProcessA(0, args.toLocal8Bit().data(),
- 0, 0, TRUE, dwCreationFlags, environment ? envlist.data() : 0,
- workingDirectory.isEmpty() ? 0
- : QDir::toNativeSeparators(workingDirectory).toLocal8Bit().data(),
- &startupInfo, pid);
-#endif // Q_OS_WINCE
- }
-#ifndef Q_OS_WINCE
+ success = CreateProcess(0, (wchar_t*)args.utf16(),
+ 0, 0, TRUE, dwCreationFlags,
+ environment ? envlist.data() : 0,
+ workingDirectory.isEmpty() ? 0
+ : (wchar_t*)QDir::toNativeSeparators(workingDirectory).utf16(),
+ &startupInfo, pid);
+
if (stdinChannel.pipe[0] != INVALID_Q_PIPE) {
CloseHandle(stdinChannel.pipe[0]);
stdinChannel.pipe[0] = INVALID_Q_PIPE;
@@ -508,7 +438,7 @@ void QProcessPrivate::startProcess()
}
// give the process a chance to start ...
- Sleep(SLEEPMIN*2);
+ Sleep(SLEEPMIN * 2);
_q_startupNotification();
}
@@ -882,42 +812,25 @@ bool QProcessPrivate::startDetached(const QString &program, const QStringList &a
PROCESS_INFORMATION pinfo;
-#ifdef UNICODE
- if (!(QSysInfo::WindowsVersion & QSysInfo::WV_DOS_based)) {
#if defined(Q_OS_WINCE)
QString fullPathProgram = program;
if (!QDir::isAbsolutePath(fullPathProgram))
fullPathProgram.prepend(QDir::currentPath().append(QLatin1Char('/')));
fullPathProgram.replace(QLatin1Char('/'), QLatin1Char('\\'));
- success = CreateProcessW((WCHAR*)fullPathProgram.utf16(),
- (WCHAR*)args.utf16(),
- 0, 0, false, CREATE_NEW_CONSOLE, 0, 0, 0, &pinfo);
+ 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 = CreateProcessW(0, (WCHAR*)args.utf16(),
- 0, 0, FALSE, CREATE_UNICODE_ENVIRONMENT | CREATE_NEW_CONSOLE, 0,
- workingDir.isEmpty() ? (const WCHAR *)0 : (const WCHAR *)workingDir.utf16(),
- &startupInfo, &pinfo);
-#endif
- } else
-#endif // UNICODE
- {
-#ifndef Q_OS_WINCE
- STARTUPINFOA startupInfo = { sizeof( STARTUPINFOA ), 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 = CreateProcessA(0, args.toLocal8Bit().data(),
- 0, 0, FALSE, CREATE_NEW_CONSOLE, 0,
- workingDir.isEmpty() ? (LPCSTR)0 : workingDir.toLocal8Bit().constData(),
+ 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
- }
if (success) {
CloseHandle(pinfo.hThread);
diff --git a/src/corelib/io/qresource.cpp b/src/corelib/io/qresource.cpp
index f59be7b..e15fcf2 100644
--- a/src/corelib/io/qresource.cpp
+++ b/src/corelib/io/qresource.cpp
@@ -56,8 +56,21 @@
#include <qplatformdefs.h>
#include "private/qabstractfileengine_p.h"
+#ifdef Q_OS_UNIX
+# include "private/qcore_unix_p.h"
+#endif
+
//#define DEBUG_RESOURCE_MATCH
+#if defined(Q_OS_VXWORKS)
+# if defined(m_data)
+# undef m_data
+# endif
+# if defined(m_len)
+# undef m_len
+# endif
+#endif
+
QT_BEGIN_NAMESPACE
@@ -568,7 +581,7 @@ QResource::addSearchPath(const QString &path)
Returns the current search path list. This list is consulted when
creating a relative resource.
- \sa addSearchPath()
+ \sa QDir::addSearchPath() QDir::setSearchPaths()
*/
QStringList
diff --git a/src/corelib/io/qresource.h b/src/corelib/io/qresource.h
index 49dacea..0bf9660 100644
--- a/src/corelib/io/qresource.h
+++ b/src/corelib/io/qresource.h
@@ -94,7 +94,7 @@ protected:
QScopedPointer<QResourcePrivate> d_ptr;
private:
- Q_DECLARE_SCOPED_PRIVATE(QResource)
+ Q_DECLARE_PRIVATE(QResource)
};
QT_END_NAMESPACE
diff --git a/src/corelib/io/qresource_iterator.cpp b/src/corelib/io/qresource_iterator.cpp
index e97ac59..11f4acf 100644
--- a/src/corelib/io/qresource_iterator.cpp
+++ b/src/corelib/io/qresource_iterator.cpp
@@ -73,13 +73,11 @@ bool QResourceFileEngineIterator::hasNext() const
return false;
// Initialize and move to the next entry.
- QResourceFileEngineIterator *that = const_cast<QResourceFileEngineIterator *>(this);
- that->entries = resource.children();
- if (!that->entries.isEmpty())
- that->index = 0;
+ entries = resource.children();
+ index = 0;
}
- return index <= entries.size();
+ return index < entries.size();
}
QString QResourceFileEngineIterator::currentFileName() const
diff --git a/src/corelib/io/qresource_iterator_p.h b/src/corelib/io/qresource_iterator_p.h
index b5e8382..5165157 100644
--- a/src/corelib/io/qresource_iterator_p.h
+++ b/src/corelib/io/qresource_iterator_p.h
@@ -71,8 +71,8 @@ public:
QString currentFileName() const;
private:
- QStringList entries;
- int index;
+ mutable QStringList entries;
+ mutable int index;
};
QT_END_NAMESPACE
diff --git a/src/corelib/io/qresource_p.h b/src/corelib/io/qresource_p.h
index 452d8e1..f58f9a2 100644
--- a/src/corelib/io/qresource_p.h
+++ b/src/corelib/io/qresource_p.h
@@ -61,7 +61,7 @@ class QResourceFileEnginePrivate;
class QResourceFileEngine : public QAbstractFileEngine
{
private:
- Q_DECLARE_SCOPED_PRIVATE(QResourceFileEngine)
+ Q_DECLARE_PRIVATE(QResourceFileEngine)
public:
explicit QResourceFileEngine(const QString &path);
~QResourceFileEngine();
diff --git a/src/corelib/io/qsettings.cpp b/src/corelib/io/qsettings.cpp
index 1650526..7df6eee 100644
--- a/src/corelib/io/qsettings.cpp
+++ b/src/corelib/io/qsettings.cpp
@@ -74,6 +74,10 @@
#endif // Q_OS_WIN
#endif // QT_NO_QOBJECT
+#ifdef Q_OS_VXWORKS
+# include <ioLib.h>
+#endif
+
#include <stdlib.h>
#ifndef CSIDL_COMMON_APPDATA
@@ -167,7 +171,7 @@ static bool isLikelyToBeNfs(int handle)
}
#elif defined(Q_OS_SOLARIS) || defined(Q_OS_IRIX) || defined(Q_OS_AIX) || defined(Q_OS_HPUX) \
- || defined(Q_OS_OSF) || defined(Q_OS_QNX) || defined(Q_OS_QNX6) || defined(Q_OS_SCO) \
+ || defined(Q_OS_OSF) || defined(Q_OS_QNX) || defined(Q_OS_SCO) \
|| defined(Q_OS_UNIXWARE) || defined(Q_OS_RELIANT) || defined(Q_OS_NETBSD)
QT_BEGIN_INCLUDE_NAMESPACE
# include <sys/statvfs.h>
@@ -1042,33 +1046,16 @@ static QString windowsConfigPath(int type)
// This only happens when bootstrapping qmake.
#ifndef Q_OS_WINCE
QLibrary library(QLatin1String("shell32"));
- QT_WA( {
- typedef BOOL (WINAPI*GetSpecialFolderPath)(HWND, LPTSTR, int, BOOL);
- GetSpecialFolderPath SHGetSpecialFolderPath = (GetSpecialFolderPath)library.resolve("SHGetSpecialFolderPathW");
- if (SHGetSpecialFolderPath) {
- TCHAR path[MAX_PATH];
- SHGetSpecialFolderPath(0, path, type, FALSE);
- result = QString::fromUtf16((ushort*)path);
- }
- } , {
- typedef BOOL (WINAPI*GetSpecialFolderPath)(HWND, char*, int, BOOL);
- GetSpecialFolderPath SHGetSpecialFolderPath = (GetSpecialFolderPath)library.resolve("SHGetSpecialFolderPathA");
- if (SHGetSpecialFolderPath) {
- char path[MAX_PATH];
- SHGetSpecialFolderPath(0, path, type, FALSE);
- result = QString::fromLocal8Bit(path);
- }
- } );
#else
QLibrary library(QLatin1String("coredll"));
- typedef BOOL (WINAPI*GetSpecialFolderPath)(HWND, LPTSTR, int, BOOL);
- GetSpecialFolderPath SHGetSpecialFolderPath = (GetSpecialFolderPath)library.resolve("SHGetSpecialFolderPath");
+#endif // Q_OS_WINCE
+ typedef BOOL (WINAPI*GetSpecialFolderPath)(HWND, LPWSTR, int, BOOL);
+ GetSpecialFolderPath SHGetSpecialFolderPath = (GetSpecialFolderPath)library.resolve("SHGetSpecialFolderPathW");
if (SHGetSpecialFolderPath) {
wchar_t path[MAX_PATH];
SHGetSpecialFolderPath(0, path, type, FALSE);
- result = QString::fromUtf16((ushort*)path);
+ result = QString::fromWCharArray(path);
}
-#endif // Q_OS_WINCE
#endif // QT_NO_QOBJECT
@@ -1466,11 +1453,7 @@ void QConfFileSettingsPrivate::syncConfFile(int confFileNo)
QString writeSemName = QLatin1String("QSettingsWriteSem ");
writeSemName.append(file.fileName());
- QT_WA( {
- writeSemaphore = CreateSemaphoreW(0, 1, 1, reinterpret_cast<const wchar_t *>(writeSemName.utf16()));
- } , {
- writeSemaphore = CreateSemaphoreA(0, 1, 1, writeSemName.toLocal8Bit());
- } );
+ writeSemaphore = CreateSemaphore(0, 1, 1, reinterpret_cast<const wchar_t *>(writeSemName.utf16()));
if (writeSemaphore) {
WaitForSingleObject(writeSemaphore, INFINITE);
@@ -1486,11 +1469,7 @@ void QConfFileSettingsPrivate::syncConfFile(int confFileNo)
QString readSemName(QLatin1String("QSettingsReadSem "));
readSemName.append(file.fileName());
- QT_WA( {
- readSemaphore = CreateSemaphoreW(0, FileLockSemMax, FileLockSemMax, reinterpret_cast<const wchar_t *>(readSemName.utf16()));
- } , {
- readSemaphore = CreateSemaphoreA(0, FileLockSemMax, FileLockSemMax, readSemName.toLocal8Bit());
- } );
+ readSemaphore = CreateSemaphore(0, FileLockSemMax, FileLockSemMax, reinterpret_cast<const wchar_t *>(readSemName.utf16()));
if (readSemaphore) {
for (int i = 0; i < numReadLocks; ++i)
diff --git a/src/corelib/io/qsettings.h b/src/corelib/io/qsettings.h
index a082d6a..0d382b66 100644
--- a/src/corelib/io/qsettings.h
+++ b/src/corelib/io/qsettings.h
@@ -80,7 +80,7 @@ class Q_CORE_EXPORT QSettings
#else
QScopedPointer<QSettingsPrivate> d_ptr;
#endif
- Q_DECLARE_SCOPED_PRIVATE(QSettings)
+ Q_DECLARE_PRIVATE(QSettings)
public:
enum Status {
diff --git a/src/corelib/io/qsettings_win.cpp b/src/corelib/io/qsettings_win.cpp
index 0cbcc10..1e1509d 100644
--- a/src/corelib/io/qsettings_win.cpp
+++ b/src/corelib/io/qsettings_win.cpp
@@ -130,24 +130,13 @@ static void mergeKeySets(NameSet *dest, const QStringList &src)
static QString errorCodeToString(DWORD errorCode)
{
- QString result;
- QT_WA({
- wchar_t *data = 0;
- FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
- 0, errorCode, 0,
- data, 0, 0);
- result = QString::fromUtf16(reinterpret_cast<const ushort *> (data));
- if (data != 0)
- LocalFree(data);
- }, {
- char *data = 0;
- FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
- 0, errorCode, 0,
- (char *)&data, 0, 0);
- result = QString::fromLocal8Bit(data);
- if (data != 0)
- LocalFree(data);
- })
+ wchar_t *data = 0;
+ FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, 0, errorCode, 0, data, 0, 0);
+ QString result = QString::fromWCharArray(data);
+
+ if (data != 0)
+ LocalFree(data);
+
if (result.endsWith(QLatin1Char('\n')))
result.truncate(result.length() - 1);
@@ -158,15 +147,8 @@ static QString errorCodeToString(DWORD errorCode)
static HKEY openKey(HKEY parentHandle, REGSAM perms, const QString &rSubKey)
{
HKEY resultHandle = 0;
-
- LONG res;
- QT_WA( {
- res = RegOpenKeyExW(parentHandle, reinterpret_cast<const wchar_t *>(rSubKey.utf16()),
- 0, perms, &resultHandle);
- } , {
- res = RegOpenKeyExA(parentHandle, rSubKey.toLocal8Bit(),
+ LONG res = RegOpenKeyEx(parentHandle, reinterpret_cast<const wchar_t *>(rSubKey.utf16()),
0, perms, &resultHandle);
- } );
if (res == ERROR_SUCCESS)
return resultHandle;
@@ -183,14 +165,8 @@ static HKEY createOrOpenKey(HKEY parentHandle, REGSAM perms, const QString &rSub
return resultHandle;
// try to create it
- LONG res;
- QT_WA( {
- res = RegCreateKeyExW(parentHandle, reinterpret_cast<const wchar_t *>(rSubKey.utf16()), 0, 0,
- REG_OPTION_NON_VOLATILE, perms, 0, &resultHandle, 0);
- } , {
- res = RegCreateKeyExA(parentHandle, rSubKey.toLocal8Bit(), 0, 0,
+ LONG res = RegCreateKeyEx(parentHandle, reinterpret_cast<const wchar_t *>(rSubKey.utf16()), 0, 0,
REG_OPTION_NON_VOLATILE, perms, 0, &resultHandle, 0);
- } );
if (res == ERROR_SUCCESS)
return resultHandle;
@@ -225,20 +201,14 @@ static HKEY createOrOpenKey(HKEY parentHandle, const QString &rSubKey, bool *rea
static QStringList childKeysOrGroups(HKEY parentHandle, QSettingsPrivate::ChildSpec spec)
{
QStringList result;
- LONG res;
DWORD numKeys;
DWORD maxKeySize;
DWORD numSubgroups;
DWORD maxSubgroupSize;
// Find the number of keys and subgroups, as well as the max of their lengths.
- QT_WA( {
- res = RegQueryInfoKeyW(parentHandle, 0, 0, 0, &numSubgroups, &maxSubgroupSize, 0,
+ LONG res = RegQueryInfoKey(parentHandle, 0, 0, 0, &numSubgroups, &maxSubgroupSize, 0,
&numKeys, &maxKeySize, 0, 0, 0);
- }, {
- res = RegQueryInfoKeyA(parentHandle, 0, 0, 0, &numSubgroups, &maxSubgroupSize, 0,
- &numKeys, &maxKeySize, 0, 0, 0);
- } );
if (res != ERROR_SUCCESS) {
qWarning("QSettings: RegQueryInfoKey() failed: %s", errorCodeToString(res).toLatin1().data());
@@ -258,36 +228,21 @@ static QStringList childKeysOrGroups(HKEY parentHandle, QSettingsPrivate::ChildS
m = maxSubgroupSize;
}
- /* Windows NT/2000/XP: The size does not include the terminating null character.
- Windows Me/98/95: The size includes the terminating null character. */
+ /* The size does not include the terminating null character. */
++m;
// Get the list
- QByteArray buff(m*sizeof(ushort), 0);
+ QByteArray buff(m * sizeof(wchar_t), 0);
for (int i = 0; i < n; ++i) {
QString item;
- QT_WA( {
- DWORD l = buff.size() / sizeof(ushort);
- if (spec == QSettingsPrivate::ChildKeys) {
- res = RegEnumValueW(parentHandle, i,
- reinterpret_cast<wchar_t *>(buff.data()),
- &l, 0, 0, 0, 0);
- } else {
- res = RegEnumKeyExW(parentHandle, i,
- reinterpret_cast<wchar_t *>(buff.data()),
- &l, 0, 0, 0, 0);
- }
- if (res == ERROR_SUCCESS)
- item = QString::fromUtf16(reinterpret_cast<ushort*>(buff.data()), l);
- }, {
- DWORD l = buff.size();
- if (spec == QSettingsPrivate::ChildKeys)
- res = RegEnumValueA(parentHandle, i, buff.data(), &l, 0, 0, 0, 0);
- else
- res = RegEnumKeyExA(parentHandle, i, buff.data(), &l, 0, 0, 0, 0);
- if (res == ERROR_SUCCESS)
- item = QString::fromLocal8Bit(buff.data(), l);
- } );
+ DWORD l = buff.size() / sizeof(wchar_t);
+ if (spec == QSettingsPrivate::ChildKeys) {
+ res = RegEnumValue(parentHandle, i, reinterpret_cast<wchar_t *>(buff.data()), &l, 0, 0, 0, 0);
+ } else {
+ res = RegEnumKeyEx(parentHandle, i, reinterpret_cast<wchar_t *>(buff.data()), &l, 0, 0, 0, 0);
+ }
+ if (res == ERROR_SUCCESS)
+ item = QString::fromWCharArray((const wchar_t *)buff.constData(), l);
if (res != ERROR_SUCCESS) {
qWarning("QSettings: RegEnumValue failed: %s", errorCodeToString(res).toLatin1().data());
@@ -342,12 +297,7 @@ static void deleteChildGroups(HKEY parentHandle)
RegCloseKey(childGroupHandle);
// delete group itself
- LONG res;
- QT_WA( {
- res = RegDeleteKeyW(parentHandle, reinterpret_cast<const wchar_t *>(group.utf16()));
- }, {
- res = RegDeleteKeyA(parentHandle, group.toLocal8Bit());
- } );
+ LONG res = RegDeleteKey(parentHandle, reinterpret_cast<const wchar_t *>(group.utf16()));
if (res != ERROR_SUCCESS) {
qWarning("QSettings: RegDeleteKey failed on subkey \"%s\": %s",
group.toLatin1().data(), errorCodeToString(res).toLatin1().data());
@@ -519,12 +469,7 @@ bool QWinSettingsPrivate::readKey(HKEY parentHandle, const QString &rSubKey, QVa
// get the size and type of the value
DWORD dataType;
DWORD dataSize;
- LONG res;
- QT_WA( {
- res = RegQueryValueExW(handle, reinterpret_cast<const wchar_t *>(rSubkeyName.utf16()), 0, &dataType, 0, &dataSize);
- }, {
- res = RegQueryValueExA(handle, rSubkeyName.toLocal8Bit(), 0, &dataType, 0, &dataSize);
- } );
+ LONG res = RegQueryValueEx(handle, reinterpret_cast<const wchar_t *>(rSubkeyName.utf16()), 0, &dataType, 0, &dataSize);
if (res != ERROR_SUCCESS) {
RegCloseKey(handle);
return false;
@@ -532,13 +477,8 @@ bool QWinSettingsPrivate::readKey(HKEY parentHandle, const QString &rSubKey, QVa
// get the value
QByteArray data(dataSize, 0);
- QT_WA( {
- res = RegQueryValueExW(handle, reinterpret_cast<const wchar_t *>(rSubkeyName.utf16()), 0, 0,
- reinterpret_cast<unsigned char*>(data.data()), &dataSize);
- }, {
- res = RegQueryValueExA(handle, rSubkeyName.toLocal8Bit(), 0, 0,
- reinterpret_cast<unsigned char*>(data.data()), &dataSize);
- } );
+ res = RegQueryValueEx(handle, reinterpret_cast<const wchar_t *>(rSubkeyName.utf16()), 0, 0,
+ reinterpret_cast<unsigned char*>(data.data()), &dataSize);
if (res != ERROR_SUCCESS) {
RegCloseKey(handle);
return false;
@@ -549,11 +489,7 @@ bool QWinSettingsPrivate::readKey(HKEY parentHandle, const QString &rSubKey, QVa
case REG_SZ: {
QString s;
if (dataSize) {
- QT_WA( {
- s = QString::fromUtf16(((const ushort*)data.constData()));
- }, {
- s = QString::fromLocal8Bit(data.constData());
- } );
+ s = QString::fromWCharArray(((const wchar_t *)data.constData()));
}
if (value != 0)
*value = stringToVariant(s);
@@ -565,12 +501,7 @@ bool QWinSettingsPrivate::readKey(HKEY parentHandle, const QString &rSubKey, QVa
if (dataSize) {
int i = 0;
for (;;) {
- QString s;
- QT_WA( {
- s = QString::fromUtf16((const ushort*)data.constData() + i);
- }, {
- s = QString::fromLocal8Bit(data.constData() + i);
- } );
+ QString s = QString::fromWCharArray((const wchar_t *)data.constData() + i);
i += s.length() + 1;
if (s.isEmpty())
@@ -587,11 +518,7 @@ bool QWinSettingsPrivate::readKey(HKEY parentHandle, const QString &rSubKey, QVa
case REG_BINARY: {
QString s;
if (dataSize) {
- QT_WA( {
- s = QString::fromUtf16((const ushort*)data.constData(), data.size()/2);
- }, {
- s = QString::fromLocal8Bit(data.constData(), data.size());
- } );
+ s = QString::fromWCharArray((const wchar_t *)data.constData(), data.size() / 2);
}
if (value != 0)
*value = stringToVariant(s);
@@ -635,13 +562,8 @@ QWinSettingsPrivate::~QWinSettingsPrivate()
#if defined(Q_OS_WINCE)
remove(regList.at(0).key());
#else
- DWORD res;
QString emptyKey;
- QT_WA( {
- res = RegDeleteKeyW(writeHandle(), reinterpret_cast<const wchar_t *>(emptyKey.utf16()));
- }, {
- res = RegDeleteKeyA(writeHandle(), emptyKey.toLocal8Bit());
- } );
+ DWORD res = RegDeleteKey(writeHandle(), reinterpret_cast<const wchar_t *>(emptyKey.utf16()));
if (res != ERROR_SUCCESS) {
qWarning("QSettings: Failed to delete key \"%s\": %s",
regList.at(0).key().toLatin1().data(), errorCodeToString(res).toLatin1().data());
@@ -666,11 +588,7 @@ void QWinSettingsPrivate::remove(const QString &uKey)
LONG res;
HKEY handle = openKey(writeHandle(), registryPermissions, keyPath(rKey));
if (handle != 0) {
- QT_WA( {
- res = RegDeleteValueW(handle, reinterpret_cast<const wchar_t *>(keyName(rKey).utf16()));
- }, {
- res = RegDeleteValueA(handle, keyName(rKey).toLocal8Bit());
- } );
+ res = RegDeleteValue(handle, reinterpret_cast<const wchar_t *>(keyName(rKey).utf16()));
RegCloseKey(handle);
}
@@ -685,12 +603,7 @@ void QWinSettingsPrivate::remove(const QString &uKey)
for (int i = 0; i < childKeys.size(); ++i) {
QString group = childKeys.at(i);
- LONG res;
- QT_WA( {
- res = RegDeleteValueW(handle, reinterpret_cast<const wchar_t *>(group.utf16()));
- }, {
- res = RegDeleteValueA(handle, group.toLocal8Bit());
- } );
+ LONG res = RegDeleteValue(handle, reinterpret_cast<const wchar_t *>(group.utf16()));
if (res != ERROR_SUCCESS) {
qWarning("QSettings: RegDeleteValue failed on subkey \"%s\": %s",
group.toLatin1().data(), errorCodeToString(res).toLatin1().data());
@@ -701,11 +614,7 @@ void QWinSettingsPrivate::remove(const QString &uKey)
// For WinCE always Close the handle first.
RegCloseKey(handle);
#endif
- QT_WA( {
- res = RegDeleteKeyW(writeHandle(), reinterpret_cast<const wchar_t *>(rKey.utf16()));
- }, {
- res = RegDeleteKeyA(writeHandle(), rKey.toLocal8Bit());
- } );
+ res = RegDeleteKey(writeHandle(), reinterpret_cast<const wchar_t *>(rKey.utf16()));
if (res != ERROR_SUCCESS) {
qWarning("QSettings: RegDeleteKey failed on key \"%s\": %s",
@@ -761,27 +670,15 @@ void QWinSettingsPrivate::set(const QString &uKey, const QVariant &value)
if (type == REG_BINARY) {
QString s = variantToString(value);
- QT_WA( {
- regValueBuff = QByteArray((const char*)s.utf16(), s.length()*2);
- }, {
- regValueBuff = QByteArray((const char*)s.toLocal8Bit(), s.length());
- } );
+ regValueBuff = QByteArray((const char*)s.utf16(), s.length() * 2);
} else {
QStringList::const_iterator it = l.constBegin();
for (; it != l.constEnd(); ++it) {
const QString &s = *it;
- QT_WA( {
- regValueBuff += QByteArray((const char*)s.utf16(), (s.length() + 1)*2);
- }, {
- regValueBuff += QByteArray((const char*)s.toLocal8Bit(), s.length() + 1);
- } );
+ regValueBuff += QByteArray((const char*)s.utf16(), (s.length() + 1) * 2);
}
- QT_WA( {
- regValueBuff.append((char)0);
- regValueBuff.append((char)0);
- }, {
- regValueBuff.append((char)0);
- } );
+ regValueBuff.append((char)0);
+ regValueBuff.append((char)0);
}
break;
}
@@ -794,21 +691,6 @@ void QWinSettingsPrivate::set(const QString &uKey, const QVariant &value)
}
case QVariant::ByteArray:
- // On Win95/98/Me QString::toLocal8Bit() fails to handle chars > 0x7F. So we don't go through variantToString() at all.
- if (QSysInfo::WindowsVersion & QSysInfo::WV_DOS_based) {
- QByteArray ba = value.toByteArray();
- regValueBuff = "@ByteArray(";
- regValueBuff += ba;
- regValueBuff += ')';
- if (ba.contains('\0')) {
- type = REG_BINARY;
- } else {
- type = REG_SZ;
- regValueBuff += '\0';
- }
-
- break;
- }
// fallthrough intended
default: {
@@ -817,33 +699,18 @@ void QWinSettingsPrivate::set(const QString &uKey, const QVariant &value)
QString s = variantToString(value);
type = stringContainsNullChar(s) ? REG_BINARY : REG_SZ;
if (type == REG_BINARY) {
- QT_WA( {
- regValueBuff = QByteArray((const char*)s.utf16(), s.length()*2);
- }, {
- regValueBuff = QByteArray((const char*)s.toLocal8Bit(), s.length());
- } );
+ regValueBuff = QByteArray((const char*)s.utf16(), s.length() * 2);
} else {
- QT_WA( {
- regValueBuff = QByteArray((const char*)s.utf16(), (s.length() + 1)*2);
- }, {
- regValueBuff = QByteArray((const char*)s.toLocal8Bit(), s.length() + 1);
- } );
+ regValueBuff = QByteArray((const char*)s.utf16(), (s.length() + 1) * 2);
}
break;
}
}
// set the value
- LONG res;
- QT_WA( {
- res = RegSetValueExW(handle, reinterpret_cast<const wchar_t *>(keyName(rKey).utf16()), 0, type,
- reinterpret_cast<const unsigned char*>(regValueBuff.constData()),
- regValueBuff.size());
- }, {
- res = RegSetValueExA(handle, keyName(rKey).toLocal8Bit(), 0, type,
+ LONG res = RegSetValueEx(handle, reinterpret_cast<const wchar_t *>(keyName(rKey).utf16()), 0, type,
reinterpret_cast<const unsigned char*>(regValueBuff.constData()),
regValueBuff.size());
- } );
if (res == ERROR_SUCCESS) {
deleteWriteHandleOnExit = false;
diff --git a/src/corelib/io/qtemporaryfile.cpp b/src/corelib/io/qtemporaryfile.cpp
index cd8d36d..ccc753a 100644
--- a/src/corelib/io/qtemporaryfile.cpp
+++ b/src/corelib/io/qtemporaryfile.cpp
@@ -60,6 +60,10 @@
#include <time.h>
#include <ctype.h>
+#if defined(Q_OS_UNIX)
+# include "private/qcore_unix_p.h" // overrides QT_OPEN
+#endif
+
#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
# include <process.h>
# if defined(_MSC_VER) && _MSC_VER >= 1400
@@ -69,9 +73,11 @@
#if defined(Q_OS_WINCE)
# include <types.h>
-# include "qfunctions_wince.h"
#endif
+#if defined(Q_OS_VXWORKS)
+# include <taskLib.h>
+#endif
QT_BEGIN_NAMESPACE
@@ -130,6 +136,8 @@ static int _gettemp(char *path, int *doopen, int domkdir, int slen)
}
#if defined(Q_OS_WIN) && defined(_MSC_VER) && _MSC_VER >= 1400
pid = _getpid();
+#elif defined(Q_OS_VXWORKS)
+ pid = (pid_t) taskIdCurrent;
#else
pid = getpid();
#endif
@@ -208,8 +216,9 @@ static int _gettemp(char *path, int *doopen, int domkdir, int slen)
if ((*doopen =
QT_OPEN(targetPath.toLocal8Bit(), O_CREAT|O_EXCL|O_RDWR
# else // CE
+ // this is Unix or older MSVC
if ((*doopen =
- open(path, QT_OPEN_CREAT|O_EXCL|QT_OPEN_RDWR
+ QT_OPEN(path, QT_OPEN_CREAT|O_EXCL|QT_OPEN_RDWR
# endif
# ifdef QT_LARGEFILE_SUPPORT
|QT_OPEN_LARGEFILE
@@ -219,18 +228,9 @@ static int _gettemp(char *path, int *doopen, int domkdir, int slen)
# elif defined(Q_OS_WIN)
|O_BINARY
# endif
-# ifdef O_CLOEXEC
- // supported on Linux >= 2.6.23; avoids one extra system call
- // and avoids a race condition: if another thread forks, we could
- // end up leaking a file descriptor...
- |O_CLOEXEC
-# endif
, 0600)) >= 0)
#endif // WIN && !CE
{
-#if defined(Q_OS_UNIX) && !defined(O_CLOEXEC)
- fcntl(*doopen, F_SETFD, FD_CLOEXEC);
-#endif
return 1;
}
if (errno != EEXIST)
@@ -239,7 +239,7 @@ static int _gettemp(char *path, int *doopen, int domkdir, int slen)
#ifdef Q_OS_WIN
if (QT_MKDIR(path) == 0)
#else
- if (mkdir(path, 0700) == 0)
+ if (QT_MKDIR(path, 0700) == 0)
#endif
return 1;
if (errno != EEXIST)
@@ -289,7 +289,7 @@ static int qt_mkstemps(char *path, int slen)
//************* QTemporaryFileEngine
class QTemporaryFileEngine : public QFSFileEngine
{
- Q_DECLARE_SCOPED_PRIVATE(QFSFileEngine)
+ Q_DECLARE_PRIVATE(QFSFileEngine)
public:
QTemporaryFileEngine(const QString &file, bool fileIsTemplate = true)
: QFSFileEngine(file), filePathIsTemplate(fileIsTemplate)
diff --git a/src/corelib/io/qtemporaryfile.h b/src/corelib/io/qtemporaryfile.h
index c0b41bb..a597a93 100644
--- a/src/corelib/io/qtemporaryfile.h
+++ b/src/corelib/io/qtemporaryfile.h
@@ -64,7 +64,7 @@ class Q_CORE_EXPORT QTemporaryFile : public QFile
#ifndef QT_NO_QOBJECT
Q_OBJECT
#endif
- Q_DECLARE_SCOPED_PRIVATE(QTemporaryFile)
+ Q_DECLARE_PRIVATE(QTemporaryFile)
public:
QTemporaryFile();
diff --git a/src/corelib/io/qtextstream.h b/src/corelib/io/qtextstream.h
index 9d4b3d0..fc4794e 100644
--- a/src/corelib/io/qtextstream.h
+++ b/src/corelib/io/qtextstream.h
@@ -72,7 +72,7 @@ class QTextDecoder;
class QTextStreamPrivate;
class Q_CORE_EXPORT QTextStream // text stream class
{
- Q_DECLARE_SCOPED_PRIVATE(QTextStream)
+ Q_DECLARE_PRIVATE(QTextStream)
public:
enum RealNumberNotation {
diff --git a/src/corelib/io/qurl.cpp b/src/corelib/io/qurl.cpp
index 180e9ec..79cd2f0 100644
--- a/src/corelib/io/qurl.cpp
+++ b/src/corelib/io/qurl.cpp
@@ -2336,12 +2336,12 @@ static const NameprepCaseFoldingEntry NameprepCaseFolding[] = {
{ 0x1D7BB, { 0x03C3, 0x0000, 0x0000, 0x0000 } }
};
-static void mapToLowerCase(QString *str)
+static void mapToLowerCase(QString *str, int from)
{
int N = sizeof(NameprepCaseFolding) / sizeof(NameprepCaseFolding[0]);
QChar *d = 0;
- for (int i = 0; i < str->size(); ++i) {
+ for (int i = from; i < str->size(); ++i) {
int uc = str->at(i).unicode();
if (uc < 0x80) {
if (uc <= 'Z' && uc >= 'A') {
@@ -2388,11 +2388,11 @@ static bool isMappedToNothing(const QChar &ch)
}
-static void stripProhibitedOutput(QString *str)
+static void stripProhibitedOutput(QString *str, int from)
{
- ushort *out = (ushort *)str->data();
+ ushort *out = (ushort *)str->data() + from;
const ushort *in = out;
- const ushort *end = out + str->size();
+ const ushort *end = (ushort *)str->data() + str->size();
while (in < end) {
ushort uc = *in;
if (uc < 0x80 ||
@@ -2901,66 +2901,99 @@ static bool isBidirectionalL(const QChar &ch)
return false;
}
+#ifdef QT_BUILD_INTERNAL
+// export for tst_qurl.cpp
+Q_AUTOTEST_EXPORT void qt_nameprep(QString *source, int from);
+Q_AUTOTEST_EXPORT bool qt_check_std3rules(const QChar *uc, int len);
+#else
+// non-test build, keep the symbols for ourselves
+static void qt_nameprep(QString *source, int from);
+static bool qt_check_std3rules(const QChar *uc, int len);
+#endif
-Q_AUTOTEST_EXPORT QString qt_nameprep(const QString &source)
+void qt_nameprep(QString *source, int from)
{
- QString mapped = source;
-
- bool simple = true;
- for (int i = 0; i < mapped.size(); ++i) {
- ushort uc = mapped.at(i).unicode();
+ QChar *src = source->data(); // causes a detach, so we're sure the only one using it
+ QChar *out = src + from;
+ const QChar *e = src + source->size();
+
+ for ( ; out < e; ++out) {
+ register ushort uc = out->unicode();
if (uc > 0x80) {
- simple = false;
break;
} else if (uc >= 'A' && uc <= 'Z') {
- mapped[i] = QChar(uc | 0x20);
+ *out = QChar(uc | 0x20);
}
}
- if (simple)
- return mapped;
-
+ if (out == e)
+ return; // everything was mapped easily (lowercased, actually)
+ int firstNonAscii = out - src;
+
// Characters commonly mapped to nothing are simply removed
// (Table B.1)
- QChar *out = mapped.data();
const QChar *in = out;
- const QChar *e = in + mapped.size();
while (in < e) {
if (!isMappedToNothing(*in))
*out++ = *in;
++in;
}
if (out != in)
- mapped.truncate(out - mapped.constData());
+ source->truncate(out - src);
// Map to lowercase (Table B.2)
- mapToLowerCase(&mapped);
+ mapToLowerCase(source, firstNonAscii);
// Normalize to Unicode 3.2 form KC
- mapped = mapped.normalized(QString::NormalizationForm_KC, QChar::Unicode_3_2);
+ extern void qt_string_normalize(QString *data, QString::NormalizationForm mode,
+ QChar::UnicodeVersion version, int from);
+ qt_string_normalize(source, QString::NormalizationForm_KC, QChar::Unicode_3_2, firstNonAscii);
// Strip prohibited output
- stripProhibitedOutput(&mapped);
+ stripProhibitedOutput(source, firstNonAscii);
// Check for valid bidirectional characters
bool containsLCat = false;
bool containsRandALCat = false;
- for (int j = 0; j < mapped.size() && (!containsLCat || !containsRandALCat); ++j) {
- if (isBidirectionalL(mapped.at(j)))
+ src = source->data();
+ e = src + source->size();
+ for (in = src + from; in < e && (!containsLCat || !containsRandALCat); ++in) {
+ if (isBidirectionalL(*in))
containsLCat = true;
- else if (isBidirectionalRorAL(mapped.at(j)))
+ else if (isBidirectionalRorAL(*in))
containsRandALCat = true;
}
if (containsRandALCat) {
- if (containsLCat || (!isBidirectionalRorAL(mapped.at(0))
- || !isBidirectionalRorAL(mapped.at(mapped.size() - 1))))
- mapped.clear();
+ if (containsLCat || (!isBidirectionalRorAL(src[from])
+ || !isBidirectionalRorAL(e[-1])))
+ source->resize(from); // not allowed, clear the label
}
+}
+
+bool qt_check_std3rules(const QChar *uc, int len)
+{
+ if (len > 63)
+ return false;
- return mapped;
+ for (int i = 0; i < len; ++i) {
+ register ushort c = uc[i].unicode();
+ if (c == '-' && (i == 0 || i == len - 1))
+ return false;
+
+ // verifying the absence of LDH is the same as verifying that
+ // only LDH is present
+ if (c == '-' || (c >= '0' && c <= '9')
+ || (c >= 'A' && c <= 'Z')
+ || (c >= 'a' && c <= 'z'))
+ continue;
+
+ return false;
+ }
+
+ return true;
}
-static inline char encodeDigit(uint digit)
+static inline uint encodeDigit(uint digit)
{
return digit + 22 + 75 * (digit < 26);
}
@@ -2977,7 +3010,7 @@ static inline uint adapt(uint delta, uint numpoints, bool firsttime)
return k + (((base - tmin + 1) * delta) / (delta + skew));
}
-static inline void appendEncode(QByteArray* output, uint& delta, uint& bias, uint& b, uint& h)
+static inline void appendEncode(QString* output, uint& delta, uint& bias, uint& b, uint& h)
{
uint qq;
uint k;
@@ -2991,17 +3024,17 @@ static inline void appendEncode(QByteArray* output, uint& delta, uint& bias, uin
t = (k <= bias) ? tmin : (k >= bias + tmax) ? tmax : k - bias;
if (qq < t) break;
- *output += encodeDigit(t + (qq - t) % (base - t));
+ *output += QChar(encodeDigit(t + (qq - t) % (base - t)));
qq = (qq - t) / (base - t);
}
- *output += encodeDigit(qq);
+ *output += QChar(encodeDigit(qq));
bias = adapt(delta, h + 1, h == b);
delta = 0;
++h;
}
-static void toPunycodeHelper(const QChar *s, int ucLength, QByteArray *output)
+static void toPunycodeHelper(const QChar *s, int ucLength, QString *output)
{
uint n = initial_n;
uint delta = 0;
@@ -3010,7 +3043,7 @@ static void toPunycodeHelper(const QChar *s, int ucLength, QByteArray *output)
int outLen = output->length();
output->resize(outLen + ucLength);
- char *d = output->data() + outLen;
+ QChar *d = output->data() + outLen;
bool skipped = false;
// copy all basic code points verbatim to output.
for (uint j = 0; j < (uint) ucLength; ++j) {
@@ -3035,7 +3068,7 @@ static void toPunycodeHelper(const QChar *s, int ucLength, QByteArray *output)
// if basic code points were copied, add the delimiter character.
if (h > 0)
- *output += 0x2d;
+ *output += QChar(0x2d);
// while there are still unprocessed non-basic code points left in
// the input string...
@@ -3083,7 +3116,7 @@ static void toPunycodeHelper(const QChar *s, int ucLength, QByteArray *output)
}
// prepend ACE prefix
- output->insert(outLen, "xn--");
+ output->insert(outLen, QLatin1String("xn--"));
return;
}
@@ -3144,11 +3177,15 @@ static bool qt_is_idn_enabled(const QString &domain)
int idx = domain.lastIndexOf(QLatin1Char('.'));
if (idx == -1)
return false;
- const QChar *tld = domain.constData() + idx + 1;
+
int len = domain.size() - idx - 1;
+ QString tldString(domain.constData() + idx + 1, len);
+ qt_nameprep(&tldString, 0);
+
+ const QChar *tld = tldString.constData();
if (user_idn_whitelist)
- return user_idn_whitelist->contains(QString(tld, len));
+ return user_idn_whitelist->contains(tldString);
int l = 0;
int r = sizeof(idn_whitelist)/sizeof(const char *) - 1;
@@ -3164,46 +3201,127 @@ static bool qt_is_idn_enabled(const QString &domain)
return equal(tld, len, idn_whitelist[i]);
}
-static QString qt_from_ACE(const QString &domainMC)
+static inline bool isDotDelimiter(ushort uc)
{
- QString domain = domainMC.toLower();
- int idx = domain.indexOf(QLatin1Char('.'));
- if (idx != -1) {
- if (!domain.contains(QLatin1String("xn--"))) {
- bool simple = true;
- for (int i = 0; i < domain.size(); ++i) {
- ushort ch = domain.at(i).unicode();
- if (ch > 'z' || ch < '-' || ch == '/' || (ch > '9' && ch < 'A') || (ch > 'Z' && ch < 'a')) {
+ // IDNA / rfc3490 describes these four delimiters used for
+ // separating labels in unicode international domain
+ // names.
+ return uc == 0x2e || uc == 0x3002 || uc == 0xff0e || uc == 0xff61;
+}
+
+static int nextDotDelimiter(const QString &domain, int from = 0)
+{
+ const QChar *b = domain.unicode();
+ const QChar *ch = b + from;
+ const QChar *e = b + domain.length();
+ while (ch < e) {
+ if (isDotDelimiter(ch->unicode()))
+ break;
+ else
+ ++ch;
+ }
+ return ch - b;
+}
+
+enum AceOperation { ToAceOnly, NormalizeAce };
+static QString qt_ACE_do(const QString &domain, AceOperation op)
+{
+ if (domain.isEmpty())
+ return domain;
+
+ QString result;
+ result.reserve(domain.length());
+
+ const bool isIdnEnabled = op == NormalizeAce ? qt_is_idn_enabled(domain) : false;
+ int lastIdx = 0;
+ QString aceForm; // this variable is here for caching
+
+ while (1) {
+ int idx = nextDotDelimiter(domain, lastIdx);
+ int labelLength = idx - lastIdx;
+ if (labelLength == 0)
+ return QString(); // two delimiters in a row -- empty label not allowed
+
+ // RFC 3490 says, about the ToASCII operation:
+ // 3. If the UseSTD3ASCIIRules flag is set, then perform these checks:
+ //
+ // (a) Verify the absence of non-LDH ASCII code points; that is, the
+ // absence of 0..2C, 2E..2F, 3A..40, 5B..60, and 7B..7F.
+ //
+ // (b) Verify the absence of leading and trailing hyphen-minus; that
+ // is, the absence of U+002D at the beginning and end of the
+ // sequence.
+ // and:
+ // 8. Verify that the number of code points is in the range 1 to 63
+ // inclusive.
+
+ // copy the label to the destination, which also serves as our scratch area, lowercasing it
+ int prevLen = result.size();
+ bool simple = true;
+ result.resize(prevLen + labelLength);
+ {
+ QChar *out = result.data() + prevLen;
+ const QChar *in = domain.constData() + lastIdx;
+ const QChar *e = in + labelLength;
+ for (; in < e; ++in, ++out) {
+ register ushort uc = in->unicode();
+ if (uc > 0x7f)
simple = false;
- break;
- }
+ if (uc >= 'A' && uc <= 'Z')
+ *out = QChar(uc | 0x20);
+ else
+ *out = *in;
}
- if (simple)
- return domain;
}
-
- const bool isIdnEnabled = qt_is_idn_enabled(domain);
- int lastIdx = 0;
- QString result;
- while (1) {
- // Nameprep the host. If the labels in the hostname are Punycode
- // encoded, we decode them immediately, then nameprep them.
- QByteArray label;
- toPunycodeHelper(domain.constData() + lastIdx, idx - lastIdx, &label);
- result += qt_nameprep(isIdnEnabled ? QUrl::fromPunycode(label) : QString::fromLatin1(label));
- lastIdx = idx + 1;
- if (lastIdx < domain.size() + 1)
- result += QLatin1Char('.');
- else
- break;
- idx = domain.indexOf(QLatin1Char('.'), lastIdx);
- if (idx == -1)
- idx = domain.size();
+
+ if (simple && labelLength > 6) {
+ // ACE form domains contain only ASCII characters, but we can't consider them simple
+ // is this an ACE form?
+ // the shortest valid ACE domain is 6 characters long (U+0080 would be 1, but it's not allowed)
+ static const ushort acePrefixUtf16[] = { 'x', 'n', '-', '-' };
+ if (memcmp(result.constData() + prevLen, acePrefixUtf16, sizeof acePrefixUtf16) == 0)
+ simple = false;
}
- return result;
- } else {
- return qt_nameprep(domain);
+
+ if (simple) {
+ // fastest case: this is the common case (non IDN-domains)
+ // so we're done
+ if (!qt_check_std3rules(result.constData() + prevLen, labelLength))
+ return QString();
+ } else {
+ // Punycode encoding and decoding cannot be done in-place
+ // That means we need one or two temporaries
+ qt_nameprep(&result, prevLen);
+ labelLength = result.length() - prevLen;
+ register int toReserve = labelLength + 4 + 6; // "xn--" plus some extra bytes
+ if (toReserve > aceForm.capacity())
+ aceForm.reserve(toReserve);
+ toPunycodeHelper(result.constData() + prevLen, result.size() - prevLen, &aceForm);
+
+ // We use resize()+memcpy() here because we're overwriting the data we've copied
+ if (isIdnEnabled) {
+ QString tmp = QUrl::fromPunycode(aceForm.toLatin1());
+ if (tmp.isEmpty())
+ return QString(); // shouldn't happen, since we've just punycode-encoded it
+ result.resize(prevLen + tmp.size());
+ memcpy(result.data() + prevLen, tmp.constData(), tmp.size() * sizeof(QChar));
+ } else {
+ result.resize(prevLen + aceForm.size());
+ memcpy(result.data() + prevLen, aceForm.constData(), aceForm.size() * sizeof(QChar));
+ }
+
+ if (!qt_check_std3rules(aceForm.constData(), aceForm.size()))
+ return QString();
+ }
+
+
+ lastIdx = idx + 1;
+ if (lastIdx < domain.size() + 1)
+ result += QLatin1Char('.');
+ else
+ break;
}
+ return result;
}
@@ -3246,12 +3364,27 @@ QUrlPrivate::QUrlPrivate(const QUrlPrivate &copy)
QString QUrlPrivate::canonicalHost() const
{
- if (QURL_HASFLAG(stateFlags, HostCanonicalized))
+ if (QURL_HASFLAG(stateFlags, HostCanonicalized) || host.isEmpty())
return host;
QUrlPrivate *that = const_cast<QUrlPrivate *>(this);
QURL_SETFLAG(that->stateFlags, HostCanonicalized);
- that->host = qt_from_ACE(host);
+ if (host.contains(QLatin1Char(':'))) {
+ // This is an IP Literal, use _IPLiteral to validate
+ QByteArray ba = host.toLatin1();
+ if (!ba.startsWith('[')) {
+ // surround the IP Literal with [ ] if it's not already done so
+ ba.reserve(ba.length() + 2);
+ ba.prepend('[');
+ ba.append(']');
+ }
+
+ const char *ptr = ba.constData();
+ if (!_IPLiteral(&ptr))
+ that->host.clear();
+ } else {
+ that->host = qt_ACE_do(host, NormalizeAce);
+ }
return that->host;
}
@@ -3737,7 +3870,10 @@ QByteArray QUrlPrivate::toEncoded(QUrl::FormattingOptions options) const
}
}
- url += QUrl::toAce(host);
+ if (host.startsWith(QLatin1Char('[')))
+ url += host.toLatin1();
+ else
+ url += QUrl::toAce(host);
if (!(options & QUrl::RemovePort) && port != -1) {
url += ':';
url += QString::number(port).toAscii();
@@ -4412,8 +4548,6 @@ void QUrl::setHost(const QString &host)
QURL_UNSETFLAG(d->stateFlags, QUrlPrivate::Validated | QUrlPrivate::Normalized | QUrlPrivate::HostCanonicalized);
d->host = host;
- if (d->host.contains(QLatin1Char(':')))
- d->host = QLatin1Char('[') + d->host + QLatin1Char(']');
}
/*!
@@ -5425,9 +5559,9 @@ QByteArray QUrl::toPercentEncoding(const QString &input, const QByteArray &exclu
*/
QByteArray QUrl::toPunycode(const QString &uc)
{
- QByteArray output;
+ QString output;
toPunycodeHelper(uc.constData(), uc.size(), &output);
- return output;
+ return output.toLatin1();
}
/*!
@@ -5528,7 +5662,7 @@ QString QUrl::fromPunycode(const QByteArray &pc)
*/
QString QUrl::fromAce(const QByteArray &domain)
{
- return qt_from_ACE(QString::fromLatin1(domain));
+ return qt_ACE_do(QString::fromLatin1(domain), NormalizeAce);
}
/*!
@@ -5545,26 +5679,8 @@ QString QUrl::fromAce(const QByteArray &domain)
*/
QByteArray QUrl::toAce(const QString &domain)
{
- // IDNA / rfc3490 describes these four delimiters used for
- // separating labels in unicode international domain
- // names.
- QString nameprepped = qt_nameprep(domain);
- int lastIdx = 0;
- QByteArray result;
- for (int i = 0; i < nameprepped.size(); ++i) {
- ushort uc = nameprepped.at(i).unicode();
- if (uc == 0x2e || uc == 0x3002 || uc == 0xff0e || uc == 0xff61) {
- if (lastIdx)
- result += '.';
- toPunycodeHelper(nameprepped.constData() + lastIdx, i - lastIdx, &result);
- lastIdx = i + 1;
- }
- }
- if (lastIdx)
- result += '.';
- toPunycodeHelper(nameprepped.constData() + lastIdx, nameprepped.size() - lastIdx, &result);
-
- return result;
+ QString result = qt_ACE_do(domain, ToAceOnly);
+ return result.toLatin1();
}
/*!