diff options
author | David Faure <faure@kde.org> | 2011-10-21 20:57:31 +0200 |
---|---|---|
committer | Qt by Nokia <qt-info@nokia.com> | 2011-10-23 00:56:51 +0200 |
commit | 4b72c3f4347bfb8493e877d26f172f2e18c69a83 (patch) | |
tree | 636fc5ca4a92678ae1c11b0d48483b23b1d1127f | |
parent | fa0ad643a6f0018544197e4eb80e8cf2cbf700cf (diff) |
Add QStandardPaths::findExecutable.
Change-Id: If30a83622e2ac5af48e47a38b8f70fce73044d74
Reviewed-by: Thiago Macieira (Intel) <thiago.macieira@intel.com>
-rw-r--r-- | src/corelib/io/qstandardpaths.cpp | 87 | ||||
-rw-r--r-- | src/corelib/io/qstandardpaths.h | 4 | ||||
-rw-r--r-- | src/corelib/kernel/qcoreapplication.cpp | 15 |
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); |