summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/libs/installer/binaryformat.cpp2
-rw-r--r--src/libs/installer/createlocalrepositoryoperation.cpp18
-rw-r--r--src/libs/installer/packagemanagercore_p.cpp17
-rw-r--r--src/libs/installer/remoteclient.cpp24
-rw-r--r--src/libs/installer/remoteclient.h1
-rw-r--r--src/libs/installer/remotefileengine.cpp4
-rw-r--r--src/libs/installer/remoteserver.cpp22
-rw-r--r--src/libs/installer/remoteserver.h1
-rw-r--r--src/libs/installer/remoteserverconnection.cpp7
-rw-r--r--tests/auto/installer/packagemanagercore/tst_packagemanagercore.cpp9
-rw-r--r--tests/auto/installer/scriptengine/tst_scriptengine.cpp4
11 files changed, 96 insertions, 13 deletions
diff --git a/src/libs/installer/binaryformat.cpp b/src/libs/installer/binaryformat.cpp
index 9a46095ce..3e7dd5a2a 100644
--- a/src/libs/installer/binaryformat.cpp
+++ b/src/libs/installer/binaryformat.cpp
@@ -158,7 +158,7 @@ bool Resource::open()
if (isOpen())
return false;
- if (!m_file.open(QIODevice::ReadOnly)) {
+ if (!m_file.open(QIODevice::ReadOnly | QIODevice::Unbuffered)) {
setErrorString(m_file.errorString());
return false;
}
diff --git a/src/libs/installer/createlocalrepositoryoperation.cpp b/src/libs/installer/createlocalrepositoryoperation.cpp
index a2f7806a3..0eabc8c35 100644
--- a/src/libs/installer/createlocalrepositoryoperation.cpp
+++ b/src/libs/installer/createlocalrepositoryoperation.cpp
@@ -38,6 +38,7 @@
#include "lib7z_facade.h"
#include "packagemanagercore.h"
#include "productkeycheck.h"
+#include "constants.h"
#include "updateoperations.h"
@@ -183,6 +184,23 @@ bool CreateLocalRepositoryOperation::performOperation()
}
setValue(QLatin1String("createddir"), mkDirOp.value(QLatin1String("createddir")));
+#if QT_VERSION >= QT_VERSION_CHECK(5,10,0)
+ // Internal changes to QTemporaryFile break copying Qt resources through
+ // QInstaller::RemoteFileEngine. We do not register resources to be handled by
+ // RemoteFileEngine, instead copying using 5.9 succeeded because QFile::copy()
+ // creates a QTemporaryFile object internally that is handled by the remote engine.
+ //
+ // This will not work with Qt 5.10 and above as QTemporaryFile introduced a new
+ // rename() implementation that explicitly uses its own QTemporaryFileEngine.
+ //
+ // Fail and return early if we are working on an elevated permission directory.
+ if (core && !core->directoryWritable(repoPath)) {
+ setError(UserDefinedError);
+ setErrorString(tr("Creating local repository into elevated permissions "
+ "directory: %1 is not supported.").arg(repoPath));
+ return false;
+ }
+#endif
// copy the whole meta data into local repository
CopyDirectoryOperation copyDirOp(core);
copyDirOp.setArguments(QStringList() << QLatin1String(":/metadata/") << repoPath);
diff --git a/src/libs/installer/packagemanagercore_p.cpp b/src/libs/installer/packagemanagercore_p.cpp
index 653869898..308bfa097 100644
--- a/src/libs/installer/packagemanagercore_p.cpp
+++ b/src/libs/installer/packagemanagercore_p.cpp
@@ -1034,7 +1034,7 @@ void PackageManagerCorePrivate::writeMaintenanceToolBinary(QFile *const input, q
qDebug() << "Writing maintenance tool:" << maintenanceToolRenamedName;
ProgressCoordinator::instance()->emitLabelAndDetailTextChanged(tr("Writing maintenance tool."));
- QTemporaryFile out;
+ QFile out(generateTemporaryFileName());
QInstaller::openForWrite(&out); // throws an exception in case of error
if (!input->seek(0))
@@ -1052,7 +1052,7 @@ void PackageManagerCorePrivate::writeMaintenanceToolBinary(QFile *const input, q
#endif
// It's a bit odd to have only the magic in the data file, but this simplifies
// other code a lot (since installers don't have any appended data either)
- QTemporaryFile dataOut;
+ QFile dataOut(generateTemporaryFileName());
QInstaller::openForWrite(&dataOut);
QInstaller::appendInt64(&dataOut, 0); // operations start
QInstaller::appendInt64(&dataOut, 0); // operations end
@@ -1070,10 +1070,9 @@ void PackageManagerCorePrivate::writeMaintenanceToolBinary(QFile *const input, q
}
if (!dataOut.rename(resourcePath.filePath(QLatin1String("installer.dat")))) {
- throw Error(tr("Cannot write maintenance tool data to %1: %2").arg(out.fileName(),
- out.errorString()));
+ throw Error(tr("Cannot write maintenance tool data to %1: %2").arg(dataOut.fileName(),
+ dataOut.errorString()));
}
- dataOut.setAutoRemove(false);
dataOut.setPermissions(dataOut.permissions() | QFile::WriteUser | QFile::ReadGroup
| QFile::ReadOther);
}
@@ -1098,6 +1097,11 @@ void PackageManagerCorePrivate::writeMaintenanceToolBinary(QFile *const input, q
} else {
qDebug() << "Failed to write permissions for maintenance tool.";
}
+
+ if (out.exists() && !out.remove()) {
+ qWarning() << tr("Cannot remove temporary data file \"%1\": %2")
+ .arg(out.fileName(), out.errorString());
+ }
}
void PackageManagerCorePrivate::writeMaintenanceToolBinaryData(QFileDevice *output, QFile *const input,
@@ -1367,7 +1371,7 @@ void PackageManagerCorePrivate::writeMaintenanceTool(OperationList performedOper
m_core->setValue(QLatin1String("installedOperationAreSorted"), QLatin1String("true"));
try {
- QTemporaryFile file;
+ QFile file(generateTemporaryFileName());
QInstaller::openForWrite(&file);
writeMaintenanceToolBinaryData(&file, &input, performedOperations, layout);
QInstaller::appendInt64(&file, BinaryContent::MagicCookieDat);
@@ -1382,7 +1386,6 @@ void PackageManagerCorePrivate::writeMaintenanceTool(OperationList performedOper
throw Error(tr("Cannot write maintenance tool binary data to %1: %2")
.arg(file.fileName(), file.errorString()));
}
- file.setAutoRemove(false);
file.setPermissions(file.permissions() | QFile::WriteUser | QFile::ReadGroup
| QFile::ReadOther);
} catch (const Error &/*error*/) {
diff --git a/src/libs/installer/remoteclient.cpp b/src/libs/installer/remoteclient.cpp
index e208620cb..ad1e5ecf6 100644
--- a/src/libs/installer/remoteclient.cpp
+++ b/src/libs/installer/remoteclient.cpp
@@ -29,6 +29,8 @@
#include "remoteclient.h"
#include "remoteclient_p.h"
+#include <QDir>
+
namespace QInstaller {
RemoteClient *RemoteClient::s_instance = nullptr;
@@ -61,6 +63,18 @@ QString RemoteClient::authorizationKey() const
return d->m_key;
}
+QString RemoteClient::socketPathName(const QString &socketName) const
+{
+ QString socketPathName;
+ if (socketName.startsWith(QLatin1Char('/'))) {
+ socketPathName = socketName;
+ } else {
+ socketPathName = QDir::tempPath();
+ socketPathName += QLatin1Char('/') + socketName;
+ }
+ return socketPathName;
+}
+
/*!
Initializes the client with \a socketName, with the \a key the client
sends to authenticate with the server, \a mode and \a startAs.
@@ -69,7 +83,17 @@ void RemoteClient::init(const QString &socketName, const QString &key, Protocol:
Protocol::StartAs startAs)
{
Q_D(RemoteClient);
+
+ // Since Qt 5.12.0, we should determince the full socket path on Unix
+ // platforms before calling QLocalSocketPrivate::_q_connectToSocket().
+ // Otherwise the new canonical implementation of QDir::tempPath()
+ // presents unintended usage of RemoteFileEngine.
+
+#if QT_VERSION >= QT_VERSION_CHECK(5,12,0) && defined(Q_OS_UNIX)
+ d->init(socketPathName(socketName), key, mode, startAs);
+#else
d->init(socketName, key, mode, startAs);
+#endif
}
void RemoteClient::setAuthorizationFallbackDisabled(bool disabled)
diff --git a/src/libs/installer/remoteclient.h b/src/libs/installer/remoteclient.h
index c2090bf98..419acccfa 100644
--- a/src/libs/installer/remoteclient.h
+++ b/src/libs/installer/remoteclient.h
@@ -54,6 +54,7 @@ public:
QString socketName() const;
QString authorizationKey() const;
+ QString socketPathName(const QString &socketName) const;
bool isActive() const;
void setActive(bool active);
diff --git a/src/libs/installer/remotefileengine.cpp b/src/libs/installer/remotefileengine.cpp
index 05f4ec212..3c54d1e29 100644
--- a/src/libs/installer/remotefileengine.cpp
+++ b/src/libs/installer/remotefileengine.cpp
@@ -324,9 +324,9 @@ bool RemoteFileEngine::open(QIODevice::OpenMode mode)
{
if (connectToServer()) {
return callRemoteMethod<bool>(QString::fromLatin1(Protocol::QAbstractFileEngineOpen),
- static_cast<qint32>(mode));
+ static_cast<qint32>(mode | QIODevice::Unbuffered));
}
- return m_fileEngine.open(mode);
+ return m_fileEngine.open(mode | QIODevice::Unbuffered);
}
/*!
diff --git a/src/libs/installer/remoteserver.cpp b/src/libs/installer/remoteserver.cpp
index ddf4d6ecf..66cfefebb 100644
--- a/src/libs/installer/remoteserver.cpp
+++ b/src/libs/installer/remoteserver.cpp
@@ -93,7 +93,17 @@ void RemoteServer::start()
void RemoteServer::init(const QString &socketName, const QString &key, Protocol::Mode mode)
{
Q_D(RemoteServer);
+
+ // Since Qt 5.12.0, we should determince the full socket path on Unix
+ // platforms before calling QLocalSocketPrivate::_q_connectToSocket().
+ // Otherwise the new canonical implementation of QDir::tempPath()
+ // presents unintended usage of RemoteFileEngine.
+
+#if QT_VERSION >= QT_VERSION_CHECK(5,12,0) && defined(Q_OS_UNIX)
+ d->m_socketName = socketPathName(socketName);
+#else
d->m_socketName = socketName;
+#endif
d->m_key = key;
d->m_mode = mode;
}
@@ -116,6 +126,18 @@ QString RemoteServer::authorizationKey() const
return d->m_key;
}
+QString RemoteServer::socketPathName(const QString &socketName) const
+{
+ QString socketPathName;
+ if (socketName.startsWith(QLatin1Char('/'))) {
+ socketPathName = socketName;
+ } else {
+ socketPathName = QDir::tempPath();
+ socketPathName += QLatin1Char('/') + socketName;
+ }
+ return socketPathName;
+}
+
/*!
Restarts the watchdog that tries to kill the server.
*/
diff --git a/src/libs/installer/remoteserver.h b/src/libs/installer/remoteserver.h
index e32bcf143..aa69baa55 100644
--- a/src/libs/installer/remoteserver.h
+++ b/src/libs/installer/remoteserver.h
@@ -53,6 +53,7 @@ public:
QString socketName() const;
QString authorizationKey() const;
+ QString socketPathName(const QString &socketName) const;
private slots:
void restartWatchdog();
diff --git a/src/libs/installer/remoteserverconnection.cpp b/src/libs/installer/remoteserverconnection.cpp
index 5a47bc472..b188e694e 100644
--- a/src/libs/installer/remoteserverconnection.cpp
+++ b/src/libs/installer/remoteserverconnection.cpp
@@ -382,7 +382,14 @@ void RemoteServerConnection::handleQFSFileEngine(QIODevice *socket, const QStrin
} else if (command == QLatin1String(Protocol::QAbstractFileEngineCopy)) {
QString newName;
data >>newName;
+#ifdef Q_OS_LINUX
+ // QFileSystemEngine::copyFile() is currently unimplemented on Linux,
+ // copy using QFile instead of directly with QFSFileEngine.
+ QFile file(m_engine->fileName(QAbstractFileEngine::AbsoluteName));
+ sendData(socket, file.copy(newName));
+#else
sendData(socket, m_engine->copy(newName));
+#endif
} else if (command == QLatin1String(Protocol::QAbstractFileEngineEntryList)) {
qint32 filters;
QStringList filterNames;
diff --git a/tests/auto/installer/packagemanagercore/tst_packagemanagercore.cpp b/tests/auto/installer/packagemanagercore/tst_packagemanagercore.cpp
index 475c4d8b4..67fa7e2c5 100644
--- a/tests/auto/installer/packagemanagercore/tst_packagemanagercore.cpp
+++ b/tests/auto/installer/packagemanagercore/tst_packagemanagercore.cpp
@@ -119,15 +119,18 @@ private slots:
QVERIFY(core.calculateComponentsToInstall());
{
- QTemporaryFile dummy(testDirectory + QLatin1String("/dummy"));
- dummy.open();
+ QFile dummy(testDirectory + QLatin1String("/dummy"));
+ QVERIFY(dummy.open(QIODevice::ReadWrite));
core.runInstaller();
QVERIFY(QDir(testDirectory).exists());
QVERIFY(QFileInfo(dummy.fileName()).exists());
+
+ dummy.close();
+ QVERIFY(dummy.remove());
}
- QDir().rmdir(testDirectory);
+ QVERIFY(QDir().rmdir(testDirectory));
ProgressCoordinator::instance()->reset();
}
diff --git a/tests/auto/installer/scriptengine/tst_scriptengine.cpp b/tests/auto/installer/scriptengine/tst_scriptengine.cpp
index 7118d067d..b7c602e26 100644
--- a/tests/auto/installer/scriptengine/tst_scriptengine.cpp
+++ b/tests/auto/installer/scriptengine/tst_scriptengine.cpp
@@ -280,7 +280,11 @@ private slots:
// ignore Output from script
setExpectedScriptOutput("function receive()");
+#if QT_VERSION >= QT_VERSION_CHECK(5,12,0)
+ QTest::ignoreMessage(QtWarningMsg, "<Unknown File>:38: ReferenceError: foo is not defined");
+#else
QTest::ignoreMessage(QtWarningMsg, ":38: ReferenceError: foo is not defined");
+#endif
emiter.produceSignal();
const QJSValue value = m_scriptEngine->evaluate("");