@@ -1,3 +1,15 @@ | |||
kpmcore (3.3.1~310-g80f5a32-1) unstable; urgency=medium | |||
* New snapshot: v3.3.0-310-g80f5a32 | |||
-- Alf Gaida <agaida@siduction.org> Thu, 29 Nov 2018 23:34:05 +0100 | |||
kpmcore (3.3.1~309-g09e4d47-3) unstable; urgency=medium | |||
* really 3.3.1~307-gb22be9a-1 | |||
-- Alf Gaida <agaida@siduction.org> Thu, 29 Nov 2018 21:07:28 +0100 | |||
kpmcore (3.3.1~309-g09e4d47-2) unstable; urgency=medium | |||
* just a rebuild |
@@ -20,7 +20,6 @@ distribution=unstable | |||
uploadrepo=extra | |||
repository="git@github.com:KDE/kpmcore" | |||
commit='b22be9ad9a39f' | |||
build="yes" | |||
clean="yes" |
@@ -59,7 +59,7 @@ void fat12::init() | |||
m_Move = cmdSupportCore; | |||
m_Copy = cmdSupportCore; | |||
m_Backup = cmdSupportCore; | |||
m_UpdateUUID = findExternal(QStringLiteral("dd")) ? cmdSupportFileSystem : cmdSupportNone; | |||
m_UpdateUUID = cmdSupportCore; | |||
m_GetUUID = cmdSupportCore; | |||
} | |||
@@ -157,7 +157,7 @@ bool fat12::create(Report& report, const QString& deviceNode) | |||
bool fat12::updateUUID(Report& report, const QString& deviceNode) const | |||
{ | |||
qint64 t = time(nullptr); | |||
long int t = time(nullptr); | |||
char uuid[4]; | |||
for (auto &u : uuid) { | |||
@@ -165,9 +165,7 @@ bool fat12::updateUUID(Report& report, const QString& deviceNode) const | |||
t >>= 8; | |||
} | |||
ExternalCommand cmd(report, QStringLiteral("dd"), { QStringLiteral("of=") + deviceNode , QStringLiteral("bs=1"), QStringLiteral("count=4"), QStringLiteral("seek=39") }); | |||
cmd.write(QByteArray(uuid, sizeof(uuid))); | |||
return cmd.start(); | |||
ExternalCommand cmd; | |||
return cmd.writeData(report, QByteArray(uuid, sizeof(uuid)), deviceNode, 39); | |||
} | |||
} |
@@ -50,7 +50,7 @@ void fat16::init() | |||
m_Move = cmdSupportCore; | |||
m_Copy = cmdSupportCore; | |||
m_Backup = cmdSupportCore; | |||
m_UpdateUUID = findExternal(QStringLiteral("dd")) ? cmdSupportFileSystem : cmdSupportNone; | |||
m_UpdateUUID = cmdSupportCore; | |||
m_Grow = findExternal(QStringLiteral("fatresize")) ? cmdSupportFileSystem : cmdSupportNone; | |||
m_Shrink = findExternal(QStringLiteral("fatresize")) ? cmdSupportFileSystem : cmdSupportNone; | |||
m_GetUUID = cmdSupportCore; |
@@ -14,6 +14,7 @@ | |||
* You should have received a copy of the GNU General Public License * | |||
* along with this program. If not, see <http://www.gnu.org/licenses/>.* | |||
*************************************************************************/ | |||
#include "fs/fat32.h" | |||
#include "util/externalcommand.h" | |||
@@ -48,7 +49,8 @@ bool fat32::create(Report& report, const QString& deviceNode) | |||
bool fat32::updateUUID(Report& report, const QString& deviceNode) const | |||
{ | |||
qint64 t = time(nullptr); | |||
// HACK: replace this hack with fatlabel "-i" (dosfstools 4.2) | |||
long int t = time(nullptr); | |||
char uuid[4]; | |||
for (auto &u : uuid) { | |||
@@ -56,10 +58,7 @@ bool fat32::updateUUID(Report& report, const QString& deviceNode) const | |||
t >>= 8; | |||
} | |||
// HACK: replace this hack with fatlabel "-i" (dosfstools 4.2) | |||
ExternalCommand cmd(report, QStringLiteral("dd"), { QStringLiteral("of=") + deviceNode, QStringLiteral("bs=1"), QStringLiteral("count=4"), QStringLiteral("seek=67") }); | |||
cmd.write(QByteArray(uuid, sizeof(uuid))); | |||
return cmd.start(); | |||
ExternalCommand cmd; | |||
return cmd.writeData(report, QByteArray(uuid, sizeof(uuid)), deviceNode, 67); | |||
} | |||
} |
@@ -29,7 +29,6 @@ | |||
#include <QString> | |||
#include <QStringList> | |||
#include <QFile> | |||
#include <QUuid> | |||
#include <algorithm> | |||
#include <ctime> | |||
@@ -188,10 +187,8 @@ bool ntfs::updateBootSector(Report& report, const QString& deviceNode) const | |||
std::swap(s[1], s[2]); | |||
#endif | |||
ExternalCommand cmd(report, QStringLiteral("dd"), { QStringLiteral("of=") + deviceNode , QStringLiteral("bs=1"), QStringLiteral("count=4"), QStringLiteral("seek=28") }); | |||
cmd.write(QByteArray(s, sizeof(s))); | |||
if (!cmd.start()) { | |||
ExternalCommand cmd; | |||
if (!cmd.writeData(report, QByteArray(s, sizeof(s)), deviceNode, 28)) { | |||
Log() << xi18nc("@info:progress", "Could not write new start sector to partition <filename>%1</filename> when trying to update the NTFS boot sector.", deviceNode); | |||
return false; | |||
} | |||
@@ -199,10 +196,7 @@ bool ntfs::updateBootSector(Report& report, const QString& deviceNode) const | |||
// Also update backup NTFS boot sector located at the end of the partition | |||
// NOTE: this should fail if filesystem does not span the whole partition | |||
qint64 pos = (lastSector() - firstSector()) * sectorSize() + 28; | |||
ExternalCommand cmd2(report, QStringLiteral("dd"), { QStringLiteral("of=") + deviceNode , QStringLiteral("bs=1"), QStringLiteral("count=4"), QStringLiteral("seek=") + QString::number(pos) }); | |||
cmd2.write(QByteArray(s, sizeof(s))); | |||
if (!cmd2.start()) { | |||
if (!cmd.writeData(report, QByteArray(s, sizeof(s)), deviceNode, pos)) { | |||
Log() << xi18nc("@info:progress", "Could not write new start sector to partition <filename>%1</filename> when trying to update the NTFS boot sector.", deviceNode); | |||
return false; | |||
} |
@@ -169,12 +169,23 @@ Device* SfdiskBackend::scanDevice(const QString& deviceNode) | |||
if ( d == nullptr && modelCommand.run(-1) && modelCommand.exitCode() == 0 ) | |||
{ | |||
QString modelName = modelCommand.output(); | |||
modelName = modelName.left(modelName.length() - 1); | |||
QString name = modelCommand.output(); | |||
name = name.left(name.length() - 1); | |||
if (name.trimmed().isEmpty()) { | |||
// Get 'lsblk --output kname' in the cases where the model name is not available. | |||
// As lsblk doesn't have an option to include a separator in its output, it is | |||
// necessary to run it again getting only the kname as output. | |||
ExternalCommand kname(QStringLiteral("lsblk"), {QStringLiteral("--nodeps"), QStringLiteral("--noheadings"), QStringLiteral("--output"), QStringLiteral("kname"), | |||
deviceNode}); | |||
if (kname.run(-1) && kname.exitCode() == 0) | |||
name = kname.output(); | |||
} | |||
Log(Log::Level::information) << xi18nc("@info:status", "Device found: %1", modelName); | |||
Log(Log::Level::information) << xi18nc("@info:status", "Device found: %1", name); | |||
d = new DiskDevice(modelName, deviceNode, 255, 63, deviceSize / logicalSectorSize / 255 / 63, logicalSectorSize); | |||
d = new DiskDevice(name, deviceNode, 255, 63, deviceSize / logicalSectorSize / 255 / 63, logicalSectorSize); | |||
} | |||
if ( d ) |
@@ -241,6 +241,55 @@ bool ExternalCommand::copyBlocks(CopySource& source, CopyTarget& target) | |||
return rval; | |||
} | |||
bool ExternalCommand::writeData(Report& commandReport, const QByteArray& buffer, const QString& deviceNode, const quint64 firstByte) | |||
{ | |||
d->m_Report = commandReport.newChild(); | |||
if (report()) | |||
report()->setCommand(xi18nc("@info:status", "Command: %1 %2", command(), args().join(QStringLiteral(" ")))); | |||
bool rval = true; | |||
if (!QDBusConnection::systemBus().isConnected()) { | |||
qWarning() << "Could not connect to DBus system bus"; | |||
return false; | |||
} | |||
auto *interface = new org::kde::kpmcore::externalcommand(QStringLiteral("org.kde.kpmcore.externalcommand"), | |||
QStringLiteral("/Helper"), QDBusConnection::systemBus(), this); | |||
interface->setTimeout(10 * 24 * 3600 * 1000); // 10 days | |||
QByteArray request; | |||
const quint64 nonce = interface->getNonce(); | |||
request.setNum(nonce); | |||
request.append(buffer); | |||
request.append(deviceNode.toUtf8()); | |||
request.append(QByteArray::number(firstByte)); | |||
QByteArray hash = QCryptographicHash::hash(request, QCryptographicHash::Sha512); | |||
QDBusPendingCall pcall = interface->writeData(privateKey->signMessage(hash, QCA::EMSA3_Raw), nonce, | |||
buffer, deviceNode, firstByte); | |||
QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pcall, this); | |||
QEventLoop loop; | |||
auto exitLoop = [&] (QDBusPendingCallWatcher *watcher) { | |||
loop.exit(); | |||
if (watcher->isError()) | |||
qWarning() << watcher->error(); | |||
else { | |||
QDBusPendingReply<bool> reply = *watcher; | |||
rval = reply.argumentAt<0>(); | |||
} | |||
setExitCode(!rval); | |||
}; | |||
connect(watcher, &QDBusPendingCallWatcher::finished, exitLoop); | |||
loop.exec(); | |||
return rval; | |||
} | |||
bool ExternalCommand::write(const QByteArray& input) | |||
{ |
@@ -69,6 +69,7 @@ public: | |||
public: | |||
bool copyBlocks(CopySource& source, CopyTarget& target); | |||
bool writeData(Report& report, const QByteArray& buffer, const QString& deviceNode, const quint64 firstByte); // same as copyBlocks but from QByteArray | |||
/**< @param cmd the command to run */ | |||
void setCommand(const QString& cmd); |
@@ -21,7 +21,6 @@ | |||
QString allowedCommands[] = { | |||
// TODO try to remove these later | |||
QStringLiteral("mv"), | |||
QStringLiteral("dd"), | |||
// TODO no root needed | |||
QStringLiteral("lsblk"), |
@@ -152,6 +152,7 @@ bool ExternalCommandHelper::writeData(const QString &targetDevice, const QByteAr | |||
return true; | |||
} | |||
// If targetDevice is empty then return QByteArray with data that was read from disk. | |||
QVariantMap ExternalCommandHelper::copyblocks(const QByteArray& signature, const quint64 nonce, const QString& sourceDevice, const qint64 sourceFirstByte, const qint64 sourceLength, const QString& targetDevice, const qint64 targetFirstByte, const qint64 blockSize) | |||
{ | |||
QVariantMap reply; | |||
@@ -213,7 +214,7 @@ QVariantMap ExternalCommandHelper::copyblocks(const QByteArray& signature, const | |||
bool rval = true; | |||
while (blocksCopied < blocksToCopy) { | |||
while (blocksCopied < blocksToCopy && !targetDevice.isEmpty()) { | |||
if (!(rval = readData(sourceDevice, buffer, readOffset + blockSize * blocksCopied * copyDirection, blockSize))) | |||
break; | |||
@@ -265,6 +266,33 @@ QVariantMap ExternalCommandHelper::copyblocks(const QByteArray& signature, const | |||
return reply; | |||
} | |||
bool ExternalCommandHelper::writeData(const QByteArray& signature, const quint64 nonce, const QByteArray& buffer, const QString& targetDevice, const qint64 targetFirstByte) | |||
{ | |||
if (m_Nonces.find(nonce) != m_Nonces.end()) | |||
m_Nonces.erase( nonce ); | |||
else | |||
return false; | |||
QByteArray request; | |||
request.setNum(nonce); | |||
request.append(buffer); | |||
request.append(targetDevice.toUtf8()); | |||
request.append(QByteArray::number(targetFirstByte)); | |||
// Do not allow using this helper for writing to arbitrary location | |||
if ( targetDevice.left(5) != QStringLiteral("/dev/") && !targetDevice.contains(QStringLiteral("/etc/fstab"))) | |||
return false; | |||
QByteArray hash = QCryptographicHash::hash(request, QCryptographicHash::Sha512); | |||
if (!m_publicKey.verifyMessage(hash, signature, QCA::EMSA3_Raw)) { | |||
qCritical() << xi18n("Invalid cryptographic signature"); | |||
return false; | |||
} | |||
return writeData(targetDevice, buffer, targetFirstByte); | |||
} | |||
QVariantMap ExternalCommandHelper::start(const QByteArray& signature, const quint64 nonce, const QString& command, const QStringList& arguments, const QByteArray& input, const int processChannelMode) | |||
{ | |||
QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8")); |
@@ -50,6 +50,7 @@ public Q_SLOTS: | |||
Q_SCRIPTABLE quint64 getNonce(); | |||
Q_SCRIPTABLE QVariantMap start(const QByteArray& signature, const quint64 nonce, const QString& command, const QStringList& arguments, const QByteArray& input, const int processChannelMode); | |||
Q_SCRIPTABLE QVariantMap copyblocks(const QByteArray& signature, const quint64 nonce, const QString& sourceDevice, const qint64 sourceFirstByte, const qint64 sourceLength, const QString& targetDevice, const qint64 targetFirstByte, const qint64 blockSize); | |||
Q_SCRIPTABLE bool writeData(const QByteArray& signature, const quint64 nonce, const QByteArray& buffer, const QString& targetDevice, const qint64 targetFirstByte); | |||
Q_SCRIPTABLE void exit(const QByteArray& signature, const quint64 nonce); | |||
private: |