summaryrefslogtreecommitdiffstats
path: root/src/libs/installer/packagemanagercore_p.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/installer/packagemanagercore_p.cpp')
-rw-r--r--src/libs/installer/packagemanagercore_p.cpp78
1 files changed, 52 insertions, 26 deletions
diff --git a/src/libs/installer/packagemanagercore_p.cpp b/src/libs/installer/packagemanagercore_p.cpp
index 29c3fb03a..308bfa097 100644
--- a/src/libs/installer/packagemanagercore_p.cpp
+++ b/src/libs/installer/packagemanagercore_p.cpp
@@ -345,6 +345,27 @@ QString PackageManagerCorePrivate::targetDir() const
return m_core->value(scTargetDir);
}
+bool PackageManagerCorePrivate::directoryWritable(const QString &path) const
+{
+ QTemporaryFile tempFile(path + QStringLiteral("/tempFile") + QString::number(qrand() % 1000));
+ if (!tempFile.open() || !tempFile.isWritable())
+ return false;
+ else
+ return true;
+}
+
+bool PackageManagerCorePrivate::subdirectoriesWritable(const QString &path) const
+{
+ // Iterate over target directory subdirectories for writing access
+ QDirIterator iterator(path, QDir::AllDirs | QDir::NoDotAndDotDot, QDirIterator::Subdirectories);
+ while (iterator.hasNext()) {
+ QTemporaryFile tempFile(iterator.next() + QLatin1String("/tempFile"));
+ if (!tempFile.open() || !tempFile.isWritable())
+ return false;
+ }
+ return true;
+}
+
QString PackageManagerCorePrivate::configurationFileName() const
{
return m_core->value(scTargetConfigurationFile, QLatin1String("components.xml"));
@@ -569,7 +590,7 @@ void PackageManagerCorePrivate::initialize(const QHash<QString, QString> &params
#endif
if (!m_core->isInstaller()) {
-#ifdef Q_OS_OSX
+#ifdef Q_OS_MACOS
readMaintenanceConfigFiles(QCoreApplication::applicationDirPath() + QLatin1String("/../../.."));
#else
readMaintenanceConfigFiles(QCoreApplication::applicationDirPath());
@@ -697,7 +718,7 @@ Operation *PackageManagerCorePrivate::takeOwnedOperation(Operation *operation)
QString PackageManagerCorePrivate::maintenanceToolName() const
{
QString filename = m_data.settings().maintenanceToolName();
-#if defined(Q_OS_OSX)
+#if defined(Q_OS_MACOS)
if (QInstaller::isInBundle(QCoreApplication::applicationDirPath()))
filename += QLatin1String(".app/Contents/MacOS/") + filename;
#elif defined(Q_OS_WIN)
@@ -1013,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))
@@ -1023,7 +1044,7 @@ void PackageManagerCorePrivate::writeMaintenanceToolBinary(QFile *const input, q
if (writeBinaryLayout) {
QDir resourcePath(QFileInfo(maintenanceToolRenamedName).dir());
-#ifdef Q_OS_OSX
+#ifdef Q_OS_MACOS
if (!resourcePath.path().endsWith(QLatin1String("Contents/MacOS")))
throw Error(tr("Maintenance tool is not a bundle"));
resourcePath.cdUp();
@@ -1031,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
@@ -1049,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);
}
@@ -1077,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,
@@ -1144,16 +1169,14 @@ void PackageManagerCorePrivate::writeMaintenanceToolBinaryData(QFileDevice *outp
void PackageManagerCorePrivate::writeMaintenanceTool(OperationList performedOperations)
{
bool gainedAdminRights = false;
- QTemporaryFile tempAdminFile(targetDir() + QLatin1String("/testjsfdjlkdsjflkdsjfldsjlfds")
- + QString::number(qrand() % 1000));
- if (!tempAdminFile.open() || !tempAdminFile.isWritable()) {
+ if (!directoryWritable(targetDir())) {
m_core->gainAdminRights();
gainedAdminRights = true;
}
const QString targetAppDirPath = QFileInfo(maintenanceToolName()).path();
if (!QDir().exists(targetAppDirPath)) {
- // create the directory containing the maintenance tool (like a bundle structure on OS X...)
+ // create the directory containing the maintenance tool (like a bundle structure on macOS...)
Operation *op = createOwnedOperation(QLatin1String("Mkdir"));
op->setArguments(QStringList() << targetAppDirPath);
performOperationThreaded(op, Backup);
@@ -1161,7 +1184,7 @@ void PackageManagerCorePrivate::writeMaintenanceTool(OperationList performedOper
performedOperations.append(takeOwnedOperation(op));
}
-#ifdef Q_OS_OSX
+#ifdef Q_OS_MACOS
// if it is a bundle, we need some stuff in it...
const QString sourceAppDirPath = QCoreApplication::applicationDirPath();
if (isInstaller() && QInstaller::isInBundle(sourceAppDirPath)) {
@@ -1321,7 +1344,7 @@ void PackageManagerCorePrivate::writeMaintenanceTool(OperationList performedOper
// On Mac data is always in a separate file so that the binary can be signed.
// On other platforms data is in separate file only after install so that the
// maintenancetool sign does not break.
-#ifdef Q_OS_OSX
+#ifdef Q_OS_MACOS
QDir dataPath(QFileInfo(binaryName).dir());
dataPath.cdUp();
dataPath.cd(QLatin1String("Resources"));
@@ -1336,7 +1359,7 @@ void PackageManagerCorePrivate::writeMaintenanceTool(OperationList performedOper
newBinaryWritten = true;
QFile tmp(binaryName);
QInstaller::openForRead(&tmp);
-#ifdef Q_OS_OSX
+#ifdef Q_OS_MACOS
writeMaintenanceToolBinary(&tmp, tmp.size(), true);
#else
writeMaintenanceToolBinary(&tmp, layout.endOfBinaryContent - layout.binaryContentSize, true);
@@ -1348,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);
@@ -1363,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*/) {
@@ -1455,8 +1477,7 @@ bool PackageManagerCorePrivate::runInstaller()
}
}
} else if (QDir(target).exists()) {
- QTemporaryFile tempAdminFile(target + QLatin1String("/adminrights"));
- if (!tempAdminFile.open() || !tempAdminFile.isWritable())
+ if (!directoryWritable(targetDir()))
adminRightsGained = m_core->gainAdminRights();
}
@@ -1536,8 +1557,8 @@ bool PackageManagerCorePrivate::runInstaller()
Operation *createRepo = createOwnedOperation(QLatin1String("CreateLocalRepository"));
if (createRepo) {
QString binaryFile = QCoreApplication::applicationFilePath();
-#ifdef Q_OS_OSX
- // The installer binary on OSX does not contain the binary content, it's put into
+#ifdef Q_OS_MACOS
+ // The installer binary on macOS does not contain the binary content, it's put into
// the resources folder as separate file. Adjust the actual binary path. No error
// checking here since we will fail later while reading the binary content.
QDir resourcePath(QFileInfo(binaryFile).dir());
@@ -1622,10 +1643,16 @@ bool PackageManagerCorePrivate::runPackageUpdater()
//to have some progress for the cleanup/write component.xml step
ProgressCoordinator::instance()->addReservePercentagePoints(1);
+#if defined(Q_OS_LINUX) || defined(Q_OS_MACOS)
// check if we need admin rights and ask before the action happens
- if (!QTemporaryFile(targetDir() + QStringLiteral("/XXXXXX")).open())
+ // on Linux and macOS also check target directory subdirectories
+ if (!directoryWritable(targetDir()) || !subdirectoriesWritable(targetDir()))
adminRightsGained = m_core->gainAdminRights();
-
+#else
+ // check if we need admin rights and ask before the action happens
+ if (!directoryWritable(targetDir()))
+ adminRightsGained = m_core->gainAdminRights();
+#endif
const QList<Component *> componentsToInstall = m_core->orderedComponentsToInstall();
qDebug() << "Install size:" << componentsToInstall.size() << "components";
@@ -1792,8 +1819,7 @@ bool PackageManagerCorePrivate::runUninstaller()
setStatus(PackageManagerCore::Running);
// check if we need to run elevated and ask before the action happens
- QTemporaryFile tempAdminFile(targetDir() + QLatin1String("/adminrights"));
- if (!tempAdminFile.open() || !tempAdminFile.isWritable())
+ if (!directoryWritable(targetDir()))
adminRightsGained = m_core->gainAdminRights();
OperationList undoOperations = m_performedOperationsOld;
@@ -2005,7 +2031,7 @@ void PackageManagerCorePrivate::deleteMaintenanceTool()
// every other platform has no problem if we just delete ourselves now
QFile maintenanceTool(QFileInfo(installerBinaryPath()).absoluteFilePath());
maintenanceTool.remove();
-# ifdef Q_OS_OSX
+# ifdef Q_OS_MACOS
if (QInstaller::isInBundle(installerBinaryPath())) {
const QLatin1String cdUp("/../../..");
removeDirectoryThreaded(QFileInfo(installerBinaryPath() + cdUp).absoluteFilePath());