diff --git a/src/plugins/sfdisk/sfdiskbackend.cpp b/src/plugins/sfdisk/sfdiskbackend.cpp index 8907bb9..efc0049 100644 --- a/src/plugins/sfdisk/sfdiskbackend.cpp +++ b/src/plugins/sfdisk/sfdiskbackend.cpp @@ -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); diff --git a/src/util/externalcommand.cpp b/src/util/externalcommand.cpp index 54996bb..9141cbc 100644 --- a/src/util/externalcommand.cpp +++ b/src/util/externalcommand.cpp @@ -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 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(); diff --git a/src/util/externalcommand.h b/src/util/externalcommand.h index 2f973e1..93b1be1 100644 --- a/src/util/externalcommand.h +++ b/src/util/externalcommand.h @@ -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 diff --git a/src/util/externalcommandhelper.cpp b/src/util/externalcommandhelper.cpp index da41261..6fc18dc 100644 --- a/src/util/externalcommandhelper.cpp +++ b/src/util/externalcommandhelper.cpp @@ -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 %1 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()) { diff --git a/src/util/externalcommandhelper.h b/src/util/externalcommandhelper.h index d0c72d4..944f012 100644 --- a/src/util/externalcommandhelper.h +++ b/src/util/externalcommandhelper.h @@ -20,6 +20,7 @@ #include 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);