summaryrefslogtreecommitdiffstats
path: root/src/corelib/io/qstandardpaths.cpp
diff options
context:
space:
mode:
authorFriedemann Kleint <Friedemann.Kleint@digia.com>2012-10-05 12:13:54 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2012-10-08 17:21:35 +0200
commit0e8a2788d84c814b698848b699af8a2c8ba3179f (patch)
treeab667f03ee102458ccc5b4a665a7bbb9590dd150 /src/corelib/io/qstandardpaths.cpp
parent43ea7154184243b78c52f40c6ed344495f1386e9 (diff)
Fix Windows: QStandardPath::findExecutable() to check suffixes.
Append the Windows executables suffixes from the PATHEXT environment variable. The previous code had a bug since the 'break' statement bailed out of the inner loop only. Factor search code out into a separate functions, avoiding repeated invocations of list.constEnd() and variable assignments in the old code. Add a static function that is called on Unix and on Windows for executable names with a suffix. Call another function applying a candidate list of suffixes in case an executable name without a suffix is passed. Lower case the extensions from PATHEXT, streamline code. Split up the test, add a _data() slot for clarity. Task-number: QTBUG-27457 Change-Id: I2bf34de52aeadddd3b937ad1e22191c3c850fd26 Reviewed-by: Joerg Bornemann <joerg.bornemann@digia.com>
Diffstat (limited to 'src/corelib/io/qstandardpaths.cpp')
-rw-r--r--src/corelib/io/qstandardpaths.cpp95
1 files changed, 62 insertions, 33 deletions
diff --git a/src/corelib/io/qstandardpaths.cpp b/src/corelib/io/qstandardpaths.cpp
index 8c127f7cf1..91e343b021 100644
--- a/src/corelib/io/qstandardpaths.cpp
+++ b/src/corelib/io/qstandardpaths.cpp
@@ -180,16 +180,12 @@ QStringList QStandardPaths::locateAll(StandardLocation type, const QString &file
#ifdef Q_OS_WIN
static QStringList executableExtensions()
{
- QStringList ret = QString::fromLocal8Bit(qgetenv("PATHEXT")).split(QLatin1Char(';'));
- if (!ret.contains(QLatin1String(".exe"), Qt::CaseInsensitive)) {
- // If %PATHEXT% does not contain .exe, it is either empty, malformed, or distorted in ways that we cannot support, anyway.
- ret.clear();
- ret << QLatin1String(".exe")
- << QLatin1String(".com")
- << QLatin1String(".bat")
- << QLatin1String(".cmd");
- }
- return ret;
+ // If %PATHEXT% does not contain .exe, it is either empty, malformed, or distorted in ways that we cannot support, anyway.
+ const QStringList pathExt = QString::fromLocal8Bit(qgetenv("PATHEXT")).toLower().split(QLatin1Char(';'));
+ return pathExt.contains(QLatin1String(".exe"), Qt::CaseInsensitive) ?
+ pathExt :
+ QStringList() << QLatin1String(".exe") << QLatin1String(".com")
+ << QLatin1String(".bat") << QLatin1String(".cmd");
}
#endif
@@ -203,6 +199,42 @@ static QString checkExecutable(const QString &path)
return QString();
}
+static inline QString searchExecutable(const QStringList &searchPaths,
+ const QString &executableName)
+{
+ const QDir currentDir = QDir::current();
+ foreach (const QString &searchPath, searchPaths) {
+ const QString candidate = currentDir.absoluteFilePath(searchPath + QLatin1Char('/') + executableName);
+ const QString absPath = checkExecutable(candidate);
+ if (!absPath.isEmpty())
+ return absPath;
+ }
+ return QString();
+}
+
+#ifdef Q_OS_WIN
+
+// Find executable appending candidate suffixes, used for suffix-less executables
+// on Windows.
+static inline QString
+ searchExecutableAppendSuffix(const QStringList &searchPaths,
+ const QString &executableName,
+ const QStringList &suffixes)
+{
+ const QDir currentDir = QDir::current();
+ foreach (const QString &searchPath, searchPaths) {
+ const QString candidateRoot = currentDir.absoluteFilePath(searchPath + QLatin1Char('/') + executableName);
+ foreach (const QString &suffix, suffixes) {
+ const QString absPath = checkExecutable(candidateRoot + suffix);
+ if (!absPath.isEmpty())
+ return absPath;
+ }
+ }
+ return QString();
+}
+
+#endif // Q_OS_WIN
+
/*!
Finds the executable named \a executableName in the paths specified by \a paths,
or the system paths if \a paths is empty.
@@ -235,33 +267,30 @@ QString QStandardPaths::findExecutable(const QString &executableName, const QStr
#else
const QLatin1Char pathSep(':');
#endif
- searchPaths = QString::fromLocal8Bit(pEnv.constData()).split(pathSep, QString::SkipEmptyParts);
+ // Remove trailing slashes, which occur on Windows.
+ const QStringList rawPaths = QString::fromLocal8Bit(pEnv.constData()).split(pathSep, QString::SkipEmptyParts);
+ searchPaths.reserve(rawPaths.size());
+ foreach (const QString &rawPath, rawPaths) {
+ QString cleanPath = QDir::cleanPath(rawPath);
+ if (cleanPath.size() > 1 && cleanPath.endsWith('/'))
+ cleanPath.truncate(cleanPath.size() - 1);
+ searchPaths.push_back(cleanPath);
+ }
}
- QDir currentDir = QDir::current();
- QString absPath;
#ifdef Q_OS_WIN
- static QStringList executable_extensions = executableExtensions();
-#endif
-
- for (QStringList::const_iterator p = searchPaths.constBegin(); p != searchPaths.constEnd(); ++p) {
- const QString candidate = currentDir.absoluteFilePath(*p + QLatin1Char('/') + executableName);
-#ifdef Q_OS_WIN
- const QString extension = QLatin1Char('.') + QFileInfo(executableName).suffix();
- if (!executable_extensions.contains(extension, Qt::CaseInsensitive)) {
- foreach (const QString &extension, executable_extensions) {
- absPath = checkExecutable(candidate + extension.toLower());
- if (!absPath.isEmpty())
- break;
- }
- }
-#endif
- absPath = checkExecutable(candidate);
- if (!absPath.isEmpty()) {
- break;
- }
+ // On Windows, if the name does not have a suffix or a suffix not
+ // in PATHEXT ("xx.foo"), append suffixes from PATHEXT.
+ static const QStringList executable_extensions = executableExtensions();
+ if (executableName.contains(QLatin1Char('.'))) {
+ const QString suffix = QFileInfo(executableName).suffix();
+ if (suffix.isEmpty() || !executable_extensions.contains(QLatin1Char('.') + suffix, Qt::CaseInsensitive))
+ return searchExecutableAppendSuffix(searchPaths, executableName, executable_extensions);
+ } else {
+ return searchExecutableAppendSuffix(searchPaths, executableName, executable_extensions);
}
- return absPath;
+#endif
+ return searchExecutable(searchPaths, executableName);
}
/*!