Commit b0e5fa66 authored by Andrius Štikonas's avatar Andrius Štikonas
Browse files

Add an explicit ReadData method to polkit helper instead of relying on...

Add an explicit ReadData method to polkit helper instead of relying on copyblocks with empty target device.
parent 502ebc04
......@@ -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);
......
......@@ -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();
......
......@@ -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
......
......@@ -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()) {
......
......@@ -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);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment