2020-10-01 00:33:19 +01:00
|
|
|
/*
|
|
|
|
SPDX-FileCopyrightText: 2017-2020 Andrius Štikonas <andrius@stikonas.eu>
|
|
|
|
SPDX-FileCopyrightText: 2018 Huzaifa Faruqui <huzaifafaruqui@gmail.com>
|
|
|
|
SPDX-FileCopyrightText: 2018 Caio Jordão Carvalho <caiojcarvalho@gmail.com>
|
|
|
|
SPDX-FileCopyrightText: 2018-2019 Harald Sitter <sitter@kde.org>
|
|
|
|
SPDX-FileCopyrightText: 2018 Simon Depiets <sdepiets@gmail.com>
|
|
|
|
SPDX-FileCopyrightText: 2019 Shubham Jangra <aryan100jangid@gmail.com>
|
2020-10-09 20:41:41 +01:00
|
|
|
SPDX-FileCopyrightText: 2020 David Edmundson <kde@davidedmundson.co.uk>
|
2020-10-01 00:33:19 +01:00
|
|
|
|
|
|
|
SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
*/
|
2017-11-07 22:55:28 +00:00
|
|
|
|
|
|
|
#include "externalcommandhelper.h"
|
2018-08-11 20:32:02 +01:00
|
|
|
#include "externalcommand_whitelist.h"
|
2017-11-07 22:55:28 +00:00
|
|
|
|
2018-03-19 10:33:20 +00:00
|
|
|
#include <QtDBus>
|
2020-10-08 02:23:24 +01:00
|
|
|
|
2019-06-03 13:46:18 +01:00
|
|
|
#include <QCoreApplication>
|
2017-11-07 22:55:28 +00:00
|
|
|
#include <QDebug>
|
2020-09-13 17:25:51 +01:00
|
|
|
#include <QElapsedTimer>
|
2018-02-03 15:57:47 +00:00
|
|
|
#include <QFile>
|
2019-06-12 17:41:11 +01:00
|
|
|
#include <QString>
|
2018-01-27 18:54:48 +00:00
|
|
|
#include <QVariant>
|
|
|
|
|
|
|
|
#include <KLocalizedString>
|
2020-10-08 02:23:24 +01:00
|
|
|
#include <PolkitQt1/Authority>
|
|
|
|
#include <PolkitQt1/Subject>
|
|
|
|
|
|
|
|
#include <polkitqt1-version.h>
|
2018-01-27 18:54:48 +00:00
|
|
|
|
2018-03-19 10:33:20 +00:00
|
|
|
/** Initialize ExternalCommandHelper Daemon and prepare DBus interface
|
2018-07-15 00:09:39 +01:00
|
|
|
*
|
2020-10-11 22:19:14 +01:00
|
|
|
* This helper runs in the background until all applications using it exit.
|
2018-08-06 12:19:13 +01:00
|
|
|
* If helper is not busy then it exits when the client services gets
|
2020-10-11 22:19:14 +01:00
|
|
|
* unregistered. In case the client crashes, the helper waits
|
|
|
|
* for the current job to finish before exiting, to avoid leaving partially moved data.
|
2020-10-08 02:23:24 +01:00
|
|
|
*
|
2020-10-11 22:19:14 +01:00
|
|
|
* This helper starts DBus interface where it listens to command execution requests.
|
|
|
|
* New clients connecting to the helper have to authenticate using Polkit.
|
2018-03-19 10:33:20 +00:00
|
|
|
*/
|
2020-10-08 02:23:24 +01:00
|
|
|
|
|
|
|
ExternalCommandHelper::ExternalCommandHelper()
|
2018-03-19 10:33:20 +00:00
|
|
|
{
|
2020-10-11 23:46:20 +01:00
|
|
|
if (!QDBusConnection::systemBus().registerObject(QStringLiteral("/Helper"), this, QDBusConnection::ExportAllSlots | QDBusConnection::ExportAllSignals)) {
|
2020-10-08 02:23:24 +01:00
|
|
|
::exit(-1);
|
2018-07-15 00:09:39 +01:00
|
|
|
}
|
|
|
|
|
2020-10-08 02:23:24 +01:00
|
|
|
if (!QDBusConnection::systemBus().registerService(QStringLiteral("org.kde.kpmcore.helperinterface"))) {
|
|
|
|
::exit(-1);
|
|
|
|
}
|
2018-03-23 22:08:23 +00:00
|
|
|
|
2020-10-08 02:23:24 +01:00
|
|
|
// we know this service must be registered already as DBus policy blocks calls from anyone else
|
|
|
|
m_serviceWatcher = new QDBusServiceWatcher(this);
|
|
|
|
m_serviceWatcher->setConnection(QDBusConnection ::systemBus());
|
|
|
|
m_serviceWatcher->setWatchMode(QDBusServiceWatcher::WatchForUnregistration);
|
2019-06-03 13:46:18 +01:00
|
|
|
|
2020-10-08 02:23:24 +01:00
|
|
|
connect(m_serviceWatcher, &QDBusServiceWatcher::serviceUnregistered, qApp, [this](const QString &service) {
|
|
|
|
m_serviceWatcher->removeWatchedService(service);
|
|
|
|
if (m_serviceWatcher->watchedServices().isEmpty()) {
|
|
|
|
qApp->quit();
|
|
|
|
}
|
|
|
|
});
|
2018-03-19 10:33:20 +00:00
|
|
|
}
|
|
|
|
|
2018-02-06 16:48:02 +00:00
|
|
|
/** Reads the given number of bytes from the sourceDevice into the given buffer.
|
|
|
|
@param sourceDevice device or file to read from
|
|
|
|
@param buffer buffer to store the bytes read in
|
|
|
|
@param offset offset where to begin reading
|
|
|
|
@param size the number of bytes to read
|
|
|
|
@return true on success
|
|
|
|
*/
|
2019-03-29 17:51:51 +00:00
|
|
|
bool ExternalCommandHelper::readData(const QString& sourceDevice, QByteArray& buffer, const qint64 offset, const qint64 size)
|
2018-01-24 15:22:42 +00:00
|
|
|
{
|
2018-02-05 12:58:37 +00:00
|
|
|
QFile device(sourceDevice);
|
2018-01-24 15:22:42 +00:00
|
|
|
|
2018-02-05 12:58:37 +00:00
|
|
|
if (!device.open(QIODevice::ReadOnly | QIODevice::Unbuffered)) {
|
|
|
|
qCritical() << xi18n("Could not open device <filename>%1</filename> for reading.", sourceDevice);
|
|
|
|
return false;
|
|
|
|
}
|
2018-01-24 15:22:42 +00:00
|
|
|
|
2018-02-05 12:58:37 +00:00
|
|
|
if (!device.seek(offset)) {
|
2018-08-21 09:35:39 +01:00
|
|
|
qCritical() << xi18n("Could not seek position %1 on device <filename>%2</filename>.", offset, sourceDevice);
|
2018-02-05 12:58:37 +00:00
|
|
|
return false;
|
2018-01-24 15:22:42 +00:00
|
|
|
}
|
2018-02-05 12:58:37 +00:00
|
|
|
|
|
|
|
buffer = device.read(size);
|
|
|
|
|
|
|
|
if (size != buffer.size()) {
|
|
|
|
qCritical() << xi18n("Could not read from device <filename>%1</filename>.", sourceDevice);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
2018-01-24 15:22:42 +00:00
|
|
|
}
|
|
|
|
|
2020-09-10 23:54:23 +01:00
|
|
|
/** Writes the data from buffer to a given device.
|
2018-02-06 16:48:02 +00:00
|
|
|
@param targetDevice device or file to write to
|
|
|
|
@param buffer the data that we write
|
|
|
|
@param offset offset where to begin writing
|
|
|
|
@return true on success
|
|
|
|
*/
|
2019-03-29 17:51:51 +00:00
|
|
|
bool ExternalCommandHelper::writeData(const QString &targetDevice, const QByteArray& buffer, const qint64 offset)
|
2018-01-24 15:22:42 +00:00
|
|
|
{
|
2018-02-03 15:57:47 +00:00
|
|
|
QFile device(targetDevice);
|
Constantify nonce and some cleanup
Reviewers: stikonas, #kde_partition_manager, cjlcarvalho
Reviewed By: stikonas, #kde_partition_manager, cjlcarvalho
Subscribers: varunp, tctara, teo, abhijeet2096, caiovosilva, cjlcarvalho, #kde_partition_manager
Tags: #kde_partition_manager
Differential Revision: https://phabricator.kde.org/D20108
2019-03-29 17:58:56 +00:00
|
|
|
|
2020-09-10 23:54:23 +01:00
|
|
|
auto flags = QIODevice::WriteOnly | QIODevice::Unbuffered | QIODevice::Append;
|
|
|
|
if (!device.open(flags)) {
|
2018-02-03 15:57:47 +00:00
|
|
|
qCritical() << xi18n("Could not open device <filename>%1</filename> for writing.", targetDevice);
|
|
|
|
return false;
|
|
|
|
}
|
2018-01-24 15:22:42 +00:00
|
|
|
|
2018-02-03 15:57:47 +00:00
|
|
|
if (!device.seek(offset)) {
|
2018-08-21 09:35:39 +01:00
|
|
|
qCritical() << xi18n("Could not seek position %1 on device <filename>%2</filename>.", offset, targetDevice);
|
2018-02-03 15:57:47 +00:00
|
|
|
return false;
|
2018-01-24 15:22:42 +00:00
|
|
|
}
|
|
|
|
|
2018-02-03 15:57:47 +00:00
|
|
|
if (device.write(buffer) != buffer.size()) {
|
|
|
|
qCritical() << xi18n("Could not write to device <filename>%1</filename>.", targetDevice);
|
|
|
|
return false;
|
|
|
|
}
|
Constantify nonce and some cleanup
Reviewers: stikonas, #kde_partition_manager, cjlcarvalho
Reviewed By: stikonas, #kde_partition_manager, cjlcarvalho
Subscribers: varunp, tctara, teo, abhijeet2096, caiovosilva, cjlcarvalho, #kde_partition_manager
Tags: #kde_partition_manager
Differential Revision: https://phabricator.kde.org/D20108
2019-03-29 17:58:56 +00:00
|
|
|
|
2018-02-03 15:57:47 +00:00
|
|
|
return true;
|
2018-01-24 15:22:42 +00:00
|
|
|
}
|
|
|
|
|
2020-09-10 23:54:23 +01:00
|
|
|
/** Creates a new file with given contents.
|
|
|
|
@param filePath file to write to
|
|
|
|
@param fileContents the data that we write
|
|
|
|
@return true on success
|
|
|
|
*/
|
2020-10-11 22:45:13 +01:00
|
|
|
bool ExternalCommandHelper::CreateFile(const QString &filePath, const QByteArray& fileContents)
|
2020-09-10 23:54:23 +01:00
|
|
|
{
|
2020-10-08 02:23:24 +01:00
|
|
|
if (!isCallerAuthorized()) {
|
|
|
|
return false;
|
|
|
|
}
|
2020-10-11 22:39:47 +01:00
|
|
|
// Do not allow using this helper for writing to arbitrary location
|
|
|
|
if ( !filePath.contains(QStringLiteral("/etc/fstab")) )
|
|
|
|
return false;
|
|
|
|
|
2020-09-10 23:54:23 +01:00
|
|
|
QFile device(filePath);
|
|
|
|
|
|
|
|
auto flags = QIODevice::WriteOnly | QIODevice::Unbuffered;
|
|
|
|
if (!device.open(flags)) {
|
|
|
|
qCritical() << xi18n("Could not open file <filename>%1</filename> for writing.", filePath);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (device.write(fileContents) != fileContents.size()) {
|
|
|
|
qCritical() << xi18n("Could not write to file <filename>%1</filename>.", filePath);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2018-11-25 20:50:22 +00:00
|
|
|
// If targetDevice is empty then return QByteArray with data that was read from disk.
|
2020-10-11 22:45:13 +01:00
|
|
|
QVariantMap ExternalCommandHelper::CopyBlocks(const QString& sourceDevice, const qint64 sourceFirstByte, const qint64 sourceLength, const QString& targetDevice, const qint64 targetFirstByte, const qint64 blockSize)
|
2018-01-24 15:22:42 +00:00
|
|
|
{
|
2020-10-08 02:23:24 +01:00
|
|
|
if (!isCallerAuthorized()) {
|
|
|
|
return QVariantMap();
|
|
|
|
}
|
2020-11-26 21:58:24 +00:00
|
|
|
|
|
|
|
// Avoid division by zero further down
|
|
|
|
if (!blockSize) {
|
|
|
|
return QVariantMap();
|
|
|
|
}
|
2020-11-29 01:08:43 +00:00
|
|
|
|
|
|
|
// Prevent some out of memory situations
|
2020-11-29 00:58:55 +00:00
|
|
|
constexpr qint64 MiB = 1 << 30;
|
|
|
|
if (blockSize > 100 * MiB) {
|
|
|
|
return QVariantMap();
|
|
|
|
}
|
2020-11-29 01:08:43 +00:00
|
|
|
if (targetDevice.isEmpty() && sourceLength > MiB) {
|
|
|
|
return QVariantMap();
|
|
|
|
}
|
2020-11-29 00:58:55 +00:00
|
|
|
|
2018-10-28 17:22:12 +00:00
|
|
|
QVariantMap reply;
|
|
|
|
reply[QStringLiteral("success")] = true;
|
|
|
|
|
2018-03-21 17:01:40 +00:00
|
|
|
const qint64 blocksToCopy = sourceLength / blockSize;
|
|
|
|
qint64 readOffset = sourceFirstByte;
|
|
|
|
qint64 writeOffset = targetFirstByte;
|
|
|
|
qint32 copyDirection = 1;
|
2018-01-24 15:22:42 +00:00
|
|
|
|
2018-03-21 17:01:40 +00:00
|
|
|
if (targetFirstByte > sourceFirstByte) {
|
|
|
|
readOffset = sourceFirstByte + sourceLength - blockSize;
|
|
|
|
writeOffset = targetFirstByte + sourceLength - blockSize;
|
|
|
|
copyDirection = -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
const qint64 lastBlock = sourceLength % blockSize;
|
2018-01-24 15:22:42 +00:00
|
|
|
|
2018-01-27 18:54:48 +00:00
|
|
|
qint64 bytesWritten = 0;
|
2018-01-24 15:22:42 +00:00
|
|
|
qint64 blocksCopied = 0;
|
|
|
|
|
2018-01-24 15:35:11 +00:00
|
|
|
QByteArray buffer;
|
2018-01-24 15:22:42 +00:00
|
|
|
int percent = 0;
|
2020-09-13 17:25:51 +01:00
|
|
|
QElapsedTimer timer;
|
2018-01-27 18:54:48 +00:00
|
|
|
|
2020-09-13 17:25:51 +01:00
|
|
|
timer.start();
|
2018-01-27 18:54:48 +00:00
|
|
|
|
2020-10-11 23:46:20 +01:00
|
|
|
QString reportText = xi18nc("@info:progress", "Copying %1 blocks (%2 bytes) from %3 to %4, direction: %5.", blocksToCopy,
|
2018-01-27 18:54:48 +00:00
|
|
|
sourceLength, readOffset, writeOffset, copyDirection == 1 ? i18nc("direction: left", "left")
|
|
|
|
: i18nc("direction: right", "right"));
|
2020-10-11 23:46:20 +01:00
|
|
|
Q_EMIT report(reportText);
|
2018-01-27 18:54:48 +00:00
|
|
|
|
2018-01-24 15:22:42 +00:00
|
|
|
bool rval = true;
|
2018-01-27 18:54:48 +00:00
|
|
|
|
2018-11-25 20:50:22 +00:00
|
|
|
while (blocksCopied < blocksToCopy && !targetDevice.isEmpty()) {
|
2018-02-03 15:57:47 +00:00
|
|
|
if (!(rval = readData(sourceDevice, buffer, readOffset + blockSize * blocksCopied * copyDirection, blockSize)))
|
2018-01-24 15:22:42 +00:00
|
|
|
break;
|
|
|
|
|
2018-02-03 15:57:47 +00:00
|
|
|
if (!(rval = writeData(targetDevice, buffer, writeOffset + blockSize * blocksCopied * copyDirection)))
|
2018-01-24 15:22:42 +00:00
|
|
|
break;
|
2018-01-27 18:54:48 +00:00
|
|
|
|
|
|
|
bytesWritten += buffer.size();
|
2018-01-24 15:22:42 +00:00
|
|
|
|
|
|
|
if (++blocksCopied * 100 / blocksToCopy != percent) {
|
|
|
|
percent = blocksCopied * 100 / blocksToCopy;
|
|
|
|
|
2020-09-13 17:25:51 +01:00
|
|
|
if (percent % 5 == 0 && timer.elapsed() > 1000) {
|
|
|
|
const qint64 mibsPerSec = (blocksCopied * blockSize / 1024 / 1024) / (timer.elapsed() / 1000);
|
|
|
|
const qint64 estSecsLeft = (100 - percent) * timer.elapsed() / percent / 1000;
|
2020-10-11 23:46:20 +01:00
|
|
|
reportText = xi18nc("@info:progress", "Copying %1 MiB/second, estimated time left: %2", mibsPerSec, QTime(0, 0).addSecs(estSecsLeft).toString());
|
|
|
|
Q_EMIT report(reportText);
|
2018-01-27 18:54:48 +00:00
|
|
|
}
|
2020-10-11 23:46:20 +01:00
|
|
|
Q_EMIT progress(percent);
|
2018-01-24 15:22:42 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// copy the remainder
|
|
|
|
if (rval && lastBlock > 0) {
|
|
|
|
Q_ASSERT(lastBlock < blockSize);
|
|
|
|
|
|
|
|
const qint64 lastBlockReadOffset = copyDirection > 0 ? readOffset + blockSize * blocksCopied : sourceFirstByte;
|
|
|
|
const qint64 lastBlockWriteOffset = copyDirection > 0 ? writeOffset + blockSize * blocksCopied : targetFirstByte;
|
2020-10-11 23:46:20 +01:00
|
|
|
reportText = xi18nc("@info:progress", "Copying remainder of block size %1 from %2 to %3.", lastBlock, lastBlockReadOffset, lastBlockWriteOffset);
|
|
|
|
Q_EMIT report(reportText);
|
2018-02-03 15:57:47 +00:00
|
|
|
rval = readData(sourceDevice, buffer, lastBlockReadOffset, lastBlock);
|
2018-01-24 15:22:42 +00:00
|
|
|
|
2018-10-28 17:22:12 +00:00
|
|
|
if (rval) {
|
|
|
|
if (targetDevice.isEmpty())
|
|
|
|
reply[QStringLiteral("targetByteArray")] = buffer;
|
|
|
|
else
|
|
|
|
rval = writeData(targetDevice, buffer, lastBlockWriteOffset);
|
|
|
|
}
|
2018-01-24 15:22:42 +00:00
|
|
|
|
2018-01-27 18:54:48 +00:00
|
|
|
if (rval) {
|
2020-10-11 23:46:20 +01:00
|
|
|
Q_EMIT progress(100);
|
2018-01-27 18:54:48 +00:00
|
|
|
bytesWritten += buffer.size();
|
|
|
|
}
|
2018-01-24 15:22:42 +00:00
|
|
|
}
|
|
|
|
|
2020-10-11 23:46:20 +01:00
|
|
|
reportText = xi18ncp("@info:progress argument 2 is a string such as 7 bytes (localized accordingly)", "Copying 1 block (%2) finished.", "Copying %1 blocks (%2) finished.", blocksCopied, i18np("1 byte", "%1 bytes", bytesWritten));
|
|
|
|
Q_EMIT report(reportText);
|
2018-01-24 15:22:42 +00:00
|
|
|
|
2018-10-28 17:22:12 +00:00
|
|
|
reply[QStringLiteral("success")] = rval;
|
|
|
|
return reply;
|
2018-01-24 15:22:42 +00:00
|
|
|
}
|
2017-11-07 22:55:28 +00:00
|
|
|
|
2020-10-11 22:45:13 +01:00
|
|
|
bool ExternalCommandHelper::WriteData(const QByteArray& buffer, const QString& targetDevice, const qint64 targetFirstByte)
|
2018-11-25 20:50:22 +00:00
|
|
|
{
|
2020-10-08 02:23:24 +01:00
|
|
|
if (!isCallerAuthorized()) {
|
|
|
|
return false;
|
|
|
|
}
|
2018-11-25 20:50:22 +00:00
|
|
|
// Do not allow using this helper for writing to arbitrary location
|
2020-09-10 23:54:23 +01:00
|
|
|
if ( targetDevice.left(5) != QStringLiteral("/dev/") )
|
2018-11-25 20:50:22 +00:00
|
|
|
return false;
|
|
|
|
|
|
|
|
return writeData(targetDevice, buffer, targetFirstByte);
|
|
|
|
}
|
|
|
|
|
2020-10-11 22:45:13 +01:00
|
|
|
QVariantMap ExternalCommandHelper::RunCommand(const QString& command, const QStringList& arguments, const QByteArray& input, const int processChannelMode)
|
2017-11-07 22:55:28 +00:00
|
|
|
{
|
2020-10-08 02:23:24 +01:00
|
|
|
if (!isCallerAuthorized()) {
|
|
|
|
return QVariantMap();
|
|
|
|
}
|
2018-04-13 00:44:12 +01:00
|
|
|
QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8"));
|
2018-03-19 10:33:20 +00:00
|
|
|
QVariantMap reply;
|
2018-07-20 21:12:13 +01:00
|
|
|
reply[QStringLiteral("success")] = true;
|
2018-04-12 22:43:12 +01:00
|
|
|
|
2018-08-16 17:59:47 +01:00
|
|
|
if (command.isEmpty()) {
|
|
|
|
reply[QStringLiteral("success")] = false;
|
|
|
|
return reply;
|
|
|
|
}
|
|
|
|
|
2018-08-11 20:32:02 +01:00
|
|
|
// Compare with command whitelist
|
|
|
|
QString basename = command.mid(command.lastIndexOf(QLatin1Char('/')) + 1);
|
2018-08-24 16:14:49 +01:00
|
|
|
if (std::find(std::begin(allowedCommands), std::end(allowedCommands), basename) == std::end(allowedCommands)) {
|
2019-05-30 18:06:06 +01:00
|
|
|
qInfo() << command <<" command is not one of the whitelisted command";
|
2020-10-08 02:23:24 +01:00
|
|
|
qApp->quit();
|
2018-08-24 16:14:49 +01:00
|
|
|
reply[QStringLiteral("success")] = false;
|
|
|
|
return reply;
|
2018-08-11 20:32:02 +01:00
|
|
|
}
|
|
|
|
|
2019-05-18 19:50:10 +01:00
|
|
|
// connect(&cmd, &QProcess::readyReadStandardOutput, this, &ExternalCommandHelper::onReadOutput);
|
2017-11-07 22:55:28 +00:00
|
|
|
|
2020-11-26 22:05:25 +00:00
|
|
|
QProcess cmd;
|
|
|
|
cmd.setEnvironment( { QStringLiteral("LVM_SUPPRESS_FD_WARNINGS=1") } );
|
|
|
|
cmd.setProcessChannelMode(static_cast<QProcess::ProcessChannelMode>(processChannelMode));
|
|
|
|
cmd.start(command, arguments);
|
|
|
|
cmd.write(input);
|
|
|
|
cmd.closeWriteChannel();
|
|
|
|
cmd.waitForFinished(-1);
|
|
|
|
QByteArray output = cmd.readAllStandardOutput();
|
2018-03-19 10:33:20 +00:00
|
|
|
reply[QStringLiteral("output")] = output;
|
2020-11-26 22:05:25 +00:00
|
|
|
reply[QStringLiteral("exitCode")] = cmd.exitCode();
|
2017-11-07 22:55:28 +00:00
|
|
|
|
|
|
|
return reply;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ExternalCommandHelper::onReadOutput()
|
|
|
|
{
|
2019-05-18 19:50:10 +01:00
|
|
|
/* const QByteArray s = cmd.readAllStandardOutput();
|
2017-11-07 22:55:28 +00:00
|
|
|
|
2019-05-18 19:50:10 +01:00
|
|
|
if(output.length() > 10*1024*1024) { // prevent memory overflow for badly corrupted file systems
|
|
|
|
if (report())
|
|
|
|
report()->line() << xi18nc("@info:status", "(Command is printing too much output)");
|
|
|
|
return;
|
|
|
|
}
|
2017-11-07 22:55:28 +00:00
|
|
|
|
2019-05-18 19:50:10 +01:00
|
|
|
output += s;
|
2017-11-07 22:55:28 +00:00
|
|
|
|
2019-05-18 19:50:10 +01:00
|
|
|
if (report())
|
|
|
|
*report() << QString::fromLocal8Bit(s);*/
|
2017-11-07 22:55:28 +00:00
|
|
|
}
|
|
|
|
|
2020-10-08 02:23:24 +01:00
|
|
|
bool ExternalCommandHelper::isCallerAuthorized()
|
|
|
|
{
|
|
|
|
if (!calledFromDBus()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2020-10-11 22:20:54 +01:00
|
|
|
// Cache successful authentication requests, so that clients don't need
|
|
|
|
// to authenticate multiple times during long partitioning operations.
|
|
|
|
if (m_serviceWatcher->watchedServices().contains(message().service())) {
|
|
|
|
return true;
|
|
|
|
}
|
2020-10-08 02:23:24 +01:00
|
|
|
|
|
|
|
PolkitQt1::SystemBusNameSubject subject(message().service());
|
|
|
|
PolkitQt1::Authority *authority = PolkitQt1::Authority::instance();
|
|
|
|
|
|
|
|
PolkitQt1::Authority::Result result;
|
|
|
|
QEventLoop e;
|
2020-10-11 21:17:09 +01:00
|
|
|
connect(authority, &PolkitQt1::Authority::checkAuthorizationFinished, &e, [&e, &result](PolkitQt1::Authority::Result _result) {
|
2020-10-08 02:23:24 +01:00
|
|
|
result = _result;
|
|
|
|
e.quit();
|
|
|
|
});
|
|
|
|
|
|
|
|
authority->checkAuthorization(QStringLiteral("org.kde.kpmcore.externalcommand.init"), subject, PolkitQt1::Authority::AllowUserInteraction);
|
|
|
|
e.exec();
|
|
|
|
|
|
|
|
if (authority->hasError()) {
|
|
|
|
qDebug() << "Encountered error while checking authorization, error code:" << authority->lastError() << authority->errorDetails();
|
|
|
|
authority->clearError();
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (result) {
|
|
|
|
case PolkitQt1::Authority::Yes:
|
2020-10-11 22:20:54 +01:00
|
|
|
// track who called into us so we can close when all callers have gone away
|
|
|
|
m_serviceWatcher->addWatchedService(message().service());
|
2020-10-08 02:23:24 +01:00
|
|
|
return true;
|
|
|
|
default:
|
|
|
|
sendErrorReply(QDBusError::AccessDenied);
|
2020-10-11 22:20:54 +01:00
|
|
|
if (m_serviceWatcher->watchedServices().isEmpty())
|
|
|
|
qApp->quit();
|
2020-10-08 02:23:24 +01:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int main(int argc, char ** argv)
|
|
|
|
{
|
|
|
|
QCoreApplication app(argc, argv);
|
|
|
|
ExternalCommandHelper helper;
|
|
|
|
app.exec();
|
|
|
|
}
|