|
|
|
@ -44,11 +44,11 @@
|
|
|
|
|
ExternalCommandHelper::ExternalCommandHelper()
|
|
|
|
|
{
|
|
|
|
|
if (!QDBusConnection::systemBus().registerObject(QStringLiteral("/Helper"), this, QDBusConnection::ExportAllSlots | QDBusConnection::ExportAllSignals)) {
|
|
|
|
|
::exit(-1);
|
|
|
|
|
exit(-1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!QDBusConnection::systemBus().registerService(QStringLiteral("org.kde.kpmcore.helperinterface"))) {
|
|
|
|
|
::exit(-1);
|
|
|
|
|
exit(-1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// we know this service must be registered already as DBus policy blocks calls from anyone else
|
|
|
|
@ -71,25 +71,25 @@ ExternalCommandHelper::ExternalCommandHelper()
|
|
|
|
|
@param size the number of bytes to read
|
|
|
|
|
@return true on success
|
|
|
|
|
*/
|
|
|
|
|
bool ExternalCommandHelper::readData(const QString& sourceDevice, QByteArray& buffer, const qint64 offset, const qint64 size)
|
|
|
|
|
bool ExternalCommandHelper::readData(QFile& device, QByteArray& buffer, const qint64 offset, const qint64 size)
|
|
|
|
|
{
|
|
|
|
|
QFile device(sourceDevice);
|
|
|
|
|
|
|
|
|
|
if (!device.isOpen()) {
|
|
|
|
|
if (!device.open(QIODevice::ReadOnly | QIODevice::Unbuffered)) {
|
|
|
|
|
qCritical() << xi18n("Could not open device <filename>%1</filename> for reading.", sourceDevice);
|
|
|
|
|
qCritical() << xi18n("Could not open device <filename>%1</filename> for reading.", device.fileName());
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Sequential devices such as /dev/zero or /dev/urandom return false on seek().
|
|
|
|
|
if (!device.isSequential() && !device.seek(offset)) {
|
|
|
|
|
qCritical() << xi18n("Could not seek position %1 on device <filename>%2</filename>.", offset, sourceDevice);
|
|
|
|
|
qCritical() << xi18n("Could not seek position %1 on device <filename>%2</filename>.", offset, device.fileName());
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
buffer = device.read(size);
|
|
|
|
|
|
|
|
|
|
if (size != buffer.size()) {
|
|
|
|
|
qCritical() << xi18n("Could not read from device <filename>%1</filename>.", sourceDevice);
|
|
|
|
|
qCritical() << xi18n("Could not read from device <filename>%1</filename>.", device.fileName());
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -97,28 +97,28 @@ bool ExternalCommandHelper::readData(const QString& sourceDevice, QByteArray& bu
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Writes the data from buffer to a given device.
|
|
|
|
|
@param targetDevice device or file to write to
|
|
|
|
|
@param device device or file to write to
|
|
|
|
|
@param buffer the data that we write
|
|
|
|
|
@param offset offset where to begin writing
|
|
|
|
|
@return true on success
|
|
|
|
|
*/
|
|
|
|
|
bool ExternalCommandHelper::writeData(const QString &targetDevice, const QByteArray& buffer, const qint64 offset)
|
|
|
|
|
bool ExternalCommandHelper::writeData(QFile& device, const QByteArray& buffer, const qint64 offset)
|
|
|
|
|
{
|
|
|
|
|
QFile device(targetDevice);
|
|
|
|
|
|
|
|
|
|
auto flags = QIODevice::WriteOnly | QIODevice::Unbuffered;
|
|
|
|
|
if (!device.isOpen()) {
|
|
|
|
|
if (!device.open(flags)) {
|
|
|
|
|
qCritical() << xi18n("Could not open device <filename>%1</filename> for writing.", targetDevice);
|
|
|
|
|
qCritical() << xi18n("Could not open device <filename>%1</filename> for writing.", device.fileName());
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!device.seek(offset)) {
|
|
|
|
|
qCritical() << xi18n("Could not seek position %1 on device <filename>%2</filename>.", offset, targetDevice);
|
|
|
|
|
qCritical() << xi18n("Could not seek position %1 on device <filename>%2</filename>.", offset, device.fileName());
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (device.write(buffer) != buffer.size()) {
|
|
|
|
|
qCritical() << xi18n("Could not write to device <filename>%1</filename>.", targetDevice);
|
|
|
|
|
qCritical() << xi18n("Could not write to device <filename>%1</filename>.", device.fileName());
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -233,11 +233,13 @@ QVariantMap ExternalCommandHelper::CopyFileData(const QString& sourceDevice, con
|
|
|
|
|
|
|
|
|
|
bool rval = true;
|
|
|
|
|
|
|
|
|
|
QFile target(targetDevice);
|
|
|
|
|
QFile source(sourceDevice);
|
|
|
|
|
while (blocksCopied < blocksToCopy) {
|
|
|
|
|
if (!(rval = readData(sourceDevice, buffer, readOffset + blockSize * blocksCopied * copyDirection, blockSize)))
|
|
|
|
|
if (!(rval = readData(source, buffer, readOffset + blockSize * blocksCopied * copyDirection, blockSize)))
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
if (!(rval = writeData(targetDevice, buffer, writeOffset + blockSize * blocksCopied * copyDirection)))
|
|
|
|
|
if (!(rval = writeData(target, buffer, writeOffset + blockSize * blocksCopied * copyDirection)))
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
bytesWritten += buffer.size();
|
|
|
|
@ -263,10 +265,10 @@ QVariantMap ExternalCommandHelper::CopyFileData(const QString& sourceDevice, con
|
|
|
|
|
const qint64 lastBlockWriteOffset = copyDirection == CopyDirection::Left ? writeOffset + blockSize * blocksCopied : targetOffset;
|
|
|
|
|
reportText = xi18nc("@info:progress", "Copying remainder of block size %1 from %2 to %3.", lastBlock, lastBlockReadOffset, lastBlockWriteOffset);
|
|
|
|
|
Q_EMIT report(reportText);
|
|
|
|
|
rval = readData(sourceDevice, buffer, lastBlockReadOffset, lastBlock);
|
|
|
|
|
rval = readData(source, buffer, lastBlockReadOffset, lastBlock);
|
|
|
|
|
|
|
|
|
|
if (rval) {
|
|
|
|
|
rval = writeData(targetDevice, buffer, lastBlockWriteOffset);
|
|
|
|
|
rval = writeData(target, buffer, lastBlockWriteOffset);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (rval) {
|
|
|
|
@ -297,7 +299,8 @@ QByteArray ExternalCommandHelper::ReadData(const QString& device, const qint64 o
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QByteArray buffer;
|
|
|
|
|
bool rval = readData(device, buffer, offset, length);
|
|
|
|
|
QFile sourceDevice(device);
|
|
|
|
|
bool rval = readData(sourceDevice, buffer, offset, length);
|
|
|
|
|
if (rval) {
|
|
|
|
|
return buffer;
|
|
|
|
|
}
|
|
|
|
@ -320,8 +323,9 @@ bool ExternalCommandHelper::WriteData(const QByteArray& buffer, const QString& t
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto canonicalTargetPath = std::filesystem::canonical(targetPath);
|
|
|
|
|
|
|
|
|
|
return writeData(QLatin1String(canonicalTargetPath.c_str()), buffer, targetOffset);
|
|
|
|
|
// TODO: Qt6 supports std::filesystem::path
|
|
|
|
|
QFile device(QLatin1String(canonicalTargetPath.c_str()));
|
|
|
|
|
return writeData(device, buffer, targetOffset);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QVariantMap ExternalCommandHelper::RunCommand(const QString& command, const QStringList& arguments, const QByteArray& input, const int processChannelMode)
|
|
|
|
|