Add an explicit ReadData method to polkit helper instead of relying on copyblocks with empty target device.

This commit is contained in:
Andrius Štikonas 2020-11-29 23:14:08 +00:00
parent 502ebc0474
commit b0e5fa66c4
5 changed files with 58 additions and 14 deletions

View File

@ -452,10 +452,9 @@ bool SfdiskBackend::updateDevicePartitionTable(Device &d, const QJsonObject &jso
qint32 maxEntries;
QByteArray gptHeader;
CopySourceDevice source(d, 512, 1023);
CopyTargetByteArray target(gptHeader);
ExternalCommand copyCmd;
if (copyCmd.copyBlocks(source, target)) {
ExternalCommand readCmd;
if (readCmd.readData(source, gptHeader)) {
QByteArray gptMaxEntries = gptHeader.mid(80, 4);
QDataStream stream(&gptMaxEntries, QIODevice::ReadOnly);
stream.setByteOrder(QDataStream::LittleEndian);

View File

@ -187,6 +187,35 @@ bool ExternalCommand::copyBlocks(const CopySource& source, CopyTarget& target)
return rval;
}
bool ExternalCommand::readData(const CopySourceDevice& source, QByteArray& target)
{
auto interface = helperInterface();
if (!interface)
return false;
QDBusPendingCall pcall = interface->ReadData(source.path(), source.firstByte(), source.length());
QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pcall, this);
QEventLoop loop;
auto exitLoop = [&] (QDBusPendingCallWatcher *watcher) {
loop.exit();
if (watcher->isError())
qWarning() << watcher->error();
else {
QDBusPendingReply<QByteArray> reply = *watcher;
target = reply.value();
}
};
connect(watcher, &QDBusPendingCallWatcher::finished, exitLoop);
loop.exec();
return target != QByteArray();
}
bool ExternalCommand::writeData(Report& commandReport, const QByteArray& buffer, const QString& deviceNode, const quint64 firstByte)
{
d->m_Report = commandReport.newChild();

View File

@ -27,6 +27,7 @@
class KJob;
class Report;
class CopySource;
class CopySourceDevice;
class CopyTarget;
class QDBusInterface;
class QDBusPendingCall;
@ -54,6 +55,7 @@ public:
public:
bool copyBlocks(const CopySource& source, CopyTarget& target);
bool readData(const CopySourceDevice& source, QByteArray& target);
bool writeData(Report& commandReport, const QByteArray& buffer, const QString& deviceNode, const quint64 firstByte); // same as copyBlocks but from QByteArray
bool createFile(const QByteArray& filePath, const QString& fileContents); // similar to writeData but creates a new file

View File

@ -103,7 +103,7 @@ bool ExternalCommandHelper::writeData(const QString &targetDevice, const QByteAr
{
QFile device(targetDevice);
auto flags = QIODevice::WriteOnly | QIODevice::Unbuffered | QIODevice::Append;
auto flags = QIODevice::WriteOnly | QIODevice::Unbuffered;
if (!device.open(flags)) {
qCritical() << xi18n("Could not open device <filename>%1</filename> for writing.", targetDevice);
return false;
@ -165,13 +165,9 @@ QVariantMap ExternalCommandHelper::CopyBlocks(const QString& sourceDevice, const
}
// Prevent some out of memory situations
constexpr qint64 MiB = 1 << 30;
if (blockSize > 100 * MiB) {
return QVariantMap();
}
if (targetDevice.isEmpty() && sourceLength > MiB) {
return QVariantMap();
}
QVariantMap reply;
reply[QStringLiteral("success")] = true;
@ -222,7 +218,7 @@ QVariantMap ExternalCommandHelper::CopyBlocks(const QString& sourceDevice, const
bool rval = true;
while (blocksCopied < blocksToCopy && !targetDevice.isEmpty()) {
while (blocksCopied < blocksToCopy) {
if (!(rval = readData(sourceDevice, buffer, readOffset + blockSize * blocksCopied * copyDirection, blockSize)))
break;
@ -255,10 +251,7 @@ QVariantMap ExternalCommandHelper::CopyBlocks(const QString& sourceDevice, const
rval = readData(sourceDevice, buffer, lastBlockReadOffset, lastBlock);
if (rval) {
if (targetDevice.isEmpty())
reply[QStringLiteral("targetByteArray")] = buffer;
else
rval = writeData(targetDevice, buffer, lastBlockWriteOffset);
rval = writeData(targetDevice, buffer, lastBlockWriteOffset);
}
if (rval) {
@ -274,6 +267,24 @@ QVariantMap ExternalCommandHelper::CopyBlocks(const QString& sourceDevice, const
return reply;
}
QByteArray ExternalCommandHelper::ReadData(const QString& device, const qint64 offset, const qint64 length)
{
if (!isCallerAuthorized()) {
return QByteArray();
}
if (length > MiB) {
return QByteArray();
}
QByteArray buffer;
bool rval = readData(device, buffer, offset, length);
if (rval) {
return buffer;
}
return QByteArray();
}
bool ExternalCommandHelper::WriteData(const QByteArray& buffer, const QString& targetDevice, const qint64 targetOffset)
{
if (!isCallerAuthorized()) {

View File

@ -20,6 +20,7 @@
#include <QDBusContext>
class QDBusServiceWatcher;
constexpr qint64 MiB = 1 << 30;
class ExternalCommandHelper : public QObject, public QDBusContext
{
@ -37,7 +38,9 @@ public:
public Q_SLOTS:
Q_SCRIPTABLE QVariantMap RunCommand(const QString& command, const QStringList& arguments, const QByteArray& input, const int processChannelMode);
Q_SCRIPTABLE QVariantMap CopyBlocks(const QString& sourceDevice, const qint64 sourceOffset, const qint64 sourceLength, const QString& targetDevice, const qint64 targetOffset, const qint64 blockSize);
Q_SCRIPTABLE QVariantMap CopyBlocks(const QString& sourceDevice, const qint64 sourceOffset, const qint64 sourceLength,
const QString& targetDevice, const qint64 targetOffset, const qint64 blockSize);
Q_SCRIPTABLE QByteArray ReadData(const QString& device, const qint64 offset, const qint64 length);
Q_SCRIPTABLE bool WriteData(const QByteArray& buffer, const QString& targetDevice, const qint64 targetOffset);
Q_SCRIPTABLE bool CreateFile(const QString& filePath, const QByteArray& fileContents);