summaryrefslogtreecommitdiffstats
path: root/src/corelib/io
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/io')
-rw-r--r--src/corelib/io/qabstractfileengine.cpp22
-rw-r--r--src/corelib/io/qdiriterator.cpp230
-rw-r--r--src/corelib/io/qfileinfo.cpp6
-rw-r--r--src/corelib/io/qfilesystemwatcher_dnotify.cpp20
-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_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_iterator_win.cpp32
-rw-r--r--src/corelib/io/qfsfileengine_p.h4
-rw-r--r--src/corelib/io/qfsfileengine_unix.cpp20
-rw-r--r--src/corelib/io/qfsfileengine_win.cpp939
-rw-r--r--src/corelib/io/qprocess_unix.cpp281
-rw-r--r--src/corelib/io/qprocess_win.cpp231
-rw-r--r--src/corelib/io/qresource.cpp4
-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/qsettings.cpp37
-rw-r--r--src/corelib/io/qsettings_win.cpp209
-rw-r--r--src/corelib/io/qtemporaryfile.cpp17
-rw-r--r--src/corelib/io/qurl.cpp318
23 files changed, 1301 insertions, 1627 deletions
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/qdiriterator.cpp b/src/corelib/io/qdiriterator.cpp
index 582d657..30d2558 100644
--- a/src/corelib/io/qdiriterator.cpp
+++ b/src/corelib/io/qdiriterator.cpp
@@ -106,26 +106,29 @@ 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;
- QAbstractFileEngine *engine;
+ QAbstractFileEngine * const engine;
+
+ const QString path;
+ const QStringList nameFilters;
+ const QDir::Filters filters;
+ const QDirIterator::IteratorFlags iteratorFlags;
+
+#ifndef QT_NO_REGEXP
+ QVector<QRegExp> nameRegExps;
+#endif
+
QStack<QAbstractFileEngineIterator *> 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;
};
@@ -135,15 +138,24 @@ public:
*/
QDirIteratorPrivate::QDirIteratorPrivate(const QString &path, const QStringList &nameFilters,
QDir::Filters filters, QDirIterator::IteratorFlags flags)
- : engine(0), 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();
}
/*!
@@ -157,20 +169,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 || (engine = QAbstractFileEngine::create(this->path))) {
+ 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) {
@@ -187,95 +198,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
@@ -289,10 +269,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();
@@ -303,16 +280,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;
}
@@ -333,17 +309,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;
}
@@ -368,7 +338,7 @@ bool QDirIteratorPrivate::matchesFilters(const QString &fileName, const QFileInf
|| (doExecutable && !fi.isExecutable()))) {
return false;
}
-
+
return true;
}
@@ -410,7 +380,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;
}
@@ -428,7 +398,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;
}
@@ -445,7 +415,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
*/
@@ -477,8 +447,6 @@ QDirIterator::~QDirIterator()
*/
QString QDirIterator::next()
{
- if (!hasNext())
- return QString();
d->advance();
return filePath();
}
@@ -491,22 +459,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
@@ -515,20 +478,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/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/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_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_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_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 84394fe..6a0e7ad 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;
@@ -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..27f4aef 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,32 @@ 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_INVALID_NAME
+ && errorCode != ERROR_FILE_NOT_FOUND && errorCode != ERROR_PATH_NOT_FOUND) {
+ 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 +611,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 +655,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 +848,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 +886,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 +900,27 @@ 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_INVALID_NAME
+ && errorCode != ERROR_FILE_NOT_FOUND && errorCode != ERROR_PATH_NOT_FOUND) {
+ // 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 +1002,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 +1018,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 +1055,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 +1115,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 +1142,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 +1184,35 @@ 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_INVALID_NAME
+ && errorCode != ERROR_FILE_NOT_FOUND && errorCode != ERROR_PATH_NOT_FOUND) {
+ 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 +1272,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 +1314,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 +1341,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 +1398,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 +1410,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 +1455,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 +1470,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 +1583,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 +1711,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 +1756,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 +1806,32 @@ 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_INVALID_NAME
+ && errorCode != ERROR_FILE_NOT_FOUND && errorCode != ERROR_PATH_NOT_FOUND) {
+ 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 +1851,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 +1868,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 +1883,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 +1919,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/qprocess_unix.cpp b/src/corelib/io/qprocess_unix.cpp
index 49869a4..fafce07 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);
@@ -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..0899eef 100644
--- a/src/corelib/io/qresource.cpp
+++ b/src/corelib/io/qresource.cpp
@@ -56,6 +56,10 @@
#include <qplatformdefs.h>
#include "private/qabstractfileengine_p.h"
+#ifdef Q_OS_UNIX
+# include "private/qcore_unix_p.h"
+#endif
+
//#define DEBUG_RESOURCE_MATCH
QT_BEGIN_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/qsettings.cpp b/src/corelib/io/qsettings.cpp
index b324441..4e44261 100644
--- a/src/corelib/io/qsettings.cpp
+++ b/src/corelib/io/qsettings.cpp
@@ -1037,33 +1037,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
@@ -1462,11 +1445,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);
@@ -1482,11 +1461,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_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 2d5bea6..e098064 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
@@ -72,7 +76,6 @@
# include "qfunctions_wince.h"
#endif
-
QT_BEGIN_NAMESPACE
/*
@@ -208,8 +211,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 +223,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)
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();
}
/*!