diff options
author | Friedemann Kleint <Friedemann.Kleint@digia.com> | 2013-06-24 15:43:03 +0200 |
---|---|---|
committer | Friedemann Kleint <Friedemann.Kleint@digia.com> | 2013-06-25 14:23:15 +0200 |
commit | 8c9396380580f5fa0e4cb6d5d7eab84c544b7863 (patch) | |
tree | e9fb84ad5537db913228748f8ffc97d511831f58 | |
parent | 8dba8dcd2c819b9453cc45fb2e07fb460c66895b (diff) | |
download | qttools-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.cpp | 21 | ||||
-rw-r--r-- | src/windeployqt/utils.h | 37 |
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()) { |