summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFriedemann Kleint <Friedemann.Kleint@digia.com>2013-06-24 15:43:03 +0200
committerFriedemann Kleint <Friedemann.Kleint@digia.com>2013-06-25 14:23:15 +0200
commit8c9396380580f5fa0e4cb6d5d7eab84c544b7863 (patch)
treee9fb84ad5537db913228748f8ffc97d511831f58
parent8dba8dcd2c819b9453cc45fb2e07fb460c66895b (diff)
downloadqttools-8c9396380580f5fa0e4cb6d5d7eab84c544b7863.tar.gz
windeployqt: Handle simple symbolic links in updateFile().
Preparing the deployment of shared libraries and their version links on Unix. Change-Id: Iee9e25e5364209c0a4aafbd6d10c18e64113c971 Reviewed-by: Joerg Bornemann <joerg.bornemann@digia.com>
-rw-r--r--src/windeployqt/utils.cpp21
-rw-r--r--src/windeployqt/utils.h37
2 files changed, 53 insertions, 5 deletions
diff --git a/src/windeployqt/utils.cpp b/src/windeployqt/utils.cpp
index fe18338d4..d042551e7 100644
--- a/src/windeployqt/utils.cpp
+++ b/src/windeployqt/utils.cpp
@@ -66,6 +66,27 @@
#include <cstdio>
int optVerboseLevel = 1;
+// Create a symbolic link by changing to the source directory to make sure the
+// link uses relative paths only (QFile::link() otherwise uses the absolute path).
+bool createSymbolicLink(const QFileInfo &source, const QString &target, QString *errorMessage)
+{
+ const QString oldDirectory = QDir::currentPath();
+ if (!QDir::setCurrent(source.absolutePath())) {
+ *errorMessage = QStringLiteral("Unable to change to directory %1.").arg(QDir::toNativeSeparators(source.absolutePath()));
+ return false;
+ }
+ QFile file(source.fileName());
+ const bool success = file.link(target);
+ QDir::setCurrent(oldDirectory);
+ if (!success) {
+ *errorMessage = QString::fromLatin1("Failed to create symbolic link %1 -> %2: %3")
+ .arg(QDir::toNativeSeparators(source.absoluteFilePath()),
+ QDir::toNativeSeparators(target), file.errorString());
+ return false;
+ }
+ return true;
+}
+
#ifdef Q_OS_WIN
QString winErrorMessage(unsigned long error)
{
diff --git a/src/windeployqt/utils.h b/src/windeployqt/utils.h
index 0bad1d2df..96fda5db5 100644
--- a/src/windeployqt/utils.h
+++ b/src/windeployqt/utils.h
@@ -60,6 +60,7 @@ QString findSdkTool(const QString &tool);
inline QString normalizeFileName(const QString &name) { return name; }
#endif // !Q_OS_WIN
+bool createSymbolicLink(const QFileInfo &source, const QString &target, QString *errorMessage);
QString findInPath(const QString &file);
QMap<QString, QString> queryQMakeAll(QString *errorMessage);
QString queryQMake(const QString &variable, QString *errorMessage);
@@ -105,13 +106,39 @@ bool updateFile(const QString &sourceFileName,
return false;
}
+ const QFileInfo targetFileInfo(targetFileName);
+
if (sourceFileInfo.isSymLink()) {
- *errorMessage = QString::fromLatin1("Symbolic links are not supported (%1).")
- .arg(QDir::toNativeSeparators(sourceFileName));
- return false;
- }
+ const QString sourcePath = sourceFileInfo.symLinkTarget();
+ const QString relativeSource = QDir(sourceFileInfo.absolutePath()).relativeFilePath(sourcePath);
+ if (relativeSource.contains(QLatin1Char('/'))) {
+ *errorMessage = QString::fromLatin1("Symbolic links across directories are not supported (%1).")
+ .arg(QDir::toNativeSeparators(sourceFileName));
+ return false;
+ }
- const QFileInfo targetFileInfo(targetFileName);
+ // Update the linked-to file
+ if (!updateFile(sourcePath, directoryFileEntryFunction, targetDirectory, errorMessage))
+ return false;
+
+ if (targetFileInfo.exists()) {
+ if (!targetFileInfo.isSymLink()) {
+ *errorMessage = QString::fromLatin1("%1 already exists and is not a symbolic link.")
+ .arg(QDir::toNativeSeparators(targetFileName));
+ return false;
+ } // Not a symlink
+ const QString relativeTarget = QDir(targetFileInfo.absolutePath()).relativeFilePath(targetFileInfo.symLinkTarget());
+ if (relativeSource == relativeTarget) // Exists and points to same entry: happy.
+ return true;
+ QFile existingTargetFile(targetFileName);
+ if (!existingTargetFile.remove()) {
+ *errorMessage = QString::fromLatin1("Cannot remove existing symbolic link %1: %2")
+ .arg(QDir::toNativeSeparators(targetFileName), existingTargetFile.errorString());
+ return false;
+ }
+ } // target symbolic link exists
+ return createSymbolicLink(QFileInfo(targetDirectory + QLatin1Char('/') + relativeSource), sourceFileInfo.fileName(), errorMessage);
+ } // Source is symbolic link
if (sourceFileInfo.isDir()) {
if (targetFileInfo.exists()) {