Merge branch 'master' into raid-support
This commit is contained in:
commit
83571aa0ef
|
@ -1,5 +1,5 @@
|
||||||
# SPDX-FileCopyrightText: 2020 Andrius Štikonas <andrius@stikonas.eu>
|
# SPDX-FileCopyrightText: none
|
||||||
# SPDX-License-Identifier: MIT
|
# SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
build
|
build
|
||||||
.kdev4/
|
.kdev4/
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
# SPDX-FileCopyrightText: 2008 Volker Lanz <vl@fidra.de>
|
# SPDX-FileCopyrightText: 2008 Volker Lanz <vl@fidra.de>
|
||||||
# SPDX-FileCopyrightText: 2015 Teo Mrnjavac <teo@kde.org>
|
# SPDX-FileCopyrightText: 2015 Teo Mrnjavac <teo@kde.org>
|
||||||
# SPDX-FileCopyrightText: 2014-2020 Andrius Štikonas <andrius@stikonas.eu>
|
# SPDX-FileCopyrightText: 2014-2020 Andrius Štikonas <andrius@stikonas.eu>
|
||||||
|
# SPDX-FileCopyrightText: 2020 David Edmundson <kde@davidedmundson.co.uk>
|
||||||
|
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
@ -39,6 +40,7 @@ include(KDECompilerSettings NO_POLICY_SCOPE)
|
||||||
include(FeatureSummary)
|
include(FeatureSummary)
|
||||||
include(GenerateExportHeader)
|
include(GenerateExportHeader)
|
||||||
include(ECMSetupVersion)
|
include(ECMSetupVersion)
|
||||||
|
include(ECMConfiguredInstall)
|
||||||
|
|
||||||
ecm_setup_version(${VERSION} VARIABLE_PREFIX KPMCORE
|
ecm_setup_version(${VERSION} VARIABLE_PREFIX KPMCORE
|
||||||
VERSION_HEADER "${CMAKE_CURRENT_BINARY_DIR}/kpmcore_version.h"
|
VERSION_HEADER "${CMAKE_CURRENT_BINARY_DIR}/kpmcore_version.h"
|
||||||
|
|
|
@ -37,7 +37,6 @@ target_link_libraries( kpmcore PUBLIC
|
||||||
KF5::I18n
|
KF5::I18n
|
||||||
KF5::CoreAddons
|
KF5::CoreAddons
|
||||||
KF5::WidgetsAddons
|
KF5::WidgetsAddons
|
||||||
KF5::AuthCore
|
|
||||||
)
|
)
|
||||||
|
|
||||||
install(TARGETS kpmcore EXPORT KPMcoreTargets ${INSTALL_TARGETS_DEFAULT_ARGS})
|
install(TARGETS kpmcore EXPORT KPMcoreTargets ${INSTALL_TARGETS_DEFAULT_ARGS})
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#include "util/report.h"
|
#include "util/report.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <array>
|
||||||
|
|
||||||
#if defined(Q_OS_LINUX)
|
#if defined(Q_OS_LINUX)
|
||||||
#include <blkid/blkid.h>
|
#include <blkid/blkid.h>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
SPDX-FileCopyrightText: 2008-2012 Volker Lanz <vl@fidra.de>
|
SPDX-FileCopyrightText: 2008-2012 Volker Lanz <vl@fidra.de>
|
||||||
SPDX-FileCopyrightText: 2009 Andrew Coles <andrew.i.coles@googlemail.com>
|
SPDX-FileCopyrightText: 2009 Andrew Coles <andrew.i.coles@googlemail.com>
|
||||||
SPDX-FileCopyrightText: 2013-2019 Andrius Štikonas <andrius@stikonas.eu>
|
SPDX-FileCopyrightText: 2013-2020 Andrius Štikonas <andrius@stikonas.eu>
|
||||||
SPDX-FileCopyrightText: 2015-2016 Teo Mrnjavac <teo@kde.org>
|
SPDX-FileCopyrightText: 2015-2016 Teo Mrnjavac <teo@kde.org>
|
||||||
SPDX-FileCopyrightText: 2016 Chantara Tith <tith.chantara@gmail.com>
|
SPDX-FileCopyrightText: 2016 Chantara Tith <tith.chantara@gmail.com>
|
||||||
SPDX-FileCopyrightText: 2018 Caio Jordão Carvalho <caiojcarvalho@gmail.com>
|
SPDX-FileCopyrightText: 2018 Caio Jordão Carvalho <caiojcarvalho@gmail.com>
|
||||||
|
@ -439,7 +439,7 @@ void PartitionTable::updateUnallocated(const Device& d)
|
||||||
qint64 PartitionTable::defaultFirstUsable(const Device& d, TableType t)
|
qint64 PartitionTable::defaultFirstUsable(const Device& d, TableType t)
|
||||||
{
|
{
|
||||||
Q_UNUSED(t)
|
Q_UNUSED(t)
|
||||||
if (d.type() == Device::Type::LVM_Device || d.type() == Device::Type::SoftwareRAID_Device) {
|
if (d.type() == Device::Type::LVM_Device || d.type() == Device::Type::SoftwareRAID_Device || t == PartitionTable::TableType::none) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -462,21 +462,21 @@ static struct {
|
||||||
bool isReadOnly; /**< does KDE Partition Manager support this only in read only mode */
|
bool isReadOnly; /**< does KDE Partition Manager support this only in read only mode */
|
||||||
PartitionTable::TableType type; /**< enum type */
|
PartitionTable::TableType type; /**< enum type */
|
||||||
} tableTypes[] = {
|
} tableTypes[] = {
|
||||||
{ QLatin1String("aix"), 4, false, true, PartitionTable::aix },
|
{ QLatin1String("aix"), 4, false, true, PartitionTable::TableType::aix },
|
||||||
{ QLatin1String("bsd"), 8, false, true, PartitionTable::bsd },
|
{ QLatin1String("bsd"), 8, false, true, PartitionTable::TableType::bsd },
|
||||||
{ QLatin1String("dasd"), 1, false, true, PartitionTable::dasd },
|
{ QLatin1String("dasd"), 1, false, true, PartitionTable::TableType::dasd },
|
||||||
{ QLatin1String("msdos"), 4, true, false, PartitionTable::msdos },
|
{ QLatin1String("msdos"), 4, true, false, PartitionTable::TableType::msdos },
|
||||||
{ QLatin1String("msdos"), 4, true, false, PartitionTable::msdos_sectorbased },
|
{ QLatin1String("msdos"), 4, true, false, PartitionTable::TableType::msdos_sectorbased },
|
||||||
{ QLatin1String("dos"), 4, true, false, PartitionTable::msdos_sectorbased },
|
{ QLatin1String("dos"), 4, true, false, PartitionTable::TableType::msdos_sectorbased },
|
||||||
{ QLatin1String("dvh"), 16, true, true, PartitionTable::dvh },
|
{ QLatin1String("dvh"), 16, true, true, PartitionTable::TableType::dvh },
|
||||||
{ QLatin1String("gpt"), 128, false, false, PartitionTable::gpt },
|
{ QLatin1String("gpt"), 128, false, false, PartitionTable::TableType::gpt },
|
||||||
{ QLatin1String("loop"), 1, false, true, PartitionTable::loop },
|
{ QLatin1String("loop"), 1, false, true, PartitionTable::TableType::loop },
|
||||||
{ QLatin1String("mac"), 0xffff, false, true, PartitionTable::mac },
|
{ QLatin1String("mac"), 0xffff, false, true, PartitionTable::TableType::mac },
|
||||||
{ QLatin1String("pc98"), 16, false, true, PartitionTable::pc98 },
|
{ QLatin1String("pc98"), 16, false, true, PartitionTable::TableType::pc98 },
|
||||||
{ QLatin1String("amiga"), 128, false, true, PartitionTable::amiga },
|
{ QLatin1String("amiga"), 128, false, true, PartitionTable::TableType::amiga },
|
||||||
{ QLatin1String("sun"), 8, false, true, PartitionTable::sun },
|
{ QLatin1String("sun"), 8, false, true, PartitionTable::TableType::sun },
|
||||||
{ QLatin1String("vmd"), 0xffff, false, false, PartitionTable::vmd },
|
{ QLatin1String("vmd"), 0xffff, false, false, PartitionTable::TableType::vmd },
|
||||||
{ QLatin1String("none"), 1, false, false, PartitionTable::none },
|
{ QLatin1String("none"), 1, false, false, PartitionTable::TableType::none },
|
||||||
};
|
};
|
||||||
|
|
||||||
PartitionTable::TableType PartitionTable::nameToTableType(const QString& n)
|
PartitionTable::TableType PartitionTable::nameToTableType(const QString& n)
|
||||||
|
@ -485,7 +485,7 @@ PartitionTable::TableType PartitionTable::nameToTableType(const QString& n)
|
||||||
if (n == type.name)
|
if (n == type.name)
|
||||||
return type.type;
|
return type.type;
|
||||||
|
|
||||||
return PartitionTable::unknownTableType;
|
return PartitionTable::TableType::unknownTableType;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString PartitionTable::tableTypeToName(TableType l)
|
QString PartitionTable::tableTypeToName(TableType l)
|
||||||
|
|
|
@ -81,7 +81,7 @@ bool fat16::create(Report& report, const QString& deviceNode)
|
||||||
|
|
||||||
bool fat16::resize(Report& report, const QString& deviceNode, qint64 length) const
|
bool fat16::resize(Report& report, const QString& deviceNode, qint64 length) const
|
||||||
{
|
{
|
||||||
ExternalCommand cmd(report, QStringLiteral("fatresize"), { QStringLiteral("--verbose"), QStringLiteral("--size"), QString::number(length), deviceNode });
|
ExternalCommand cmd(report, QStringLiteral("fatresize"), { QStringLiteral("--verbose"), QStringLiteral("--size"), QString::number(length - 1), deviceNode });
|
||||||
return cmd.run(-1) && cmd.exitCode() == 0;
|
return cmd.run(-1) && cmd.exitCode() == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
namespace FS
|
namespace FS
|
||||||
{
|
{
|
||||||
|
|
||||||
FileSystem::CommandSupportType unknown::m_Move = FileSystem::cmdSupportNone;
|
FileSystem::CommandSupportType unknown::m_Move = FileSystem::cmdSupportCore;
|
||||||
|
|
||||||
unknown::unknown(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label, const QVariantMap& features) :
|
unknown::unknown(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label, const QVariantMap& features) :
|
||||||
FileSystem(firstsector, lastsector, sectorsused, label, features, FileSystem::Type::Unknown)
|
FileSystem(firstsector, lastsector, sectorsused, label, features, FileSystem::Type::Unknown)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
SPDX-FileCopyrightText: 2008-2010 Volker Lanz <vl@fidra.de>
|
SPDX-FileCopyrightText: 2008-2010 Volker Lanz <vl@fidra.de>
|
||||||
SPDX-FileCopyrightText: 2013-2018 Andrius Štikonas <andrius@stikonas.eu>
|
SPDX-FileCopyrightText: 2013-2020 Andrius Štikonas <andrius@stikonas.eu>
|
||||||
SPDX-FileCopyrightText: 2016 Chantara Tith <tith.chantara@gmail.com>
|
SPDX-FileCopyrightText: 2016 Chantara Tith <tith.chantara@gmail.com>
|
||||||
SPDX-FileCopyrightText: 2018 Caio Jordão Carvalho <caiojcarvalho@gmail.com>
|
SPDX-FileCopyrightText: 2018 Caio Jordão Carvalho <caiojcarvalho@gmail.com>
|
||||||
SPDX-FileCopyrightText: 2019 Yuri Chornoivan <yurchor@ukr.net>
|
SPDX-FileCopyrightText: 2019 Yuri Chornoivan <yurchor@ukr.net>
|
||||||
|
@ -40,9 +40,16 @@ bool CreatePartitionJob::run(Report& parent)
|
||||||
Q_ASSERT(partition().devicePath() == device().deviceNode());
|
Q_ASSERT(partition().devicePath() == device().deviceNode());
|
||||||
|
|
||||||
bool rval = false;
|
bool rval = false;
|
||||||
|
|
||||||
Report* report = jobStarted(parent);
|
Report* report = jobStarted(parent);
|
||||||
|
|
||||||
|
if (device().partitionTable()->type() == PartitionTable::TableType::none) {
|
||||||
|
partition().setPartitionPath(device().deviceNode());
|
||||||
|
partition().setState(Partition::State::None);
|
||||||
|
rval = true;
|
||||||
|
jobFinished(*report, rval);
|
||||||
|
return rval;
|
||||||
|
}
|
||||||
|
|
||||||
if (device().type() == Device::Type::Disk_Device || device().type() == Device::Type::SoftwareRAID_Device) {
|
if (device().type() == Device::Type::Disk_Device || device().type() == Device::Type::SoftwareRAID_Device) {
|
||||||
std::unique_ptr<CoreBackendDevice> backendDevice = CoreBackendManager::self()->backend()->openDevice(device());
|
std::unique_ptr<CoreBackendDevice> backendDevice = CoreBackendManager::self()->backend()->openDevice(device());
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
SPDX-FileCopyrightText: 2008-2010 Volker Lanz <vl@fidra.de>
|
SPDX-FileCopyrightText: 2008-2010 Volker Lanz <vl@fidra.de>
|
||||||
SPDX-FileCopyrightText: 2014-2018 Andrius Štikonas <andrius@stikonas.eu>
|
SPDX-FileCopyrightText: 2014-2020 Andrius Štikonas <andrius@stikonas.eu>
|
||||||
SPDX-FileCopyrightText: 2016 Chantara Tith <tith.chantara@gmail.com>
|
SPDX-FileCopyrightText: 2016 Chantara Tith <tith.chantara@gmail.com>
|
||||||
SPDX-FileCopyrightText: 2018 Caio Jordão Carvalho <caiojcarvalho@gmail.com>
|
SPDX-FileCopyrightText: 2018 Caio Jordão Carvalho <caiojcarvalho@gmail.com>
|
||||||
|
|
||||||
|
@ -35,6 +35,9 @@ bool CreatePartitionTableJob::run(Report& parent)
|
||||||
|
|
||||||
Report* report = jobStarted(parent);
|
Report* report = jobStarted(parent);
|
||||||
|
|
||||||
|
if (device().partitionTable()->type() == PartitionTable::TableType::none)
|
||||||
|
return true;
|
||||||
|
|
||||||
if (device().type() == Device::Type::Disk_Device || device().type() == Device::Type::SoftwareRAID_Device) {
|
if (device().type() == Device::Type::Disk_Device || device().type() == Device::Type::SoftwareRAID_Device) {
|
||||||
std::unique_ptr<CoreBackendDevice> backendDevice = CoreBackendManager::self()->backend()->openDevice(device());
|
std::unique_ptr<CoreBackendDevice> backendDevice = CoreBackendManager::self()->backend()->openDevice(device());
|
||||||
|
|
||||||
|
|
|
@ -94,9 +94,9 @@ void Job::emitProgress(int i)
|
||||||
Q_EMIT progress(i);
|
Q_EMIT progress(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Job::updateReport(const QVariantMap& reportString)
|
void Job::updateReport(const QString& report)
|
||||||
{
|
{
|
||||||
m_Report->line() << reportString[QStringLiteral("report")].toString();
|
m_Report->line() << report;
|
||||||
}
|
}
|
||||||
|
|
||||||
Report* Job::jobStarted(Report& parent)
|
Report* Job::jobStarted(Report& parent)
|
||||||
|
|
|
@ -71,7 +71,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
void emitProgress(int i);
|
void emitProgress(int i);
|
||||||
void updateReport(const QVariantMap& reportString);
|
void updateReport(const QString& report);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool copyBlocks(Report& report, CopyTarget& target, CopySource& source);
|
bool copyBlocks(Report& report, CopyTarget& target, CopySource& source);
|
||||||
|
|
|
@ -560,7 +560,7 @@ FileSystem::Type SfdiskBackend::fileSystemNameToType(const QString& name, const
|
||||||
else if (name == QStringLiteral("vfat")) {
|
else if (name == QStringLiteral("vfat")) {
|
||||||
if (version == QStringLiteral("FAT32"))
|
if (version == QStringLiteral("FAT32"))
|
||||||
rval = FileSystem::Type::Fat32;
|
rval = FileSystem::Type::Fat32;
|
||||||
else if (version == QStringLiteral("FAT16"))
|
else if (version == QStringLiteral("FAT16") || version == QStringLiteral("msdos")) // blkid uses msdos for both FAT16 and FAT12
|
||||||
rval = FileSystem::Type::Fat16;
|
rval = FileSystem::Type::Fat16;
|
||||||
else if (version == QStringLiteral("FAT12"))
|
else if (version == QStringLiteral("FAT12"))
|
||||||
rval = FileSystem::Type::Fat12;
|
rval = FileSystem::Type::Fat12;
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
# SPDX-FileCopyrightText: 2018 Huzaifa Faruqui <huzaifafaruqui@gmail.com>
|
# SPDX-FileCopyrightText: 2018 Huzaifa Faruqui <huzaifafaruqui@gmail.com>
|
||||||
# SPDX-FileCopyrightText: 2019 Albert Astals Cid <aacid@kde.org>
|
# SPDX-FileCopyrightText: 2019 Albert Astals Cid <aacid@kde.org>
|
||||||
# SPDX-FileCopyrightText: 2019 Antonio Rojas <arojas@archlinux.org>
|
# SPDX-FileCopyrightText: 2019 Antonio Rojas <arojas@archlinux.org>
|
||||||
|
# SPDX-FileCopyrightText: 2020 David Edmundson <kde@davidedmundson.co.uk>
|
||||||
|
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
@ -23,6 +24,9 @@ qt5_generate_dbus_interface(
|
||||||
OPTIONS -a
|
OPTIONS -a
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
find_package(PolkitQt5-1 REQUIRED)
|
||||||
|
|
||||||
qt5_add_dbus_interface(ApplicationInterface_SRCS ${CMAKE_CURRENT_BINARY_DIR}/${application_interface_xml} externalcommand_interface)
|
qt5_add_dbus_interface(ApplicationInterface_SRCS ${CMAKE_CURRENT_BINARY_DIR}/${application_interface_xml} externalcommand_interface)
|
||||||
qt5_add_dbus_interface(HelperInterface_SRCS ${CMAKE_CURRENT_BINARY_DIR}/${helper_interface_xml} externalcommandhelper_interface)
|
qt5_add_dbus_interface(HelperInterface_SRCS ${CMAKE_CURRENT_BINARY_DIR}/${helper_interface_xml} externalcommandhelper_interface)
|
||||||
|
|
||||||
|
@ -65,12 +69,16 @@ target_link_libraries(kpmcore_externalcommand
|
||||||
Qt5::DBus
|
Qt5::DBus
|
||||||
KF5::AuthCore
|
KF5::AuthCore
|
||||||
KF5::I18n
|
KF5::I18n
|
||||||
|
PolkitQt5-1::Core
|
||||||
)
|
)
|
||||||
|
|
||||||
install(TARGETS kpmcore_mdadmupdateconf DESTINATION ${LIBEXEC_INSTALL_DIR})
|
install(TARGETS kpmcore_mdadmupdateconf DESTINATION ${LIBEXEC_INSTALL_DIR})
|
||||||
install(TARGETS kpmcore_externalcommand DESTINATION ${KAUTH_HELPER_INSTALL_DIR})
|
install(TARGETS kpmcore_externalcommand DESTINATION ${KDE_INSTALL_LIBEXECDIR})
|
||||||
install( FILES util/org.kde.kpmcore.helperinterface.conf DESTINATION ${KDE_INSTALL_DBUSDIR}/system.d )
|
install( FILES util/org.kde.kpmcore.helperinterface.conf DESTINATION ${KDE_INSTALL_DBUSDIR}/system.d )
|
||||||
install( FILES util/org.kde.kpmcore.applicationinterface.conf DESTINATION ${KDE_INSTALL_DBUSDIR}/system.d )
|
install( FILES util/org.kde.kpmcore.applicationinterface.conf DESTINATION ${KDE_INSTALL_DBUSDIR}/system.d )
|
||||||
|
|
||||||
kauth_install_helper_files(kpmcore_externalcommand org.kde.kpmcore.externalcommand root)
|
|
||||||
kauth_install_actions(org.kde.kpmcore.externalcommand util/org.kde.kpmcore.externalcommand.actions)
|
kauth_install_actions(org.kde.kpmcore.externalcommand util/org.kde.kpmcore.externalcommand.actions)
|
||||||
|
ecm_install_configured_files(
|
||||||
|
INPUT util/org.kde.kpmcore.helperinterface.service.in
|
||||||
|
DESTINATION ${KDE_INSTALL_DBUSDIR}/system-services
|
||||||
|
)
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
SPDX-FileCopyrightText: 2018 Caio Jordão Carvalho <caiojcarvalho@gmail.com>
|
SPDX-FileCopyrightText: 2018 Caio Jordão Carvalho <caiojcarvalho@gmail.com>
|
||||||
SPDX-FileCopyrightText: 2019 Shubham Jangra <aryan100jangid@gmail.com>
|
SPDX-FileCopyrightText: 2019 Shubham Jangra <aryan100jangid@gmail.com>
|
||||||
SPDX-FileCopyrightText: 2019 Yuri Chornoivan <yurchor@ukr.net>
|
SPDX-FileCopyrightText: 2019 Yuri Chornoivan <yurchor@ukr.net>
|
||||||
|
SPDX-FileCopyrightText: 2020 David Edmundson <kde@davidedmundson.co.uk>
|
||||||
|
|
||||||
SPDX-License-Identifier: GPL-3.0-or-later
|
SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
*/
|
*/
|
||||||
|
@ -36,8 +37,6 @@
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
#include <QThread>
|
#include <QThread>
|
||||||
#include <QVariant>
|
#include <QVariant>
|
||||||
|
|
||||||
#include <KAuth>
|
|
||||||
#include <KJob>
|
#include <KJob>
|
||||||
#include <KLocalizedString>
|
#include <KLocalizedString>
|
||||||
|
|
||||||
|
@ -49,15 +48,9 @@ struct ExternalCommandPrivate
|
||||||
int m_ExitCode;
|
int m_ExitCode;
|
||||||
QByteArray m_Output;
|
QByteArray m_Output;
|
||||||
QByteArray m_Input;
|
QByteArray m_Input;
|
||||||
DBusThread *m_thread;
|
|
||||||
QProcess::ProcessChannelMode processChannelMode;
|
QProcess::ProcessChannelMode processChannelMode;
|
||||||
};
|
};
|
||||||
|
|
||||||
KAuth::ExecuteJob* ExternalCommand::m_job;
|
|
||||||
bool ExternalCommand::helperStarted = false;
|
|
||||||
QWidget* ExternalCommand::parent;
|
|
||||||
|
|
||||||
|
|
||||||
/** Creates a new ExternalCommand instance without Report.
|
/** Creates a new ExternalCommand instance without Report.
|
||||||
@param cmd the command to run
|
@param cmd the command to run
|
||||||
@param args the arguments to pass to the command
|
@param args the arguments to pass to the command
|
||||||
|
@ -70,11 +63,6 @@ ExternalCommand::ExternalCommand(const QString& cmd, const QStringList& args, co
|
||||||
d->m_Args = args;
|
d->m_Args = args;
|
||||||
d->m_ExitCode = -1;
|
d->m_ExitCode = -1;
|
||||||
d->m_Output = QByteArray();
|
d->m_Output = QByteArray();
|
||||||
|
|
||||||
if (!helperStarted)
|
|
||||||
if(!startHelper())
|
|
||||||
Log(Log::Level::error) << xi18nc("@info:status", "Could not obtain administrator privileges.");
|
|
||||||
|
|
||||||
d->processChannelMode = processChannelMode;
|
d->processChannelMode = processChannelMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,7 +123,7 @@ bool ExternalCommand::start(int timeout)
|
||||||
|
|
||||||
bool rval = false;
|
bool rval = false;
|
||||||
|
|
||||||
QDBusPendingCall pcall = interface->start(cmd, args(), d->m_Input, d->processChannelMode);
|
QDBusPendingCall pcall = interface->RunCommand(cmd, args(), d->m_Input, d->processChannelMode);
|
||||||
|
|
||||||
QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pcall, this);
|
QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pcall, this);
|
||||||
QEventLoop loop;
|
QEventLoop loop;
|
||||||
|
@ -165,15 +153,14 @@ bool ExternalCommand::copyBlocks(const CopySource& source, CopyTarget& target)
|
||||||
bool rval = true;
|
bool rval = true;
|
||||||
const qint64 blockSize = 10 * 1024 * 1024; // number of bytes per block to copy
|
const qint64 blockSize = 10 * 1024 * 1024; // number of bytes per block to copy
|
||||||
|
|
||||||
// TODO KF6:Use new signal-slot syntax
|
|
||||||
connect(m_job, SIGNAL(percent(KJob*, unsigned long)), this, SLOT(emitProgress(KJob*, unsigned long)));
|
|
||||||
connect(m_job, &KAuth::ExecuteJob::newData, this, &ExternalCommand::emitReport);
|
|
||||||
|
|
||||||
auto interface = helperInterface();
|
auto interface = helperInterface();
|
||||||
if (!interface)
|
if (!interface)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
QDBusPendingCall pcall = interface->copyblocks(source.path(), source.firstByte(), source.length(),
|
connect(interface, &OrgKdeKpmcoreExternalcommandInterface::progress, this, &ExternalCommand::progress);
|
||||||
|
connect(interface, &OrgKdeKpmcoreExternalcommandInterface::report, this, &ExternalCommand::reportSignal);
|
||||||
|
|
||||||
|
QDBusPendingCall pcall = interface->CopyBlocks(source.path(), source.firstByte(), source.length(),
|
||||||
target.path(), target.firstByte(), blockSize);
|
target.path(), target.firstByte(), blockSize);
|
||||||
|
|
||||||
QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pcall, this);
|
QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pcall, this);
|
||||||
|
@ -210,17 +197,17 @@ bool ExternalCommand::writeData(Report& commandReport, const QByteArray& buffer,
|
||||||
if (!interface)
|
if (!interface)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
QDBusPendingCall pcall = interface->writeData(buffer, deviceNode, firstByte);
|
QDBusPendingCall pcall = interface->WriteData(buffer, deviceNode, firstByte);
|
||||||
return waitForDbusReply(pcall);
|
return waitForDbusReply(pcall);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ExternalCommand::createFile(const QByteArray& buffer, const QString& deviceNode)
|
bool ExternalCommand::createFile(const QByteArray& fileContents, const QString& filePath)
|
||||||
{
|
{
|
||||||
auto interface = helperInterface();
|
auto interface = helperInterface();
|
||||||
if (!interface)
|
if (!interface)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
QDBusPendingCall pcall = interface->createFile(buffer, deviceNode);
|
QDBusPendingCall pcall = interface->CreateFile(filePath, fileContents);
|
||||||
return waitForDbusReply(pcall);
|
return waitForDbusReply(pcall);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -231,7 +218,7 @@ OrgKdeKpmcoreExternalcommandInterface* ExternalCommand::helperInterface()
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto *interface = new org::kde::kpmcore::externalcommand(QStringLiteral("org.kde.kpmcore.externalcommand"),
|
auto *interface = new org::kde::kpmcore::externalcommand(QStringLiteral("org.kde.kpmcore.helperinterface"),
|
||||||
QStringLiteral("/Helper"), QDBusConnection::systemBus(), this);
|
QStringLiteral("/Helper"), QDBusConnection::systemBus(), this);
|
||||||
interface->setTimeout(10 * 24 * 3600 * 1000); // 10 days
|
interface->setTimeout(10 * 24 * 3600 * 1000); // 10 days
|
||||||
return interface;
|
return interface;
|
||||||
|
@ -342,59 +329,3 @@ void ExternalCommand::setExitCode(int i)
|
||||||
{
|
{
|
||||||
d->m_ExitCode = i;
|
d->m_ExitCode = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ExternalCommand::startHelper()
|
|
||||||
{
|
|
||||||
if (!QDBusConnection::systemBus().isConnected()) {
|
|
||||||
qWarning() << QDBusConnection::systemBus().lastError().message();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
QDBusInterface iface(QStringLiteral("org.kde.kpmcore.helperinterface"), QStringLiteral("/Helper"), QStringLiteral("org.kde.kpmcore.externalcommand"), QDBusConnection::systemBus());
|
|
||||||
if (iface.isValid()) {
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
d->m_thread = new DBusThread;
|
|
||||||
d->m_thread->start();
|
|
||||||
|
|
||||||
KAuth::Action action = KAuth::Action(QStringLiteral("org.kde.kpmcore.externalcommand.init"));
|
|
||||||
action.setHelperId(QStringLiteral("org.kde.kpmcore.externalcommand"));
|
|
||||||
action.setTimeout(10 * 24 * 3600 * 1000); // 10 days
|
|
||||||
action.setParentWidget(parent);
|
|
||||||
QVariantMap arguments;
|
|
||||||
action.setArguments(arguments);
|
|
||||||
m_job = action.execute();
|
|
||||||
m_job->start();
|
|
||||||
|
|
||||||
// Wait until ExternalCommand Helper is ready (helper sends newData signal just before it enters event loop)
|
|
||||||
QEventLoop loop;
|
|
||||||
auto exitLoop = [&] () { loop.exit(); };
|
|
||||||
auto conn = QObject::connect(m_job, &KAuth::ExecuteJob::newData, exitLoop);
|
|
||||||
QObject::connect(m_job, &KJob::finished, [=] () { if(m_job->error()) exitLoop(); } );
|
|
||||||
loop.exec();
|
|
||||||
QObject::disconnect(conn);
|
|
||||||
|
|
||||||
helperStarted = true;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ExternalCommand::stopHelper()
|
|
||||||
{
|
|
||||||
auto *interface = new org::kde::kpmcore::externalcommand(QStringLiteral("org.kde.kpmcore.externalcommand"),
|
|
||||||
QStringLiteral("/Helper"), QDBusConnection::systemBus());
|
|
||||||
interface->exit();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void DBusThread::run()
|
|
||||||
{
|
|
||||||
if (!QDBusConnection::systemBus().registerService(QStringLiteral("org.kde.kpmcore.applicationinterface")) ||
|
|
||||||
!QDBusConnection::systemBus().registerObject(QStringLiteral("/Application"), this, QDBusConnection::ExportAllSlots)) {
|
|
||||||
qWarning() << QDBusConnection::systemBus().lastError().message();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QEventLoop loop;
|
|
||||||
loop.exec();
|
|
||||||
}
|
|
||||||
|
|
|
@ -24,8 +24,6 @@
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
namespace KAuth { class ExecuteJob; }
|
|
||||||
|
|
||||||
class KJob;
|
class KJob;
|
||||||
class Report;
|
class Report;
|
||||||
class CopySource;
|
class CopySource;
|
||||||
|
@ -36,15 +34,6 @@ class OrgKdeKpmcoreExternalcommandInterface;
|
||||||
|
|
||||||
struct ExternalCommandPrivate;
|
struct ExternalCommandPrivate;
|
||||||
|
|
||||||
class DBusThread : public QThread
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
// We register on DBus so the helper can monitor us and terminate if we
|
|
||||||
// terminate.
|
|
||||||
Q_CLASSINFO("D-Bus Interface", "org.kde.kpmcore.applicationinterface")
|
|
||||||
void run() override;
|
|
||||||
};
|
|
||||||
|
|
||||||
/** An external command.
|
/** An external command.
|
||||||
|
|
||||||
Runs an external command as a child process.
|
Runs an external command as a child process.
|
||||||
|
@ -66,7 +55,7 @@ public:
|
||||||
public:
|
public:
|
||||||
bool copyBlocks(const CopySource& source, CopyTarget& target);
|
bool copyBlocks(const CopySource& source, CopyTarget& target);
|
||||||
bool writeData(Report& commandReport, const QByteArray& buffer, const QString& deviceNode, const quint64 firstByte); // same as copyBlocks but from QByteArray
|
bool writeData(Report& commandReport, const QByteArray& buffer, const QString& deviceNode, const quint64 firstByte); // same as copyBlocks but from QByteArray
|
||||||
bool createFile(const QByteArray& buffer, const QString& deviceNode); // similar to writeData but creates a new file
|
bool createFile(const QByteArray& filePath, const QString& fileContents); // similar to writeData but creates a new file
|
||||||
|
|
||||||
/**< @param cmd the command to run */
|
/**< @param cmd the command to run */
|
||||||
void setCommand(const QString& cmd);
|
void setCommand(const QString& cmd);
|
||||||
|
@ -98,28 +87,9 @@ public:
|
||||||
/**< @return pointer to the Report or nullptr */
|
/**< @return pointer to the Report or nullptr */
|
||||||
Report* report();
|
Report* report();
|
||||||
|
|
||||||
void emitReport(const QVariantMap& report) { Q_EMIT reportSignal(report); }
|
|
||||||
|
|
||||||
// KAuth
|
|
||||||
/**< start ExternalCommand Helper */
|
|
||||||
bool startHelper();
|
|
||||||
|
|
||||||
/**< stop ExternalCommand Helper */
|
|
||||||
static void stopHelper();
|
|
||||||
|
|
||||||
/**< Sets a parent widget for the authentication dialog.
|
|
||||||
* @param p parent widget
|
|
||||||
*/
|
|
||||||
static void setParentWidget(QWidget *p) {
|
|
||||||
parent = p;
|
|
||||||
}
|
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void progress(int);
|
void progress(int);
|
||||||
void reportSignal(const QVariantMap&);
|
void reportSignal(const QString&);
|
||||||
|
|
||||||
public Q_SLOTS:
|
|
||||||
void emitProgress(KJob*, unsigned long percent) { Q_EMIT progress(percent); }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void setExitCode(int i);
|
void setExitCode(int i);
|
||||||
|
@ -130,10 +100,6 @@ private:
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<ExternalCommandPrivate> d;
|
std::unique_ptr<ExternalCommandPrivate> d;
|
||||||
|
|
||||||
// KAuth
|
|
||||||
static KAuth::ExecuteJob *m_job;
|
|
||||||
static bool helperStarted;
|
|
||||||
static QWidget *parent;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
SPDX-FileCopyrightText: 2018-2019 Harald Sitter <sitter@kde.org>
|
SPDX-FileCopyrightText: 2018-2019 Harald Sitter <sitter@kde.org>
|
||||||
SPDX-FileCopyrightText: 2018 Simon Depiets <sdepiets@gmail.com>
|
SPDX-FileCopyrightText: 2018 Simon Depiets <sdepiets@gmail.com>
|
||||||
SPDX-FileCopyrightText: 2019 Shubham Jangra <aryan100jangid@gmail.com>
|
SPDX-FileCopyrightText: 2019 Shubham Jangra <aryan100jangid@gmail.com>
|
||||||
|
SPDX-FileCopyrightText: 2020 David Edmundson <kde@davidedmundson.co.uk>
|
||||||
|
|
||||||
SPDX-License-Identifier: GPL-3.0-or-later
|
SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
*/
|
*/
|
||||||
|
@ -13,6 +14,7 @@
|
||||||
#include "externalcommand_whitelist.h"
|
#include "externalcommand_whitelist.h"
|
||||||
|
|
||||||
#include <QtDBus>
|
#include <QtDBus>
|
||||||
|
|
||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QElapsedTimer>
|
#include <QElapsedTimer>
|
||||||
|
@ -21,66 +23,45 @@
|
||||||
#include <QVariant>
|
#include <QVariant>
|
||||||
|
|
||||||
#include <KLocalizedString>
|
#include <KLocalizedString>
|
||||||
|
#include <PolkitQt1/Authority>
|
||||||
|
#include <PolkitQt1/Subject>
|
||||||
|
|
||||||
|
#include <polkitqt1-version.h>
|
||||||
|
|
||||||
/** Initialize ExternalCommandHelper Daemon and prepare DBus interface
|
/** Initialize ExternalCommandHelper Daemon and prepare DBus interface
|
||||||
*
|
*
|
||||||
* KAuth helper runs in the background until application exits.
|
* This helper runs in the background until all applications using it exit.
|
||||||
* To avoid forever running helper in case of application crash
|
|
||||||
* ExternalCommand class opens a DBus service that we monitor for changes.
|
|
||||||
* If helper is not busy then it exits when the client services gets
|
* If helper is not busy then it exits when the client services gets
|
||||||
* unregistered. Otherwise,
|
* unregistered. In case the client crashes, the helper waits
|
||||||
* we wait for the current job to finish before exiting, so even in case
|
* for the current job to finish before exiting, to avoid leaving partially moved data.
|
||||||
* of main application crash, we do not leave partially moved data.
|
|
||||||
*
|
*
|
||||||
* This helper also starts another DBus interface where it listens to
|
* This helper starts DBus interface where it listens to command execution requests.
|
||||||
* command execution requests from the application that started the helper.
|
* New clients connecting to the helper have to authenticate using Polkit.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
ActionReply ExternalCommandHelper::init(const QVariantMap& args)
|
|
||||||
|
ExternalCommandHelper::ExternalCommandHelper()
|
||||||
{
|
{
|
||||||
Q_UNUSED(args)
|
if (!QDBusConnection::systemBus().registerObject(QStringLiteral("/Helper"), this, QDBusConnection::ExportAllSlots | QDBusConnection::ExportAllSignals)) {
|
||||||
|
::exit(-1);
|
||||||
ActionReply reply;
|
|
||||||
|
|
||||||
if (!QDBusConnection::systemBus().isConnected() || !QDBusConnection::systemBus().registerService(QStringLiteral("org.kde.kpmcore.helperinterface")) ||
|
|
||||||
!QDBusConnection::systemBus().registerObject(QStringLiteral("/Helper"), this, QDBusConnection::ExportAllSlots)) {
|
|
||||||
qWarning() << QDBusConnection::systemBus().lastError().message();
|
|
||||||
reply.addData(QStringLiteral("success"), false);
|
|
||||||
|
|
||||||
// Also end the application loop started by KAuth's main() code. Our loop
|
|
||||||
// exits when our client disappears. Without client we have no reason to
|
|
||||||
// live.
|
|
||||||
qApp->quit();
|
|
||||||
|
|
||||||
return reply;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
m_loop = std::make_unique<QEventLoop>();
|
|
||||||
HelperSupport::progressStep(QVariantMap());
|
|
||||||
|
|
||||||
// End the loop and return only once the client is done using us.
|
if (!QDBusConnection::systemBus().registerService(QStringLiteral("org.kde.kpmcore.helperinterface"))) {
|
||||||
auto serviceWatcher =
|
::exit(-1);
|
||||||
new QDBusServiceWatcher(QStringLiteral("org.kde.kpmcore.applicationinterface"),
|
}
|
||||||
QDBusConnection::systemBus(),
|
|
||||||
QDBusServiceWatcher::WatchForUnregistration,
|
// we know this service must be registered already as DBus policy blocks calls from anyone else
|
||||||
this);
|
m_serviceWatcher = new QDBusServiceWatcher(this);
|
||||||
connect(serviceWatcher, &QDBusServiceWatcher::serviceUnregistered,
|
m_serviceWatcher->setConnection(QDBusConnection ::systemBus());
|
||||||
[this]() {
|
m_serviceWatcher->setWatchMode(QDBusServiceWatcher::WatchForUnregistration);
|
||||||
m_loop->exit();
|
|
||||||
|
connect(m_serviceWatcher, &QDBusServiceWatcher::serviceUnregistered, qApp, [this](const QString &service) {
|
||||||
|
m_serviceWatcher->removeWatchedService(service);
|
||||||
|
if (m_serviceWatcher->watchedServices().isEmpty()) {
|
||||||
|
qApp->quit();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
m_loop->exec();
|
|
||||||
reply.addData(QStringLiteral("success"), true);
|
|
||||||
|
|
||||||
// Also end the application loop started by KAuth's main() code. Our loop
|
|
||||||
// exits when our client disappears. Without client we have no reason to
|
|
||||||
// live.
|
|
||||||
qApp->quit();
|
|
||||||
|
|
||||||
return reply;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** Reads the given number of bytes from the sourceDevice into the given buffer.
|
/** Reads the given number of bytes from the sourceDevice into the given buffer.
|
||||||
@param sourceDevice device or file to read from
|
@param sourceDevice device or file to read from
|
||||||
@param buffer buffer to store the bytes read in
|
@param buffer buffer to store the bytes read in
|
||||||
|
@ -146,8 +127,15 @@ bool ExternalCommandHelper::writeData(const QString &targetDevice, const QByteAr
|
||||||
@param fileContents the data that we write
|
@param fileContents the data that we write
|
||||||
@return true on success
|
@return true on success
|
||||||
*/
|
*/
|
||||||
bool ExternalCommandHelper::createFile(const QString &filePath, const QByteArray& fileContents)
|
bool ExternalCommandHelper::CreateFile(const QString &filePath, const QByteArray& fileContents)
|
||||||
{
|
{
|
||||||
|
if (!isCallerAuthorized()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Do not allow using this helper for writing to arbitrary location
|
||||||
|
if ( !filePath.contains(QStringLiteral("/etc/fstab")) )
|
||||||
|
return false;
|
||||||
|
|
||||||
QFile device(filePath);
|
QFile device(filePath);
|
||||||
|
|
||||||
auto flags = QIODevice::WriteOnly | QIODevice::Unbuffered;
|
auto flags = QIODevice::WriteOnly | QIODevice::Unbuffered;
|
||||||
|
@ -165,8 +153,11 @@ bool ExternalCommandHelper::createFile(const QString &filePath, const QByteArray
|
||||||
}
|
}
|
||||||
|
|
||||||
// If targetDevice is empty then return QByteArray with data that was read from disk.
|
// If targetDevice is empty then return QByteArray with data that was read from disk.
|
||||||
QVariantMap ExternalCommandHelper::copyblocks(const QString& sourceDevice, const qint64 sourceFirstByte, const qint64 sourceLength, const QString& targetDevice, const qint64 targetFirstByte, const qint64 blockSize)
|
QVariantMap ExternalCommandHelper::CopyBlocks(const QString& sourceDevice, const qint64 sourceFirstByte, const qint64 sourceLength, const QString& targetDevice, const qint64 targetFirstByte, const qint64 blockSize)
|
||||||
{
|
{
|
||||||
|
if (!isCallerAuthorized()) {
|
||||||
|
return QVariantMap();
|
||||||
|
}
|
||||||
QVariantMap reply;
|
QVariantMap reply;
|
||||||
reply[QStringLiteral("success")] = true;
|
reply[QStringLiteral("success")] = true;
|
||||||
|
|
||||||
|
@ -192,13 +183,10 @@ QVariantMap ExternalCommandHelper::copyblocks(const QString& sourceDevice, const
|
||||||
|
|
||||||
timer.start();
|
timer.start();
|
||||||
|
|
||||||
QVariantMap report;
|
QString reportText = xi18nc("@info:progress", "Copying %1 blocks (%2 bytes) from %3 to %4, direction: %5.", blocksToCopy,
|
||||||
|
|
||||||
report[QStringLiteral("report")] = xi18nc("@info:progress", "Copying %1 blocks (%2 bytes) from %3 to %4, direction: %5.", blocksToCopy,
|
|
||||||
sourceLength, readOffset, writeOffset, copyDirection == 1 ? i18nc("direction: left", "left")
|
sourceLength, readOffset, writeOffset, copyDirection == 1 ? i18nc("direction: left", "left")
|
||||||
: i18nc("direction: right", "right"));
|
: i18nc("direction: right", "right"));
|
||||||
|
Q_EMIT report(reportText);
|
||||||
HelperSupport::progressStep(report);
|
|
||||||
|
|
||||||
bool rval = true;
|
bool rval = true;
|
||||||
|
|
||||||
|
@ -217,10 +205,10 @@ QVariantMap ExternalCommandHelper::copyblocks(const QString& sourceDevice, const
|
||||||
if (percent % 5 == 0 && timer.elapsed() > 1000) {
|
if (percent % 5 == 0 && timer.elapsed() > 1000) {
|
||||||
const qint64 mibsPerSec = (blocksCopied * blockSize / 1024 / 1024) / (timer.elapsed() / 1000);
|
const qint64 mibsPerSec = (blocksCopied * blockSize / 1024 / 1024) / (timer.elapsed() / 1000);
|
||||||
const qint64 estSecsLeft = (100 - percent) * timer.elapsed() / percent / 1000;
|
const qint64 estSecsLeft = (100 - percent) * timer.elapsed() / percent / 1000;
|
||||||
report[QStringLiteral("report")]= xi18nc("@info:progress", "Copying %1 MiB/second, estimated time left: %2", mibsPerSec, QTime(0, 0).addSecs(estSecsLeft).toString());
|
reportText = xi18nc("@info:progress", "Copying %1 MiB/second, estimated time left: %2", mibsPerSec, QTime(0, 0).addSecs(estSecsLeft).toString());
|
||||||
HelperSupport::progressStep(report);
|
Q_EMIT report(reportText);
|
||||||
}
|
}
|
||||||
HelperSupport::progressStep(percent);
|
Q_EMIT progress(percent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -230,8 +218,8 @@ QVariantMap ExternalCommandHelper::copyblocks(const QString& sourceDevice, const
|
||||||
|
|
||||||
const qint64 lastBlockReadOffset = copyDirection > 0 ? readOffset + blockSize * blocksCopied : sourceFirstByte;
|
const qint64 lastBlockReadOffset = copyDirection > 0 ? readOffset + blockSize * blocksCopied : sourceFirstByte;
|
||||||
const qint64 lastBlockWriteOffset = copyDirection > 0 ? writeOffset + blockSize * blocksCopied : targetFirstByte;
|
const qint64 lastBlockWriteOffset = copyDirection > 0 ? writeOffset + blockSize * blocksCopied : targetFirstByte;
|
||||||
report[QStringLiteral("report")]= xi18nc("@info:progress", "Copying remainder of block size %1 from %2 to %3.", lastBlock, lastBlockReadOffset, lastBlockWriteOffset);
|
reportText = xi18nc("@info:progress", "Copying remainder of block size %1 from %2 to %3.", lastBlock, lastBlockReadOffset, lastBlockWriteOffset);
|
||||||
HelperSupport::progressStep(report);
|
Q_EMIT report(reportText);
|
||||||
rval = readData(sourceDevice, buffer, lastBlockReadOffset, lastBlock);
|
rval = readData(sourceDevice, buffer, lastBlockReadOffset, lastBlock);
|
||||||
|
|
||||||
if (rval) {
|
if (rval) {
|
||||||
|
@ -242,20 +230,23 @@ QVariantMap ExternalCommandHelper::copyblocks(const QString& sourceDevice, const
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rval) {
|
if (rval) {
|
||||||
HelperSupport::progressStep(100);
|
Q_EMIT progress(100);
|
||||||
bytesWritten += buffer.size();
|
bytesWritten += buffer.size();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
report[QStringLiteral("report")] = 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));
|
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));
|
||||||
HelperSupport::progressStep(report);
|
Q_EMIT report(reportText);
|
||||||
|
|
||||||
reply[QStringLiteral("success")] = rval;
|
reply[QStringLiteral("success")] = rval;
|
||||||
return reply;
|
return reply;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ExternalCommandHelper::writeData(const QByteArray& buffer, const QString& targetDevice, const qint64 targetFirstByte)
|
bool ExternalCommandHelper::WriteData(const QByteArray& buffer, const QString& targetDevice, const qint64 targetFirstByte)
|
||||||
{
|
{
|
||||||
|
if (!isCallerAuthorized()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
// Do not allow using this helper for writing to arbitrary location
|
// Do not allow using this helper for writing to arbitrary location
|
||||||
if ( targetDevice.left(5) != QStringLiteral("/dev/") )
|
if ( targetDevice.left(5) != QStringLiteral("/dev/") )
|
||||||
return false;
|
return false;
|
||||||
|
@ -263,17 +254,11 @@ bool ExternalCommandHelper::writeData(const QByteArray& buffer, const QString& t
|
||||||
return writeData(targetDevice, buffer, targetFirstByte);
|
return writeData(targetDevice, buffer, targetFirstByte);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ExternalCommandHelper::createFile(const QByteArray& fileContents, const QString& filePath)
|
QVariantMap ExternalCommandHelper::RunCommand(const QString& command, const QStringList& arguments, const QByteArray& input, const int processChannelMode)
|
||||||
{
|
|
||||||
// Do not allow using this helper for writing to arbitrary location
|
|
||||||
if ( !filePath.contains(QStringLiteral("/etc/fstab")) )
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return createFile(filePath, fileContents);
|
|
||||||
}
|
|
||||||
|
|
||||||
QVariantMap ExternalCommandHelper::start(const QString& command, const QStringList& arguments, const QByteArray& input, const int processChannelMode)
|
|
||||||
{
|
{
|
||||||
|
if (!isCallerAuthorized()) {
|
||||||
|
return QVariantMap();
|
||||||
|
}
|
||||||
QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8"));
|
QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8"));
|
||||||
QVariantMap reply;
|
QVariantMap reply;
|
||||||
reply[QStringLiteral("success")] = true;
|
reply[QStringLiteral("success")] = true;
|
||||||
|
@ -287,7 +272,7 @@ QVariantMap ExternalCommandHelper::start(const QString& command, const QStringLi
|
||||||
QString basename = command.mid(command.lastIndexOf(QLatin1Char('/')) + 1);
|
QString basename = command.mid(command.lastIndexOf(QLatin1Char('/')) + 1);
|
||||||
if (std::find(std::begin(allowedCommands), std::end(allowedCommands), basename) == std::end(allowedCommands)) {
|
if (std::find(std::begin(allowedCommands), std::end(allowedCommands), basename) == std::end(allowedCommands)) {
|
||||||
qInfo() << command <<" command is not one of the whitelisted command";
|
qInfo() << command <<" command is not one of the whitelisted command";
|
||||||
m_loop->exit();
|
qApp->quit();
|
||||||
reply[QStringLiteral("success")] = false;
|
reply[QStringLiteral("success")] = false;
|
||||||
return reply;
|
return reply;
|
||||||
}
|
}
|
||||||
|
@ -307,14 +292,6 @@ QVariantMap ExternalCommandHelper::start(const QString& command, const QStringLi
|
||||||
return reply;
|
return reply;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExternalCommandHelper::exit()
|
|
||||||
{
|
|
||||||
m_loop->exit();
|
|
||||||
|
|
||||||
QDBusConnection::systemBus().unregisterObject(QStringLiteral("/Helper"));
|
|
||||||
QDBusConnection::systemBus().unregisterService(QStringLiteral("org.kde.kpmcore.helperinterface"));
|
|
||||||
}
|
|
||||||
|
|
||||||
void ExternalCommandHelper::onReadOutput()
|
void ExternalCommandHelper::onReadOutput()
|
||||||
{
|
{
|
||||||
/* const QByteArray s = cmd.readAllStandardOutput();
|
/* const QByteArray s = cmd.readAllStandardOutput();
|
||||||
|
@ -331,4 +308,52 @@ void ExternalCommandHelper::onReadOutput()
|
||||||
*report() << QString::fromLocal8Bit(s);*/
|
*report() << QString::fromLocal8Bit(s);*/
|
||||||
}
|
}
|
||||||
|
|
||||||
KAUTH_HELPER_MAIN("org.kde.kpmcore.externalcommand", ExternalCommandHelper)
|
bool ExternalCommandHelper::isCallerAuthorized()
|
||||||
|
{
|
||||||
|
if (!calledFromDBus()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
PolkitQt1::SystemBusNameSubject subject(message().service());
|
||||||
|
PolkitQt1::Authority *authority = PolkitQt1::Authority::instance();
|
||||||
|
|
||||||
|
PolkitQt1::Authority::Result result;
|
||||||
|
QEventLoop e;
|
||||||
|
connect(authority, &PolkitQt1::Authority::checkAuthorizationFinished, &e, [&e, &result](PolkitQt1::Authority::Result _result) {
|
||||||
|
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:
|
||||||
|
// track who called into us so we can close when all callers have gone away
|
||||||
|
m_serviceWatcher->addWatchedService(message().service());
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
sendErrorReply(QDBusError::AccessDenied);
|
||||||
|
if (m_serviceWatcher->watchedServices().isEmpty())
|
||||||
|
qApp->quit();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char ** argv)
|
||||||
|
{
|
||||||
|
QCoreApplication app(argc, argv);
|
||||||
|
ExternalCommandHelper helper;
|
||||||
|
app.exec();
|
||||||
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
SPDX-FileCopyrightText: 2018 Huzaifa Faruqui <huzaifafaruqui@gmail.com>
|
SPDX-FileCopyrightText: 2018 Huzaifa Faruqui <huzaifafaruqui@gmail.com>
|
||||||
SPDX-FileCopyrightText: 2018 Caio Jordão Carvalho <caiojcarvalho@gmail.com>
|
SPDX-FileCopyrightText: 2018 Caio Jordão Carvalho <caiojcarvalho@gmail.com>
|
||||||
SPDX-FileCopyrightText: 2019 Shubham Jangra <aryan100jangid@gmail.com>
|
SPDX-FileCopyrightText: 2019 Shubham Jangra <aryan100jangid@gmail.com>
|
||||||
|
SPDX-FileCopyrightText: 2020 David Edmundson <kde@davidedmundson.co.uk>
|
||||||
|
|
||||||
SPDX-License-Identifier: GPL-3.0-or-later
|
SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
*/
|
*/
|
||||||
|
@ -13,42 +14,40 @@
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
|
|
||||||
#include <KAuth>
|
|
||||||
|
|
||||||
#include <QEventLoop>
|
#include <QEventLoop>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QProcess>
|
#include <QProcess>
|
||||||
|
#include <QDBusContext>
|
||||||
|
|
||||||
using namespace KAuth;
|
class QDBusServiceWatcher;
|
||||||
|
|
||||||
class ExternalCommandHelper : public QObject
|
class ExternalCommandHelper : public QObject, public QDBusContext
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_CLASSINFO("D-Bus Interface", "org.kde.kpmcore.externalcommand")
|
Q_CLASSINFO("D-Bus Interface", "org.kde.kpmcore.externalcommand")
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void progress(int);
|
Q_SCRIPTABLE void progress(int);
|
||||||
void quit();
|
Q_SCRIPTABLE void report(QString);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
ExternalCommandHelper();
|
||||||
bool readData(const QString& sourceDevice, QByteArray& buffer, const qint64 offset, const qint64 size);
|
bool readData(const QString& sourceDevice, QByteArray& buffer, const qint64 offset, const qint64 size);
|
||||||
bool writeData(const QString& targetDevice, const QByteArray& buffer, const qint64 offset);
|
bool writeData(const QString& targetDevice, const QByteArray& buffer, const qint64 offset);
|
||||||
bool createFile(const QString& filePath, const QByteArray& fileContents);
|
|
||||||
|
|
||||||
public Q_SLOTS:
|
public Q_SLOTS:
|
||||||
ActionReply init(const QVariantMap& args);
|
Q_SCRIPTABLE QVariantMap RunCommand(const QString& command, const QStringList& arguments, const QByteArray& input, const int processChannelMode);
|
||||||
Q_SCRIPTABLE QVariantMap start(const QString& command, const QStringList& arguments, const QByteArray& input, const int processChannelMode);
|
Q_SCRIPTABLE QVariantMap CopyBlocks(const QString& sourceDevice, const qint64 sourceFirstByte, const qint64 sourceLength, const QString& targetDevice, const qint64 targetFirstByte, const qint64 blockSize);
|
||||||
Q_SCRIPTABLE QVariantMap copyblocks(const QString& sourceDevice, const qint64 sourceFirstByte, const qint64 sourceLength, const QString& targetDevice, const qint64 targetFirstByte, const qint64 blockSize);
|
Q_SCRIPTABLE bool WriteData(const QByteArray& buffer, const QString& targetDevice, const qint64 targetFirstByte);
|
||||||
Q_SCRIPTABLE bool writeData(const QByteArray& buffer, const QString& targetDevice, const qint64 targetFirstByte);
|
Q_SCRIPTABLE bool CreateFile(const QString& filePath, const QByteArray& fileContents);
|
||||||
Q_SCRIPTABLE bool createFile(const QByteArray& fileContents, const QString& filePath);
|
|
||||||
Q_SCRIPTABLE void exit();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void onReadOutput();
|
|
||||||
|
|
||||||
std::unique_ptr<QEventLoop> m_loop;
|
bool isCallerAuthorized();
|
||||||
|
|
||||||
|
void onReadOutput();
|
||||||
QProcess m_cmd;
|
QProcess m_cmd;
|
||||||
// QByteArray output;
|
QDBusServiceWatcher *m_serviceWatcher = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -60,6 +60,7 @@ KAboutData aboutKPMcore()
|
||||||
aboutData.addCredit(xi18nc("@info:credit", "Pali Rohár"), i18nc("@info:credit", "UDF support"), QStringLiteral("pali.rohar@gmail.com"));
|
aboutData.addCredit(xi18nc("@info:credit", "Pali Rohár"), i18nc("@info:credit", "UDF support"), QStringLiteral("pali.rohar@gmail.com"));
|
||||||
aboutData.addCredit(xi18nc("@info:credit", "Adriaan de Groot"), i18nc("@info:credit", "Calamares maintainer"), QStringLiteral("groot@kde.org"));
|
aboutData.addCredit(xi18nc("@info:credit", "Adriaan de Groot"), i18nc("@info:credit", "Calamares maintainer"), QStringLiteral("groot@kde.org"));
|
||||||
aboutData.addCredit(xi18nc("@info:credit", "Caio Jordão Carvalho"), i18nc("@info:credit", "Improved SMART support"), QStringLiteral("caiojcarvalho@gmail.com"));
|
aboutData.addCredit(xi18nc("@info:credit", "Caio Jordão Carvalho"), i18nc("@info:credit", "Improved SMART support"), QStringLiteral("caiojcarvalho@gmail.com"));
|
||||||
|
aboutData.addCredit(xi18nc("@info:credit", "David Edmundson"), i18nc("@info:credit", "Port from KAuth to Polkit"), QStringLiteral("kde@davidedmundson.co.uk"));
|
||||||
|
|
||||||
return aboutData;
|
return aboutData;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
</policy>
|
</policy>
|
||||||
|
|
||||||
<policy context="default">
|
<policy context="default">
|
||||||
<allow send_destination="org.kde.kpmcore.externalcommand"
|
<allow send_destination="org.kde.kpmcore.helperinterface"
|
||||||
send_interface="org.kde.kpmcore.externalcommand"/>
|
send_interface="org.kde.kpmcore.externalcommand"/>
|
||||||
|
|
||||||
</policy>
|
</policy>
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
# SPDX-FileCopyrightText: 2020 David Edmundson <kde@davidedmundson.co.uk>
|
||||||
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
[D-BUS Service]
|
||||||
|
Name=org.kde.kpmcore.helperinterface
|
||||||
|
Exec=@KDE_INSTALL_FULL_LIBEXECDIR@/kpmcore_externalcommand
|
||||||
|
User=root
|
|
@ -46,7 +46,3 @@ KPMCoreInitializer::KPMCoreInitializer( const char* backend ) : KPMCoreInitializ
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
KPMCoreInitializer::~KPMCoreInitializer()
|
|
||||||
{
|
|
||||||
ExternalCommand::stopHelper();
|
|
||||||
}
|
|
||||||
|
|
|
@ -20,7 +20,6 @@ public:
|
||||||
KPMCoreInitializer(); /// Default backend
|
KPMCoreInitializer(); /// Default backend
|
||||||
KPMCoreInitializer( const QString& backend ); /// Use named backend
|
KPMCoreInitializer( const QString& backend ); /// Use named backend
|
||||||
KPMCoreInitializer( const char* backend ); /// Use named backend
|
KPMCoreInitializer( const char* backend ); /// Use named backend
|
||||||
~KPMCoreInitializer();
|
|
||||||
|
|
||||||
bool isValid() const
|
bool isValid() const
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue