summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Faure <faure@kde.org>2011-10-21 20:57:31 +0200
committerQt by Nokia <qt-info@nokia.com>2011-10-23 00:56:51 +0200
commit4b72c3f4347bfb8493e877d26f172f2e18c69a83 (patch)
tree636fc5ca4a92678ae1c11b0d48483b23b1d1127f
parentfa0ad643a6f0018544197e4eb80e8cf2cbf700cf (diff)
Add QStandardPaths::findExecutable.
Change-Id: If30a83622e2ac5af48e47a38b8f70fce73044d74 Reviewed-by: Thiago Macieira (Intel) <thiago.macieira@intel.com>
-rw-r--r--src/corelib/io/qstandardpaths.cpp87
-rw-r--r--src/corelib/io/qstandardpaths.h4
-rw-r--r--src/corelib/kernel/qcoreapplication.cpp15
3 files changed, 92 insertions, 14 deletions
diff --git a/src/corelib/io/qstandardpaths.cpp b/src/corelib/io/qstandardpaths.cpp
index 58a6ab13eb..86d0f7424d 100644
--- a/src/corelib/io/qstandardpaths.cpp
+++ b/src/corelib/io/qstandardpaths.cpp
@@ -176,6 +176,93 @@ QStringList QStandardPaths::locateAll(StandardLocation type, const QString &file
return result;
}
+#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;
+}
+#endif
+
+static QString checkExecutable(const QString &path)
+{
+ const QFileInfo info(path);
+ if (info.isBundle())
+ return info.bundleName();
+ if (info.isFile() && info.isExecutable())
+ return QDir::cleanPath(path);
+ return QString();
+}
+
+/*!
+ Finds the executable named \a executableName in the paths specified by \a paths,
+ or the system paths if \a paths is empty.
+
+ On most operating systems the system path is determined by the PATH environment variable.
+
+ The directories where to search for the executable can be set in the \a paths argument.
+ To search in both your own paths and the system paths, call findExecutable twice, once with
+ \a paths set and once with \a paths empty.
+
+ Symlinks are not resolved, in order to preserve behavior for the case of executables
+ whose behavior depends on the name they are invoked with.
+
+ \note On Windows, the usual executable extensions (from the PATHEXT environment variable)
+ are automatically appended, so that for instance findExecutable("foo") will find foo.exe
+ or foo.bat if present.
+
+ Returns the absolute file path to the executable, or an empty string if not found.
+ */
+QString QStandardPaths::findExecutable(const QString &executableName, const QStringList &paths)
+{
+ if (QFileInfo(executableName).isAbsolute())
+ return checkExecutable(executableName);
+
+ QStringList searchPaths = paths;
+ if (paths.isEmpty()) {
+ QByteArray pEnv = qgetenv("PATH");
+#if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN)
+ const QLatin1Char pathSep(';');
+#else
+ const QLatin1Char pathSep(':');
+#endif
+ searchPaths = QString::fromLocal8Bit(pEnv.constData()).split(pathSep, QString::SkipEmptyParts);
+ }
+
+ 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;
+ }
+ }
+ return absPath;
+}
+
/*!
\fn QString QStandardPaths::displayName(StandardLocation type)
diff --git a/src/corelib/io/qstandardpaths.h b/src/corelib/io/qstandardpaths.h
index 1688e16be7..d0293ab3fd 100644
--- a/src/corelib/io/qstandardpaths.h
+++ b/src/corelib/io/qstandardpaths.h
@@ -42,7 +42,7 @@
#ifndef QSTANDARDPATHS_H
#define QSTANDARDPATHS_H
-#include <QtCore/qstring.h>
+#include <QtCore/qstringlist.h>
QT_BEGIN_HEADER
@@ -87,6 +87,8 @@ public:
static QStringList locateAll(StandardLocation type, const QString &fileName, LocateOptions options = LocateFile);
static QString displayName(StandardLocation type);
+ static QString findExecutable(const QString &executableName, const QStringList &paths = QStringList());
+
private:
// prevent construction
QStandardPaths();
diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp
index 9acf1f22c3..24d0ceef56 100644
--- a/src/corelib/kernel/qcoreapplication.cpp
+++ b/src/corelib/kernel/qcoreapplication.cpp
@@ -53,6 +53,7 @@
#include <qfileinfo.h>
#include <qhash.h>
#include <private/qprocess_p.h>
+#include <qstandardpaths.h>
#include <qtextcodec.h>
#include <qthread.h>
#include <qthreadpool.h>
@@ -2019,19 +2020,7 @@ QString QCoreApplication::applicationFilePath()
Otherwise, the file path has to be determined using the
PATH environment variable.
*/
- QByteArray pEnv = qgetenv("PATH");
- QDir currentDir = QDir::current();
- QStringList paths = QString::fromLocal8Bit(pEnv.constData()).split(QLatin1Char(':'));
- for (QStringList::const_iterator p = paths.constBegin(); p != paths.constEnd(); ++p) {
- if ((*p).isEmpty())
- continue;
- QString candidate = currentDir.absoluteFilePath(*p + QLatin1Char('/') + argv0);
- QFileInfo candidate_fi(candidate);
- if (candidate_fi.exists() && !candidate_fi.isDir()) {
- absPath = candidate;
- break;
- }
- }
+ absPath = QStandardPaths::findExecutable(argv0);
}
absPath = QDir::cleanPath(absPath);