diff options
Diffstat (limited to 'src/libs/installer/packagemanagercore_p.cpp')
-rw-r--r-- | src/libs/installer/packagemanagercore_p.cpp | 78 |
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> ¶ms #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()); |